Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

L'approccio Iac (Infrastructure as Code) consiste non solo del codice archiviato nel repository, ma anche delle persone e dei processi che circondano questo codice. È possibile riutilizzare gli approcci dallo sviluppo del software alla gestione e descrizione dell'infrastruttura? Sarebbe una buona idea tenere a mente questa idea mentre leggi l’articolo.

English version

Questa è una trascrizione del mio spettacoli su DevopsConf2019-05-28.

Diapositive e video

L'infrastruttura come storia di Bash

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Supponiamo che tu arrivi a un nuovo progetto e ti dicano: “abbiamo Infrastruttura come codice". In realtà si scopre L'infrastruttura come storia di Bash o per esempio Documentazione come cronologia di bash. Questa è una situazione molto reale, ad esempio, un caso simile è stato descritto da Denis Lysenko in un discorso Come sostituire l'intera infrastruttura e iniziare a dormire sonni tranquilli, ha raccontato come hanno ottenuto un'infrastruttura coerente per il progetto dalla storia di bash.

Con un po' di voglia, possiamo dirlo L'infrastruttura come storia di Bash questo è come il codice:

  1. riproducibilità: Puoi prendere la cronologia di bash, eseguire i comandi da lì e potresti, comunque, ottenere una configurazione funzionante come output.
  2. controllo delle versioni: sai chi è entrato e cosa ha fatto, ancora una volta, non è un dato di fatto che questo ti porterà a una configurazione funzionante all'uscita.
  3. storia: la storia di chi ha fatto cosa. solo che non potrai usarlo se perdi il server.

Cosa fare?

Infrastruttura come codice

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Anche un caso così strano come L'infrastruttura come storia di Bash puoi tirarlo per le orecchie Infrastruttura come codice, ma quando vogliamo fare qualcosa di più complicato del buon vecchio server LAMP, arriveremo alla conclusione che questo codice necessita di essere in qualche modo modificato, cambiato, migliorato. Successivamente vorremmo considerare i parallelismi tra Infrastruttura come codice e sviluppo software.

ASCIUTTO

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

In un progetto di sviluppo di un sistema di storage era presente un'attività secondaria configurare periodicamente SDS: stiamo rilasciando una nuova versione: deve essere implementata per ulteriori test. Il compito è estremamente semplice:

  • accedi qui tramite ssh ed esegui il comando.
  • copia il file lì.
  • correggi la configurazione qui.
  • avviare il servizio da lì
  • ...
  • UTILE!

Per la logica descritta, bash è più che sufficiente, soprattutto nelle prime fasi del progetto, quando è appena agli inizi. Questo non è male che usi bash, ma nel tempo ci sono richieste per implementare qualcosa di simile, ma leggermente diverso. La prima cosa che mi viene in mente è il copia-incolla. E ora abbiamo già due script molto simili che fanno quasi la stessa cosa. Nel corso del tempo, il numero di script è cresciuto e ci siamo trovati di fronte al fatto che esiste una certa logica aziendale per la distribuzione di un'installazione che deve essere sincronizzata tra diversi script, questo è piuttosto complicato.

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Si scopre che esiste una pratica come DRY (Non ripeterti). L'idea è quella di riutilizzare il codice esistente. Sembra semplice, ma non siamo arrivati ​​subito a questo. Nel nostro caso l'idea era banale: separare le configurazioni dagli script. Quelli. logica aziendale di come l'installazione viene distribuita separatamente, configurazioni separatamente.

SOLIDO per CFM

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Nel tempo il progetto è cresciuto e naturale continuazione fu l'emergere di Ansible. La ragione principale della sua apparizione è che c'è esperienza nel team e che bash non è progettato per una logica complessa. Ansible iniziò anche a contenere una logica complessa. Per evitare che la logica complessa si trasformi in caos, esistono principi per organizzare il codice nello sviluppo del software SOLIDO Inoltre, ad esempio, Grigory Petrov nel rapporto "Perché uno specialista IT ha bisogno di un marchio personale" ha sollevato la questione che una persona è progettata in modo tale che sia più facile per lui operare con alcune entità sociali, nello sviluppo di software queste sono oggetti. Se combiniamo queste due idee e continuiamo a svilupparle, noteremo che possiamo anche usarle SOLIDO per rendere più semplice mantenere e modificare questa logica in futuro.

Il principio di responsabilità unica

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Ogni classe svolge un solo compito.

Non c'è bisogno di mescolare il codice e creare mostri di spaghetti divini monolitici. L'infrastruttura dovrebbe essere costituita da semplici mattoni. Si scopre che se dividi il playbook Ansible in piccoli pezzi, leggi i ruoli Ansible, allora sono più facili da mantenere.

Il principio aperto chiuso

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Principio aperto/chiuso.

  • Aperto all'estensione: significa che il comportamento di un'entità può essere esteso creando nuovi tipi di entità.
  • Chiuso al cambiamento: come risultato dell'estensione del comportamento di un'entità, non è necessario apportare modifiche al codice che utilizza tali entità.

Inizialmente, abbiamo distribuito l'infrastruttura di test su macchine virtuali, ma poiché la logica aziendale della distribuzione era separata dall'implementazione, abbiamo aggiunto l'implementazione su baremetall senza problemi.

Il principio di sostituzione di Liskov

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Principio di sostituzione di Barbara Liskov. gli oggetti in un programma devono essere sostituibili con istanze dei loro sottotipi senza modificare la corretta esecuzione del programma

Se lo guardi più in generale, non è una caratteristica di nessun progetto particolare che possa essere applicata lì SOLIDO, si tratta generalmente di CFM, ad esempio, su un altro progetto è necessario distribuire un'applicazione Java in scatola sopra vari Java, server applicazioni, database, sistema operativo, ecc. Utilizzando questo esempio, prenderò in considerazione ulteriori principi SOLIDO

Nel nostro caso, esiste un accordo all'interno del team dell'infrastruttura secondo cui se abbiamo installato il ruolo imbjava o oraclejava, allora avremo un eseguibile binario Java. Questo è necessario perché I ruoli upstream dipendono da questo comportamento; si aspettano Java. Allo stesso tempo, questo ci consente di sostituire un'implementazione/versione Java con un'altra senza modificare la logica di distribuzione dell'applicazione.

Il problema qui sta nel fatto che è impossibile implementarlo in Ansible, per cui compaiono alcuni accordi all'interno del team.

Il principio di segregazione dell'interfaccia

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Principio di separazione delle interfacce: “Molte interfacce specifiche del cliente sono migliori di un’interfaccia generica.

Inizialmente, abbiamo provato a inserire tutta la variabilità della distribuzione dell'applicazione in un unico playbook Ansible, ma era difficile da supportare e l'approccio quando abbiamo specificato un'interfaccia esterna (il client si aspetta la porta 443), quindi un'infrastruttura può essere assemblata da singoli utenti mattoni per un'implementazione specifica.

Il principio di inversione della dipendenza

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Il principio dell'inversione delle dipendenze. I moduli ai livelli più alti non dovrebbero dipendere dai moduli ai livelli più bassi. Entrambi i tipi di moduli devono dipendere da astrazioni. Le astrazioni non dovrebbero dipendere dai dettagli. I dettagli devono dipendere dalle astrazioni.

Qui l'esempio sarà basato su un antipattern.

  1. Uno dei clienti aveva un cloud privato.
  2. Abbiamo ordinato macchine virtuali all'interno del cloud.
  3. Tuttavia, a causa della natura del cloud, la distribuzione delle applicazioni era legata all'hypervisor su cui si trovava la VM.

Quelli. La logica di distribuzione dell'applicazione di alto livello scorreva con le dipendenze ai livelli inferiori dell'hypervisor e ciò comportava problemi durante il riutilizzo di questa logica. Non fare così.

Interazione

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

L'infrastruttura come codice non riguarda solo il codice, ma anche la relazione tra codice e persone, le interazioni tra gli sviluppatori dell'infrastruttura.

Fattore autobus

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Supponiamo che tu abbia Vasya nel tuo progetto. Vasya sa tutto della tua infrastruttura, cosa succederebbe se Vasya scomparisse all'improvviso? Questa è una situazione molto reale, perché potrebbe essere investito da un autobus. A volte succede. Se ciò accade e la conoscenza del codice, della sua struttura, del suo funzionamento, delle apparenze e delle password non è distribuita tra il team, potresti riscontrare una serie di situazioni spiacevoli. Per ridurre al minimo questi rischi e distribuire la conoscenza all’interno del team, è possibile utilizzare diversi approcci

Coppia Devopsing

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Non è come per scherzo, che gli amministratori hanno bevuto birra, cambiato password e un analogo della programmazione in coppia. Quelli. due ingegneri si siedono davanti a un computer, una tastiera e iniziano a configurare insieme la vostra infrastruttura: impostare un server, scrivere un ruolo Ansible, ecc. Sembra carino, ma per noi non ha funzionato. Ma casi speciali di questa pratica hanno funzionato. Arriva un nuovo dipendente, il suo mentore assume insieme a lui un vero compito, lavora e trasferisce conoscenze.

Un altro caso speciale è una chiamata incidente. Durante un problema, un gruppo di persone in servizio e coinvolte si riunisce, viene nominato un leader, che condivide il suo schermo ed esprime il filo del pensiero. Gli altri partecipanti seguono i pensieri del leader, spiano i trucchi dalla console, controllano di non aver perso una riga nel registro e imparano cose nuove sul sistema. Questo approccio ha funzionato il più delle volte.

Revisione del codice

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Soggettivamente, è stato più efficace diffondere la conoscenza sull’infrastruttura e sul suo funzionamento utilizzando la revisione del codice:

  • L'infrastruttura è descritta dal codice nel repository.
  • Le modifiche si verificano in un ramo separato.
  • Durante una richiesta di fusione, puoi vedere il delta delle modifiche nell'infrastruttura.

Il punto forte qui è che i revisori sono stati selezionati uno per uno, secondo un programma, ad es. con un certo grado di probabilità entrerai in una nuova infrastruttura.

Stile del codice

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Con il passare del tempo, durante le recensioni iniziarono ad apparire dei litigi, perché... i revisori avevano il proprio stile e la rotazione dei revisori li sovrapponeva con stili diversi: 2 spazi o 4, camelCase o snake_case. Non è stato possibile attuarlo subito.

  • La prima idea è stata quella di consigliare l'uso di linter, dopotutto tutti sono ingegneri, tutti sono intelligenti. Ma diversi editor e sistemi operativi non sono convenienti
  • Questo si è evoluto in un bot che scriveva su Slack per ogni commit problematico e allegava l'output del linter. Ma nella maggior parte dei casi c’erano cose più importanti da fare e il codice rimaneva intatto.

Maestro della costruzione verde

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Il tempo passa e siamo giunti alla conclusione che i commit che non superano determinati test non possono essere ammessi nel master. Ecco! Abbiamo inventato Green Build Master, che viene praticato da molto tempo nello sviluppo di software:

  • Lo sviluppo è in corso in una filiale separata.
  • Sono in corso dei test su questo thread.
  • Se i test falliscono, il codice non verrà inserito nel master.

Prendere questa decisione è stato molto doloroso, perché... ha suscitato molte polemiche, ma ne è valsa la pena, perché... Le recensioni iniziarono a ricevere richieste di fusioni senza differenze di stile e nel tempo il numero delle aree problematiche cominciò a diminuire.

Test IaC

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Oltre al controllo dello stile, puoi utilizzare altre cose, ad esempio, per verificare che la tua infrastruttura possa effettivamente essere implementata. Oppure verificare che i cambiamenti nelle infrastrutture non comportino perdite di denaro. Perché potrebbe essere necessario? La domanda è complessa e filosofica, è meglio rispondere con una storia che in qualche modo su Powershell c'era un auto-scaler che non controllava le condizioni al contorno => sono state create più VM del necessario => il cliente ha speso più soldi del previsto. Questo non è molto piacevole, ma sarebbe del tutto possibile individuare questo errore nelle fasi precedenti.

Ci si potrebbe chiedere: perché rendere le infrastrutture complesse ancora più complesse? I test per l'infrastruttura, proprio come per il codice, non riguardano la semplificazione, ma la conoscenza di come dovrebbe funzionare la tua infrastruttura.

Piramide di test IaC

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Test IaC: analisi statica

Se distribuisci l'intera infrastruttura in una volta e controlli che funzioni, potresti scoprire che ci vuole molto tempo e richiede molto tempo. Pertanto, la base deve essere qualcosa che funzioni rapidamente, ce n'è molto e copre molti luoghi primitivi.

Bash è complicato

Consideriamo un esempio banale. seleziona tutti i file nella directory corrente e copiali in un'altra posizione. La prima cosa che mi viene in mente:

for i in * ; do 
    cp $i /some/path/$i.bak
done

Cosa succede se c'è uno spazio nel nome del file? Bene, ok, siamo intelligenti, sappiamo come usare le virgolette:

for i in * ; do cp "$i" "/some/path/$i.bak" ; done

Ben fatto? NO! Cosa succede se non c'è nulla nella directory, ad es. il globbing non funzionerà.

find . -type f -exec mv -v {} dst/{}.bak ;

Ben fatto adesso? No... Ho dimenticato cosa può esserci nel nome del file n.

touch x
mv x  "$(printf "foonbar")"
find . -type f -print0 | xargs -0 mv -t /path/to/target-dir

Strumenti di analisi statica

Il problema del passaggio precedente potrebbe essere riscontrato quando abbiamo dimenticato le virgolette, per questo esistono molti rimedi in natura Shellcheck, in generale ce ne sono molti e molto probabilmente puoi trovare un linter per il tuo stack sotto il tuo IDE.

Lingua
Strumento

bash
Shellcheck

Ruby
RuboCop

python
pylint

ansible
Ansible Lint

Test IaC: test unitari

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Come abbiamo visto nell'esempio precedente, i linter non sono onnipotenti e non possono evidenziare tutte le aree problematiche. Inoltre, per analogia con i test nello sviluppo del software, possiamo richiamare i test unitari. Quello che mi viene subito in mente è shunit, giugno, specifica, pitest. Ma cosa fare con ansible, chef, saltstack e altri come loro?

All'inizio ne abbiamo parlato SOLIDO e che la nostra infrastruttura dovrebbe essere costituita da piccoli mattoncini. È giunto il loro momento.

  1. L'infrastruttura è divisa in piccoli mattoncini, ad esempio i ruoli Ansible.
  2. Viene distribuito un qualche tipo di ambiente, che si tratti di una finestra mobile o di una VM.
  3. Applichiamo il nostro ruolo Ansible a questo ambiente di test.
  4. Controlliamo che tutto abbia funzionato come previsto (eseguiamo dei test).
  5. Decidiamo ok o no, ok.

Test IaC: strumenti di test unitario

Domanda, cosa sono i test per il CFM? Puoi semplicemente eseguire lo script oppure utilizzare soluzioni già pronte per questo:

CFM
Strumento

ansible
Test infra

Chef
Ispeziona

Chef
Specifiche del server

mucchio di sale
Goss

Esempio per testinfra, verifica che users test1, test2 esistono e fanno parte di un gruppo sshusers:

def test_default_users(host):
    users = ['test1', 'test2' ]
    for login in users:
        assert host.user(login).exists
        assert 'sshusers' in host.user(login).groups

Cosa scegliere? La questione è complessa e ambigua, ecco un esempio di modifiche ai progetti su github per il 2018-2019:

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Strutture di test IaC

La domanda sorge spontanea: come mettere tutto insieme e lanciarlo? Potere prendilo e fallo da solo se c'è un numero sufficiente di ingegneri. Oppure puoi prendere soluzioni già pronte, anche se non ce ne sono molte:

CFM
Strumento

ansible
molecola

Chef
Cucina di prova

Terraform
Terratest

Esempio di modifiche nei progetti su github per il 2018-2019:

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Molecola vs. Cucina di prova

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Inizialmente noi ho provato a usare testkitchen:

  1. Crea una VM in parallelo.
  2. Applicare ruoli Ansible.
  3. Eseguire l'ispezione.

Per 25-35 ruoli ha funzionato 40-70 minuti, il che è stato molto tempo.

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Il passo successivo è stato il passaggio a jenkins/docker/ansible/molecule. Idiologicamente è tutto uguale

  1. Playbook Lint.
  2. Allinea i ruoli.
  3. Lanciare il contenitore
  4. Applicare ruoli Ansible.
  5. Esegui testinfra.
  6. Controlla l'idempotenza.

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Il lancio di 40 ruoli e i test per una dozzina hanno iniziato a richiedere circa 15 minuti.

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Cosa scegliere dipende da molti fattori, come lo stack utilizzato, l’esperienza del team, ecc. qui ognuno decide da solo come chiudere la questione Unit testing

Test IaC: test di integrazione

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Il prossimo passo nella piramide dei test dell'infrastruttura saranno i test di integrazione. Sono simili ai test unitari:

  1. L'infrastruttura è divisa in piccoli mattoncini, ad esempio i ruoli Ansible.
  2. Viene distribuito un qualche tipo di ambiente, che si tratti di una finestra mobile o di una VM.
  3. Per questo ambiente di test si applica molti Ruoli ansibili.
  4. Controlliamo che tutto abbia funzionato come previsto (eseguiamo dei test).
  5. Decidiamo ok o no, ok.

In parole povere, non controlliamo le prestazioni di un singolo elemento del sistema come negli unit test, controlliamo come è configurato il server nel suo insieme.

Test IaC: test end-to-end

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Al vertice della piramide siamo accolti dai test End to End. Quelli. Non controlliamo le prestazioni di un server separato, di uno script separato o di un componente separato della nostra infrastruttura. Controlliamo che molti server siano collegati tra loro, la nostra infrastruttura funzioni come ci aspettiamo. Purtroppo non ho mai visto soluzioni in scatola già pronte, probabilmente perché... L'infrastruttura è spesso unica ed è difficile modellarla e creare un framework per i test. Di conseguenza, ognuno crea le proprie soluzioni. C’è una richiesta, ma non c’è risposta. Pertanto, ti dirò cosa c'è per spingere gli altri a pensare in modo sano o per sbattere il naso sul fatto che tutto è stato inventato molto tempo fa prima di noi.

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Un progetto dalla ricca storia. Viene utilizzato nelle grandi organizzazioni e probabilmente ognuno di voi lo ha indirettamente incrociato. L'applicazione supporta molti database, integrazioni, ecc. Sapere come potrebbe apparire l'infrastruttura richiede molti file di composizione docker e sapere quali test eseguire in quale ambiente è Jenkins.

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Questo schema ha funzionato per un periodo piuttosto lungo, fino all'interno del quadro ricerca non abbiamo provato a trasferirlo su Openshift. I contenitori rimangono gli stessi, ma l'ambiente di lancio è cambiato (ciao di nuovo DRY).

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

L'idea della ricerca è andata oltre e in openshift hanno trovato qualcosa come APB (Ansible Playbook Bundle), che consente di racchiudere la conoscenza su come distribuire l'infrastruttura in un contenitore. Quelli. esiste un punto di conoscenza ripetibile e verificabile su come implementare l'infrastruttura.

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

Tutto ciò sembrava buono finché non ci siamo imbattuti in un'infrastruttura eterogenea: avevamo bisogno di Windows per i test. Di conseguenza, la conoscenza di cosa, dove, come distribuire e testare è in Jenkins.

Conclusione

Cosa ho imparato testando 200 righe di codice dell'infrastruttura

L'infrastruttura come è il codice

  • Codice nel repository.
  • Interazione umana.
  • Test dell'infrastruttura.

Collegamento

Fonte: habr.com

Aggiungi un commento