Стратегии тестирования
Интеграция тестирования с Ansible Playbook
Часто задаётся вопрос: «Как лучше всего интегрировать тестирование с Ansible playbook?» Есть много вариантов. Ansible фактически разработан как «быстро ломающаяся» и упорядоченная система, поэтому легко встраивать тестирование непосредственно в Ansible playbook. В этой главе мы рассмотрим некоторые шаблоны для интеграции тестов инфраструктуры и обсудим подходящий уровень тестирования.
Примечание
Эта глава посвящена тестированию приложения, которое вы развёртываете, а не тестированию Ansible модулей во время разработки. Для этой информации перейдите в раздел Разработки.
Включив в рабочий процесс развертывания определённую степень тестирования, можно уменьшить количество неожиданностей при попадании кода в производство, и во многих случаях тесты можно использовать в производстве для предотвращения распространения неполадок обновления по всей установке. Поскольку это основанная на «толчке» система, очень легко выполнить действия на локальном сервере или тестовых серверах. Ansible позволяет вставлять в ваш процесс обновления столько проверок и балансиров, сколько вам нужно.
Правильный уровень тестирования
Ansible ресурсы являются моделями желаемого состояния. Поэтому не нужно проверять, запущены ли службы, установлены ли пакеты или подобные вещи. Ansible система, которая гарантирует декларативную истинность этих вещей. Вместо этого, заявляйте эти вещи в своих playbook.
tasks:
- service:
name: foo
state: started
enabled: yes
Если вы думаете, что служба может не запуститься, лучше всего попросить запустить её. Если служба не запустится, Ansible должным образом об этом сообщит. (Это не должно путаться с тем, делает ли служба что-то функциональное, как мы покажем позже).
Режим проверки как тест на дрейф
В указанной выше настройке режим проверки в Ansible также может использоваться как уровень тестирования. Если вы выполняете playbook развертывания на существующей системе, использование флага –check для команды ansible покажет, считает ли Ansible, что ему пришлось бы внести какие-либо изменения для приведения системы в желаемое состояние.
Это позволяет заранее узнать, есть ли необходимость развертывания на данной системе. Обычно скрипты и команды не выполняются в режиме проверки, поэтому если вы хотите, чтобы определённые шаги выполнялись в обычном режиме, даже когда используется флаг –check, например, вызовы скриптового модуля, отключите режим проверки для этих задач:
roles:
- webserver
tasks:
- script: verify.sh
check_mode: no
Модули, полезные для тестирования
Определённые модули playbook особенно подходят для тестирования. Ниже приведен пример, который гарантирует, что порт открыт:
tasks:
- wait_for:
host: "{{ inventory_hostname }}"
port: 22
delegate_to: localhost
Вот пример использования модуля URI для проверки того, что веб-служба возвращает:
tasks:
- action: uri url=http://www.example.com return_content=yes
register: webpage
- fail:
msg: 'service is not happy'
when: "'AWESOME' not in webpage.content"
Легко «подтолкнуть» произвольный скрипт (на любом языке) на удалённый хост, и скрипт автоматически завершится ошибкой, если возвращаемый код не равен нулю:
tasks: - script: test_script1 - script: test_script2 --parameter value --parameter2 value
Если вы используете роли (что нужно, роли — отличная штука!), скрипты, «подталкиваемые» модулем script, могут храниться в каталоге «files/» роли.
А модуль assert очень легко позволяет валидировать различные типы истинности:
tasks:
- shell: /usr/bin/some-command --parameter value
register: cmd_result
- assert:
that:
- "'not ready' not in cmd_result.stderr"
- "'gizmo enabled' in cmd_result.stdout"
Если вам нужно проверить существование файлов, которые не устанавливаются декларативно вашей Ansible конфигурацией, модуль «stat» — отличный выбор:
tasks:
- stat:
path: /path/to/something
register: p
- assert:
that:
- p.stat.exists and p.stat.isdir
Как упоминалось выше, нет необходимости проверять такие вещи, как возвращаемые коды команд. Ansible проверяет их автоматически. Вместо проверки существования пользователя, воспользуйтесь модулем «user», чтобы он существовал.
Ansible — это система быстрого отказа, поэтому при возникновении ошибки создания этого пользователя выполнение playbook прекратится. Вам не нужно проверять его.
Жизненный цикл тестирования
Если вы добавите некоторую степень базовой валидации своего приложения в playbook, они будут выполняться каждый раз при развертывании.
Поэтому развертывание в локальной VM для разработки и в среде подготовки будет проверять, соответствуют ли вещи плану перед развертыванием в производство.
Ваш рабочий процесс может выглядеть следующим образом:
- Use the same playbook all the time with embedded tests in development - Use the playbook to deploy to a staging environment (with the same playbooks) that simulates production - Run an integration test battery written by your QA team against staging - Deploy to production, with the same integrated tests.
Если вы разрабатываете веб-сервис для производства, команда QA должна написать набор интеграционных тестов. Это будут такие вещи, как тесты Selenium или автоматизированные API-тесты, и обычно они не будут встраиваться в ваши Ansible playbooks.
Тем не менее, имеет смысл включить некоторые базовые проверки работоспособности в ваши playbooks, и в некоторых случаях может быть возможно запустить подмножество набора QA на удалённых узлах. Об этом говорится в следующем разделе.
Интеграция тестирования с последовательными обновлениями
Если вы ознакомились с Управление запуском задач: делегирование и локальные действия, быстро станет понятно, что шаблон последовательного обновления можно расширить, и вы можете использовать результат выполнения playbook для принятия решения о добавлении машины в балансировщик нагрузки или нет.
Вот кульминация встроенных тестов:
---
- hosts: webservers
serial: 5
pre_tasks:
- name: take out of load balancer pool
command: /usr/bin/take_out_of_pool {{ inventory_hostname }}
delegate_to: 127.0.0.1
roles:
- common
- webserver
- apply_testing_checks
post_tasks:
- name: add back to load balancer pool
command: /usr/bin/add_back_to_pool {{ inventory_hostname }}
delegate_to: 127.0.0.1
Конечно, в примере выше шаги «удаление из пула» и «возврат» будут заменены вызовом модуля балансировщика нагрузки Ansible или соответствующей командной оболочки. У вас могут быть и шаги, использующие модуль мониторинга для запуска и завершения периода простоя машины.
Однако, из примера видно, что тесты используются как заслон — если шаг «apply_testing_checks» не выполнен, машина не вернётся в пул.
Прочитайте главу о делегировании о «max_fail_percentage», и вы также можете контролировать, сколько тестов с ошибками остановят процесс последовательного обновления.
Этот подход также можно изменить для запуска шага с тестовой машины удалённо на машине:
---
- hosts: webservers
serial: 5
pre_tasks:
- name: take out of load balancer pool
command: /usr/bin/take_out_of_pool {{ inventory_hostname }}
delegate_to: 127.0.0.1
roles:
- common
- webserver
tasks:
- script: /srv/qa_team/app_testing_script.sh --server {{ inventory_hostname }}
delegate_to: testing_server
post_tasks:
- name: add back to load balancer pool
command: /usr/bin/add_back_to_pool {{ inventory_hostname }}
delegate_to: 127.0.0.1
В вышеприведённом примере скрипт запускается с тестового сервера на удалённом узле перед возвращением его в пул.
В случае проблемы, исправьте несколько серверов, которые завершились сбоем, используя автоматически сгенерированный Ansible файл для повторения развертывания только на этих серверах.
Достижение непрерывного развертывания
При необходимости вышеуказанные методы можно расширить для поддержки непрерывного развертывания.
Рабочий процесс может выглядеть следующим образом:
- Write and use automation to deploy local development VMs - Have a CI system like Jenkins deploy to a staging environment on every code change - The deploy job calls testing scripts to pass/fail a build on every deploy - If the deploy job succeeds, it runs the same deploy playbook against production inventory
Некоторые пользователи Ansible используют этот подход для развертывания в течение получаса или больше без отключения всей инфраструктуры. Культура автоматизированного QA имеет решающее значение, если вы хотите достичь этого уровня.
Если вы все ещё используете большое количество ручного QA, вы по-прежнему должны принять решение о том, нужно ли развертывать вручную, но это может помочь работать по шаблонам последовательного обновления из предыдущего раздела и включить некоторые базовые проверки работоспособности, используя модули «script», «stat», «uri» и «assert».
Заключение
Ansible считает, что вам не нужен ещё один фреймворк для проверки основных свойств вашей инфраструктуры. Это так потому, что Ansible — это упорядоченная система, которая немедленно завершается ошибкой на узле при возникновении необработанных ошибок и предотвращает дальнейшую настройку этого узла. Это приводит ошибки наверх и показывает их в сводке в конце выполнения Ansible.
Однако, поскольку Ansible разработан как система многоуровневой оркестрации, он очень легко позволяет интегрировать тесты в конец выполнения playbook, используя либо отдельные задачи, либо роли. При использовании с последовательными обновлениями шаги тестирования могут принимать решение о возврате машины в пул балансировщика нагрузки или нет.
Наконец, поскольку ошибки Ansible распространяются до кода возврата самого Ansible-программы, и Ansible по умолчанию работает в простом режиме «толчка», Ansible — отличная платформа для включения в среду сборки, если вы хотите использовать его для развертывания систем как части конвейера непрерывной интеграции/непрерывной доставки, как описано выше.
Фокус должен быть не на тестировании инфраструктуры, а на тестировании приложений, поэтому мы настоятельно рекомендуем вам обсудить с вашей командой QA, какие тесты будут уместны при каждом развертывании виртуальных машин разработки и какие типы тестов они хотели бы запускать для среды подготовки при каждом развертывании. Очевидно, что на этапе разработки модульные тесты тоже хороши. Но не тестируйте свой playbook модульно. Ansible описывает состояния ресурсов декларативно, поэтому вы не должны этого делать. Однако, если есть случаи, когда вам нужно убедиться в чём-то, это замечательно, и модули типа stat/assert — отличные варианты для этого.
В целом, тестирование — очень организационная и специфичная для сайта вещь. Все должны это делать, но что будет наиболее подходящим для вашей среды, зависит от того, что вы развертываете и кто его использует — но все выигрывают от более надёжной и стабильной системы развертывания.
См. также
- Индекс коллекций
-
Просмотрите существующие коллекции, модули и плагины
- Работа с playbooks
-
Вступление к playbooks
- Управление запуском задач: делегирование и локальные действия
-
Делегирование, полезно для работы с балансировщиками нагрузки, облаками и локально выполняемыми шагами.
- Список рассылки пользователей
-
У вас есть вопрос? Загляните в группу Google!
- irc.freenode.net
-
IRC-чат-канал #ansible
© 2012–2018 Michael DeHaan
© 2018–2019 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/ansible/2.10/reference_appendices/test_strategies.html