Как я могу показать прогресс для долговременной задачи Ansible?
У меня есть некоторые Ansible задачи, которые выполняют, к сожалению, длительные операции - например, выполнение операции синхронизации с папкой S3. Это не всегда ясно, если они прогрессируют или просто застревают (или сбой ssh), так что было бы неплохо отобразить какой-то прогресс. Если команда stdout/stderr была непосредственно отображена, я бы это увидел, но Ansible захватил вывод.
Выход на трубопровод назад является трудной проблемой для решения Ansible в ее текущей форме. Но есть ли какие-либо Ansible трюки, которые я могу использовать, чтобы дать какое-то указание на то, что вещи все еще движутся?
Текущий билет https://github.com/ansible/ansible/issues/4870
Ответы
Ответ 1
Сегодня я столкнулся с этой проблемой на OSX, где я запускал команду оболочки докеров, которая занимала много времени, и не было никакого выхода во время ее создания. Было очень неприятно не понимать, была ли команда висела или просто прогрессировала медленно.
Я решил передать вывод (и ошибку) команды оболочки на порт, который затем можно было бы прослушать через netcat в отдельном терминале.
myplaybook.yml
- name: run some long-running task and pipe to a port
shell: myLongRunningApp > /dev/tcp/localhost/4000 2>&1
И в отдельном окне терминала:
$ nc -lk 4000
Output from my
long
running
app will appear here
Обратите внимание, что я передаю вывод ошибки в тот же порт; Я мог бы легко подключиться к другому порту.
Кроме того, я установил переменную с именем nc_port
, которая позволит изменить порт в случае использования порта. Последовательная задача выглядит следующим образом:
shell: myLongRunningApp > /dev/tcp/localhost/{{nc_port}} 2>&1
Обратите внимание, что команда myLongRunningApp
выполняется на локальном хосте (т.е. что узел установлен в инвентаре), поэтому я слушаю localhost с помощью nc
.
Ответ 2
Есть несколько вещей, которые вы можете сделать, но, как вы правильно указали, Ansible в своей нынешней форме действительно не предлагает хорошего решения.
Официальные решения:
Одна идея - отметить задачу как асинхронную и опросить ее. Очевидно, что это подходит только в том случае, если он способен работать таким образом, не вызывая сбоев в другом месте в вашем плейбуке. Асинхронные документы здесь, и вот пример, снятый с них:
- hosts: all
remote_user: root
tasks:
- name: simulate long running op (15 sec), wait for up to 45 sec, poll every 5 sec
command: /bin/sleep 15
async: 45
poll: 5
Это может по крайней мере дать вам "ping", чтобы знать, что задача не висит.
Единственным другим официально одобренным методом будет Ansible Tower, у которого есть индикаторы выполнения задач, но не являются бесплатными.
Хакки-иш-решения:
Помимо вышеизложенного, вам в значительной степени придется сворачивать самостоятельно. Ваш конкретный пример синхронизации ведра S3 можно довольно легко контролировать с помощью script, периодически вызывающего CLI AWS и подсчета количества элементов в ведре, но это вряд ли хорошее, общее решение.
Единственное, что я мог представить, будучи несколько эффективным, - это наблюдать за входящей сессией ssh с одного из ваших узлов.
Для этого вы можете настроить доступного пользователя на этом компьютере для подключения через экран и активно наблюдать за ним. Альтернативно, возможно, используя параметр log_output
в записи sudoers для этого пользователя, что позволяет вам зачеркнуть файл. Подробные сведения о log_output можно найти на странице sudoers man
Ответ 3
Если вы работаете в Linux, вы можете использовать systemd-run
для создания временного модуля и проверки вывода с помощью journalctl
, например:
sudo systemd-run --unit foo \
bash -c 'for i in {0..10}; do
echo "$((i * 10))%"; sleep 1;
done;
echo "Complete"'
И в другой сессии
sudo journalctl -xf --unit foo
Это вывело бы что-то вроде:
Apr 07 02:10:34 localhost.localdomain systemd[1]: Started /bin/bash -c for i in {0..10}; do echo "$((i * 10))%"; sleep 1; done; echo "Complete".
-- Subject: Unit foo.service has finished start-up
-- Defined-By: systemd
-- Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
-- Unit foo.service has finished starting up.
--
-- The start-up result is done.
Apr 07 02:10:34 localhost.localdomain bash[10083]: 0%
Apr 07 02:10:35 localhost.localdomain bash[10083]: 10%
Apr 07 02:10:36 localhost.localdomain bash[10083]: 20%
Apr 07 02:10:37 localhost.localdomain bash[10083]: 30%
Apr 07 02:10:38 localhost.localdomain bash[10083]: 40%
Apr 07 02:10:39 localhost.localdomain bash[10083]: 50%
Apr 07 02:10:40 localhost.localdomain bash[10083]: 60%
Apr 07 02:10:41 localhost.localdomain bash[10083]: 70%
Apr 07 02:10:42 localhost.localdomain bash[10083]: 80%
Apr 07 02:10:43 localhost.localdomain bash[10083]: 90%
Apr 07 02:10:44 localhost.localdomain bash[10083]: 100%
Apr 07 02:10:45 localhost.localdomain bash[10083]: Complete
Ответ 4
С тех пор Ansible реализовал следующее:
---
# Requires ansible 1.8+
- name: 'YUM - async task'
yum:
name: docker-io
state: installed
async: 1000
poll: 0
register: yum_sleeper
- name: 'YUM - check on async task'
async_status:
jid: "{{ yum_sleeper.ansible_job_id }}"
register: job_result
until: job_result.finished
retries: 30