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