Стратегии тестирования
Интеграция тестирования с Ansible Playbook
Многие задаются вопросом: «Как лучше всего интегрировать тестирование с Ansible playbook?» Есть много вариантов. Ansible фактически разработан как система «быстрого отказа» и упорядоченной работы, поэтому легко встроить тестирование непосредственно в Ansible playbook. В этой главе мы рассмотрим некоторые шаблоны для интеграции тестов инфраструктуры и обсудим подходящий уровень тестирования.
Примечание
Эта глава посвящена тестированию приложения, которое вы развертываете, а не тестированию Ansible модулей во время разработки. Для этой информации перейдите к разделу «Разработка».
Внедрение определенного уровня тестирования в ваш рабочий процесс развертывания позволит избежать неожиданностей при переходе кода в производство, и в многих случаях тесты можно использовать в производстве для предотвращения распространения сбоев обновлений по всей установке. Поскольку это основанный на push-методе подход, легко запустить шаги на локальном хосте или тестовых серверах. Ansible позволяет вставить столько проверок и балансировок в свой процесс обновления, сколько вам необходимо.
Правильный уровень тестирования
Ansible ресурсы представляют модели желаемого состояния. Поэтому не нужно тестировать запуск служб, установку пакетов или подобные вещи. Ansible – это система, которая гарантирует, что эти вещи будут истинны в декларативном смысле. Вместо этого укажите эти вещи в своих playbook.
tasks:
- service:
name: foo
state: started
enabled: yes
Если вы считаете, что служба может не запуститься, лучше всего попросить ее запуститься. Если служба не запустится, Ansible соответствующим образом об этом сообщит. (Это не следует путать с тем, выполняет ли служба функциональную задачу, о чем мы расскажем позже).
Режим проверки как тест на отклонения
В приведенной выше настройке –check режим 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
Если вы используете роли (а вы должны, роли отличные!), скрипты, запускаемые модулем скрипта, могут храниться в каталоге «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 проверяет их автоматически. Вместо проверки существования пользователя, используйте модуль пользователя для его создания.
Ansible – система быстрого отказа, поэтому при ошибке создания пользователя выполнение playbook остановится. Вам не нужно следить за этим.
Жизненный цикл тестирования
Если вы внедрите некоторый уровень базовой проверки своего приложения в свои playbook, они будут выполняться каждый раз при развертывании.
Таким образом, развертывание на виртуальной машине локальной разработки и в среде предварительного просмотра позволит убедиться, что все соответствует плану до развертывания в производственной среде.
Ваш рабочий процесс может выглядеть так:
- 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 playbook.
Однако имеет смысл включить в playbook некоторые базовые проверки работоспособности, и в некоторых случаях возможно запустить подмножество набора 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, вы всё равно должны принять решение о том, стоит ли выполнять развертывание вручную. Однако это может помочь в работе с поэтапными обновлениями предыдущего раздела и включить некоторые базовые проверки работоспособности с помощью таких модулей, как «script», «stat», «uri» и «assert».
Заключение
Ansible считает, что вам не нужен другой фреймворк для проверки базовых аспектов вашей инфраструктуры. Это связано с тем, что Ansible — это основанная на порядке система, которая немедленно завершится ошибкой при возникновении необработанных ошибок для узла и предотвратит дальнейшую конфигурацию этого узла. Это позволяет быстро обнаружить ошибки и отображает их в сводке в конце выполнения Ansible.
Однако, поскольку Ansible разработан как система многоуровневой оркестрации, очень легко интегрировать тесты в конец выполнения playbook, используя отдельные задачи или роли. При использовании с поэтапными обновлениями шаги тестирования могут определять, следует ли возвращать машину в пул балансировщика нагрузки или нет.
Наконец, поскольку ошибки Ansible распространяются до кода возврата самой программы Ansible, а Ansible по умолчанию работает в простом режиме push, Ansible является отличным компонентом для включения в среду сборки, если вы хотите использовать его для развертывания систем в рамках конвейера непрерывной интеграции/непрерывной доставки, как показано в разделах выше.
Фокус должен быть не на тестировании инфраструктуры, а на тестировании приложения, поэтому мы настоятельно рекомендуем обсудить с вашей командой QA, какие типы тестов имеют смысл для запуска на виртуальных машинах разработки и какие типы тестов они хотели бы запускать в среде предварительного просмотра при каждом развертывании. Очевидно, что на этапе разработки также подойдут модульные тесты. Но не тестируйте свой playbook модульно. Ansible декларативно описывает состояния ресурсов, поэтому это не нужно. Однако если есть случаи, когда вы хотите убедиться в чем-то, это прекрасно, и такие модули, как stat/assert, отлично подходят для этой цели.
В конечном итоге тестирование – это очень организационная и специфичная для сайта вещь. Все должны этим заниматься, но наиболее подходящий подход для вашей среды будет зависеть от того, что вы развертываете и кто его использует – но все извлекают выгоду из более надёжной и стабильной системы развертывания.
См. также
- Индекс коллекций
-
Просмотрите существующие коллекции, модули и плагины
- Работа с playbooks
-
Введение в playbooks
- Управление выполнением задач: делегирование и локальные действия
-
Делегирование, полезное для работы с балансировщиками нагрузки, облаками и локальными действиями.
- Список рассылки пользователей
-
Есть вопрос? Задайте его на форуме!
- irc.freenode.net
-
Чат-канал IRC #ansible
© 2012–2018 Michael DeHaan
© 2018–2021 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/ansible/2.11/reference_appendices/test_strategies.html