Spec-Zone.ru › Ansible 2.11

Обработка ошибок в плейбуках

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

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

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

Игнорирование ошибок команд

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

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

Директива 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: yes

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

И на уровне плейбука:

- hosts: all
  ignore_unreachable: yes
  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: no

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

Если 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.stdout'

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

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

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

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

- 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

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

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

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

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

Прерывание плейбука на всех хостах

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

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

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

- hosts: somehosts
  any_errors_fatal: true
  roles:
    - myrole

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

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

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

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

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

Примечание

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

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

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

См. также

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

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

Советы и хитрости

Советы и хитрости для плейбуков

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

Условные операторы в плейбуках

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

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

Список рассылки пользователей

Есть вопрос? Заходите на форум!

irc.freenode.net

Канал IRC-чата #ansible

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

Spec-Zone.ru

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