Spec-Zone.ru › Ansible

Обработка ошибок в playbook

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

  • Игнорирование неудачных команд
  • Игнорирование ошибок недоступных хостов
  • Сброс недоступных хостов
  • Обработчики и ошибки
  • Определение ошибки
  • Определение «изменено»
  • Обеспечение успеха для команд и оболочки
  • Прерывание выполнения playbook на всех хостах

    • Прерывание по первой ошибке: any_errors_fatal
    • Установка максимального процента ошибок
  • Управление ошибками в блоках

Игнорирование неудачных команд

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

- name: Do not count this as a failure
  ansible.builtin.command: /bin/false
  ignore_errors: true

Директива ignore_errors работает только тогда, когда задача может выполняться и возвращает значение «failed». Она не заставляет Ansible игнорировать ошибки неопределённой переменной, ошибки подключения, проблемы с выполнением (например, отсутствие пакетов) или синтаксические ошибки.

Игнорирование ошибок недоступных хостов

Введено в версии 2.7.

Вы можете проигнорировать ошибку задачи из-за того, что хост «НЕДОСТУПЕН», используя ключевое слово ignore_unreachable. Ansible игнорирует ошибки задачи, но продолжает выполнение последующих задач на недоступном хосте. Например, на уровне задачи:

- name: This executes, fails, and the failure is ignored
  ansible.builtin.command: /bin/true
  ignore_unreachable: true

- name: This executes, fails, and ends the play for this host
  ansible.builtin.command: /bin/true

И на уровне playbook:

- hosts: all
  ignore_unreachable: true
  tasks:
  - name: This executes, fails, and the failure is ignored
    ansible.builtin.command: /bin/true

  - name: This executes, fails, and ends the play for this host
    ansible.builtin.command: /bin/true
    ignore_unreachable: false

Сброс недоступных хостов

Если Ansible не может подключиться к хосту, он помечает этот хост как «НЕДОСТУПЕН» и удаляет его из списка активных хостов для выполнения. Вы можете использовать meta: clear_host_errors для повторной активации всех хостов, чтобы последующие задачи могли снова попытаться подключиться к ним.

Обработчики и ошибки

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

Вы можете изменить это поведение с помощью параметра командной строки --force-handlers, включив force_handlers: True в выполнение или добавив force_handlers = True в ansible.cfg. Принудительном запуске обработчиков Ansible запустит все уведомлённые обработчики на всех хостах, даже на хостах с неудачными задачами. (Обратите внимание, что некоторые ошибки всё ещё могут предотвратить запуск обработчика, например, если хост станет недоступным).

Определение ошибки

Ansible позволяет определить, что означает «ошибка» в каждой задаче, используя условное выражение failed_when. Как и со всеми условными выражениями в Ansible, списки из нескольких failed_when условий объединяются с неявным and, что означает, что задача завершается неудачно только тогда, когда все условия выполняются. Если вы хотите вызвать ошибку, когда выполняется любое из условий, вы должны определить условия в строке с явным оператором or.

Вы можете проверить ошибку, выискивая слово или фразу в выводе команды

- name: Fail task when the command error output prints FAILED
  ansible.builtin.command: /usr/bin/example-command -x -y -z
  register: command_result
  failed_when: "'FAILED' in command_result.stderr"

или на основе возвращаемого кода

- name: Fail task when both files are identical
  ansible.builtin.raw: diff foo/file1 bar/file2
  register: diff_cmd
  failed_when: diff_cmd.rc == 0 or diff_cmd.rc >= 2

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

- name: Check if a file exists in temp and fail task if it does
  ansible.builtin.command: ls /tmp/this_should_not_be_here
  register: result
  failed_when:
    - result.rc == 0
    - '"No such" not in result.stderr'

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

failed_when: result.rc == 0 or "No such" not in result.stderr

Если у вас слишком много условий для одной строки, вы можете разбить их на несколько строк в значении YAML с >.

- name: example of many failed_when conditions with OR
  ansible.builtin.shell: "./myBinary"
  register: ret
  failed_when: >
    ("No such file or directory" in ret.stdout) or
    (ret.stderr != '') or
    (ret.rc == 10)

Определение «изменено»

Ansible позволяет определить, когда конкретная задача «изменила» удалённый узел, используя условное выражение changed_when. Это позволяет определить, на основе возвращаемых кодов или вывода, нужно ли сообщать об изменении в статистике Ansible и нужно ли запускать обработчик или нет. Как и со всеми условными выражениями в Ansible, списки из нескольких changed_when условий объединяются с неявным and, что означает, что задача сообщает об изменении только тогда, когда все условия выполнены. Если вы хотите сообщить об изменении, когда выполняется любое из условий, вы должны определить условия в строке с явным оператором or. Например:

tasks:

  - name: Report 'changed' when the return code is not equal to 2
    ansible.builtin.shell: /usr/bin/billybass --mode="take me to the river"
    register: bass_result
    changed_when: "bass_result.rc != 2"

  - name: This will never report 'changed' status
    ansible.builtin.shell: wall 'beep'
    changed_when: False

  - name: This task will always report 'changed' status
    ansible.builtin.command: /path/to/command
    changed_when: True

Вы также можете комбинировать несколько условий для переопределения результата «изменено».

- name: Combine multiple conditions to override 'changed' result
  ansible.builtin.command: /bin/fake_command
  register: result
  ignore_errors: True
  changed_when:
    - '"ERROR" in result.stderr'
    - result.rc == 2

Примечание

Так же, как when эти два условных выражения не требуют разделителей шаблонов ({{ }}). , так как они подразумеваются.

См. Определение ошибки для дополнительных примеров синтаксиса условных выражений.

Обеспечение успеха для команд и оболочки

Модули command и shell учитывают возвращаемые коды, поэтому, если у вас есть команда, для успешного выхода которой нужен не ноль, вы можете сделать так:

tasks:
  - name: Run this command and ignore the result
    ansible.builtin.shell: /usr/bin/somecommand || /bin/true

Прерывание выполнения playbook на всех хостах

Иногда вы хотите, чтобы ошибка на одном хосте или ошибки на определённом проценте хостов прервали всё выполнение playbook на всех хостах. Вы можете остановить выполнение playbook после первой ошибки с помощью any_errors_fatal. Для более точного управления вы можете использовать max_fail_percentage для прерывания выполнения после достижения заданного процента ошибок.

Прерывание по первой ошибке: any_errors_fatal

Если вы установите any_errors_fatal и задача возвращает ошибку, Ansible завершит задачу fatal на всех хостах в текущей группе, а затем прекратит выполнение playbook на всех хостах. Последующие задачи и playbooks не будут выполнены. Вы можете восстановиться после ошибок fatal, добавив блок обработки ошибок в блок. Вы можете установить any_errors_fatal на уровне playbook или блока.

- hosts: somehosts
  any_errors_fatal: true
  roles:
    - myrole

- hosts: somehosts
  tasks:
    - block:
        - include_tasks: mytasks.yml
      any_errors_fatal: true

Вы можете использовать эту функцию, когда все задачи должны быть на 100% успешными для продолжения выполнения playbook. Например, если вы запускаете службу на машинах в нескольких центрах обработки данных с балансировщиками нагрузки для передачи трафика пользователей в службу, вы хотите, чтобы все балансировщики нагрузки были отключены до того, как вы остановите службу на техническое обслуживание. Чтобы гарантировать, что любая ошибка в задаче, которая отключает балансировщики нагрузки, остановит все другие задачи:

---
- hosts: load_balancers_dc_a
  any_errors_fatal: true

  tasks:
    - name: Shut down datacenter 'A'
      ansible.builtin.command: /usr/bin/disable-dc

- hosts: frontends_dc_a

  tasks:
    - name: Stop service
      ansible.builtin.command: /usr/bin/stop-software

    - name: Update software
      ansible.builtin.command: /usr/bin/upgrade-software

- hosts: load_balancers_dc_a

  tasks:
    - name: Start datacenter 'A'
      ansible.builtin.command: /usr/bin/enable-dc

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

Установка максимального процента ошибок

По умолчанию Ansible продолжает выполнение задач, пока есть хосты, которые ещё не завершились ошибкой. В некоторых ситуациях, таких как при выполнении rolling update, вы можете захотеть прервать выполнение playbook, когда будет достигнут определённый порог ошибок. Для этого вы можете установить максимальный процент ошибок в play:

---
- hosts: webservers
  max_fail_percentage: 30
  serial: 10

Настройка max_fail_percentage применяется к каждой группе, когда вы используете её с serial. В приведённом выше примере, если более 3 из 10 серверов в первой (или любой) группе серверов завершились ошибкой, остальная часть выполнения playbook прерывается.

Примечание

Процент должен быть превышен, а не равен. Например, если serial был установлен на 4, а вы хотели, чтобы задача прервала выполнение playbook, когда 2 системы завершились ошибкой, установите max_fail_percentage на 49, а не на 50.

Управление ошибками в блоках

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

См. также

Ansible playbooks

Введение в playbook

Общие советы

Советы и рекомендации по playbooks

Условные выражения

Условные операторы в playbooks

Использование переменных

Все о переменных

Связь

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

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

Spec-Zone.ru

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