Spec-Zone.ru › Ansible 2.9

Стратегии тестирования

Интеграция тестирования с 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, что ему нужно внести какие-либо изменения для приведения системы в желаемое состояние.

Это позволит вам сразу узнать, есть ли необходимость развертывать на данной системе. Обычно скрипты и команды не выполняются в режиме проверки, поэтому, если вы хотите, чтобы определённые шаги всегда выполнялись в режиме проверки, например, вызовы модуля скрипта, отключите режим проверки для этих задач:

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 используют вышеописанный подход для развертывания несколько десятков раз в час без выключения всей своей инфраструктуры. Важна культура автоматизированного контроля качества, если вы хотите достичь такого уровня.

Если вы всё ещё выполняете значительное количество ручного контроля качества, вы по-прежнему должны принимать решение о ручном развертывании, но это может помочь работать по шаблонам поэтапных обновлений из предыдущего раздела и включать некоторые базовые проверки работоспособности, используя модули «script», «stat», «uri» и «assert».

Заключение

Ansible считает, что вам не нужен другой фреймворк для проверки базовых истинности вашей инфраструктуры. Это так, потому что Ansible — это система на основе порядка, которая немедленно завершится ошибкой при возникновении необработанных ошибок для узла и предотвратит дальнейшую конфигурацию этого узла. Это заставляет ошибки всплывать наверх и показывает их в сводном отчёте в конце выполнения Ansible.

Однако, поскольку Ansible спроектирован как система многоуровневой оркестрации, он очень легко интегрирует тесты в конец выполнения playbook'а, используя отдельные задачи или роли. При использовании с поэтапными обновлениями шаги тестирования могут решать, возвращать ли машину в пул балансировщика нагрузки или нет.

Наконец, поскольку ошибки Ansible распространяются до кода возврата самой программы Ansible, а Ansible по умолчанию работает в легковечном режиме отправки, Ansible является отличным инструментом для интеграции в среду сборки, если вы хотите использовать его для развертывания систем в рамках конвейера непрерывной интеграции/непрерывной поставки, как это описано в разделах выше.

Фокус должен быть не на тестировании инфраструктуры, а на тестировании приложения, поэтому мы настоятельно рекомендуем сотрудничать с вашей командой QA и спросить, какие тесты имели бы смысл запускать каждый раз при развертывании виртуальных машин разработки и какие тесты они хотели бы запускать в среде подготовки при каждом развертывании. Естественно, на стадии разработки отличными являются также unit-тесты. Но не unit-тестируйте ваш playbook. Ansible описывает состояния ресурсов декларативно, поэтому вам не нужно.

Однако, если есть случаи, когда вы хотите быть уверены в чём-то, это отлично, и модули типа stat/assert — отличные варианты для этой цели.

В общем, тестирование — это очень организационная и специфичная для сайта вещь. Каждый должен это делать, но что имеет наибольший смысл для вашей среды, будет зависеть от того, что вы разворачиваете и кто это использует — но все извлекают выгоду из более надёжной и стабильной системы развертывания.

См. также

Все модули
Вся документация по Ansible модулям
Работа с playbook'ами
Вводное руководство по playbook'ам
Делегирование, поэтапные обновления и локальные действия
Делегирование, полезно для работы с балансировщиками нагрузки, облаками и локальными шагами.
Список рассылки пользователей
Есть вопрос? Загляните в группу 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.9/reference_appendices/test_strategies.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API