Ynstruksjes: hoe kinne jo ansible rollen testen en útfine oer problemen foar produksje

Hello everyone!

Ik wurkje as DevOps-yngenieur yn in hotelboekingstsjinst. Ostrovok.ru. Yn dit artikel wol ik prate oer ús ûnderfining yn it testen fan ansible rollen.

Op Ostrovok.ru brûke wy ansible as konfiguraasjebehearder. Koartlyn kamen wy ta de needsaak om rollen te testen, mar sa die bliken, binne d'r net safolle ark foar dit - it populêrste is miskien it Molecule-ramt, dus wy besletten it te brûken. Mar it die bliken dat syn dokumintaasje stil is oer in protte falkûlen. Wy koenen net fine in foldwaande detaillearre hânlieding yn it Russysk, dus wy besletten om te skriuwen dit artikel.

Ynstruksjes: hoe kinne jo ansible rollen testen en útfine oer problemen foar produksje

Molekule

Molecule - in ramt om mooglike rollen te testen.

Ienfâldige beskriuwing: De molekule makket in eksimplaar op it platfoarm dat jo oantsjutte (wolk, firtuele masine, kontener; foar mear details, sjoch de seksje Sjauffeur), rint jo rol derop, rint dan tests en wisket it eksimplaar. Yn gefal fan mislearring op ien fan 'e stappen, sil de Molecule jo der oer ynformearje.

No mear.

In bytsje teory

Beskôgje twa wichtige entiteiten fan 'e molekule: senario en bestjoerder.

Sesje

It skript befettet in beskriuwing fan wat, wêr, hoe en yn hokker folchoarder wurdt útfierd. Ien rol kin hawwe ferskate skripts, en elk is in map lâns it paad <role>/molecule/<scenario>, dy't beskriuwingen befettet fan 'e aksjes dy't nedich binne foar de test. Skript moat opnommen wurde default, dy't automatysk oanmakke wurde as jo de rol inisjalisearje mei in Molecule. De nammen fan de folgjende skripts binne oan jo.

De folchoarder fan testaksjes yn in skript wurdt neamd matrix, en standert is it:

(Stappen markearre ?, standert oerslein as net oantsjutte troch de brûker)

  • lint - rinnende linters. Standert wurde brûkt yamllint и flake8,
  • destroy - eksimplaren wiskje fan 'e lêste lansearring fan' e molekule (as ien),
  • dependency? - ynstallaasje fan de mooglike ôfhinklikens fan 'e testte rol,
  • syntax - kontrolearje de syntaksis fan 'e rol mei help fan ansible-playbook --syntax-check,
  • create - it meitsjen fan in eksimplaar,
  • prepare? - tarieding fan it eksimplaar; bygelyks kontrolearje / ynstallearje python2
  • converge - lansearring fan it teste playbook,
  • idempotence - it playbook opnij starte foar de idempotinsjetest,
  • side_effect? - aksjes dy't net direkt relatearre binne oan 'e rol, mar nedich foar tests,
  • verify - rinnende tests fan de resultearjende konfiguraasje mei help fan testinfra(standert) /goss/inspec,
  • cleanup? - (yn nije ferzjes) - rûchwei, "skjinmeitsjen" fan 'e eksterne ynfrastruktuer beynfloede troch de Molecule,
  • destroy - In eksimplaar wiskje.

Dizze folchoarder beslacht de measte gefallen, mar kin feroare wurde as it nedich is.

Elk fan 'e boppesteande stappen kinne wurde útfierd apart mei molecule <command>. Mar it moat begrepen wurde dat foar elk sa'n cli-kommando in eigen folchoarder fan aksjes kin wêze, dy't jo kinne fine troch it útfieren molecule matrix <command>. Bygelyks by it útfieren fan it kommando converge (it útfiere fan it playbook ûnder test), sille de folgjende aksjes wurde útfierd:

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

De folchoarder fan dizze aksjes kin wurde bewurke. As der al wat út de list dien is, wurdt it oerslein. De hjoeddeistige steat, lykas de konfiguraasje fan 'e eksimplaren, bewarret de Molecule yn' e map $TMPDIR/molecule/<role>/<scenario>.

Foegje stappen mei ? jo kinne de winske aksjes beskriuwe yn it ansible-playbook-formaat, en de triemnamme meitsje neffens de stap: prepare.yml/side_effect.yml. Ferwachtsje dizze bestannen It molekule sil yn 'e skriptmap wêze.

Sjauffeur

In bestjoerder is in entiteit dêr't testeksimplaren wurde makke.
De list mei standertbestjoerders wêrfoar Molecule sjabloanen klear hat is as folget: Azure, Docker, EC2, GCE, LXC, LXD, OpenStack, Vagrant, Delegated.

Yn 'e measte gefallen binne sjabloanen bestannen create.yml и destroy.yml yn 'e skriptmap dy't respektivelik it oanmeitsjen en wiskjen fan in eksimplaar beskriuwe.
De útsûnderingen binne Docker en Vagrant, om't ynteraksjes mei har modules kinne foarkomme sûnder de earder neamde bestannen.

It is de muoite wurdich om de Delegearre stjoerprogramma te markearjen, om't as it wurdt brûkt yn 'e bestannen foar it meitsjen en wiskjen fan in eksimplaar, allinich wurk mei de konfiguraasje fan eksimplaren wurdt beskreaun, de rest moat wurde beskreaun troch de yngenieur.

De standert stjoerprogramma is Docker.

Litte wy no trochgean nei de praktyk en beskôgje fierdere funksjes dêr.

Om te begjinnen

As "hallo wrâld", litte wy in ienfâldige nginx-ynstallaasjerol testen. Wy sille docker kieze as de bestjoerder - ik tink dat de measte fan jo it ynstalleare hawwe (en tink derom dat docker de standertbestjoerder is).

Lit ús tariede virtualenv en ynstallearje yn it molecule:

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

De folgjende stap is it inisjalisearjen fan de nije rol.
Inisjalisaasje fan in nije rol, lykas in nij skript, wurdt útfierd mei it kommando 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

It waard in typyske ansible-rol. Fierder wurde alle ynteraksjes mei CLI-molekulen makke fan 'e woartel fan' e rol.

Litte wy sjen wat der yn 'e rolmap stiet:

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

1 directory, 6 files

Litte wy de konfiguraasje analysearje molecule/default/molecule.yml (ferfang allinich dockerôfbylding):

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

ôfhinklikens

Dizze paragraaf beskriuwt de boarne fan ôfhinklikens.

Mooglike opsjes: galaxy, gild, skelp.

Shell is gewoan in kommando shell dy't wurdt brûkt yn gefal galaxy en gilt net dekke jo behoeften.

Ik sil hjir net lang wenje, it is genôch beskreaun yn dokumintaasje.

sjauffeur

De namme fan de bestjoerder. Us is docker.

lintsje

De linter is yamllint.

Nuttige opsjes yn dit diel fan 'e konfiguraasje binne de mooglikheid om in konfiguraasjetriem op te jaan foar yamllint, omjouwingsfariabelen foarút, of de linter útskeakelje:

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

platfoarms

Beskriuwt de konfiguraasje fan 'e eksimplaren.
Yn it gefal fan docker as bestjoerder wurdt de molekule oer dizze seksje iterearre, en elk elemint fan 'e list is beskikber yn Dockerfile.j2 as fariabele item.

Yn it gefal fan in bestjoerder dat fereasket create.yml и destroy.yml, de seksje is beskikber yn harren as molecule_yml.platforms, en iteraasjes deroer binne al beskreaun yn dizze triemmen.

Sûnt de Molecule jout kontrôle fan eksimplaren oan ansible modules, de list mei mooglike ynstellings moat ek socht wurde dêr. Foar docker wurdt bygelyks de module brûkt docker_container_module. Hokker modules wurde brûkt yn oare bestjoerders kinne fûn wurde yn dokumintaasje.

Lykas foarbylden fan it brûken fan ferskate bestjoerders kinne fûn wurde yn 'e tests fan' e Molecule sels.

Ferfange hjir sint:7 op ubuntu.

provider

"Supplier" - in entiteit dy't ynstânsjes beheart. Yn it gefal fan Molecule is dit mooglik, stipe foar oaren is net pland, dus dizze seksje kin neamd wurde as in útwreide konfiguraasje mei in warskôging.
Hjir kinne jo in protte dingen oantsjutte, ik sil de haadpunten markearje, nei myn miening:

  • boartersboeken: jo kinne opjaan hokker playbooks moatte wurde brûkt yn bepaalde stadia.

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

  • opsjes: Ansible opsjes en omjouwingsfariabelen

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

senario

Namme en beskriuwing fan skriptsekwinsjes.
Jo kinne de standert aksjematrix fan elk kommando feroarje troch de kaai ta te foegjen <command>_sequence en as wearde foar it troch it definiearjen fan de list mei stappen dy't wy nedich binne.
Litte wy sizze dat wy de folchoarder fan aksjes feroarje wolle by it útfieren fan it playbook run kommando: molecule converge

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

ferifikaasje

It opsetten fan in ramt foar toetsen en in linter deroan. De standert linter is testinfra и flake8. De mooglike opsjes binne itselde as hjirboppe:

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

Lit ús weromgean nei ús rol. Litte wy it bestân bewurkje tasks/main.yml oan dit soarte:

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

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

En foegje tests ta 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")

Dien, it bliuwt allinich om te rinnen (fan 'e woartel fan' e rol, lit my jo herinnerje):

> molecule test

Lange útlaat ûnder de spoiler:

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

Us ienfâldige rol waard sûnder problemen testen.
It is de muoite wurdich ûnthâlden dat as der problemen tidens it wurk molecule test, dan as jo de standert folchoarder net feroare hawwe, sil de Molecule de eksimplaar wiskje.

De folgjende kommando's binne nuttich foar debuggen:

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

Besteande rol

It tafoegjen fan in nij skript oan in besteande rol is út de rol triemtafel mei de folgjende kommando's:

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

As dit it earste senario is yn 'e rol, dan de parameter -s kin wurde weilitten as it sil meitsje in skript default.

konklúzje

Sa't jo sjen kinne, is de Molecule net heul kompleks, en troch jo eigen sjabloanen te brûken, kin it ynsetten fan in nij skript wurde fermindere ta it bewurkjen fan fariabelen yn 'e eksimplaar oanmeitsjen en wiskjen fan playbooks. De molekule yntegreart naadloos mei CI-systemen, wêrtroch jo de snelheid fan ûntwikkeling kinne ferheegje troch de tiid foar hânmjittich testen fan playbooks te ferminderjen.

Tank foar jo oandacht. As jo ​​ûnderfining hawwe yn it testen fan ansible rollen, en it is net besibbe oan de Molecule, fertel ús deroer yn 'e kommentaren!

Boarne: www.habr.com

Add a comment