Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

Това е стенограмата представления на DevOps-40 2020-03-18:

Започвайки от втория комит, всеки код става наследен, защото първоначалните идеи започват да се разминават със суровата реалност. Това не е нито добро, нито лошо, това е даденост, с която трудно се спори и трябва да се живее. Част от този процес е рефакторингът. Рефакторинг на инфраструктурата като код. Нека историята започне с това как да преработим Ansible за една година и да не полудеем.

Раждането на наследството

Ден #1: Нулев пациент

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

Имало едно време един условен проект. Имаше екип за разработка на Dev и инженери на Ops. Те решаваха същия проблем: как да разположат сървъри и да стартират приложение. Проблемът беше, че всеки отбор реши този проблем по свой начин. По време на проекта беше решено да се използва Ansible за синхронизиране на знанията между екипите Dev и Ops.

Ден #89: Раждането на наследството

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

Без да го забелязват, те искаха да го направят възможно най-добре, но се оказа, че е наследство. как става това

  • Имаме спешна задача тук, нека направим мръсен хак и след това да го поправим.
  • Не е нужно да пишете документация и всичко е ясно какво се случва тук.
  • Знам Ansible/Python/Bash/Terraform! Вижте как мога да избягвам!
  • Аз съм разработчик на Full Stack Overflow и копирах това от stackoverflow, не знам как работи, но изглежда страхотно и решава проблема.

В резултат на това можете да получите неразбираем тип код, за който няма документация, не е ясно какво прави, дали е необходим, но проблемът е, че трябва да го разработите, модифицирате, добавите патерици и опори , което прави ситуацията още по-лоша.

- hosts: localhost
  tasks:
    - shell: echo -n Z >> a.txt && cat a.txt
      register: output
      delay: 1
      retries: 5
      until: not output.stdout.find("ZZZ")

Ден #109: Осъзнаване на проблема

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

Първоначално замисленият и внедрен IaC модел вече не отговаря на изискванията на потребителите / бизнеса / други екипи и времето за извършване на промени в инфраструктурата престава да бъде приемливо. В този момент идва разбирането, че е време да се действа.

IaC рефакторинг

Ден #139: Наистина ли имате нужда от рефакторинг?

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

Преди да се втурнете да преработвате, трябва да отговорите на няколко важни въпроса:

  1. Защо ти трябва всичко това?
  2. Имаш ли време?
  3. Знанието достатъчно ли е?

Ако не знаете как да отговорите на въпросите, тогава рефакторингът ще приключи, преди дори да започне, или може само да се влоши. защото имаше опит( Какво научих от тестването на 200 000 реда инфраструктурен код), тогава проектът получи молба за помощ за коригиране на ролите и покриването им с тестове.

Ден #149: Подготовка на рефакторинга

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

Първото нещо е да се подготвите. Решете какво ще правим. За да направим това, ние общуваме, намираме проблемни области и измисляме начини за разрешаването им. Ние записваме получените концепции по някакъв начин, например статия в сливане, така че когато възникне въпросът „кое е най-добро?“ или "кое е правилното?" Не сме се изгубили. В нашия случай се придържахме към идеята разделяй и владей: разбиваме инфраструктурата на малки парчета/тухли. Този подход ви позволява да вземете изолирана част от инфраструктурата, да разберете какво прави, да я покриете с тестове и да я промените, без да се страхувате, че ще счупите нещо.

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

Оказва се, че тестването на инфраструктурата става крайъгълен камък и тук си струва да споменем пирамидата за тестване на инфраструктура. Абсолютно същата идея, която е в процес на разработка, но за инфраструктура: преминаваме от евтини бързи тестове, които проверяват прости неща, като отстъп, към скъпи пълноценни тестове, които разгръщат цялата инфраструктура.

Ansible тестови опити

Преди да започнем да описваме как покрихме Ansible тестовете по проекта, ще опиша опитите и подходите, които имах възможността да използвам по-рано, за да разбера контекста на взетите решения.

Ден № -997: Предоставяне на SDS

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

Първият път, когато тествах Ansible, беше по проект за разработване на SDS (софтуерно дефинирано съхранение). Има отделна статия по тази тема
Как да счупите велосипеди с патерици, когато тествате разпределението си, но накратко, завършихме с обърната тестова пирамида и тествайки прекарахме 60-90 минути на една роля, което е много време. Основата беше e2e тестове, т.е. внедрихме пълноценна инсталация и след това я тествахме. Това, което беше още по-утежняващо, беше изобретяването на собствения му велосипед. Но трябва да призная, че това решение проработи и позволи стабилно издание.

Ден # -701: Ansible и тестова кухня

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

Развитието на идеята за тестване на Ansible беше използването на готови инструменти, а именно test kitchen / kitchen-ci и inspec. Изборът се определя от познаването на Ruby (за повече подробности вижте статията на Habré: YML програмистите мечтаят ли да тестват Ansible?) работи по-бързо, около 40 минути за 10 роли. Създадохме пакет от виртуални машини и проведохме тестове вътре.

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

Като цяло решението работи, но имаше известна утайка поради разнородност. Когато броят на тестваните хора беше увеличен до 13 основни роли и 2 мета роли, комбиниращи по-малки роли, изведнъж тестовете започнаха да се изпълняват за 70 минути, което е почти 2 пъти повече. Беше трудно да се говори за практики на XP (екстремно програмиране), защото... никой не иска да чака 70 минути. Това беше причината за промяна на подхода

Ден # -601: Анзибъл и молекула

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

Концептуално това е подобно на testkitchen, само че преместихме ролевото тестване в docker и променихме стека. В резултат на това времето беше намалено до стабилни 20-25 минути за 7 роли.

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

Чрез увеличаване на броя на тестваните роли до 17 и линтинг на 45 роли, ние изпълнихме това за 28 минути на 2 дженкинс подчинени устройства.

Ден #167: Добавяне на Ansible тестове към проекта

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

Най-вероятно няма да е възможно да изпълните задачата за рефакторинг набързо. Задачата трябва да е измерима, за да можете да я натрошите на малки парчета и да изядете слона парче по парче с чаена лъжичка. Трябва да има разбиране дали се движите в правилната посока, колко дълго да вървите.

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

Като цяло, няма значение как ще се направи, можете да пишете на лист хартия, можете да поставите стикери на шкафа, можете да създавате задачи в Jira или можете да отворите Google Docs и да запишете текущото състояние там. Краката растат от факта, че процесът не е незабавен, ще бъде дълъг и досаден. Малко вероятно е някой да иска да изгорите от идеи, да се уморите и да бъдете претоварени по време на рефакторинг.

Рефакторингът е прост:

  • Яжте.
  • Спете.
  • Код.
  • IaC тест.
  • Повтарям

и повтаряме това, докато достигнем желаната цел.

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

Може да не е възможно да започнем да тестваме всичко веднага, така че първата ни задача беше да започнем с линтинг и проверка на синтаксиса.

Ден #181: Майстор на екологичното строителство

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

Linting е малка първа стъпка към Green Build Master. Това няма да счупи почти нищо, но ще ви позволи да дебъгвате процеси и да правите зелени компилации в jenkins. Идеята е да се развият навици сред екипа:

  • Червените тестове са лоши.
  • Дойдох да поправя нещо и в същото време да направя кода малко по-добър, отколкото беше преди вас.

Ден #193: От линтинг до модулни тестове

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

След като изградите процеса на въвеждане на кода в главния код, можете да започнете процеса на подобрение стъпка по стъпка - замяна на linting с стартиращи роли, можете дори да го направите без идемпотентност. Трябва да разберете как да прилагате роли и как работят.

Ден #211: От модулни към интеграционни тестове

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

Когато повечето роли са покрити с модулни тестове и всичко е разпръснато, можете да преминете към добавяне на интеграционни тестове. Тези. тестване не на отделна тухла в инфраструктурата, а на комбинация от тях, например пълна конфигурация на инстанция.

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

Използвайки jenkins, ние генерирахме много етапи, които паралелно написваха роли/книги за игри, след това тестове на модули в контейнери и накрая тестове за интеграция.

Jenkins + Docker + Ansible = Тестове

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

  1. Checkout repo и генериране на етапи на изграждане.
  2. Изпълнявайте паралелно етапите на lint playbook.
  3. Изпълнете успоредно етапите на ролята на мъх.
  4. Изпълнете успоредно етапите на ролята за проверка на синтаксиса.
  5. Изпълнете успоредно етапите на тестовата роля.
    1. Роля на мъх.
    2. Проверете зависимостта от други роли.
    3. Проверете синтаксиса.
    4. Създайте докер екземпляр
    5. Стартирайте molecule/default/playbook.yml.
    6. Проверете идемпотентността.
  6. Изпълнете интеграционни тестове
  7. завършеност

Ден #271: Автобусен фактор

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

Първоначално рефакторингът се извършваше от малка група от двама или трима души. Те прегледаха кода в мастера. С течение на времето екипът разви знания за това как да пише код и прегледът на кода допринесе за разпространението на знания за инфраструктурата и как тя работи. Акцентът тук беше, че рецензентите се избираха един по един, по график, т.е. с известна степен на вероятност ще се изкачите в нова част от инфраструктурата.

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

И тук трябва да е удобно. Удобно е да направите преглед, да видите в рамките на каква задача е изпълнена и историята на дискусиите. Имаме интегрирани jenkins + bitbucket + jira.

Но като такъв прегледът не е панацея; някак си попаднахме в главния код, което ни накара да направим провалени тестове:

- get_url:
    url: "{{ actk_certs }}/{{ item.1 }}"
    dest: "{{ actk_src_tmp }}/"
    username: "{{ actk_mvn_user }}"
    password: "{{ actk_mvn_pass }}"
  with_subelements:
    - "{{ actk_cert_list }}"
    - "{{ actk_certs }}"
  delegate_to: localhost

- copy:
    src: "{{ actk_src_tmp }}/{{ item.1 }}"
    dest: "{{ actk_dst_tmp }}"
  with_subelements:
    - "{{ actk_cert_list }}"
    - "{{ actk_certs }}"

После го оправиха, но утайката остана.

get_url:
    url: "{{ actk_certs }}/{{ actk_item }}"
    dest: "{{ actk_src_tmp }}/{{ actk_item }}"
    username: "{{ actk_mvn_user }}"
    password: "{{ actk_mvn_pass }}"
  loop_control:
    loop_var: actk_item
  with_items: "{{ actk_cert_list }}"
  delegate_to: localhost

- copy:
    src: "{{ actk_src_tmp }}/{{ actk_item }}"
    dest: "{{ actk_dst_tmp }}"
  loop_control:
    loop_var: actk_item
  with_items: "{{ actk_cert_list }}"

Ден #311: Ускоряване на тестовете

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

С течение на времето имаше повече тестове, компилациите вървяха по-бавно, до час в най-лошия случай. На едно от ретротата имаше фраза като „добре е, че има тестове, но те са бавни“. В резултат на това изоставихме интеграционните тестове на виртуални машини и ги адаптирахме за Docker, за да го направим по-бърз. Също така заменихме testinfra с ansible verifier, за да намалим броя на използваните инструменти.

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

Строго погледнато, имаше набор от мерки:

  1. Превключете към докер.
  2. Премахнете ролевото тестване, което се дублира поради зависимости.
  3. Увеличете броя на робите.
  4. Ред за пробно изпълнение.
  5. Възможност за мъх ВСИЧКО локално с една команда.

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

В резултат на това Pipeline on jenkins също беше унифициран

  1. Генерирайте етапи на изграждане.
  2. Линт всички паралелно.
  3. Изпълнете успоредно етапите на тестовата роля.
  4. Завършек.

Поуки

Избягвайте глобалните променливи

Ansible използва глобални променливи, във формата има частично решение private_role_varis, но това не е панацея.

Нека ви дам един пример. Нека имаме role_a и role_b

# cat role_a/defaults/main.yml
---
msg: a

# cat role_a/tasks/main.yml
---
- debug:
    msg: role_a={{ msg }}

# cat role_b/defaults/main.yml
---
msg: b

# cat role_b/tasks/main.yml
---
- set_fact:
    msg: b
- debug:
    msg: role_b={{ msg }}

- hosts: localhost
  vars:
    msg: hello
  roles:
    - role: role_a
    - role: role_b
  tasks:
    - debug:
        msg: play={{msg}}

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

Смешното е, че резултатът от книгите за игри ще зависи от неща, които не винаги са очевидни, като например реда, в който са изброени ролите. За съжаление, това е природата на Ansible и най-доброто нещо, което може да се направи, е да се използва някакъв вид споразумение, например в рамките на роля, използвайте само променливата, описана в тази роля.

BAD: използвайте глобална променлива.

# cat roles/some_role/tasks/main.yml
---
debug:
  var: java_home

ДОБРА: V defaults дефинирайте необходимите променливи и по-късно използвайте само тях.

# cat roles/some_role/defaults/main.yml
---
r__java_home:
 "{{ java_home | default('/path') }}"

# cat roles/some_role/tasks/main.yml
---
debug:
  var: r__java_home

Ролеви променливи с префикс

BAD: използвайте глобална променлива.

# cat roles/some_role/defaults/main.yml
---
db_port: 5432

ДОБРА: В ролите за променливи използвайте променливи с префикс името на ролята; това, като гледате инвентара, ще улесни разбирането какво се случва.

# cat roles/some_role/defaults/main.yml
---
some_role__db_port: 5432

Използвайте контролна променлива за цикъл

BAD: Използвайте стандартна променлива в цикли item, ако тази задача/игра е включена някъде, това може да доведе до неочаквано поведение

---
- hosts: localhost
  tasks:
    - debug:
        msg: "{{ item }}"
      loop:
        - item1
        - item2

ДОБРА: Предефинирайте променлива в цикъл чрез loop_var.

---
- hosts: localhost
  tasks:
    - debug:
        msg: "{{ item_name }}"
      loop:
        - item1
        - item2
      loop_control:
        loop_var: item_name

Проверете входните променливи

Съгласихме се да използваме променливи префикси; не би било излишно да проверим дали те са дефинирани както очакваме и например не са заменени от празна стойност

ДОБРА: Проверете променливите.

- name: "Verify that required string variables are defined"
  assert:
    that: ahs_var is defined and ahs_var | length > 0 and ahs_var != None
    fail_msg: "{{ ahs_var }} needs to be set for the role to work "
    success_msg: "Required variables {{ ahs_var }} is defined"
  loop_control:
    loop_var: ahs_var
  with_items:
    - ahs_item1
    - ahs_item2
    - ahs_item3

Избягвайте хеш речници, използвайте плоска структура

Ако дадена роля очаква хеш/речник в един от своите параметри, тогава, ако искаме да променим един от дъщерните параметри, ще трябва да заменим целия хеш/речник, което ще увеличи сложността на конфигурацията.

BAD: Използвайте хеш/речник.

---
user:
  name: admin
  group: admin

ДОБРА: Използвайте плоска променлива структура.

---
user_name: admin
user_group: "{{ user_name }}"

Създавайте идемпотентни книги и роли

Ролите и книгите трябва да са идемпотентни, защото намалява отклоненията в конфигурацията и страха от счупване на нещо. Но ако използвате молекула, това е поведението по подразбиране.

Избягвайте използването на модули на командната обвивка

Използването на шел модул води до императивна парадигма на описание, вместо декларативна, която е ядрото на Ansible.

Тествайте ролите си чрез молекула

Молекулата е много гъвкаво нещо, нека да разгледаме няколко сценария.

Молекула Множество инстанции

В molecule.yml в раздел platforms можете да опишете много хостове, които можете да внедрите.

---
    driver:
      name: docker
    platforms:
      - name: postgresql-instance
        hostname: postgresql-instance
        image: registry.example.com/postgres10:latest
        pre_build_image: true
        override_command: false
        network_mode: host
      - name: app-instance
        hostname: app-instance
        pre_build_image: true
        image: registry.example.com/docker_centos_ansible_tests
        network_mode: host

Съответно тези хостове могат да бъдат converge.yml използвайте:

---
- name: Converge all
  hosts: all
  vars:
    ansible_user: root
  roles:
    - role: some_role

- name: Converge db
  hosts: db-instance
  roles:
    - role: some_db_role

- name: Converge app
  hosts: app-instance
  roles:
    - role: some_app_role

Ansible верификатор

В molecule е възможно да се използва ansible, за да се провери дали екземплярът е конфигуриран правилно, освен това това е по подразбиране от версия 3. Не е толкова гъвкав като testinfra/inspec, но можем да проверим дали съдържанието на файла отговаря на нашите очаквания:

---
- name: Verify
  hosts: all
  tasks:
    - name: copy config
      copy:
        src: expected_standalone.conf
        dest: /root/wildfly/bin/standalone.conf
        mode: "0644"
        owner: root
        group: root
      register: config_copy_result

    - name: Certify that standalone.conf changed
      assert:
        that: not config_copy_result.changed

Или внедрите услугата, изчакайте да стане достъпна и направете тест за дим:

---
  - name: Verify
    hosts: solr
    tasks:
      - command: /blah/solr/bin/solr start -s /solr_home -p 8983 -force
      - uri:
          url: http://127.0.0.1:8983/solr
          method: GET
          status_code: 200
        register: uri_result
        until: uri_result is not failed
        retries: 12
        delay: 10
      - name: Post documents to solr
        command: /blah/solr/bin/post -c master /exampledocs/books.csv

Поставете сложна логика в модули и добавки

Ansible се застъпва за декларативен подход, така че когато правите разклоняване на кода, трансформация на данни, шел модули, кодът става труден за четене. За да се борите с това и да го поддържате лесен за разбиране, не би било излишно да се борите с тази сложност, като създадете свои собствени модули.

Обобщете съвети и трикове

  1. Избягвайте глобалните променливи.
  2. Ролеви променливи с префикс.
  3. Използвайте контролна променлива за цикъл.
  4. Проверете входните променливи.
  5. Избягвайте хеш речници, използвайте плоска структура.
  6. Създавайте идемпотентни книги и роли.
  7. Избягвайте използването на модули на командната обвивка.
  8. Тествайте ролите си чрез молекула.
  9. Поставете сложна логика в модули и добавки.

Заключение

Как да започнете да тествате Ansible, да преработите проекта за една година и да не полудеете

Не можете просто да отидете и да преработите инфраструктурата на проект, дори ако имате IAC. Това е дълъг процес, изискващ търпение, време и знания.

UPD1 2020.05.01 20:30 — За първично профилиране на книги за игри, които можете да използвате callback_whitelist = profile_tasks да разбере какво точно работи за дълго време. След това минаваме Класически анзибилни ускорения. Можете също да опитате митоген
UPD2 2020.05.03 16:34 - Angielski версия

Източник: www.habr.com

Добавяне на нов коментар