Udhëzim: si të testoni rolet ansible dhe të zbuloni probleme para prodhimit

Përshëndetje të gjithëve!

Punoj si inxhinier DevOps në një shërbim rezervimi hotelesh Ostrovok.ru. Në këtë artikull, dua të flas për përvojën tonë në testimin e rolëve ansible.

Në Ostrovok.ru, si menaxher konfiguracionesh, ne përdorim ansible. Së fundmi, arritëm në nevojën për të testuar rolët, por, siç rezultoi, nuk ka shumë mjete për këtë — framework-u më i njohur ndoshta është Molecule, prandaj vendosëm ta përdorim atë. Por rezultoi se dokumentacioni i tij përmban shumë mungesa. Nuk arritëm të gjenim një udhëzues të mjaftueshëm në rusisht, kështu që vendosëm të shkruajmë këtë artikull.

Udhëzim: si të testoni rolet ansible dhe të zbuloni probleme para prodhimit

Molecule

Molekula — është një framework për ndihmë në testimin e rolëve ansible.

Përshkrimi i thjeshtuar: Molekula krijon një instancë në platformën që keni caktuar (re, virtuale, konteiner; më shumë informacion në seksionin Driver), ekzekuton rolin tuaj mbi të, më pas nis testet dhe fshin instancën. Në rast një dështimi në një nga hapat, Molekula do t'ju njoftojë për këtë.

Tani më me detaje.

Pak teori

Le të shqyrtojmë dy entitete kryesore të Molekulës: Scenario dhe Driver.

Scenario

Skema përmban një përshkrim të asaj që, ku, si dhe në cilën rend do të realizohet. Një rol mund të ketë disa skenarë, dhe çdo skenar është një direktori sipas rrugës /molecule/, e cila përmban përshkrime të veprimeve të nevojshme për test. Domosdoshmërisht duhet të jetë i pranishëm një skenar default, i cili do të krijohet automatikisht nëse e inicializoni rolin me Molekulën. Emrat e skenarëve të tjerë zgjedhën sipas dëshirës tuaj.

Renditja e veprimeve të testit në skenar quhet matrix, dhe sipas parashikimit është si më poshtë:

(Hapat e shënuar ?, sipas parashikimit anashkalohen nëse nuk përshkruhen nga përdoruesi)

  • lint — ekzekutimi i linteve. Sipërfaqësisht përdoren yamllint dhe flake8,
  • destroy — fshirja e instancave nga rinisja e mëparshme të Molekulës (nëse ka mbetur ndonjë)
  • dependency? — установка ansible-зависимости тестируемой роли,
  • syntax — kontrolli i sintaksës së rolit me ndihmën e ansible-playbook --syntax-check,
  • krijo — krijimi i një instance,
  • prepare? — подготовка инстанса; например, проверка / установка python2
  • converge — ekzekutimi i playbook-ut të testuar,
  • idempotence — ekzekutimi i përsëritur i playbook-ut për testimin e idempotencës,
  • side_effect? — действия, не относящиеся непосредственно к роли, но нужные для тестов,
  • verify — ekzekutimi i testeve të konfiguracionit të rezultuar me ndihmën e testinfra(sipas parashikimit) /goss/inspec,
  • cleanup? — (в новых версиях) — грубо говоря, «очистка» внешней инфраструктуры, задетой Молекулой,
  • destroy — fshirja e instancës.

Ky sekvencë mbulon shumicën e rasteve, por, nëse është e nevojshme, mund të ndryshohet.

Çdo hap të mësipërm mund të ekzekutohet veçmas me anë të molecule. Por është e rëndësishme të kuptohet se për çdo komandë të tillë cli mund të ekzistojë një sekvencë veprimesh, të cilën mund ta zbuloni duke ekzekutuar molecule matrix. Për shembull, kur ekzekutohet komanda converge (ekzekutimi i playbook-ut të testuar) do të kryhen veprimet e mëposhtme:

$ molecule matrix converge
...
└── default         # emri i skenarit
    ├── dependency  # instalimi i varësive
    ├── create      # krijimi i instancës
    ├── prepare     # përgatitja e instancës
    └── converge    # ekzekutimi i playbook-ut

Sekuenca e këtyre veprimeve mund të redaktohet. Nëse diçka nga lista tashmë është kryer, do të kalojë. Gjendja aktuale, si dhe konfigurimi i instancave, Molecule i ruan në direktorinë $TMPDIR/molecule//.

Hapat me ? mund të shtohen, duke përshkruar veprimet e dëshiruara në formatin e playbook-ut të ansible, dhe emri i skedarit të bëhet përkatësisht hapit: prepare.yml/side_effect.yml. Molecule do të presë këto skedarë në dosjen e skenarit.

Driver

Drejtori është një entitet, ku krijohen instancat për testime.
Lista e drejtuesve standard për të cilët Molecula ka përgatitur shabllone është si më poshtë: Azure, Docker, EC2, GCE, LXC, LXD, OpenStack, Vagrant, Delegated.

Në shumicën e rasteve, shabllonet janë skedarë create.yml dhe destroy.yml në dosjen e skenarit, të cilat përshkruajnë krijimin dhe fshirjen e instancave përkatësisht.
Përjashtim përbëjnë Docker dhe Vagrant, pasi ndërveprimi me modulet e tyre mund të ndodhë pa skedarët e përmendur më sipër.

Vlen të theksohet drejtuesi Delegated, pasi në rastin e përdorimit të tij në skedarin e krijimit dhe fshirjes së instancës, përshkruhet vetëm puna me konfigurimin e instanceve, pjesa tjetër duhet të përshkruhet nga inxhinieri.

Drejtuesi default është Docker.

Tani le të kalojmë në praktikë dhe të shqyrtojmë veçoritë e mëtejshme atje.

Fillimi i punës

Si 'hello world', do të testojmë një rol të thjeshtë për instalimin e nginx. Si drejtues do të zgjedhim docker – besoj se është instaluar tek shumica prej jush (dhe kujtojmë se docker është drejtuesi default).

Të përgatisim virtualenv dhe ta instalojmë në të molecule:

> pip install virtualenv
> virtualenv -p `which python2` venv
> source venv/bin/activate
> pip install molecule docker  # molecule do të instalojë ansible si varësi; docker për drejtuesin

Hapi tjetër është të inicializojmë një rol të ri.
Inicimi i një roli të re, ashtu si edhe një skenari të ri, bëhet përmes komandës molecule init:

> molecule init role -r nginx
--> Po inicializohet roli i ri nginx...
Inicimi i rolit në /nginx u bë me sukses.
> cd nginx
> tree -L 1
.
├── README.md
├── defaults
├── handlers
├── meta
├── molecule
├── tasks
└── vars

6 direktorë, 1 skedar

Kemi marrë një rol tipik ansible. Më tej, të gjitha ndërveprimet me CLI të Molekulës bëhen nga rrënja e rolit.

Le të shohim çfarë ndodhet në direktorinë e rolit:

> tree molecule/default/
molecule/default/
├── Dockerfile.j2  # Shablloni Jinja për Dockerfile
├── INSTALL.rst.   # Pak informacion mbi instalimin e varësive të skenarit
├── molecule.yml   # File konfigurimi
├── playbook.yml   # Playbook që aktivizon rolin
└── tests          # Direktorinë me testet e stagës verify
    └── test_default.py

1 direktor, 6 skedare

Të shqyrtojmë konfigurimin molecule/default/molecule.yml (do ta zëvendosim vetëm imazhin docker):

---
dependencë:
  emri: galaxy
driver:
  emri: docker
lint:
  emri: yamllint
platforms:
  - emri: instance
    imazh: centos:7
provisioner:
  emri: ansible
  lint:
    emri: ansible-lint
scenario:
  emri: default
verifier:
  emri: testinfra
  lint:
    emri: flake8

dependency

Ky seksion përshkruan burimin e varësive.

Opsionet e mundshme: galaxy, gilt, shell.

Shell është thjesht një shell komandash që përdoret në rast se galaxy dhe gilt nuk mbulojnë nevojat tuaja.

Nuk do të qëndroj këtu gjatë, është mjaft e përshkruar në dokumentacion.

driver

Emri i driver-it. Ne këtë e kemi docker.

lint

Si linte, përdoret yamllint.

Mundësi të dobishme në këtë pjesë të konfigurimit janë mundësia për të treguar skedarin e konfigurimit për yamllint, për të kaluar variablat mjedisorë ose për të çaktivizuar lintern:

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

platformat

Përshkruan konfigurimin e instancave.
Në rastin e docker-it si driver, Molecule iteron përmes kësaj seksioni, dhe çdo element i listës është i disponueshëm në Dockerfile.j2 si variabël item.

Në rastin e driver-it ku janë të domosdoshme create.yml dhe destroy.yml, seksioni është i disponueshëm në to si molecule_yml.platforms, dhe iterimet për të përshkruhen tashmë në këto skedarë.

Pasi Molecule ofron menaxhimin e instancave për modulët ansible, lista e mundshme e konfigurimeve duhet të kërkohet aty. Për docker-in, për shembull, përdoret moduli docker_container_module. Cilat module përdoren në driver-at e tjerë, mund të gjenden në dokumentacion.

Gjithashtu, shembuj të përdorimit të driver-eve të ndryshme mund të gjenden në testet e Moleculës vetë.

Do ta zëvendësojmë këtu centos:7ubuntu.

provisioner

«Furnizuesi» është një entitet që menaxhon instancat. Në rastin e Molekulës, kjo është ansible, mbështetje për të tjera nuk është e planifikuar, prandaj ky seksion mund të quhet me kusht konfigurim i zgjeruar i ansible.
Këtu mund të specifikoni shumë gjëra, por do të theksoj momentet kryesore, sipas mendimit tim:

  • playbooks: mund të specifikoni se cilat playbook duhet të përdoren në faza të caktuara.

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: parametrat e Ansible dhe variablat e ambientit

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

scenario

Emri dhe përshkrimi i sekuencave të skenarit.
Mund të ndryshoni matricën e veprimeve të paracaktuar të ndonjë komande, duke shtuar kyçin <command>_sequence dhe si vlerë për të përcaktoni listën e hapave që na nevojitet.
Supozoni se dëshirojmë të ndryshojmë sekuencën e veprimit gjatë ekzekutimit të komandës për të ekzekutuar playbook: molecule converge

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

verifikuesi

Konfigurimi i kornizës për testet dhe linters që i përket. Siç është e parazgjedhur, përdoret për lintern testinfra dhe flake8. Opsionet e mundshme janë të ngjashme me ato të përmendura më lart:

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

Të kthehemi te roli ynë. Të redaktojmë skedarin tasks/main.yml në këtë formë:

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

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

Dhe do të shtojmë testet në 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")

Gati, mbetet vetëm të ekzekutojmë (nga rrënja e rolit, kujtoj):

> molecule test

Një dalje e gjatë nën spoiler:

--> Duke validimin e skemës /nginx/molecule/default/molecule.yml.
Validimi u përfundua me sukses.
--> Matricha e testit

└── default
    ├── lint
    ├── shkathtëso
    ├── varësia
    ├── sintaksë
    ├── krijo
    ├── përgatit
    ├── bashko
    ├── idempotencë
    ├── efekt_anësor
    ├── verifiko
    └── shkathtëso

--> Scenari: 'default'
--> Veprimi: 'lint'
--> Duke ekzekutuar Yamllint në skedarët e gjetur në /nginx/...
Lintimi përfundoi me sukses.
--> Duke ekzekutuar Flake8 në skedarët e gjetur në /nginx/molecule/default/tests/...
Lintimi përfundoi me sukses.
--> Duke ekzekutuar Ansible Lint në /nginx/molecule/default/playbook.yml...
Lintimi përfundoi me sukses.
--> Scenari: 'default'
--> Veprimi: 'shkathtëso'

    LOJA [Shkathtësia] *****************************************************************

    DETYRA [Shkathtëso instancat e molekulës] ********************************************
    u ndryshua: [localhost] => (item=None)
    u ndryshua: [localhost]

    DETYRA [Prisni që fshirja e instancave të përfundojë] *******************************
    ok: [localhost] => (item=None)
    ok: [localhost]

    DETYRA [Fshirja e rrjeteve docker] ************************************************

    RISHIKIM I LOJES *********************************************************************
    localhost                  : ok=2    u ndryshua=1    e paarritshme=0    dështuar=0

--> Scenari: 'default'
--> Veprimi: 'varësia'
Duke e anashkaluar, mungon skedari i kërkesave.
--> Scenari: 'default'
--> Veprimi: 'sintaksë'

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

--> Scenari: 'default'
--> Veprimi: 'krijo'

    LOJA [Krijo] ******************************************************************

    DETYRA [Hyni në një regjistrim Docker] **********************************************
    duke e anashkaluar: [localhost] => (item=None)

    DETYRA [Krijoni Dockerfile nga emrat e figurave] *************************************
    u ndryshua: [localhost] => (item=None)
    u ndryshua: [localhost]

    DETYRA [Zbulo imazhet e Docker në nivel lokal] ********************************************
    ok: [localhost] => (item=None)
    ok: [localhost]

    DETYRA [Ndërto një figurë të përputhshme me Ansible] ***************************************
    u ndryshua: [localhost] => (item=None)
    u ndryshua: [localhost]

    DETYRA [Krijoni rrjetet docker] ************************************************

    DETYRA [Krijoni instancat e molekulës] *********************************************
    u ndryshua: [localhost] => (item=None)
    u ndryshua: [localhost]

    DETYRA [Prisni që krijimi i instancave të përfundojë] *******************************
    u ndryshua: [localhost] => (item=None)
    u ndryshua: [localhost]

    RISHIKIM I LOJES *********************************************************************
    localhost                  : ok=5    u ndryshua=4    e paarritshme=0    dështuar=0

--> Scenari: 'default'
--> Veprimi: 'përgatit'
Duke e anashkaluar, libri përgatitës nuk është i konfiguruar.
--> Scenari: 'default'
--> Veprimi: 'bashko'

    LOJA [Bashko] ****************************************************************

    DETYRA [Grumbullimi i Fakteve] *********************************************************
    ok: [instance]

    DETYRA [nginx : Instaloni nginx] ***************************************************
    u ndryshua: [instance]

    DETYRA [nginx : Filloni nginx] *****************************************************
    u ndryshua: [instance]

    RISHIKIM I LOJES *********************************************************************
    instance                   : ok=3    u ndryshua=2    e paarritshme=0    dështuar=0

--> Scenari: 'default'
--> Veprimi: 'idempotencë'
Idempotenca përfundoi me sukses.
--> Scenari: 'default'
--> Veprimi: 'efekt_anësor'
Duke e anashkaluar, libri i efektit anësor nuk është i konfiguruar.
--> Scenari: 'default'
--> Veprimi: 'verifiko'
--> Duke ekzekutuar testet Testinfra të gjetura në /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
mbled 4 items

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

    ========================== 4 kaluan në 27.23 sekonda ===========================
Verifikuesi përfundoi me sukses.
--> Scenari: 'default'
--> Veprimi: 'shkathtëso'

    LOJA [Shkathtësia] *****************************************************************

    DETYRA [Shkathtëso instancat e molekulës] ********************************************
    u ndryshua: [localhost] => (item=None)
    u ndryshua: [localhost]

    DETYRA [Prisni që fshirja e instancave të përfundojë] *******************************
    u ndryshua: [localhost] => (item=None)
    u ndryshua: [localhost]

    DETYRA [Fshirja e rrjeteve docker] ************************************************

    RISHIKIM I LOJES *********************************************************************
    localhost                  : ok=2    u ndryshua=2    e paarritshme=0    dështuar=0

Roli ynë e thjeshtë u testua pa probleme.
Është e rëndësishme të mbani mend se nëse hasni probleme gjatë punës testi i molekulës, nëse nuk keni ndryshuar renditjen standarde, Molekula do të fshijë instancën.

Për debagimin, komandat e mëposhtme janë të dobishme:

> molecule --debug  # informacion për debagim. Në kohën e funksionimit normal, Molekula fsheh logët.
> molecule converge          # Mbush instancën pas ekzekutimit të rolit të testuar.
> molecule login             # Hyni në instancën e krijuar.
> molecule --help            # Lista e plotë e komandave.

Roli ekzistues

Shtimi i një skenari të ri në rolin ekzistues ndodh nga direktoriumi i rolit me komandat e mëposhtme:

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

Nëse ky është skenari i parë në rol, parametri -s mund të lihet jashtë, pasi do të krijohet një skenar default.

Përfundimi

Siç e shihni, Molekula nuk është shumë e komplikuar, dhe duke përdorur template të veta, mund të reduktoni shpërndarjen e një skenari të ri në modifikimin e variablave në playbook-et e krijimit dhe fshirjes së instancave. Molekula integrohet pa vështirësi me sistemet CI, duke lejuar rritjen e shpejtësisë së zhvillimit përmes reduktimit të kohës për testimin manual të playbook-eve.

Faleminderit për vëmendjen tuaj. Nëse keni përvojë në testimin e rolleve ansible, dhe ajo nuk është e lidhur me Molekulën — tregoni për të në komentet!

Burimi: habr.com

Bleni hostim të besueshëm për faqe me mbrojtje nga DDoS, serverë VPS VDS 🔥 Bleni hostim të besueshëm për faqe me mbrojtje nga DDoS, serverë VPS VDS | ProHoster