Instruksies: hoe om moontlike rolle te toets en uit te vind oor probleme voor produksie

Hallo almal!

Ek werk as 'n DevOps-ingenieur in 'n hotelbesprekingsdiens. Ostrovok.ru. In hierdie artikel wil ek praat oor ons ervaring in die toets van moontlike rolle.

By Ostrovok.ru gebruik ons ​​ansible as 'n konfigurasiebestuurder. Ons het onlangs tot die behoefte gekom om rolle te toets, maar soos dit geblyk het, is daar nie soveel instrumente hiervoor nie - die gewildste is miskien die Molekule-raamwerk, so ons het besluit om dit te gebruik. Maar dit het geblyk dat sy dokumentasie swyg oor baie slaggate. Ons kon nie 'n voldoende gedetailleerde handleiding in Russies vind nie, daarom het ons besluit om hierdie artikel te skryf.

Instruksies: hoe om moontlike rolle te toets en uit te vind oor probleme voor produksie

molekule

Molekule - 'n raamwerk om moontlike rolle te help toets.

Vereenvoudigde beskrywing: Die molekule skep 'n instansie op die platform wat jy spesifiseer (wolk, virtuele masjien, houer; vir meer besonderhede, sien die afdeling Driver), voer jou rol daarop uit, voer dan toetse uit en vee die instansie uit. In die geval van mislukking op een van die stappe, sal die Molekule jou daaroor inlig.

Nou meer.

'N bietjie teorie

Oorweeg twee sleutelentiteite van die molekule: scenario en drywer.

scenario

Die draaiboek bevat 'n beskrywing van wat, waar, hoe en in watter volgorde uitgevoer gaan word. Een rol kan verskeie skrifte hê, en elkeen is 'n gids langs die pad <role>/molecule/<scenario>, wat beskrywings bevat van die aksies wat vir die toets vereis word. Skrip moet ingesluit word default, wat outomaties geskep sal word as jy die rol met 'n Molekule inisialiseer. Die name van die volgende skrifte is aan jou.

Die volgorde van toetsaksies in 'n skrif word genoem matriks, en by verstek is dit:

(Stappe gemerk ?, by verstek oorgeslaan indien nie deur die gebruiker gespesifiseer nie)

  • lint - lopende linters. By verstek word gebruik yamllint и flake8,
  • destroy - die verwydering van gevalle vanaf die laaste bekendstelling van die Molekule (indien enige),
  • dependency? - installering van die moontlike afhanklikheid van die getoetsde rol,
  • syntax - kontrolering van die sintaksis van die rol met behulp van ansible-playbook --syntax-check,
  • create - skep 'n instansie,
  • prepare? — voorbereiding van die instansie; bv kontroleer/installeer python2
  • converge - bekendstelling van die speelboek wat getoets word,
  • idempotence - herbegin die speelboek vir die idempotensietoets,
  • side_effect? - aksies wat nie direk verband hou met die rol nie, maar nodig is vir toetse,
  • verify - hardloop toetse van die gevolglike konfigurasie met behulp van testinfra(verstek) /goss/inspec,
  • cleanup? - (in nuwe weergawes) - rofweg gesproke, "skoonmaak" van die eksterne infrastruktuur wat deur die Molekule geraak word,
  • destroy - Vee 'n instansie uit.

Hierdie volgorde dek die meeste gevalle, maar kan verander word indien nodig.

Elkeen van die bogenoemde stappe kan afsonderlik uitgevoer word molecule <command>. Maar dit moet verstaan ​​word dat daar vir elke so 'n cli-opdrag sy eie volgorde van aksies kan wees, wat u kan uitvind deur uit te voer molecule matrix <command>. Byvoorbeeld, wanneer die opdrag uitgevoer word converge (met die speelboek wat getoets word), sal die volgende aksies uitgevoer word:

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

Die volgorde van hierdie aksies kan gewysig word. As iets uit die lys reeds gedoen is, sal dit oorgeslaan word. Die huidige toestand, sowel as die konfigurasie van die gevalle, stoor die Molekule in die gids $TMPDIR/molecule/<role>/<scenario>.

Voeg stappe by met ? jy kan die verlangde aksies in die ansible-playbook-formaat beskryf en die lêernaam maak volgens die stap: prepare.yml/side_effect.yml. Verwag hierdie lêers Die molekule sal in die script-lêergids wees.

Driver

'n Bestuurder is 'n entiteit waar toetsgevalle geskep word.
Die lys standaardbestuurders waarvoor Molecule sjablone gereed het, is soos volg: Azure, Docker, EC2, GCE, LXC, LXD, OpenStack, Vagrant, Delegated.

In die meeste gevalle is sjablone lêers create.yml и destroy.yml in die script-lêergids wat onderskeidelik die skepping en verwydering van 'n instansie beskryf.
Die uitsonderings is Docker en Vagrant, aangesien interaksies met hul modules sonder die bogenoemde lêers kan plaasvind.

Dit is die moeite werd om die Gedelegeerde bestuurder uit te lig, want as dit in die lêers gebruik word om 'n instansie te skep en te verwyder, word slegs werk met die konfigurasie van instansies beskryf, die res moet deur die ingenieur beskryf word.

Die verstekbestuurder is Docker.

Kom ons gaan nou verder na oefening en oorweeg verdere kenmerke daar.

Aan die slag

As 'n "hallo wêreld", laat ons 'n eenvoudige nginx-installasierol toets. Kom ons kies docker as die bestuurder - ek dink die meeste van julle het dit geïnstalleer (en onthou dat docker die verstekbestuurder is).

Berei virtualenv en installeer daarin molecule:

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

Die volgende stap is om die nuwe rol te inisialiseer.
Inisialisering van 'n nuwe rol, sowel as 'n nuwe skrif, word uitgevoer met behulp van die opdrag 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

Dit het 'n tipiese ansible-rol uitgedraai. Verder word alle interaksies met CLI-molekules gemaak vanaf die wortel van die rol.

Kom ons kyk wat is in die rolgids:

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

1 directory, 6 files

Kom ons ontleed die konfigurasie molecule/default/molecule.yml (vervang slegs docker-prent):

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

afhanklikheid

Hierdie afdeling beskryf die bron van afhanklikhede.

Moontlike opsies: sterrestelsel, toepassing, dop.

Shell is net 'n opdragdop wat gebruik word ingeval sterrestelsel en goud nie jou behoeftes dek nie.

Ek sal nie lank hier stilstaan ​​nie, dit is genoeg beskryf in dokumentasie.

bestuurder

Die naam van die bestuurder. Ons s'n is docker.

pluis

Die linter is yamllint.

Nuttige opsies in hierdie deel van die konfigurasie is die vermoë om 'n konfigurasielêer vir yamllint, vorentoe omgewingsveranderlikes te spesifiseer, of die linter deaktiveer:

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

platforms

Beskryf die opstelling van die gevalle.
In die geval van docker as 'n bestuurder, word die Molekule oor hierdie afdeling herhaal, en elke element van die lys is beskikbaar in Dockerfile.j2 as 'n veranderlike item.

In die geval van 'n bestuurder wat vereis create.yml и destroy.yml, die afdeling is beskikbaar in hulle as molecule_yml.platforms, en herhalings daaroor word reeds in hierdie lêers beskryf.

Aangesien die Molekule beheer van gevalle aan moontlike modules verskaf, moet daar ook na die lys van moontlike instellings gesoek word. Vir docker word die module byvoorbeeld gebruik docker_houer_module. Watter modules in ander drywers gebruik word, kan gevind word in dokumentasie.

Sowel as voorbeelde van die gebruik van verskeie drywers kan gevind word in die toetse van die Molekule self.

Vervang hier sent:7 op Ubuntu.

voorsiener

"Verskaffer" - 'n entiteit wat gevalle bestuur. In die geval van Molekule is dit moontlik, ondersteuning vir ander word nie beplan nie, so hierdie afdeling kan 'n moontlike uitgebreide konfigurasie genoem word met 'n waarskuwing.
Hier kan jy baie dinge spesifiseer, ek sal na my mening die hoofpunte uitlig:

  • speelboeke: jy kan spesifiseer watter speelboeke in sekere stadiums gebruik moet word.

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

  • verbinding_opsies: opsies verband

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

  • opsies: Aanspreeklike opsies en omgewingsveranderlikes

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

scenario

Naam en beskrywing van skrifreekse.
Jy kan die verstekaksiematriks van enige opdrag verander deur die sleutel by te voeg <command>_sequence en as 'n waarde daarvoor deur die lys van stappe wat ons nodig het te definieer.
Kom ons sê ons wil die volgorde van aksies verander wanneer die playbook run-opdrag uitgevoer word: molecule converge

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

verifieerder

Die opstel van 'n raamwerk vir toetse en 'n linter daaraan. Die verstek linter is testinfra и flake8. Die moontlike opsies is dieselfde as hierbo:

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

Kom ons keer terug na ons rol. Kom ons redigeer die lêer tasks/main.yml na hierdie soort:

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

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

En voeg toetse by 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")

Klaar, dit bly net om te hardloop (van die wortel van die rol, laat ek jou herinner):

> molecule test

Lang uitlaat onder die 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

Ons eenvoudige rol is sonder probleme getoets.
Dit is die moeite werd om te onthou dat as daar probleme tydens die werk is molecule test, dan as jy nie die verstekvolgorde verander het nie, sal die Molekule die instansie uitvee.

Die volgende opdragte is nuttig vir ontfouting:

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

Bestaande rol

Om 'n nuwe skrif by 'n bestaande rol te voeg is uit die rolgids met die volgende opdragte:

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

As dit die eerste scenario in die rol is, dan die parameter -s kan weggelaat word aangesien dit 'n skrif sal skep default.

Gevolgtrekking

Soos u kan sien, is die Molekule nie baie kompleks nie, en deur u eie sjablone te gebruik, kan die implementering van 'n nuwe skrif verminder word tot die redigering van veranderlikes in die instansie-skepping en -skrap-speelboeke. Die molekule integreer naatloos met CI-stelsels, wat jou toelaat om die spoed van ontwikkeling te verhoog deur die tyd vir handmatige toetsing van speelboeke te verminder.

Dankie vir jou aandag. As jy ondervinding het in die toets van moontlike rolle, en dit hou nie verband met die Molekule nie, vertel ons daarvan in die kommentaar!

Bron: will.com

Voeg 'n opmerking