Massimizzare le Prestazioni di Ansible con ControlPersist e Pipelining

Aumenta significativamente le prestazioni dei tuoi playbook Ansible abilitando il riutilizzo della connessione SSH con ControlPersist e ottimizzando l'esecuzione dei moduli tramite Pipelining. Questa guida fornisce approfondimenti essenziali e configurazioni pratiche per ridurre i tempi di esecuzione, specialmente in ambienti su larga scala. Scopri come ottimizzare il tuo `ansible.cfg` per un'automazione IT più veloce ed efficiente.

39 visualizzazioni

Massimizzare le prestazioni di Ansible con ControlPersist e Pipelining

Ansible è uno strumento potente per automatizzare l'infrastruttura IT, consentendo la gestione della configurazione e il deployment di applicazioni su larga scala. Tuttavia, in ambienti ad alto volume o quando si gestisce un gran numero di nodi, l'overhead intrinseco della creazione di connessioni SSH per ogni attività può diventare un collo di bottiglia significativo. Ciò può portare a tempi di esecuzione dei playbook dolorosamente lenti. Fortunatamente, Ansible offre due potenti funzionalità, ControlPersist e Pipelining, che possono migliorare drasticamente le prestazioni ottimizzando il modo in cui Ansible comunica con i nodi gestiti.

Questa guida ti illustrerà la comprensione e l'implementazione di ControlPersist e Pipelining. Sfruttando queste tecniche, puoi ridurre significativamente i tempi di esecuzione, rendendo la tua automazione Ansible più efficiente e reattiva, specialmente in ambienti con centinaia o migliaia di host. Padroneggiare queste ottimizzazioni è cruciale per chiunque desideri scalare efficacemente i propri deployment Ansible.

Comprensione del comportamento di connessione predefinito di Ansible

Per impostazione predefinita, Ansible stabilisce una nuova connessione SSH a ciascun host gestito per ogni attività eseguita all'interno di un playbook. Per ogni connessione, esegue diversi passaggi:

  1. Avvia connessione SSH: Viene stabilita una nuova connessione SSH.
  2. Trasferisci moduli: Ansible trasferisce i moduli Python necessari (o altri file pertinenti) all'host remoto.
  3. Esegui modulo: Il modulo viene eseguito sull'host remoto.
  4. Ricevi output: Ansible recupera i risultati dell'esecuzione.
  5. Chiudi connessione: La connessione SSH viene terminata.

Sebbene questo approccio sia robusto e garantisca uno stato pulito per ogni attività, il processo ripetuto di connessione e trasferimento di moduli consuma tempo considerevole, in particolare quando si tratta di numerose attività o di un ampio inventario.

Ottimizzazione delle connessioni con ControlPersist

ControlPersist è una funzionalità SSH che ti consente di mantenere aperte le connessioni SSH per un periodo specificato, anche dopo che il comando iniziale è terminato. Ciò significa che le attività Ansible successive che si rivolgono allo stesso host possono riutilizzare la connessione esistente e aperta anziché crearne una nuova. Ciò riduce significativamente la latenza associata all'impostazione delle sessioni SSH.

Come funziona ControlPersist

Quando abilitato, ControlPersist istruisce il client SSH a mantenere una connessione master di controllo. Le connessioni SSH successive allo stesso host utilizzando le stesse credenziali e opzioni possono quindi essere multiplexate su questa connessione master. Ansible sfrutta ciò impostando le opzioni ControlPath e ControlPersist nella sua configurazione SSH.

Abilitazione di ControlPersist in Ansible

Puoi abilitare ControlPersist in diversi modi:

  1. Tramite ansible.cfg (Consigliato per impostazioni globali o specifiche del progetto):
    Modifica o crea il tuo file ansible.cfg (situato nella directory del tuo progetto Ansible, ~/.ansible.cfg o /etc/ansible/ansible.cfg). Aggiungi la seguente configurazione alla sezione [ssh_connection]:

    ini [ssh_connection] ssh_args = -o ControlMaster=auto -o ControlPersist=600 -o ControlPath=~/.ssh/ansible_control_%r@%h:%p

    • -o ControlMaster=auto: Abilita la condivisione della connessione. Se esiste una connessione master, utilizzala; altrimenti, creane una.
    • -o ControlPersist=600: Mantiene la connessione di controllo aperta per 600 secondi (10 minuti). Modifica questo valore in base al tuo flusso di lavoro e alle politiche di sicurezza. Una durata maggiore significa un potenziale riutilizzo maggiore, ma anche più risorse mantenute aperte.
    • -o ControlPath=~/.ssh/ansible_control_%r@%h:%p: Definisce il percorso per il socket di controllo. %r è il nome utente remoto, %h è l'hostname e %p è la porta. Ciò garantisce socket unici per connessioni diverse.
  2. Tramite variabile d'ambiente:
    Puoi impostare gli argomenti SSH direttamente utilizzando una variabile d'ambiente:

    bash export ANSIBLE_SSH_ARGS='-o ControlMaster=auto -o ControlPersist=600 -o ControlPath=~/.ssh/ansible_control_%r@%h:%p' ansible-playbook your_playbook.yml

  3. Tramite Playbook (meno comune per questa impostazione):
    Sebbene sia possibile, generalmente non è consigliabile impostare opzioni SSH persistenti all'interno di un playbook stesso, poiché si tratta di un'impostazione a livello di connessione. Tuttavia, per completezza, potresti utilizzare ansible.builtin.set_fact o simili per influenzarla, ma ansible.cfg è preferibile.

Considerazioni per ControlPersist

  • Sicurezza: Assicurati che ControlPath sia protetto in modo che solo gli utenti autorizzati possano accedere ai socket di controllo. Il percorso predefinito nell'esempio è generalmente sicuro per le configurazioni a livello utente.
  • Utilizzo delle risorse: Mantenere le connessioni aperte consuma risorse sia sul nodo di controllo che sui nodi gestiti. Monitora l'utilizzo delle risorse se hai un numero molto elevato di connessioni persistenti.
  • Reset della connessione: Se un dispositivo di rete intermedio o il server SSH remoto impone timeout di connessione inferiori a ControlPersist, la connessione potrebbe comunque interrompersi. ControlPersist funziona meglio con ambienti di rete stabili.

Semplificazione dell'esecuzione dei moduli con Pipelining

Pipelining è un'altra potente ottimizzazione Ansible che riduce ulteriormente l'overhead dell'esecuzione delle attività. Invece di trasferire i moduli all'host remoto, eseguirli e quindi recuperare l'output, il pipelining trasmette i comandi direttamente attraverso la connessione SSH. Ciò significa che Ansible non ha bisogno di posizionare moduli sul file system remoto o creare file temporanei per l'output.

Come funziona Pipelining

Quando il pipelining è abilitato, Ansible esegue i moduli direttamente tramite ssh sull'host remoto. L'output standard e l'errore standard del modulo vengono inviati tramite pipe ad Ansible attraverso la stessa connessione SSH. Ciò elimina la necessità per Ansible di scrivere file sul file system remoto (come /usr/bin/ansible_module_name o file temporanei) ed eseguirli. Ciò è particolarmente efficace per i moduli che non richiedono l'escalation dei privilegi o un'interazione significativa con il file system remoto.

Abilitazione del Pipelining in Ansible

Il pipelining è abilitato tramite il file ansible.cfg o variabili d'ambiente.

  1. Tramite ansible.cfg:
    Aggiungi o modifica la sezione [ssh_connection]:

    ini [ssh_connection] pipelining = True

  2. Tramite variabile d'ambiente:
    bash export ANSIBLE_PIPELINING=True ansible-playbook your_playbook.yml

Considerazioni per Pipelining

  • Escalation dei privilegi: Il pipelining funziona meglio con i moduli che non richiedono l'escalation dei privilegi (ad esempio, utilizzando become: yes o sudo). Quando viene utilizzato become, Ansible in genere deve copiare file sul sistema remoto. Se utilizzi frequentemente become, il pipelining potrebbe non offrire molti vantaggi o addirittura causare problemi con alcuni tipi di moduli.
  • Compatibilità dei moduli: La maggior parte dei moduli Ansible integrati funziona bene con il pipelining. Tuttavia, i moduli personalizzati o quelli che si basano pesantemente sulle operazioni del file system remoto potrebbero comportarsi in modo diverso. Testa approfonditamente.
  • Stabilità della connessione: Una connessione SSH stabile è cruciale affinché il pipelining funzioni correttamente.
  • Impostazione SSH requiretty: Il pipelining è incompatibile con l'opzione SSH requiretty sul server remoto. Se il tuo server SSH ha Defaults requiretty in /etc/sudoers, potrebbe essere necessario disabilitarlo o utilizzare !requiretty per l'utente specifico con cui Ansible si connette.

Combinazione di ControlPersist e Pipelining per massime prestazioni

Per i guadagni di prestazioni più significativi, è altamente consigliato abilitare sia ControlPersist che Pipelining. Questa combinazione affronta i due principali overhead: l'impostazione della connessione e l'esecuzione dei moduli.

Ecco come potrebbe apparire il tuo ansible.cfg con entrambi abilitati:

[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=600 -o ControlPath=~/.ssh/ansible_control_%r@%h:%p
pipelining = True

Quando entrambi sono attivi:

  1. Ansible avvia una connessione SSH e stabilisce un ControlMaster se non esiste (ControlPersist).
  2. Per le attività successive, la connessione aperta esistente viene riutilizzata.
  3. I moduli vengono eseguiti direttamente tramite lo stream senza essere copiati nel file system (Pipelining).

Questa sinergia riduce drasticamente il tempo che Ansible dedica alla comunicazione con ogni nodo gestito, portando a esecuzioni di playbook molto più veloci.

Scenario di esempio pratico

Immaginiamo un playbook che deve eseguire 10 attività semplici su 100 host.

Senza ottimizzazioni:
Ogni attività richiede una nuova connessione SSH, trasferimento di moduli, esecuzione e chiusura della connessione. Ciò ammonta a 100 host * 10 attività * (tempo_connessione + tempo_trasferimento_moduli). Se tempo_connessione è 0,5 secondi e tempo_trasferimento_moduli è 0,2 secondi, si tratta di 100 * 10 * 0,7 = 700 secondi di overhead solo per la comunicazione e i trasferimenti, escludendo l'effettiva esecuzione del modulo.

Con ControlPersist e Pipelining abilitati:

  1. La prima attività su ciascun host stabilisce la connessione iniziale e imposta il ControlMaster.
  2. Tutte le 9 attività successive su quell'host riutilizzano la connessione aperta e trasmettono l'esecuzione del modulo in streaming.

L'overhead per host si avvicina a tempo_connessione + (9 * overhead_streaming_minimale). Il tempo totale è significativamente ridotto, con la maggior parte del tempo di esecuzione del playbook dedicata al lavoro effettivo svolto dai moduli, piuttosto che alla meccanica della comunicazione.

Quando essere cauti

Sebbene queste ottimizzazioni siano potenti, non sono universalmente applicabili senza considerazione:

  • Ambienti con firewall rigorosi o restrizioni di rete: Interruzioni frequenti della connessione o ispezione stateful potrebbero interferire con ControlPersist.
  • Ambienti ad alta sicurezza: Connessioni SSH di lunga durata potrebbero rappresentare un problema di sicurezza in ambienti altamente regolamentati. Modifica la durata di ControlPersist di conseguenza.
  • Playbook che si basano pesantemente su become e operazioni sui file: L'efficacia del pipelining è ridotta quando become viene utilizzato costantemente, poiché spesso richiede operazioni sui file. Testa l'impatto sulle prestazioni.

Conclusione

Ottimizzare la comunicazione di Ansible con i nodi gestiti è un passo fondamentale verso un'automazione efficiente e scalabile. Comprendendo e implementando ControlPersist e Pipelining, puoi ridurre drasticamente i tempi di esecuzione dei playbook. ControlPersist mantiene vive le connessioni SSH, riducendo l'overhead di connessione, mentre Pipelining trasmette l'esecuzione dei moduli, eliminando la necessità di trasferimenti di file. Combinare queste due impostazioni, principalmente tramite ansible.cfg, è una best practice per qualsiasi utente Ansible che gestisce un numero significativo di host o esegue playbook complessi. Testa sempre queste configurazioni nel tuo ambiente specifico per ottimizzare le prestazioni e garantire la compatibilità.