Upute: kako testirati ansible uloge i otkriti probleme prije produkcije

Pozdrav svima!

Radim kao DevOps inženjer u servisu za rezervaciju hotela. Ostrovok.ruU ovom članku želim podijeliti naše iskustvo s testiranjem ansible uloga.

U Ostrovok.ru kao menadžer konfiguracija koristimo ansible. Nedavno smo došli do potrebe za testiranjem uloga, ali, ispostavilo se, da ne postoji mnogo alata za to – najpopularniji je vjerojatno okvir Molecule, pa smo odlučili koristiti njega. Međutim, pokazalo se da dokumentacija krije mnoge zamke. Nismo uspjeli pronaći dovoljno detaljan vodič na ruskom, pa smo odlučili napisati ovaj članak.

Upute: kako testirati ansible uloge i otkriti probleme prije produkcije

Molecule

Molekula – okvir za pomoć u testiranju ansible uloga.

P pojednostavljena definicija: Molekula stvara instancu na odabranoj platformi (oblak, virtualka, kontejner; više informacija potražite u odjeljku Driver), izvršava vašu ulogu na njoj, zatim pokreće testove i briše instancu. Ukoliko dođe do problema tijekom bilo kojeg koraka, Molekula će vas obavijestiti o tome.

Sada detaljnije.

Malo teorije

Razmotrimo dvije ključne entitete Molekule: Scenario i Driver.

Scenario

Scenario sadrži opis onoga što, gdje, kako i u kojem redoslijedu će biti izvršeno. Jedna uloga može imati više scenarija, a svaki je direktorij na putu /molecule/, koji sadrži opise potrebnih radnji za testiranje. Obavezno mora postojati scenario default, koji će biti automatski stvoren ako inicijalizirate ulogu pomoću Molekule. Imena sljedećih scenarija biraju se po vašoj želji.

Redoslijed radnji testiranja u scenariju naziva se matrix, a prema zadanim postavkama to je:

(Koraci označeni ?, prema zadanim postavkama se preskoče, osim ako ih korisnik ne opiše)

  • lint – pokretanje linters. Prema zadanim postavkama se koriste yamllint i flake8,
  • destroy – brisanje instanci s prethodnog pokretanja Molekule (ako su ostale),
  • dependency? — установка ansible-зависимости тестируемой роли,
  • syntax – provjera sintakse uloge pomoću ansible-playbook --syntax-check,
  • create – stvaranje instance,
  • prepare? — подготовка инстанса; например, проверка / установка python2
  • converge – pokretanje testiranog playbooka,
  • idempotence – ponovni pokretanje playbooka za test na idempotentnost,
  • side_effect? — действия, не относящиеся непосредственно к роли, но нужные для тестов,
  • verify – pokretanje testova rezultantne konfiguracije pomoću testinfra(prema zadanim postavkama) /goss/inspec,
  • cleanup? — (в новых версиях) — грубо говоря, «очистка» внешней инфраструктуры, задетой Молекулой,
  • destroy – brisanje instance.

Ovaj redoslijed pokriva većinu slučajeva, no, prema potrebi, može se promijeniti.

Svaki od gore navedenih koraka može se pokretati posebno pomoću molecule. No, važno je razumjeti da za svaku od ove cli naredbi može postojati vlastiti slijed akcija koje možete saznati izvršavanjem molecule matrix. Na primjer, kada se pokrene naredba converge (izvršavanje testiranog playbook-a) bit će izvršene sljedeće akcije:

$ molecule matrix converge
...
└── default         # naziv scenarija
    ├── dependency  # instalacija ovisnosti
    ├── create      # kreiranje instanse
    ├── prepare     # priprema instanse
    └── converge    # izvršavanje playbook-a

Slijed ovih radnji se može uređivati. Ako je nešto iz popisa već izvršeno, bit će preskočeno. Trenutno stanje, kao i konfiguracija instanci, Molekula čuva u direktoriju $TMPDIR/molecule//.

Dodati korake s ? može se, opisujući željene akcije u formatu ansible playbook-a, a ime datoteke prilagođava se koraku: prepare.yml/side_effect.yml. Očekivati će da će se ove datoteke nalaziti u mapi scenarija.

Driver

Driver je entitet u kojem se kreiraju instance za testove.
Popis standardnih drajvera za koje Molekula ima pripremljene šablone je sljedeći: Azure, Docker, EC2, GCE, LXC, LXD, OpenStack, Vagrant, Delegated.

U većini slučajeva, šabloni su datoteke create.yml i destroy.yml u mapi scenarija koje opisuju kreiranje i brisanje instance, redom.
Izuzeci su Docker i Vagrant, jer interakcija s njihovim modulima može se odvijati bez gore navedenih datoteka.

Treba istaknuti drajver Delegated, jer u slučaju njegove upotrebe u datotekama za kreiranje i brisanje instance, opisana je samo obrada sa konfiguracijom instanci, ostatak bi trebao opisati inženjer.

Zadani drajver je Docker.

Sada prelazimo na praksu, a dodatne značajke ćemo razmotriti tamo.

Početak rada

Kao "hello world" testirat ćemo jednostavnu ulogu za instalaciju nginx-a. Kao drajver odabrat ćemo docker – mislim da ga većina od vas ima instaliranog (i sjetimo se, docker je zadan drajver).

Pripremimo virtualenv i instalirajmo ga u molecule:

> pip install virtualenv
> virtualenv -p `which python2` venv
> source venv/bin/activate
> pip install molecule docker  # molecule će instalirati ansible kao ovisnost; docker za drajver

Sljedeći korak je inicijalizacija nove uloge.
Inicijalizacija nove uloge, kao i novog scenarija, vrši se pomoću naredbe molecule init:

> molecule init role -r nginx
--> Initializing new role nginx...
Initialized role in /nginx successfully.
> cd nginx
> tree -L 1
.
├── README.md
├── defaults
├── handlers
├── meta
├── molecule
├── tasks
└── vars

6 directories, 1 file

Dobila se tipična ansible uloga. Dalje, sve interakcije s CLI Molecule obavljaju se iz korijena uloge.

Pogledajmo što se nalazi u direktoriju uloge:

> tree molecule/default/
molecule/default/
├── Dockerfile.j2  # Jinja predložak za Dockerfile
├── INSTALL.rst.   # Malo informacija o instalaciji ovisnosti scenarija
├── molecule.yml   # Konfiguracijska datoteka
├── playbook.yml   # Playbook za pokretanje uloge
└── tests          # Direktorij s testovima faze verifikacije
    └── test_default.py

1 direktorij, 6 datoteka

Razmotrit ćemo konfiguraciju molecule/default/molecule.yml (zamijenit ćemo samo docker sliku):

---
dependency:
  name: galaxy
driver:
  name: docker
lint:
  name: yamllint
platforms:
  - name: instance
    image: centos:7
provisioner:
  name: ansible
  lint:
    name: ansible-lint
scenario:
  name: default
verifier:
  name: testinfra
  lint:
    name: flake8

dependency

Ovaj odjeljak opisuje izvor ovisnosti.

Moguće opcije: galaxy, gilt, shell.

Shell je jednostavno komandna ljuska koja se koristi ako galaxy i gilt ne pokrivaju vaše potrebe.

Neću se ovdje dulje zadržavati, dovoljno je opisano u dokumentaciju.

driver

Ime drajvera. U našem slučaju to je docker.

lint

Kao linterski alat koristi se yamllint.

Korisne opcije u ovom dijelu konfiguracije su mogućnost određivanja konfiguracijske datoteke za yamllint, prosljeđivanje varijabli okruženja ili isključivanje lintera:

lint:
  name: yamllint
  options:
    config-file: foo/bar
  env:
    FOO: bar
  enabled: False

platforms

Opisuje konfiguraciju instanci.
U slučaju da je docker uloga drajvera, Molecule iterira kroz ovaj odjeljak, a svaki element popisa dostupan je u Dockerfile.j2 kao varijabla item.

U slučaju drajvera, u kojem su obavezni create.yml i destroy.yml, odjeljak je dostupan u njima kao molecule_yml.platforms, a iteracije po njemu opisane su već u tim datotekama.

Budući da Molecule pruža upravljanje instancama ansible modula, popis mogućih postavki treba tražiti tamo. Na primjer, za docker se koristi modul docker_container_module. Koji moduli se koriste u ostalim drajverima mogu se pronaći u dokumentaciju.

Također, primjeri korištenja različitih drajvera mogu se naći u testovima same Molecule.

Zamijenit ćemo ovdje centos:7 na ubuntu.

provisioner

„Pružatelj“ je entitet koji upravlja instancama. U slučaju Molecule to je ansible, podrška za druge nije planirana, stoga se ovaj odjeljak može s oprezom nazvati proširenom konfiguracijom ansible.
Ovdje možete navesti mnogo toga, istaknuo bih glavne, po mom mišljenju, trenutke:

  • playbooks: možete navesti koje playbookove treba koristiti u određenim fazama.

provisioner:
  name: ansible
  playbooks:
    create: create.yml
    destroy: ..\/default\/destroy.yml
    converge: playbook.yml
    side_effect: side_effect.yml
    cleanup: cleanup.yml

provisioner:
  name: ansible
  config_options:
    defaults:
      fact_caching: jsonfile
    ssh_connection:
      scp_if_ssh: True

provisioner:
  name: ansible  
  connection_options:
    ansible_ssh_common_args: "-o 'UserKnownHostsFile=\/dev\/null' -o 'ForwardAgent=yes'"

  • opcije: Ansible parametri i varijable okruženja

provisioner:
  name: ansible  
  options:
    vvv: true
    diff: true
  env:
    FOO: BAR

scenario

Naziv i opis sekvenci scenarija.
Matrica akcija po defaultu za neku komandu može se promijeniti dodavanjem ključa <command>_sequence i kao vrijednost za njega definirajući potrebni nam popis koraka.
Pretpostavimo da želimo promijeniti redoslijed akcija prilikom pokretanja komande za izvršavanje playbooka: molecule converge

# изначально:
# - dependency
# - create
# - prepare
# - converge
scenario:
  name: default
  converge_sequence:
    - create
    - converge

verifier

Postavke okvira za testiranje i linternu okvir. Po defaultu se koristi testinfra i flake8. Moguće opcije su slične onima navedenim ranije:

verifier:
  name: testinfra
  additional_files_or_dirs:
    - ..\/path\/to\/test_1.py
    - ..\/path\/to\/test_2.py
    - ..\/path\/to\/directory\/*
  options:
    n: 1
  enabled: False
  env:
    FOO: bar
  lint:
    name: flake8
    options:
      benchmark: True
    enabled: False
    env:
      FOO: bar

Vratimo se našoj ulozi. Uredimo datoteku tasks\/main.yml do sljedećeg oblika:

---
- name: Install nginx
  apt:
    name: nginx
    state: present

- name: Start nginx
  service:
    name: nginx
    state: started

I dodajmo testove u molecule\/default\/tests\/test_default.py

def test_nginx_is_installed(host):
    nginx = host.package("nginx")
    assert nginx.is_installed

def test_nginx_running_and_enabled(host):
    nginx = host.service("nginx")
    assert nginx.is_running
    assert nginx.is_enabled

def test_nginx_config(host):
    host.run("nginx -t")

Gotovo, ostaje samo pokrenuti (iz korijena uloge, da podsjetim):

> molecule test

Dug ishod pod razotkrivanjem:

--> Potvrđivanje sheme /nginx/molecule/default/molecule.yml.
Validacija je uspješno završena.
--> Testna matrica

└── default
    ├── lint
    ├── uništavanje
    ├── ovisnost
    ├── sintaksa
    ├── kreiranje
    ├── priprema
    ├── sužavanje
    ├── idempotentnost
    ├── nuspojava
    ├── verifikacija
    └── uništavanje

--> Scenarij: 'default'
--> Akcija: 'lint'
--> Izvršavanje Yamllint-a na datotekama pronađenim u /nginx/...
Lint je uspješno završio.
--> Izvršavanje Flake8-a na datotekama pronađenim u /nginx/molecule/default/tests/...
Lint je uspješno završio.
--> Izvršavanje Ansible Lint na /nginx/molecule/default/playbook.yml...
Lint je uspješno završio.
--> Scenarij: 'default'
--> Akcija: 'uništavanje'

    IGRA [Uništi] *****************************************************************

    ZADATAK [Uništi molekularne instance] ********************************************
    promijenjeno: [localhost] => (stavka=None)
    promijenjeno: [localhost]

    ZADATAK [Čekaj da se brisanje instance završi] *******************************
    u redu: [localhost] => (stavka=None)
    u redu: [localhost]

    ZADATAK [Izbriši docker mrežu(e)] ************************************************

    IGRA REKAP *********************************************************************
    localhost                  : u redu=2    promijenjeno=1    nedostupno=0    neuspješno=0

--> Scenarij: 'default'
--> Akcija: 'ovisnost'
Preskočeno, nedostaje datoteka s zahtjevima.
--> Scenarij: 'default'
--> Akcija: 'sintaksa'

    playbook: /nginx/molecule/default/playbook.yml

--> Scenarij: 'default'
--> Akcija: 'kreiranje'

    IGRA [Kreiraj] ******************************************************************

    ZADATAK [Prijavi se na Docker registraciju] **********************************************
    preskočeno: [localhost] => (stavka=None)

    ZADATAK [Kreiraj Dockerfile-ove iz imena slika] *************************************
    promijenjeno: [localhost] => (stavka=None)
    promijenjeno: [localhost]

    ZADATAK [Otkrij lokalne Docker slike] ********************************************
    u redu: [localhost] => (stavka=None)
    u redu: [localhost]

    ZADATAK [Izgradi sliku kompatibilnu s Ansible-om] ***************************************
    promijenjeno: [localhost] => (stavka=None)
    promijenjeno: [localhost]

    ZADATAK [Kreiraj docker mrežu(e)] ************************************************

    ZADATAK [Kreiraj molekularne instance] *********************************************
    promijenjeno: [localhost] => (stavka=None)
    promijenjeno: [localhost]

    ZADATAK [Čekaj da se kreiranje instance završi] *******************************
    promijenjeno: [localhost] => (stavka=None)
    promijenjeno: [localhost]

    IGRA REKAP *********************************************************************
    localhost                  : u redu=5    promijenjeno=4    nedostupno=0    neuspješno=0

--> Scenarij: 'default'
--> Akcija: 'priprema'
Preskočeno, playbook za pripremu nije konfiguriran.
--> Scenarij: 'default'
--> Akcija: 'sužavanje'

    IGRA [Sužavanje] ****************************************************************

    ZADATAK [Prikupljanje činjenica] *********************************************************
    u redu: [instance]

    ZADATAK [nginx : Instaliraj nginx] ***************************************************
    promijenjeno: [instance]

    ZADATAK [nginx : Pokreni nginx] *****************************************************
    promijenjeno: [instance]

    IGRA REKAP *********************************************************************
    instance                   : u redu=3    promijenjeno=2    nedostupno=0    neuspješno=0

--> Scenarij: 'default'
--> Akcija: 'idempotentnost'
Idempotentnost je uspješno završena.
--> Scenarij: 'default'
--> Akcija: 'nuspojava'
Preskočeno, playbook za nuspojavu nije konfiguriran.
--> Scenarij: 'default'
--> Akcija: 'verifikacija'
--> Izvršavanje Testinfra testova pronađenih u /nginx/molecule/default/tests/...
    ============================= test sesija počinje ==============================
    platform darwin -- Python 2.7.15, pytest-4.3.0, py-1.8.0, pluggy-0.9.0
    rootdir: /nginx/molecule/default, inifile:
    dodaci: testinfra-1.16.0
prikupljeno 4 stavke

    tests/test_default.py ....                                               [100%]

    ========================== 4 prošlo u 27.23 sekundi ===========================
Verifikator je uspješno završio.
--> Scenarij: 'default'
--> Akcija: 'uništavanje'

    IGRA [Uništi] *****************************************************************

    ZADATAK [Uništi molekularne instance] ********************************************
    promijenjeno: [localhost] => (stavka=None)
    promijenjeno: [localhost]

    ZADATAK [Čekaj da se brisanje instance završi] *******************************
    promijenjeno: [localhost] => (stavka=None)
    promijenjeno: [localhost]

    ZADATAK [Izbriši docker mrežu(e)] ************************************************

Naša jednostavna uloga testirana je bez problema.
Važno je napomenuti da, ako dođe do problema tijekom rada, molecule test, ako niste mijenjali standardni redoslijed, Molecula će ukloniti instancu.

Za debagiranje su korisne sljedeće komande:

> molecule --debug  # informacije za debagiranje. Prilikom uobičajenog pokretanja Molecula skriva logove.
> molecule converge          # Ostavlja instancu nakon izvršavanja testirane uloge.
> molecule login             # Prijavite se u stvorenu instancu.
> molecule --help            # Potpuni popis komandi.

Postojeća uloga

Dodavanje novog scenarija postojećoj ulozi odvija se iz direktorija uloge sljedećim komandama:

# полный список доступных параметров
> molecule init scenarion --help
# создание нового сценария
> molecule init scenario -r <role_name> -s <scenario_name>

U slučaju da je ovo prvi scenarij u ulozi, parametar -s može se izostaviti, jer će se stvoriti scenarij. default.

Zaključak

Kao što vidite, Molecula nije vrlo složena, a korištenjem vlastitih predložaka možete svesti implementaciju novog scenarija na uređivanje varijabli u playbook-ima za kreiranje i brisanje instanci. Molecula se bez problema integrira s CI sustavima, što omogućava povećanje brzine razvoja smanjivanjem vremena potrebnog za ručno testiranje playbook-ova.

Hvala na vašoj pažnji. Ako imate iskustva s testiranjem ansible uloga koje nije povezano s Moleculom - podijelite ga u komentarima!

Izvor: habr.com

Kupite pouzdan hosting za web stranice s DDoS zaštitom, VPS VDS servere 🔥 Kupite pouzdan hosting za web stranice s DDoS zaštitom, VPS VDS servere | ProHoster