Ohjeet: kuinka testata mahdollisia rooleja ja ottaa selvää ongelmista ennen tuotantoa

Hei kaikille!

Työskentelen DevOps-insinöörinä hotellivarauspalvelussa. Ostrovok.ru. Tässä artikkelissa haluan puhua kokemuksistamme mahdollisten roolien testaamisesta.

Ostrovok.ru:ssa käytämme ansiblea kokoonpanonhallinnana. Äskettäin tulimme tarpeeseen testata rooleja, mutta kuten kävi ilmi, tähän ei ole niin paljon työkaluja - ehkä suosituin on Molecule-kehys, joten päätimme käyttää sitä. Mutta kävi ilmi, että hänen asiakirjansa vaikenevat monista sudenkuoppista. Emme löytäneet riittävän yksityiskohtaista venäjänkielistä käsikirjaa, joten päätimme kirjoittaa tämän artikkelin.

Ohjeet: kuinka testata mahdollisia rooleja ja ottaa selvää ongelmista ennen tuotantoa

molekyyli

Molekyyli - kehys, joka auttaa testaamaan mahdollisia rooleja.

Yksinkertaistettu kuvaus: Molekyyli luo ilmentymän määrittämällesi alustalle (pilvi, virtuaalikone, kontti; katso lisätietoja kohdasta kuljettaja), suorittaa roolisi siinä, suorittaa sitten testejä ja poistaa esiintymän. Jos jokin vaihe epäonnistuu, molekyyli ilmoittaa sinulle siitä.

Nyt enemmän.

Hieman teoria

Tarkastellaan kahta molekyylin avainyksikköä: Skenaario ja ohjain.

skenaario

Käsikirjoitus sisältää kuvauksen siitä, mitä, missä, miten ja missä järjestyksessä tehdään. Yhdessä roolissa voi olla useita skriptejä, ja jokainen on hakemisto polun varrella <role>/molecule/<scenario>, joka sisältää kuvaukset testissä tarvittavista toimista. Käsikirjoitus on sisällytettävä default, joka luodaan automaattisesti, jos alustat roolin molekyylillä. Seuraavien skriptien nimet ovat sinun päätettävissäsi.

Komentosarjan testaustoimintojen sarjaa kutsutaan matriisi, ja oletuksena se on:

(Vaiheet merkitty ?, ohitetaan oletuksena, jos käyttäjä ei ole määrittänyt sitä)

  • lint - juoksevat linterit. Oletuksena käytetään yamllint и flake8,
  • destroy - esiintymien poistaminen molekyylin viimeisestä käynnistyksestä (jos sellainen on),
  • dependency? — testatun roolin mahdollisen riippuvuuden asentaminen,
  • syntax - roolin syntaksin tarkistaminen käyttämällä ansible-playbook --syntax-check,
  • create - luoda ilmentymä,
  • prepare? — tapauksen valmistelu; esim. tarkista/asenna python2
  • converge — testattavan pelikirjan julkaisu,
  • idempotence - idempotenssitestin ohjekirjan käynnistäminen uudelleen,
  • side_effect? - toimet, jotka eivät liity suoraan rooliin, mutta ovat tarpeellisia testejä varten,
  • verify - testien suorittaminen tuloksena olevasta kokoonpanosta käyttämällä testinfra(oletus) /goss/inspec,
  • cleanup? - (uusissa versioissa) - karkeasti sanottuna "puhdistamalla" ulkoista infrastruktuuria, johon molekyyli vaikuttaa,
  • destroy - Ilmentymän poistaminen.

Tämä järjestys kattaa useimmat tapaukset, mutta sitä voidaan muuttaa tarvittaessa.

Jokainen yllä olevista vaiheista voidaan suorittaa erikseen molecule <command>. Mutta on ymmärrettävä, että jokaiselle tällaiselle klikoskomentolle voi olla oma toimintosarjansa, jonka voit selvittää suorittamalla molecule matrix <command>. Esimerkiksi suoritettaessa komentoa converge (käytetään testattavana olevaa pelikirjaa), suoritetaan seuraavat toimet:

$ molecule matrix converge
...
└── default         # название сценария
    ├── dependency  # установка зависимостей
    ├── create      # создание инстанса
    ├── prepare     # преднастройка инстанса
    └── converge    # прогон плейбука

Näiden toimien järjestystä voidaan muokata. Jos jokin luettelosta on jo tehty, se ohitetaan. Molecule tallentaa hakemistoon nykyisen tilan sekä ilmentymien konfiguraation $TMPDIR/molecule/<role>/<scenario>.

Lisää vaiheet kanssa ? voit kuvata haluamasi toiminnot ansible-playbook -muodossa ja antaa tiedostolle nimen vaiheen mukaisesti: prepare.yml/side_effect.yml. Odota näitä tiedostoja Molekyyli on komentosarjakansiossa.

kuljettaja

Ajuri on entiteetti, jossa testiinstanssit luodaan.
Luettelo vakioajureista, joille Moleculella on valmiita malleja, on seuraava: Azure, Docker, EC2, GCE, LXC, LXD, OpenStack, Vagrant, Delegated.

Useimmissa tapauksissa mallit ovat tiedostoja create.yml и destroy.yml komentosarjakansiossa, joka kuvaa esiintymän luomista ja poistamista.
Poikkeuksia ovat Docker ja Vagrant, koska vuorovaikutus niiden moduulien kanssa voi tapahtua ilman edellä mainittuja tiedostoja.

Delegated-ohjainta kannattaa korostaa, koska jos sitä käytetään tiedostoissa ilmentymän luomiseen ja poistamiseen, kuvataan vain työ ilmentymien konfiguroinnin kanssa, loput tulee kuvata insinöörin toimesta.

Oletusohjain on Docker.

Jatketaan nyt harjoittelua ja harkitaan muita ominaisuuksia siellä.

Aloittaminen

"Hei maailmana" testataan yksinkertaista nginx-asennusroolia. Valitaan ajuriksi docker - luulen, että useimmat teistä ovat asentaneet sen (ja muista, että docker on oletusohjain).

Valmistella virtualenv ja asenna siihen molecule:

> pip install virtualenv
> virtualenv -p `which python2` venv
> source venv/bin/activate
> pip install molecule docker  # molecule установит ansible как зависимость; docker для драйвера

Seuraava askel on uuden roolin alustaminen.
Uuden roolin ja uuden skriptin alustus suoritetaan komennolla molecule init <params>:

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

6 directories, 1 file

Siitä tuli tyypillinen mahdollinen rooli. Lisäksi kaikki vuorovaikutukset CLI-molekyylien kanssa tehdään roolin juuresta.

Katsotaanpa mitä roolihakemistossa on:

> tree molecule/default/
molecule/default/
├── Dockerfile.j2  # Jinja-шаблон для Dockerfile
├── INSTALL.rst.   # Немного информации об установке зависимостей сценария
├── molecule.yml   # Файл конфигурации
├── playbook.yml   # Плейбук запуска роли
└── tests          # Директория с тестами стадии verify
    └── test_default.py

1 directory, 6 files

Analysoidaan konfiguraatio molecule/default/molecule.yml (korvaa vain Docker-kuva):

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

riippuvuus

Tässä osiossa kuvataan riippuvuuksien lähde.

Mahdolliset vaihtoehdot: galaxy, sovelletaan, kuori.

Shell on vain komentokuori, jota käytetään, jos galaxy ja gilt eivät kata tarpeitasi.

En viihdy täällä pitkään, se on tarpeeksi kuvattu dokumentointi.

kuljettaja

Kuljettajan nimi. Meidän on telakka.

nukka

Linter on yamllint.

Hyödyllisiä vaihtoehtoja tässä kokoonpanon osassa ovat kyky määrittää yamllint-asetustiedosto, välittää ympäristömuuttujat tai poistaa linterin käytöstä:

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

alustat

Kuvaa esiintymien kokoonpanoa.
Jos kyseessä on docker ajurina, molekyyli iteroidaan tässä osiossa, ja jokainen luettelon elementti on saatavilla Dockerfile.j2 muuttujana item.

Kun kyseessä on kuljettaja, joka vaatii create.yml и destroy.yml, osio on saatavilla niissä nimellä molecule_yml.platforms, ja sen iteraatiot on jo kuvattu näissä tiedostoissa.

Koska Molecule ohjaa ilmentymiä mahdollisille moduuleille, kannattaa sieltä myös etsiä luettelo mahdollisista asetuksista. Esimerkiksi telakointiasemassa moduulia käytetään docker_container_module. Mitä moduuleja käytetään muissa ohjaimissa, voit lukea kohdasta dokumentointi.

Sekä esimerkkejä eri ajurien käytöstä löytyy itse molekyylin testeissä.

Vaihda tähän centos:7 päälle Ubuntu.

huolehtija

"Toimittaja" - entiteetti, joka hallitsee esiintymiä. Moleculen tapauksessa tämä on mahdollista, tukea muille ei ole suunniteltu, joten tätä osaa voidaan kutsua mahdolliseksi laajennetuksi konfiguraatioksi varoin.
Täällä voit määrittää monia asioita, korostan mielestäni pääkohdat:

  • hyökkäyskuvioita: voit määrittää, mitä pelikirjoja tulee käyttää tietyissä vaiheissa.

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

  • yhteys_asetukset: vaihtoehtoja yhteys

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

  • vaihtoehdot: Mahdolliset vaihtoehdot ja ympäristömuuttujat

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

skenaario

Skriptisekvenssien nimi ja kuvaus.
Voit muuttaa minkä tahansa komennon oletustoimintomatriisia lisäämällä avaimen <command>_sequence ja sen arvoksi määrittelemällä tarvittavien vaiheiden luettelo.
Oletetaan, että haluamme muuttaa toimintojen järjestystä ajaessamme playbook run -komentoa: molecule converge

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

Todentajan

Kehyksen luominen testeille ja linterille. Oletuslinteri on testinfra и flake8. Mahdolliset vaihtoehdot ovat samat kuin yllä:

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

Palataan rooliimme. Muokataan tiedostoa tasks/main.yml tähän lajiin:

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

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

Ja lisää testejä 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")

Valmis, jää vain juosta (roolin juurelta, muistutan teitä):

> molecule test

Pitkä pakoputki spoilerin alla:

--> Validating schema <path>/nginx/molecule/default/molecule.yml.
Validation completed successfully.
--> Test matrix

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

--> Scenario: 'default'
--> Action: 'lint'
--> Executing Yamllint on files found in <path>/nginx/...
Lint completed successfully.
--> Executing Flake8 on files found in <path>/nginx/molecule/default/tests/...
Lint completed successfully.
--> Executing Ansible Lint on <path>/nginx/molecule/default/playbook.yml...
Lint completed successfully.
--> Scenario: 'default'
--> Action: 'destroy'

    PLAY [Destroy] *****************************************************************

    TASK [Destroy molecule instance(s)] ********************************************
    changed: [localhost] => (item=None)
    changed: [localhost]

    TASK [Wait for instance(s) deletion to complete] *******************************
    ok: [localhost] => (item=None)
    ok: [localhost]

    TASK [Delete docker network(s)] ************************************************

    PLAY RECAP *********************************************************************
    localhost                  : ok=2    changed=1    unreachable=0    failed=0

--> Scenario: 'default'
--> Action: 'dependency'
Skipping, missing the requirements file.
--> Scenario: 'default'
--> Action: 'syntax'

    playbook: <path>/nginx/molecule/default/playbook.yml

--> Scenario: 'default'
--> Action: 'create'

    PLAY [Create] ******************************************************************

    TASK [Log into a Docker registry] **********************************************
    skipping: [localhost] => (item=None)

    TASK [Create Dockerfiles from image names] *************************************
    changed: [localhost] => (item=None)
    changed: [localhost]

    TASK [Discover local Docker images] ********************************************
    ok: [localhost] => (item=None)
    ok: [localhost]

    TASK [Build an Ansible compatible image] ***************************************
    changed: [localhost] => (item=None)
    changed: [localhost]

    TASK [Create docker network(s)] ************************************************

    TASK [Create molecule instance(s)] *********************************************
    changed: [localhost] => (item=None)
    changed: [localhost]

    TASK [Wait for instance(s) creation to complete] *******************************
    changed: [localhost] => (item=None)
    changed: [localhost]

    PLAY RECAP *********************************************************************
    localhost                  : ok=5    changed=4    unreachable=0    failed=0

--> Scenario: 'default'
--> Action: 'prepare'
Skipping, prepare playbook not configured.
--> Scenario: 'default'
--> Action: 'converge'

    PLAY [Converge] ****************************************************************

    TASK [Gathering Facts] *********************************************************
    ok: [instance]

    TASK [nginx : Install nginx] ***************************************************
    changed: [instance]

    TASK [nginx : Start nginx] *****************************************************
    changed: [instance]

    PLAY RECAP *********************************************************************
    instance                   : ok=3    changed=2    unreachable=0    failed=0

--> Scenario: 'default'
--> Action: 'idempotence'
Idempotence completed successfully.
--> Scenario: 'default'
--> Action: 'side_effect'
Skipping, side effect playbook not configured.
--> Scenario: 'default'
--> Action: 'verify'
--> Executing Testinfra tests found in <path>/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: <path>/nginx/molecule/default, inifile:
    plugins: testinfra-1.16.0
collected 4 items

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

    ========================== 4 passed in 27.23 seconds ===========================
Verifier completed successfully.
--> Scenario: 'default'
--> Action: 'destroy'

    PLAY [Destroy] *****************************************************************

    TASK [Destroy molecule instance(s)] ********************************************
    changed: [localhost] => (item=None)
    changed: [localhost]

    TASK [Wait for instance(s) deletion to complete] *******************************
    changed: [localhost] => (item=None)
    changed: [localhost]

    TASK [Delete docker network(s)] ************************************************

    PLAY RECAP *********************************************************************
    localhost                  : ok=2    changed=2    unreachable=0    failed=0

Yksinkertainen roolimme testattiin ilman ongelmia.
On syytä muistaa, että jos työn aikana ilmenee ongelmia molecule test, jos et muuttanut oletussekvenssiä, Molecule poistaa esiintymän.

Seuraavat komennot ovat hyödyllisiä virheenkorjauksessa:

> molecule --debug <command> # debug info. При обычном запуске Молекула скрывает логи.
> molecule converge          # Оставляет инстанс после прогона тестируемой роли.
> molecule login             # Зайти в созданный инстанс.
> molecule --help            # Полный список команд.

Olemassa oleva rooli

Uuden skriptin lisääminen olemassa olevaan rooliin on roolihakemistosta seuraavilla komennoilla:

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

Jos tämä on roolin ensimmäinen skenaario, niin parametri -s voidaan jättää pois, koska se luo skriptin default.

Johtopäätös

Kuten näet, Molecule ei ole kovin monimutkainen, ja käyttämällä omia mallejasi uuden skriptin käyttöönotto voidaan rajoittua muuttujien muokkaamiseen ilmentymien luonti- ja poistamisohjeissa. Molekyyli integroituu saumattomasti CI-järjestelmiin, mikä mahdollistaa kehitysnopeuden lisäämisen vähentämällä pelikirjojen manuaaliseen testaukseen kuluvaa aikaa.

Kiitos huomiostasi. Jos sinulla on kokemusta mahdollisten roolien testaamisesta, eikä se liity Moleculiin, kerro siitä meille kommenteissa!

Lähde: will.com

Lisää kommentti