Návod: ako testovať ansible role a zistiť problémy pred produkciou

Ahojte všetci!

Pracujem ako DevOps inžinier v službe rezervácie hotelov Ostrovok.ru. V tomto článku chcem rozprávať o našich skúsenostiach s testovaním ansible rolí.

Na Ostrovok.ru ako správca konfigurácií používame ansible. Nedávno sme dospeli k potrebe testovania rolí, ale, ako sa ukázalo, existuje len málo nástrojov na tento účel — najpopulárnejší je pravdepodobne framework Molecule, a preto sme sa rozhodli ho použiť. Ale ukázalo sa, že jeho dokumentácia opomína mnohé nástrahy. Nedokázali sme nájsť dostatočne podrobný návod v slovenčine, preto sme sa rozhodli napísať tento článok.

Návod: ako testovať ansible role a zistiť problémy pred produkciou

Molecule

Molekula — framework na pomoc pri testovaní ansible rolí.

Zjednodušený popis: Molekula vytvára inštanciu na platforme, ktorú ste určili (cloud, virtuálny stroj, kontajner; podrobnejšie si pozrite časť Driver), spustí na nej vašu rolu, potom vykoná testy a odstráni inštanciu. V prípade zlyhania v jednom z krokov vás Molekula o tom informuje.

Teraz podrobnejšie.

Trochu teórie

Preskúmame dve kľúčové entity Molekuly: Scenario a Driver.

Scenario

Scenár obsahuje popis toho, čo, kde, ako a v akom poradí sa má vykonať. Jedna rola môže mať niekoľko scenárov a každý z nich je adresárová štruktúra na ceste /molecule/, ktorá obsahuje opisy potrebných akcií na test. Určite musí existovať scenár, default, ktorý bude automaticky vytvorený, ak inicializujete rolu pomocou Molekuly. Názvy ďalších scenárov si vyberáte podľa vlastného uváženia.

Sekvencia akcií testovania v scenári sa nazýva matica, a predvolene je nasledovná:

(Kroky označené ?, sa predvolene preskočia, ak ich používateľ nenapíše)

  • lint — spustenie linterov. Predvolene sa používajú yamllint a flake8,
  • destroy — odstránenie inštancií z predchádzajúceho spustenia Molekuly (ak zostali),
  • dependency? — установка ansible-зависимости тестируемой роли,
  • syntax — kontrola syntaktickej správnosti rolí pomocou ansible-playbook --syntax-check,
  • create — vytvorenie inštancie,
  • prepare? — подготовка инстанса; например, проверка / установка python2
  • converge — spustenie testovaného playbooku,
  • idempotence — opätovné spustenie playbooku pre testovanie idempotencie,
  • side_effect? — действия, не относящиеся непосредственно к роли, но нужные для тестов,
  • verify — spustenie testov výslednej konfigurácie pomocou testinfra(predvolene) /goss/inspec,
  • cleanup? — (в новых версиях) — грубо говоря, «очистка» внешней инфраструктуры, задетой Молекулой,
  • destroy — odstránenie inštancie.

Táto sekvencia pokrýva väčšinu prípadov, ale v prípade potreby ju môžete zmeniť.

Každý z uvedených krokov je možné spustiť samostatne pomocou molecule. Je však potrebné pochopiť, že pre každý takýto príkaz CLI môže existovať svoj vlastný postup, ktorý sa dá zistiť vykonaním molecule matrix. Napríklad pri spustení príkazu converge (spustenie testovacej playbooku) sa vykonajú nasledujúce kroky:

$ molecule matrix converge
...
└── default         # názov scenára
    ├── dependency  # inštalácia závislostí
    ├── create      # vytvorenie inštancie
    ├── prepare     # predpríprava inštancie
    └── converge    # spustenie playbooku

Postup týchto krokov je možné upravovať. Pokiaľ už niečo zo zoznamu bolo vykonané, preskočí sa. Aktuálny stav, ako aj konfigurácia inštancií, Molekula uchováva v adresári $TMPDIR/molecule//.

Pridať kroky s ? je možné, ak popíšete požadované akcie vo formáte ansible-playbooku, a názov súboru prispôsobíte kroku: prepare.yml/side_effect.yml. Tieto súbory Molekula očakáva v priečinku scenára.

Driver

Ovládač je entita, kde sa vytvárajú inštancie na testy.
Zoznam štandardných ovládačov, pre ktoré má Molekula pripravené šablóny, je takýto: Azure, Docker, EC2, GCE, LXC, LXD, OpenStack, Vagrant, Delegated.

Vo väčšine prípadov sú šablóny súbory create.yml a destroy.yml v priečinku scenára, ktoré popisujú vytvorenie a odstránenie inštancie.
Výnimkou sú Docker a Vagrant, keďže interakcia s ich modulmi môže prebiehať bez vyššie spomenutých súborov.

Stojí za zmienku ovládač Delegated, pretože v prípade jeho použitia v súboroch vytvárania a odstraňovania inštancie je popísaná iba práca s konfiguráciou inštancií, všetko ostatné musí popísať inžinier.

Predvoleným ovládačom je Docker.

Teraz prejdeme k praxi a ďalšie vlastnosti preskúmame tam.

Začiatok práce

Ako "hello world" otestujeme jednoduchú úlohu inštalácie nginx. Ako ovládač vyberieme Docker – myslím, že ho má väčšina z vás nainštalovaný (a pamätáme, že Docker je predvolené ovládanie).

Pripravíme virtualenv a nainštalujeme do neho molecule:

> pip install virtualenv
> virtualenv -p `which python2` venv
> source venv/bin/activate
> pip install molecule docker  # molecule nainštaluje ansible ako závislosť; docker pre ovládač

Ďalším krokom inicializujeme novú úlohu.
Inicializácia novej úlohy, rovnako ako nového scenára, sa vykonáva pomocou príkazu molecule init:

> molecule init role -r nginx
--> Inicializovanie novej úlohy nginx...
Úloha bola úspešne inicializovaná v /nginx.
> cd nginx
> tree -L 1
.
├── README.md
├── defaults
├── handlers
├── meta
├── molecule
├── tasks
└── vars

6 adresárov, 1 súbor

Vytvorila sa typická ansible-úloha. Ďalšie interakcie s CLI Molekuly sa vykonávajú z koreňa úlohy.

Pozrime sa, čo sa nachádza v adresári úlohy:

> tree molecule/default/
molecule/default/
├── Dockerfile.j2  # Jinja šablóna pre Dockerfile
├── INSTALL.rst.   # Niekoľko informácií o inštalácii závislostí scénara
├── molecule.yml   # Konfiguračný súbor
├── playbook.yml   # Hlavný súbor pre spustenie úlohy
└── tests          # Adresár s testami štádia overovania
    └── test_default.py

1 adresár, 6 súborov

Rozoberieme konfiguráciu molecule/default/molecule.yml (zmeníme len docker image):

---
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

Táto sekcia popisuje zdroj závislostí.

Možné voľby: galaxy, gilt, shell.

Shell je jednoducho príkazový riadok, ktorý sa používa, ak galaxy a gilt nepokrývajú vaše potreby.

Nebudem sa tu zdržiavať, dostatočne je to popísané v dokumenácie.

driver

Názov ovládača. Pre nás je to docker.

lint

Na linterský účel sa používa yamllint.

Užitočné možnosti v tejto časti konfigurácie sú možnosť zadať konfiguračný súbor pre yamllint, preniesť premenné prostredia alebo vypnúť linterský nástroj:

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

platforms

Popisuje konfiguráciu inštancií.
V prípade dockeru ako ovládača Molekula prechádza touto sekciou a každý prvok zo zoznamu je dostupný v Dockerfile.j2 ako premenná item.

V prípade ovládača, kde sú potrebné create.yml a destroy.yml, sekcia je v nich dostupná ako molecule_yml.platforms, a iterácia po nej je už popísaná v týchto súboroch.

Keďže Molekula poskytuje riadenie inštancií pre ansible-moduly, zoznam možných nastavení treba hľadať tam. Pre docker sa napríklad používa modul docker_container_module. Aké moduly sa používajú v ostatných ovládačoch, môžete nájsť v dokumenácie.

A tiež príklady použitia rôznych ovládačov môžete nájsť v testoch samotnej Molekuly.

Tu nahradíme centos:7 na ubuntu.

provisioner

"Poskytovateľ" je entita, ktorá spravuje inštancie. V prípade Molekuly je to ansible, podpora iných nie je plánovaná, takže túto sekciu môžeme s opatrnosťou nazvať rozšírenou konfiguráciou ansible.
Tu môžete uviesť veľa vecí, vyzdvihnem hlavné, podľa môjho názoru, body:

  • playbooks: môžete uvádzať, ktoré playbooky by sa mali používať v určitých fázach.

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'"

  • options: parametre Ansible a premenné prostredia

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

scenario

Názov a popis sekvencií scenára.
Maticu akcií predvolenej príkazu môžete zmeniť pridaním kľúča <command>_sequence a ako hodnotu pre neho zadefinovať požadovaný zoznam krokov.
Predpokladajme, že chceme zmeniť sekvenciu akcií pri spustení príkazu na vygenerovanie playbooku: molecule converge

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

verifier

Nastavenie rámca pre testy a linter k nemu. Predvolene sa používa ako linter testinfra a flake8. Možné možnosti sú podobné ako vyššie uvedené:

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

Vráťme sa k našej úlohe. Upravíme súbor tasks\/main.yml na takýto tvar:

---
- name: Nainštalovať nginx
  apt:
    name: nginx
    state: present

- name: Spustiť nginx
  service:
    name: nginx
    state: started

A pridáme testy do 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")

Hotovo, zostáva len spustiť (z koreňa úlohy, pripomínam):

> molecule test

Dlhý výstup pod spoilerom:

--> Validácia schémy /nginx/molecule/default/molecule.yml.
Validation bola úspešne dokončená.
--> Testovacia matica

└── default
    ├── lint
    ├── destroy
    ├── dependency
    ├── syntax
    ├── create
    ├── prepare
    ├── converge
    ├── idempotence
    ├── side_effect
    ├── verify
    └── destroy

--> Scenár: 'default'
--> Akcia: 'lint'
--> Spúšťam Yamllint na súboroch nájdených v /nginx/...
Lint bol úspešne dokončený.
--> Spúšťam Flake8 na súboroch nájdených v /nginx/molecule/default/tests/...
Lint bol úspešne dokončený.
--> Spúšťam Ansible Lint na /nginx/molecule/default/playbook.yml...
Lint bol úspešne dokončený.
--> Scenár: 'default'
--> Akcia: 'destroy'

    HRA [Destrovanie] *****************************************************************

    ÚLOHA [Destrovanie inštancie molekuly] ********************************************
    zmenené: [localhost] => (item=None)
    zmenené: [localhost]

    ÚLOHA [Čakajte na dokončenie vymazania inštancie] *******************************
    ok: [localhost] => (item=None)
    ok: [localhost]

    ÚLOHA [Vymazať docker siete] ************************************************

    HRA RECAP *********************************************************************
    localhost                  : ok=2    zmenené=1    nedostupné=0    neuspešné=0

--> Scenár: 'default'
--> Akcia: 'dependency'
Preskočené, chýba súbor požiadaviek.
--> Scenár: 'default'
--> Akcia: 'syntax'

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

--> Scenár: 'default'
--> Akcia: 'create'

    HRA [Vytvorenie] ******************************************************************

    ÚLOHA [Prihlásiť sa do Docker registry] **********************************************
    preskočené: [localhost] => (item=None)

    ÚLOHA [Vytvorenie Dockerfiles z názvov obrázkov] *************************************
    zmenené: [localhost] => (item=None)
    zmenené: [localhost]

    ÚLOHA [Objaviť miestne Docker obrázky] ********************************************
    ok: [localhost] => (item=None)
    ok: [localhost]

    ÚLOHA [Vytvoriť obraz kompatibilný s Ansible] ***************************************
    zmenené: [localhost] => (item=None)
    zmenené: [localhost]

    ÚLOHA [Vytvoriť docker siete] ************************************************

    ÚLOHA [Vytvoriť inštancie molekuly] *********************************************
    zmenené: [localhost] => (item=None)
    zmenené: [localhost]

    ÚLOHA [Čakajte na dokončenie vytvorenia inštancie] *******************************
    zmenené: [localhost] => (item=None)
    zmenené: [localhost]

    HRA RECAP *********************************************************************
    localhost                  : ok=5    zmenené=4    nedostupné=0    neuspešné=0

--> Scenár: 'default'
--> Akcia: 'prepare'
Preskočené, herný plán nebol nastavený.
--> Scenár: 'default'
--> Akcia: 'converge'

    HRA [Spojenie] ****************************************************************

    ÚLOHA [Zber faktov] *********************************************************
    ok: [instance]

    ÚLOHA [nginx : Nainštalovať nginx] ***************************************************
    zmenené: [instance]

    ÚLOHA [nginx : Spustiť nginx] *****************************************************
    zmenené: [instance]

    HRA RECAP *********************************************************************
    instance                   : ok=3    zmenené=2    nedostupné=0    neuspešné=0

--> Scenár: 'default'
--> Akcia: 'idempotence'
Idempotencia bola úspešne dokončená.
--> Scenár: 'default'
--> Akcia: 'side_effect'
Preskočené, herný plán vedľajšieho efektu nebol nastavený.
--> Scenár: 'default'
--> Akcia: 'verify'
--> Spúšťam Testinfra testy nájdené v /nginx/molecule/default/tests/...
    ============================= test session starts ==============================
    platform darwin -- Python 2.7.15, pytest-4.3.0, py-1.8.0, pluggy-0.9.0
    rootdir: /nginx/molecule/default, inifile:
    plugins: testinfra-1.16.0
collected 4 items

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

    ========================== 4 prešlo v 27.23 sekundy ===========================
Verifikátor bol úspešne dokončený.
--> Scenár: 'default'
--> Akcia: 'destroy'

    HRA [Destrovanie] *****************************************************************

    ÚLOHA [Destrovanie inštancie molekuly] ********************************************
    zmenené: [localhost] => (item=None)
    zmenené: [localhost]

    ÚLOHA [Čakajte na dokončenie vymazania inštancie] *******************************
    zmenené: [localhost] => (item=None)
    zmenené: [localhost]

    ÚLOHA [Vymazať docker siete] ************************************************

    HRA RECAP *********************************************************************
    localhost                  : ok=2    zmenené=2    nedostupné=0    neuspešné=0

Naša jednoduchá úloha bola úspešne otestovaná.
Je dobré mať na pamäti, že ak sa vyskytnú problémy pri práci molecule test, ak ste nezmenili štandardnú postupnosť, Molekula odstráni inštanciu.

Pre ladenie sú užitočné nasledujúce príkazy:

> molecule --debug  # informačné o ladení. Pri bežnom spustení Molekula skrýva logy.
> molecule converge          # Zanechá inštanciu po spustení testovacej úlohy.
> molecule login             # Prihláste sa do vytvorenej inštancie.
> molecule --help            # Kompletný zoznam príkazov.

Existujúca úloha

Pridanie nového scenára k existujúcej úlohe prebieha z adresára úlohy nasledujúcimi príkazmi:

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

V prípade, že ide o prvý scenár v úlohe, parameter -s je možné vynechať, pretože sa vytvorí scenár. default.

Záver

Ako vidíte, Molekula nie je veľmi zložitá, a pri použití vlastných šablón môžete zjednodušiť nasadenie nového scenára na úpravu premenných v playbookoch pre vytváranie a odstraňovanie inštancií. Molekula sa bez problémov integruje so systémami CI, čo umožňuje zvýšiť rýchlosť vývoja skrátením času na manuálne testovanie playbookov.

Ďakujem za vašu pozornosť. Ak máte skúsenosti s testovaním ansible-úloh, ktoré nie sú spojené s Molekulou — podeľte sa o ne v komentároch!

Zdroj: habr.com

Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster