Come un team dell'infrastruttura inizia a utilizzare CI/CD

La maggior parte delle officine operative è ben avviata verso sistemi di configurazione e provisioning altamente automatizzati. A volte questa trasformazione fa parte di una trasformazione DevOps, altre volte è perché è il modo migliore per gestire il cambiamento nell'ambiente.

Questi sistemi sono molto bravi a creare artefatti di sistema che si adattano alle nostre esigenze, ma i problemi si verificano ancora la prima volta che un team di sviluppo distribuisce un'applicazione al nodo. I problemi non vengono rilevati finché non viene coinvolto un essere umano e la risoluzione dei problemi è un lungo processo manuale che coinvolge elenchi di controllo e correzioni ad hoc. Come possiamo spianare quella strada rocciosa dove si incontrano operazioni e artefatti di sviluppo?

Índice

Immettere CI/CD

Integrazione e consegna continue (CI/CD) sono da anni una parola d'ordine nei negozi IT, ma principalmente come processo di sviluppo. CI riguarda l'automazione del test per le modifiche apportate al codice e per evitare che le modifiche introdotte alla base di codice interrompano l'applicazione. Il CD consiste nell'assicurarsi che tutti gli artefatti finali siano adatti all'uso in un ambiente di produzione. Qualsiasi build dell'applicazione che superi i test di integrazione può essere identificata per una facile distribuzione.

Da un punto di vista operativo, la nostra "applicazione" è adatta per un server o un container. Il nostro "codice" sono i singoli frammenti di automazione che eseguono azioni. Il nostro "build" è il progetto per mettere insieme questi frammenti per ottenere un sistema funzionante. Tutte le modifiche a uno script o file di automazione devono essere verificate per garantire che non causino problemi.

Pensa ai test della tua automazione come panca o Fumo prove. La maggior parte dell'automazione non consiste in un grande blob di codice per ogni sistema. Piuttosto, abbiamo adottato altri modelli, come "non ripetere te stesso" (DRY) per creare blocchi riutilizzabili di automazione che possiamo ricombinare per ottenere la configurazione che desideriamo. Questo tipo di test ci consente di trovare problemi di integrazione tra i ruoli, scoprire problemi prima che si manifestino in produzione e, in generale, dimostrare che il sistema è adatto al suo scopo. Una pipeline CI/CD è uno strumento progettato per eseguire e gestire questo tipo di test e approvazioni.

Fondamenti per oleodotti solidi

Dobbiamo concordare alcuni principi per sfruttare una pipeline nelle operazioni:

  • Tutto il codice dell'infrastruttura è nel controllo della versione
    • Il controllo della versione è importante in un ambiente non pipeline ma critico alle operazioni di un gasdotto. Le operazioni devono essere a conoscenza di quali modifiche hanno "rotto la build" e fornire indicazioni chiare su ciò che è distribuibile. Ciò significa che puoi essere sicuro che un'immagine del contenitore creata e archiviata in un registro dalla pipeline o una macchina virtuale fornita e configurata dall'automazione sarà identica e funzionale.
  • Tutte le modifiche al codice dell'infrastruttura vengono testate individualmente
    • Apportiamo piccole modifiche alla nostra base di codice e tali modifiche vengono controllate per la correttezza di base. Ciò include il controllo della sintassi, la funzionalità, le dipendenze, ecc. Questo livello di test è come il test di unità per un'applicazione.
  • Tutto il codice dell'infrastruttura viene testato come un sistema combinato
    • I componenti dell'infrastruttura sono costituiti da blocchi discreti e più piccoli e devono essere testati nel loro insieme. Questi test sono per le caratteristiche ei comportamenti di quello che riteniamo essere un "sistema di lavoro". La nostra automazione può essere corretta e funzionante, ma essere ancora incompleta o avere passaggi in conflitto in ruoli diversi (ad esempio, abbiamo avviato MySQL ma non abbiamo aperto il firewall o abbiamo bloccato la porta in un ruolo di sicurezza).

Pitone concreto

Questo è tutto astratto, quindi passerò attraverso un semplice esempio. I ruoli e i test non sono di qualità della produzione, ma si spera siano abbastanza funzionali da poterli utilizzare come punto di partenza nelle tue indagini. Lavorerò anche con gli strumenti che mi sono più familiari. Il tuo ambiente varierà, ma i concetti dovrebbero essere tradotti in uno qualsiasi degli strumenti nella tua cassetta degli attrezzi. Se desideri vedere il codice di esempio, puoi controllare il Archivio GitHub.

Ecco cosa c'è nella mia cassetta degli attrezzi:

  • Abile: Un popolare motore di automazione scritto in Python che utilizzo da diversi anni, che utilizzerò per creare un unico ruolo per i test
  • Molecola: Un nuovo cablaggio di test basato sui ruoli per Ansible che porta alcuni concetti di progettazione basati su test allo sviluppo dei ruoli
  • Testinfra: Un framework basato su Pytest per l'ispezione degli stati del sistema, che userò per testare il comportamento del ruolo
  • Jenkins Blue Ocean: Un nuovo plug-in di pipeline per Jenkins che fornisce una nuova interfaccia utente per le pipeline e supporta le definizioni Jenkinsfile per una pipeline

Ecco alcuni altri dettagli sulla configurazione su un sistema Fedora 28:

  • Poiché Ansible, Molecule e Testinfra sono tutti distribuiti tramite PyPi, li ho installati tutti con pip a livello globale.
  • C'è un contenitore per Jenkins con il nuovo plug-in dell'interfaccia utente, quindi lo eseguo sullo stesso host Fedora 28.
  • Molecule supporta i test all'interno di un contenitore e Jenkins può utilizzare quel contenitore come builder in una pipeline. Per ottenere il plug-in della finestra mobile Jenkins nel contenitore Jenkins che parla con Docker sull'host, ho eseguito quel contenitore come "privilegiato", ho montato il file socket della finestra mobile e ho modificato il contesto SELinux sull'host. Dovrai determinare cosa è meglio per il tuo ambiente, poiché questa non sarà l'opzione migliore per nulla al di là di questa prova di concetto.

Successivamente ti mostrerò l'immagine di base di CentOS 7 che ho creato per Molecule che include tutte le stesse dipendenze dell'host Fedora 28 in cui abbiamo sviluppato il ruolo.

Crea la directory dei ruoli

Costruiamo un ruolo per installare un server Web Apache. Nella cartella del progetto di primo livello, avremo il nostro inventario, un playbook del sito e a roles directory. Nel roles directory, useremo Molecule per inizializzare la struttura della directory dei ruoli.

molecule init role -r webserver
--> Initializing new role webserver...
Initialized role in /root/iac-ci/blog/ansible/roles/webserver successfully.

Nella nuova creazione webserver directory, vedrai qualcosa che assomiglia al risultato di un file ansible-galaxy init comando con l'aggiunta di a molecule directory. Non ho modificato nessuna delle impostazioni predefinite sulla riga di comando, il che significa che Molecule utilizzerà Docker come destinazione per eseguire i playbook e Testinfra come verificatore per eseguire i test. Puoi guardare molecule/default/molecule.yml per quei dettagli o per modificare le opzioni.

Scrivi il nostro ruolo

Normalmente attiveremmo il nostro editor tasks/main.yml e inizia a scrivere attività Ansible. Ma dal momento che stiamo pensando in anticipo ai test, iniziamo da lì (altrimenti chiamato test-driven design). Dal momento che abbiamo bisogno di un server web in esecuzione, abbiamo due requisiti:

  • il servizio è attivo?
  • c'è una pagina da servire?

Quindi possiamo aprire lo script Python predefinito che Molecule ha creato per Testinfra, eseguire molecule/default/tests/test_default.pye aggiungere quanto segue dopo il test.

def test_httpd_runing(host):
  httpd = host.service("httpd")
  assert httpd.is_running

def test_index_contents(host):
  index = host.file("/var/www/html/index.html")
  assert index.exists

Stiamo utilizzando due moduli integrati, Service e File, per controllare lo stato del sistema dopo l'esecuzione del ruolo Ansible. Utilizzeremo questi stessi test per i nostri test del fumo, ma in un ambiente dal vivo, vorrai controlli più sofisticati rispetto ai comportamenti previsti.

Ora possiamo aggiungere le attività ei modelli desiderati al ruolo per soddisfare i requisiti. Installeremo il pacchetto, creeremo il modello index.htmltasks/main.ymle puoi vedere il resto nel repository.

- name: Install Apache
  package
:
    name
: "{{ item }}"
    state
: present
  with_items
:
   - httpd

- name
: Create index
  template
:
    src
: templates/index.html.j2
    dest
: /var/www/html/index.html
  notify
:
   - restart httpd

Esecuzione di un test

Il passaggio finale prima di eseguire qualsiasi test con Molecule o Testinfra è creare l'immagine di base di cui abbiamo bisogno. Non solo abbiamo bisogno delle dipendenze per il framework, vogliamo anche usare un contenitore che abbia un init sistema. Questo ci consente di testare l'eventuale destinazione di una macchina virtuale senza la necessità di una seconda macchina virtuale disponibile.

FROM centos/systemd

RUN yum -y install epel-release &&
    yum -y install gcc python-pip python-devel openssl-devel docker openssh-clients &&
    pip install docker molecule testinfra ansible &&
    yum clean all

Assegna al contenitore un nome che ricorderai poiché lo useremo nella nostra pipeline Jenkins.

docker build . -t molecule-base

È possibile eseguire i test sull'host ora prima di creare la pipeline. Dal roles/webserver directory, esegui molecule test, che eseguirà la sua matrice predefinita, inclusi i test Testinfra. Puoi controllare la matrice, ma quando creiamo la nostra pipeline, sceglieremo di eseguire i passaggi individualmente invece di utilizzare il test comando.

Con il nostro ruolo scritto e i nostri test in atto, possiamo creare la pipeline per controllare la nostra build.

Costruire il gasdotto

Il Guida all'installazione di Jenkins mostra come ottenere il contenitore e come sbloccare Jenkins dopo l'esecuzione. In alternativa, puoi usare questo tutorial sulla pipeline, che ti guiderà anche attraverso la connessione della tua istanza Jenkins a GitHub. La pipeline controllerà il tuo codice ogni volta che viene eseguito, quindi è fondamentale avere Ansible, Molecule e Testinfra sotto il controllo del codice sorgente.

Vai all'interfaccia utente web di Jenkins Blue Ocean all'indirizzo localhost:8080/blue e fare clic su Nuova pipeline. Se stai utilizzando un fork del mio repository GitHub, Jenkins rileverà il file Jenkins esistente e inizierà immediatamente a eseguire la pipeline. Potresti voler scegliere un nuovo repository senza un Jenkinsfile.

Nella nuova pipeline, dovresti vedere una colonna Impostazioni pipeline sul lato destro. Seleziona Docker nella casella a discesa e aggiungi il nome dell'immagine di base alla casella denominata Immagine. Questa sarà l'immagine di base utilizzata per tutti i contenitori Docker creati da questa pipeline.

In Ambiente, fai clic sul blu + simbolo e aggiungi ROLEDIR sotto Nome e ansible/roles/webserver sotto Valore. Lo useremo più volte nella pipeline. L'impostazione di una variabile di ambiente al livello più alto significa che è possibile accedervi in ​​qualsiasi fase.

Clicca sul + al centro della pagina per creare una nuova fase. Le fasi sono porzioni di lavoro eseguite dal lavoro della pipeline e ciascuna fase può essere composta da più fasi sequenziali. Per questa pipeline, creeremo una fase per ogni comando Molecule che vogliamo eseguire, per il playbook Ansible eseguito sulla VM e per i test Testinfra eseguiti sulla VM.

Le fasi Molecule saranno tutte comandi della shell, quindi fai clic su Aggiungi passaggio e seleziona Script Shell. Nella casella, aggiungi le seguenti righe:

cd $ROLEDIR
molecule syntax

Questo assicurerà che siamo nella directory del ruolo nella directory di lavoro locale di Jenkins prima di chiamare Molecule. Puoi guardare la matrice di test per vedere quali controlli specifici vuoi eseguire. Non sarà necessario creare o distruggere alcuna istanza, poiché Jenkins gestirà quei contenitori.

Dopo aver aggiunto alcune fasi, puoi premere Salva. Ciò eseguirà automaticamente il commit del file Jenkins nel repository e avvierà il lavoro della pipeline. Puoi scegliere di impegnarti per master o un nuovo ramo, il che significa che puoi testare nuovo codice senza interrompere la produzione.

In alternativa, il file Jenkins viene eseguito nello stesso repository del resto del nostro codice. Puoi modificare direttamente il file per duplicare le fasi Molecule e utilizzare Git per confermare le modifiche dalla riga di comando. Puoi fare in modo che Jenkins esegua la scansione del repository e raccolga le nuove fasi.

Per la fase Ansible, dobbiamo assicurarci di avere una voce nell'host di test nel inventory file e un playbook del sito che include il ruolo che vogliamo eseguire.

# inventory
iac-tgt.example.com ansible_user=root

# site.yml
---
- hosts
: all
  roles
:
    - role
: webserver

Il tipo di passaggio per questa fase è "Invoca un playbook Ansible". Inserisci tutti i valori appropriati. Per qualsiasi cosa abbia bisogno di un percorso, come Playbook, usa un percorso relativo dalla base del repository, come ansible/site.yml. Puoi importare chiavi SSH o utilizzare un file del vault Ansible per le credenziali.

La nostra ultima fase è la fase Testinfra, che è anche uno script di shell. Per eseguire Testinfra dalla riga di comando senza invocare Molecule, dovremo assicurarci di passare alcune variabili. Testinfra può utilizzare Ansible come back-end di connessione, quindi possiamo utilizzare lo stesso inventario e le stesse credenziali di prima.

Nella casella Shell Script, aggiungi quanto segue:

testinfra --ssh-identity-file=${KEYFILE} --connection=ansible --ansible-inventory=${MOLECULE_INVENTORY_FILE}
${ROLEDIR}/molecule/default/tests/test_default.py

Nelle Impostazioni per lo stage, crea la seguente variabile di ambiente:

MOLECULE_INVENTORY_FILE ansible/inventory

Il KEYFILE variabile viene creata da un'associazione variabile di una credenziale. Questo deve essere fatto nel Jenkinsfile, poiché la configurazione di quel passaggio non è ancora supportata nell'interfaccia. Ciò renderà la stessa chiave SSH configurata per la fase Ansible disponibile come file per la durata della fase.

Attraverso il file Jenkins nel repository di esempio e questi passaggi, dovresti avere una pipeline funzionante. E si spera che tu abbia un'idea non solo di come funziona, ma anche del motivo per cui vale la pena provare la nostra infrastruttura nello stesso modo in cui i nostri colleghi sviluppatori testano le modifiche al codice dell'applicazione. Sebbene gli esempi siano semplici, puoi creare una suite di test che garantisca che il codice dell'infrastruttura distribuisca un sistema su cui il codice dell'applicazione può fare affidamento. Nello spirito di DevOps, dovrai collaborare con il tuo team di sviluppatori per eliminare questi test di accettazione.

Artículos de interés

Subir