← Назад к вопросам

Как обработать отказ операции в Ansible playbook

2.0 Middle🔥 181 комментариев
#Ansible и управление конфигурацией

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Обработка сбоев в Ansible Playbook

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

Базовые директивы управления ошибками

Основные инструменты располагаются на уровне задачи (task):

- name: Пытаемся перезапустить нестабильную службу
  ansible.builtin.service:
    name: my_app
    state: restarted
  ignore_errors: yes           # Игнорирует любую ошибку, play продолжается
  register: restart_result     # Результат всё равно регистрируется

- name: Пытаемся установить пакет с продолжением при неудаче
  ansible.builtin.apt:
    name: "{{ item }}"
    state: present
  loop: [ "nginx", "postfix", "unknown_package" ]
  ignore_errors: yes           # Позволяет продолжить цикл после ошибки

Более гранулированный подход — использование failed_when для определения кастомных условий сбоя:

- name: Проверка доступности порта (ожидаем временную недоступность)
  ansible.builtin.wait_for:
    port: 8080
    timeout: 5
  register: port_check
  failed_when: 
    - port_check.failed
    - "'Connection refused' not in port_check.msg"  # Сбой только если ошибка НЕ 'Connection refused'
  # Здесь play продолжится, если ошибка именно "Connection refused"

Расширенная обработка с блоком rescue

Структура block-rescue-always (аналогия try-catch-finally) — наиболее мощный инструмент:

- block:
    - name: Основная операция  развертывание новой версии
      ansible.builtin.command: /opt/deploy.sh --version 2.0

    - name: Проверка работоспособности после деплоя
      ansible.builtin.uri:
        url: http://localhost/health
        status_code: 200

  rescue:
    - name: Оповещение о сбое деплоя
      ansible.builtin.slack:
        token: "{{ slack_token }}"
        msg: "Сбой деплоя на {{ inventory_hostname }}"

    - name: Откат к предыдущей версии
      ansible.builtin.command: /opt/rollback.sh --to-version 1.5
      
    - name: Явное указание, что блок завершился с ошибкой после отката
      meta: end_play  # или fail, чтобы остановить play с ошибкой

  always:
    - name: Всегда очищаем временные файлы
      ansible.builtin.file:
        path: /tmp/deploy_cache
        state: absent

Стратегии выполнения и обработка на уровне Playbook

Глобальное поведение контролируется директивой strategy и настройками:

- hosts: all
  strategy: linear  # По умолчанию. Останавливает выполнение на хосте при ошибке.
  max_fail_percentage: 30  # Допускает сбой на 30% хостов до остановки всего play
  force_handlers: yes      # Запускает handlers даже при сбое

  tasks:
    - name: Критическая задача, которая должна прервать выполнение
      ansible.builtin.service:
        name: db
        state: started
      ignore_errors: no  # Значение по умолчанию

    - name: Проверка нескольких условий с помощью assert
      ansible.builtin.assert:
        that:
          - available_memory_mb > 512
          - "/opt" in ansible_mounts | map(attribute="mount") | list
        fail_msg: "Система не соответствует минимальным требованиям"
        success_msg: "Проверка ресурсов пройдена"

Управление сбоями в циклах и делегировании

- name: Обновление списка серверов с обработкой временных сетевых сбоев
  ansible.builtin.apt:
    name: security_updates
    state: present
  delegate_to: "{{ item }}"
  loop: "{{ lb_servers }}"
  loop_control:
    loop_var: backend_server
    label: "{{ backend_server }}"
  retries: 3                    # Попытки повтора
  delay: 10                     # Пауза между попытками
  until: backend_server is succeeded  # Условие успеха для retries
  ignore_errors: yes            # Продолжить обновление других серверов при сбое
  when: backend_server in groups['production']  # Условное выполнение

Практические рекомендации

  • Логирование и отладка: Всегда регистрируйте результат задач (register) для последующего анализа
  • Гранулярность: Используйте failed_when для точного определения, что считать сбоем в контексте вашей задачи
  • Откаты: Для идемпотентных операций часто достаточно повторного запуска, но для деплоя приложений реализуйте явный механизм отката
  • Уведомления: Интегрируйте оповещения в блок rescue для оперативного реагирования
  • Тестирование: Специально тестируйте сценарии сбоев, используя модули fail или debug для их симуляции

Правильная обработка ошибок превращает Ansible playbook из простого скрипта развертывания в надежный производственный инструмент, способный корректно работать в неидеальных условиях реальной инфраструктуры. Ключ — баланс между автоматическим продолжением (когда это безопасно) и контролируемой остановкой (когда требуется вмешательство).