Короткий ответ
Нужно смотреть вывод ansible-playbook с -v: для каждой итерации цикла Ansible печатает результат с ключом item, что сразу показывает, на каком элементе списка и на каком хосте произошёл сбой; чтобы ошибка на одном хосте не останавливала выполнение задачи на остальных хостах, используется ignore_errors: true в сочетании с явной проверкой результата (register + последующий when: result is failed) или стратегия free вместо linear, а для одного «плохого» элемента внутри списка — loop_control: { label: "{{ item }}" } для читаемости и, при необходимости, отдельная задача-обработчик неудачных элементов.
Как это работает подробнее
при linear strategy (дефолтной) Ansible выполняет задачу на всех хостах пакетного батча параллельно, но следующая задача не начнётся, пока предыдущая не завершится на всех хостах; при ошибке без ignore_errors хост, на котором она произошла, исключается из дальнейшего выполнения плейбука (хотя другие хосты батча продолжают текущую задачу), а loop внутри задачи выполняется последовательно по списку элементов для данного хоста, и по умолчанию падение на одном элементе останавливает весь loop для этого хоста.
Пример кода
- name: Install optional packages
ansible.builtin.package:
name: "{{ item }}"
state: present
loop: "{{ packages_to_install }}"
loop_control:
label: "{{ item }}"
register: pkg_result
ignore_errors: true
when: ansible_facts['os_family'] == 'Debian'
- name: Report failed packages
ansible.builtin.debug:
msg: "Package {{ item.item }} failed on {{ inventory_hostname }}"
loop: "{{ pkg_result.results }}"
when: item is failedЧто использовать на практике
- Практика. для некритичных элементов списка (например, опциональный инструмент, который есть не во всех репозиториях) стоит явно обрабатывать ожидаемые сбои через
ignore_errors: true+register+ отдельный шаг логирования/уведомления, а не глушить все ошибки одинаково; для диагностики на проде полезно сразу прогонять с--limitна упавшем хосте и-vvv, чтобы увидеть точную командуapt/yum, которая не сработала.
Подводные камни
- Ошибка. частая ошибка — ставить
ignore_errors: trueна весь плейбук или на все задачи подряд «чтобы не падало», из-за чего реальные критичные сбои (например, недоступность сети) тоже тихо игнорируются; другая ошибка — не использоватьloop_control: label, из-за чего в длинном списке переменных сложного типа (словари) вывод ошибки превращается в нечитаемую стену текста без понимания, какой именно элемент сломался.