Spec-Zone.ru › Ansible

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

Интеграция тестирования с плейбуками Ansible

Люди часто спрашивают: «Как лучше всего интегрировать тестирование с плейбуками Ansible?» Есть множество вариантов. Ansible разработан как упорядоченная система, которая быстро завершается при ошибках, поэтому встроить тестирование непосредственно в плейбуки Ansible очень просто. В этой главе мы рассмотрим несколько шаблонов интеграции тестов инфраструктуры и обсудим подходящий уровень тестирования.

Примечание

Эта глава посвящена тестированию развёртываемого приложения, а не тестированию модулей Ansible в процессе разработки. Эту тему можно найти в разделе «Разработка».

Если включить определённый объём тестирования в процесс развёртывания, при попадании кода в рабочую среду будет меньше неожиданностей. Во многих случаях тесты можно запускать и в рабочей среде, чтобы предотвратить распространение неудачных обновлений на всю установку. Поскольку Ansible работает по модели отправки, шаги также очень легко выполнять на localhost или тестовых серверах. Ansible позволяет добавлять в процесс обновления столько проверок и предохранителей, сколько вам нужно.

Подходящий уровень тестирования

Ресурсы Ansible представляют собой модели желаемого состояния. Поэтому проверять, запущены ли службы, установлены ли пакеты и выполнены ли подобные действия, не требуется. Именно Ansible обеспечивает декларативное достижение этих состояний. Вместо этого задавайте такие требования в плейбуках.

tasks:
  - ansible.builtin.service:
      name: foo
      state: started
      enabled: true

Если вы считаете, что служба может быть не запущена, лучше всего задать требование запустить её. Если служба не запустится, Ansible сообщит об этом соответствующим образом. (Не следует путать это с проверкой того, выполняет ли служба какие-либо полезные функции; позже мы подробнее расскажем, как это проверить.)

Режим проверки как тест на отклонение от требуемого состояния

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

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

roles:
  - webserver

tasks:
  - ansible.builtin.script: verify.sh
    check_mode: false

Модули, полезные для тестирования

Некоторые модули плейбуков особенно удобны для тестирования. Ниже приведён пример проверки того, что порт открыт:

tasks:

  - ansible.builtin.wait_for:
      host: "{{ inventory_hostname }}"
      port: 22
    delegate_to: localhost

Вот пример использования модуля URI для проверки того, что веб-служба отвечает:

tasks:

  - action: uri url=https://www.example.com return_content=yes
    register: webpage

  - fail:
      msg: 'service is not happy'
    when: "'AWESOME' not in webpage.content"

На удалённый узел легко отправить произвольный скрипт (на любом языке); скрипт автоматически завершится с ошибкой, если вернёт ненулевой код:

tasks:

  - ansible.builtin.script: test_script1
  - ansible.builtin.script: test_script2 --parameter value --parameter2 value

Если вы используете роли (а вам стоит это делать — роли замечательны!), скрипты, отправляемые модулем script, могут храниться в каталоге ‘files/’ роли.

Модуль assert позволяет легко проверять различные условия:

tasks:

   - ansible.builtin.shell: /usr/bin/some-command --parameter value
     register: cmd_result

   - ansible.builtin.assert:
       that:
         - "'not ready' not in cmd_result.stderr"
         - "'gizmo enabled' in cmd_result.stdout"

Если вам нужно проверить наличие файлов, которые не задаются декларативно в конфигурации Ansible, модуль ‘stat’ станет отличным выбором:

tasks:

   - ansible.builtin.stat:
       path: /path/to/something
     register: p

   - ansible.builtin.assert:
       that:
         - p.stat.exists and p.stat.isdir

Как упоминалось выше, проверять коды возврата команд не нужно. Ansible проверяет их автоматически. Вместо проверки существования пользователя рассмотрите возможность создания пользователя с помощью модуля user.

Ansible — это система, которая быстро завершается при ошибках, поэтому при сбое создания пользователя выполнение плейбука остановится. Проверять результат дополнительно не нужно.

Жизненный цикл тестирования

Если добавить в плейбуки базовые проверки приложения, они будут выполняться при каждом развёртывании.

Таким образом, развёртывание в локальной виртуальной машине для разработки и в промежуточной среде позволит проверить соответствие запланированному до развёртывания в рабочей среде.

Ваш рабочий процесс может выглядеть примерно так:

- 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.

Если вы разрабатываете рабочий веб-сервис, команда контроля качества должна подготовить набор интеграционных тестов. Он может включать, например, тесты Selenium или автоматизированные тесты API; обычно такие тесты не встраивают в плейбуки Ansible.

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

Интеграция тестирования с последовательными обновлениями

Если вы ознакомились с разделом Управление местом выполнения задач: делегирование и локальные действия, то, вероятно, уже заметили, что шаблон последовательного обновления можно расширить: успешное или неудачное выполнение плейбука может определять, добавлять ли машину в пул балансировщика нагрузки.

Это позволяет в полной мере использовать встроенные тесты:

---

- hosts: webservers
  serial: 5

  pre_tasks:

    - name: take out of load balancer pool
      ansible.builtin.command: /usr/bin/take_out_of_pool {{ inventory_hostname }}
      delegate_to: 127.0.0.1

  tasks:

    - ansible.builtin.include_role:
        name: "{{ item }}"
      loop:
        - common
        - webserver

    - name: run any notified handlers
      ansible.builtin.meta: flush_handlers

    - name: test the configuration
      ansible.builtin.include_role:
        name: apply_testing_checks

  post_tasks:

    - name: add back to load balancer pool
      ansible.builtin.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
      ansible.builtin.command: /usr/bin/take_out_of_pool {{ inventory_hostname }}
      delegate_to: 127.0.0.1

  roles:

     - common
     - webserver

  tasks:
     - ansible.builtin.script: /srv/qa_team/app_testing_script.sh --server {{ inventory_hostname }}
       delegate_to: testing_server

  post_tasks:

    - name: add back to load balancer pool
      ansible.builtin.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 разработан как многоуровневая система оркестрации, поэтому тесты очень легко включить в завершение выполнения плейбука — в виде отдельных задач или ролей. При последовательных обновлениях результаты тестов могут определять, возвращать ли машину в пул балансировщика нагрузки.

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

Основное внимание следует уделять тестированию приложения, а не инфраструктуры. Поэтому мы настоятельно рекомендуем обсудить с командой контроля качества, какие тесты имеет смысл запускать при каждом развёртывании виртуальных машин для разработки и какие тесты следует выполнять в промежуточной среде при каждом развёртывании. На этапе разработки полезны и модульные тесты. Но не пишите модульные тесты для плейбука. Ansible декларативно описывает состояния ресурсов, поэтому в этом нет необходимости. Если же в каких-то случаях важно проверить определённое условие, это тоже хорошо: для таких целей отлично подходят модули stat и assert.

В целом тестирование во многом зависит от организации и особенностей конкретного сайта. Тестирование необходимо всем, но оптимальный подход для вашей среды зависит от того, что вы развёртываете и кто этим пользуется. При этом более надёжная и отказоустойчивая система развёртывания принесёт пользу каждому.

См. также

Указатель коллекций

Просмотр существующих коллекций, модулей и плагинов

Работа с плейбуками

Введение в плейбуки

Управление местом выполнения задач: делегирование и локальные действия

Делегирование, полезное при работе с балансировщиками нагрузки, облачными средами и локально выполняемыми шагами.

Общение

Есть вопросы? Нужна помощь? Хотите поделиться идеями? Посетите руководство Ansible по общению

© 2012–2018 Michael DeHaan
© 2018–2025 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/projects/ansible/latest/reference_appendices/test_strategies.html

Spec-Zone.ru

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