Հրահանգներ. ինչպես փորձարկել անլուրջ դերերը և պարզել խնդիրների մասին մինչև արտադրությունը

Hello everyone!

Ես աշխատում եմ որպես DevOps-ի ինժեներ հյուրանոցների ամրագրման ծառայությունում: Ostrovok.ru. Այս հոդվածում ես ուզում եմ խոսել անսխալ դերերի փորձարկման մեր փորձի մասին:

Ostrovok.ru-ում մենք օգտագործում ենք ansible-ը որպես կոնֆիգուրացիայի կառավարիչ: Վերջերս մենք հասանք դերերը փորձարկելու անհրաժեշտությանը, բայց, ինչպես պարզվեց, դրա համար այդքան էլ շատ գործիքներ չկան. ամենահայտնին, հավանաբար, Molecule շրջանակն է, ուստի մենք որոշեցինք օգտագործել այն: Բայց պարզվեց, որ նրա փաստաթղթավորումը լռում է բազմաթիվ ծուղակների մասին։ Մենք չկարողացանք գտնել բավականաչափ մանրամասն ձեռնարկ ռուսերեն լեզվով, ուստի որոշեցինք գրել այս հոդվածը:

Հրահանգներ. ինչպես փորձարկել անլուրջ դերերը և պարզել խնդիրների մասին մինչև արտադրությունը

Մոլեկուլ

Մոլեկուլ - շրջանակ, որը կօգնի ստուգել իրական դերերը:

Պարզեցված նկարագրություն. Մոլեկուլը ստեղծում է օրինակ ձեր նշած հարթակում (ամպ, վիրտուալ մեքենա, կոնտեյներ; լրացուցիչ մանրամասների համար տե՛ս բաժինը Վարորդ), գործարկում է ձեր դերը դրա վրա, այնուհետև կատարում է թեստեր և ջնջում օրինակը: Քայլերից մեկի ձախողման դեպքում Մոլեկուլը ձեզ կտեղեկացնի այդ մասին:

Հիմա ավելին:

Մի քիչ տեսություն

Դիտարկենք մոլեկուլի երկու հիմնական միավորները՝ Սցենարը և Վարորդը:

Սցենար

Սցենարը պարունակում է նկարագրություն, թե ինչ, որտեղ, ինչպես և ինչ հաջորդականությամբ է կատարվելու։ Մեկ դերը կարող է ունենալ մի քանի սցենար, և յուրաքանչյուրը ճանապարհի երկայնքով գրացուցակ է <role>/molecule/<scenario>, որը պարունակում է թեստի համար անհրաժեշտ գործողությունների նկարագրություններ: Սցենարը պետք է ներառվի default, որը ավտոմատ կերպով կստեղծվի, եթե դերը նախաստորագրեք մոլեկուլով: Հետևյալ սցենարների անունները կախված են ձեզանից:

Ստուգման գործողությունների հաջորդականությունը սցենարում կոչվում է matrix, և լռելյայն դա հետևյալն է.

(Քայլերը նշված են ?, լռելյայն բաց թողնված, եթե օգտագործողի կողմից նշված չէ)

  • lint - հոսող գլանափաթեթներ: Լռելյայն օգտագործվում են yamllint и flake8,
  • destroy - մոլեկուլի վերջին գործարկումից (եթե այդպիսիք կան) օրինակների ջնջում
  • dependency? - ստուգված դերի զգալի կախվածության տեղադրում,
  • syntax - օգտագործելով դերի շարահյուսությունը ansible-playbook --syntax-check,
  • create - ստեղծել օրինակ,
  • prepare? - օրինակի պատրաստում; օրինակ՝ ստուգել/տեղադրել python2
  • converge - փորձարկվող խաղային գրքի գործարկում,
  • idempotence - վերսկսել խաղատախտակը անգործունակության թեստի համար,
  • side_effect? - գործողություններ, որոնք անմիջականորեն կապված չեն դերի հետ, բայց անհրաժեշտ են թեստերի համար,
  • verify - արդյունքում ստացված կոնֆիգուրացիայի փորձարկումներ օգտագործելով testinfra(կանխադրված) /goss/inspec,
  • cleanup? - (նոր տարբերակներում) - կոպիտ ասած, «մաքրում» է մոլեկուլից տուժած արտաքին ենթակառուցվածքը,
  • destroy - Օրինակի ջնջում:

Այս հաջորդականությունը ընդգրկում է դեպքերի մեծ մասը, բայց անհրաժեշտության դեպքում կարող է փոփոխվել:

Վերոհիշյալ քայլերից յուրաքանչյուրը կարող է իրականացվել առանձին molecule <command>. Բայց պետք է հասկանալ, որ յուրաքանչյուր նման cli-հրամանի համար կարող է լինել իր գործողությունների հաջորդականությունը, որը դուք կարող եք պարզել կատարելով. molecule matrix <command>. Օրինակ՝ հրամանը գործարկելիս converge (փորձարկվող խաղագիրքը գործարկելով), կկատարվեն հետևյալ գործողությունները.

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

Այս գործողությունների հաջորդականությունը կարող է խմբագրվել: Եթե ​​ցուցակից ինչ-որ բան արդեն արված է, այն բաց կթողնեն: Ընթացիկ վիճակը, ինչպես նաև օրինակների կազմաձևումը, Molecule-ը պահում է գրացուցակում $TMPDIR/molecule/<role>/<scenario>.

Ավելացրեք քայլերի հետ ? Դուք կարող եք նկարագրել ցանկալի գործողությունները ansible-playbook ձևաչափով և կատարել ֆայլի անվանումը ըստ քայլի՝ prepare.yml/side_effect.yml. Սպասեք այս ֆայլերին Մոլեկուլը կլինի սցենարի թղթապանակում:

Վարորդ

Վարորդը մի միավոր է, որտեղ ստեղծվում են փորձարկման օրինակներ:
Ստանդարտ դրայվերների ցանկը, որոնց համար Molecule-ը պատրաստի կաղապարներ ունի, հետևյալն է՝ Azure, Docker, EC2, GCE, LXC, LXD, OpenStack, Vagrant, Delegated:

Շատ դեպքերում կաղապարները ֆայլեր են create.yml и destroy.yml սցենարի թղթապանակում, որը նկարագրում է համապատասխանաբար օրինակի ստեղծումը և ջնջումը:
Բացառություն են կազմում Docker-ը և Vagrant-ը, քանի որ նրանց մոդուլների հետ փոխազդեցությունը կարող է տեղի ունենալ առանց վերը նշված ֆայլերի:

Արժե առանձնացնել Պատվիրակված դրայվերը, քանի որ եթե այն օգտագործվում է ֆայլերում օրինակ ստեղծելու և ջնջելու համար, նկարագրված է միայն օրինակների կազմաձևման հետ աշխատանքը, մնացածը պետք է նկարագրի ինժեները:

Նախնական դրայվերը Docker-ն է:

Այժմ եկեք անցնենք պրակտիկային և քննարկենք այնտեղ հետագա առանձնահատկությունները:

Ինչից սկսել

Որպես «բարև աշխարհ», եկեք փորձարկենք nginx տեղադրման պարզ դերը: Մենք կընտրենք docker-ը որպես վարորդ. կարծում եմ, որ ձեզանից շատերն այն տեղադրել են (և հիշեք, որ դոկերը լռելյայն դրայվերն է):

Եկեք պատրաստվենք virtualenv և տեղադրել դրա մեջ molecule:

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

Հաջորդ քայլը նոր դերի սկզբնավորումն է:
Նոր դերի, ինչպես նաև նոր սցենարի սկզբնավորումն իրականացվում է հրամանի միջոցով 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

Ստացվեց տիպիկ անսիբլ-դեր: Ավելին, CLI մոլեկուլների հետ բոլոր փոխազդեցությունները կատարվում են դերի արմատից:

Տեսնենք, թե ինչ կա դերերի գրացուցակում.

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

1 directory, 6 files

Եկեք վերլուծենք կազմաձևը molecule/default/molecule.yml (փոխարինեք միայն դոկերի պատկերը):

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

կախվածություն

Այս բաժինը նկարագրում է կախվածության աղբյուրը:

Հնարավոր ընտրանքներ. Հարդագողի ճանապարհ, giltar, պատյան.

Shell-ը պարզապես հրամանի պատյան է, որն օգտագործվում է այն դեպքում, երբ գալակտիկան և ոսկեզօծը չեն բավարարում ձեր կարիքները:

Ես երկար չեմ բնակվի այստեղ, բավական է նկարագրված փաստաթղթավորում.

վարորդ

Վարորդի անունը. Մերը նավահանգիստ է:

կնճռոտ

Լինտերը յամլինտ է։

Կազմաձևի այս մասի օգտակար տարբերակներն են yamllint-ի համար կազմաձևման ֆայլը նշելու, առաջ միջավայրի փոփոխականների կամ անջատելու հնարավորությունը.

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

պլատֆորմներ

Նկարագրում է ատյանների կոնֆիգուրացիան:
Դոկերի՝ որպես վարորդի դեպքում, մոլեկուլը կրկնվում է այս բաժնի վրա, և ցանկի յուրաքանչյուր տարր հասանելի է. Dockerfile.j2 որպես փոփոխական item.

Վարորդի դեպքում, որը պահանջում է create.yml и destroy.yml, բաժինը հասանելի է դրանցում որպես molecule_yml.platforms, և դրա կրկնությունները արդեն նկարագրված են այս ֆայլերում:

Քանի որ Molecule-ն ապահովում է անսարք մոդուլների կառավարումը, հնարավոր պարամետրերի ցանկը նույնպես պետք է փնտրել այնտեղ: Դոկերի համար, օրինակ, մոդուլն օգտագործվում է docker_container_module. Որ մոդուլներն են օգտագործվում այլ դրայվերներում, կարելի է գտնել փաստաթղթավորում.

Ինչպես նաև կարելի է գտնել տարբեր վարորդների օգտագործման օրինակներ հենց մոլեկուլի փորձարկումներում.

Փոխարինեք այստեղ ցենտ:7 մասին Ubuntu.

մատակարարող

«Մատակարար»՝ օրինակներ կառավարող կազմակերպություն: Molecule-ի դեպքում սա անընդունելի է, մյուսների համար աջակցություն նախատեսված չէ, ուստի այս բաժինը կարելի է անվանել անլուրջ ընդլայնված կոնֆիգուրացիա՝ նախազգուշացումով:
Այստեղ դուք կարող եք շատ բան նշել, ես ընդգծեմ հիմնական կետերը, իմ կարծիքով.

  • խաղային գրքերԴուք կարող եք նշել, թե որ գրքույկները պետք է օգտագործվեն որոշակի փուլերում:

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

  • ընտրանքներAnsible ընտրանքներ և շրջակա միջավայրի փոփոխականներ

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

սցենար

Սցենարների հաջորդականությունների անվանումը և նկարագրությունը:
Դուք կարող եք փոխել ցանկացած հրամանի լռելյայն գործողության մատրիցը՝ ավելացնելով ստեղնը <command>_sequence և որպես արժեք դրա համար՝ սահմանելով մեզ անհրաժեշտ քայլերի ցանկը։
Ենթադրենք, որ ուզում ենք փոխել գործողությունների հաջորդականությունը playbook run հրամանը գործարկելիս. molecule converge

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

ստուգում

Թեստերի շրջանակի ստեղծում և դրա վրա տեղադրում: Լռելյայն linter է testinfra и flake8. Հնարավոր տարբերակները նույնն են, ինչ վերը նշվածը.

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

Վերադառնանք մեր դերին. Եկեք խմբագրենք ֆայլը tasks/main.yml այս տեսակի համար:

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

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

Եվ ավելացրեք թեստեր 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")

Կատարված է, մնում է միայն վազել (դերի արմատից, հիշեցնեմ).

> molecule test

Երկար արտանետում սփոյլերի տակ.

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

Մեր պարզ դերը փորձարկվեց առանց խնդիրների:
Հարկ է հիշել, որ եթե աշխատանքի ընթացքում խնդիրներ կան molecule test, ապա, եթե դուք չեք փոխել լռելյայն հաջորդականությունը, Մոլեկուլը կջնջի օրինակը։

Վրիպազերծման համար օգտակար են հետևյալ հրամանները.

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

Առկա դերը

Գոյություն ունեցող դերին նոր սցենար ավելացնելն է դերերի գրացուցակից հետևյալ հրամաններով.

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

Այն դեպքում, երբ սա դերի առաջին սցենարն է, ապա պարամետրը -s կարող է բաց թողնել, քանի որ այն կստեղծի սցենար default.

Ամփոփում

Ինչպես տեսնում եք, մոլեկուլը այնքան էլ բարդ չէ, և օգտագործելով ձեր սեփական ձևանմուշները, նոր սցենարի տեղակայումը կարող է կրճատվել մինչև փոփոխականների խմբագրում օրինակների ստեղծման և ջնջման գրքույկներում: Մոլեկուլն անխափան կերպով ինտեգրվում է CI համակարգերին, ինչը թույլ է տալիս մեծացնել զարգացման արագությունը՝ նվազեցնելով խաղային տետրերի ձեռքով փորձարկման ժամանակը:

Շնորհակալություն ուշադրության համար. Եթե ​​դուք ունեք փորձարկվող դերեր փորձարկելու փորձ, և դա կապված չէ մոլեկուլի հետ, ասեք մեզ այդ մասին մեկնաբանություններում:

Source: www.habr.com

Добавить комментарий