Введение
Ansible – это широко используемый инструмент автоматизации IT, упрощающий управление сложной инфраструктурой и развертыванием приложений. В этом руководстве мы рассмотрим, как захватывать вывод скриптов, выполняемых через плейбуки Ansible. Эта возможность необходима для мониторинга, отладки и анализа результатов ваших задач автоматизации. К концу этой лабораторной работы вы поймете различные методы захвата и использования вывода скриптов в ваших рабочих процессах Ansible.
Настройка среды Ansible
Прежде чем мы сможем начать захватывать вывод скриптов с помощью Ansible, нам необходимо настроить базовую среду Ansible. Это включает в себя создание необходимой структуры каталогов и файлов конфигурации.
Основы Ansible
Ansible работает, подключаясь к целевым хостам и отправляя небольшие программы, называемые модулями. Эти модули выполняются на целевых хостах и удаляются после завершения. Ansible не требует агентов (agent-less), что означает, что вам не нужно устанавливать какое-либо специальное программное обеспечение на управляемых узлах.
Давайте начнем с создания каталога проекта и необходимых файлов Ansible:
mkdir -p ~/project/ansible-output-demo/scripts
cd ~/project/ansible-output-demo
Теперь давайте создадим простой файл инвентаризации. В Ansible файл инвентаризации определяет хосты и группы хостов, на которых выполняются команды, модули и задачи в плейбуке.
Создайте файл инвентаризации, используя редактор кода:
- Нажмите на меню "File" в верхнем левом углу IDE
- Выберите "New File"
- Сохраните его как
inventoryв каталоге~/project/ansible-output-demo
Добавьте следующее содержимое в файл inventory:
[local]
localhost ansible_connection=local
Этот файл инвентаризации указывает, что мы будем запускать Ansible на локальной машине.
Далее давайте создадим простой скрипт, который будет генерировать некоторый вывод для захвата. Этот скрипт:
- Выведет некоторую информацию о системе
- Сгенерирует стандартный вывод
- Сгенерирует стандартный вывод об ошибках
Создайте новый файл в каталоге scripts с именем info.sh:
- Нажмите на меню "File"
- Выберите "New File"
- Сохраните его как
scripts/info.shв каталоге~/project/ansible-output-demo
Добавьте следующее содержимое в файл info.sh:
#!/bin/bash
## Print system information
echo "=== System Information ==="
echo "Hostname: $(hostname)"
echo "Date: $(date)"
echo "Kernel: $(uname -r)"
echo "Memory:"
free -h
## Generate some standard output
echo "=== Standard Output ==="
echo "This is standard output"
echo "Hello from the script!"
## Generate some standard error
echo "=== Standard Error ===" >&2
echo "This is standard error" >&2
echo "An example error message" >&2
## Exit with a specific code
exit 0
Теперь давайте сделаем скрипт исполняемым:
chmod +x ~/project/ansible-output-demo/scripts/info.sh
Давайте запустим скрипт напрямую, чтобы увидеть, какой вывод он производит:
~/project/ansible-output-demo/scripts/info.sh
Вы должны увидеть вывод, содержащий информацию о системе, сообщения стандартного вывода и сообщения об ошибках.
Теперь у нас настроена базовая среда. На следующем шаге мы создадим плейбук Ansible для выполнения этого скрипта и захвата его вывода.
Базовый захват вывода с помощью Ansible
Теперь, когда мы настроили нашу среду, давайте создадим простой плейбук Ansible, который выполняет наш скрипт и захватывает его вывод.
Создание базового плейбука
В Ansible плейбуки – это YAML-файлы, которые определяют набор задач для выполнения на удаленных хостах. Давайте создадим плейбук, который запускает наш скрипт info.sh и захватывает его вывод, используя ключевое слово register.
Создайте новый файл с именем capture_output.yml в каталоге ~/project/ansible-output-demo:
- Нажмите на меню "File"
- Выберите "New File"
- Сохраните его как
capture_output.ymlв каталоге~/project/ansible-output-demo
Добавьте следующее содержимое в файл capture_output.yml:
---
- name: Capture Script Output
hosts: local
gather_facts: no
tasks:
- name: Execute the info.sh script
command: "{{ playbook_dir }}/scripts/info.sh"
register: script_output
- name: Display the script output
debug:
var: script_output.stdout
Давайте рассмотрим этот плейбук:
- Плейбук нацелен на группу
local, определенную в нашей инвентаризации. - Первая задача выполняет наш скрипт
info.shс помощью модуляcommand. - Ключевое слово
registerсохраняет вывод команды в переменную с именемscript_output. - Вторая задача использует модуль
debugдля отображения стандартного вывода (stdout) скрипта.
Запуск плейбука
Теперь давайте запустим плейбук, чтобы увидеть, как он захватывает и отображает вывод скрипта:
cd ~/project/ansible-output-demo
ansible-playbook -i inventory capture_output.yml
Вы должны увидеть вывод, похожий на следующий:
PLAY [Capture Script Output] *******************************************
TASK [Execute the info.sh script] **************************************
changed: [localhost]
TASK [Display the script output] ***************************************
ok: [localhost] => {
"script_output.stdout": "=== System Information ===\nHostname: ubuntu\nDate: Tue Oct 17 12:34:56 UTC 2023\nKernel: 5.15.0-1031-aws\nMemory:\n total used free shared buff/cache available\nMem: 7.7Gi 1.2Gi 5.2Gi 12Mi 1.3Gi 6.3Gi\nSwap: 0B 0B 0B\n=== Standard Output ===\nThis is standard output\nHello from the script!"
}
PLAY RECAP ************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Обратите внимание, что отображается только стандартный вывод. Стандартный вывод ошибок (stderr) не отображается, потому что мы попросили отобразить только script_output.stdout.
Улучшение читаемости вывода
Вывод немного сложно читать как одну строку. Давайте изменим наш плейбук, чтобы отображать вывод в более читаемом формате, используя атрибут stdout_lines, который представляет вывод в виде списка строк.
Отредактируйте файл capture_output.yml и измените вторую задачу следующим образом:
- name: Display the script output
debug:
var: script_output.stdout_lines
Запустите плейбук снова:
ansible-playbook -i inventory capture_output.yml
Теперь вывод должен быть более читаемым, с каждой строкой, отображаемой отдельно:
TASK [Display the script output] ***************************************
ok: [localhost] => {
"script_output.stdout_lines": [
"=== System Information ===",
"Hostname: ubuntu",
"Date: Tue Oct 17 12:34:56 UTC 2023",
"Kernel: 5.15.0-1031-aws",
"Memory:",
" total used free shared buff/cache available",
"Mem: 7.7Gi 1.2Gi 5.2Gi 12Mi 1.3Gi 6.3Gi",
"Swap: 0B 0B 0B",
"=== Standard Output ===",
"This is standard output",
"Hello from the script!"
]
}
Этот формат делает вывод намного проще для чтения и работы с ним. На следующем шаге мы рассмотрим, как захватывать и отображать различные типы вывода.
Захват различных типов вывода
На предыдущем шаге мы захватили и отобразили стандартный вывод нашего скрипта. Однако при выполнении скриптов существует несколько типов вывода, которые мы можем захотеть захватить:
- Стандартный вывод (stdout): Обычный вывод скрипта
- Стандартный вывод ошибок (stderr): Сообщения об ошибках и предупреждения
- Код возврата (rc): Статус завершения скрипта (0 обычно означает успех, ненулевые значения указывают на ошибки)
Давайте создадим новый плейбук, который захватывает и отображает все три типа вывода.
Создайте новый файл с именем capture_all_output.yml в каталоге ~/project/ansible-output-demo:
- Нажмите на меню "File"
- Выберите "New File"
- Сохраните его как
capture_all_output.ymlв каталоге~/project/ansible-output-demo
Добавьте следующее содержимое в файл capture_all_output.yml:
---
- name: Capture All Types of Script Output
hosts: local
gather_facts: no
tasks:
- name: Execute the info.sh script
command: "{{ playbook_dir }}/scripts/info.sh"
register: script_output
- name: Display standard output
debug:
msg: "Standard Output (stdout):"
- name: Display stdout content
debug:
var: script_output.stdout_lines
- name: Display standard error
debug:
msg: "Standard Error (stderr):"
- name: Display stderr content
debug:
var: script_output.stderr_lines
- name: Display return code
debug:
msg: "Return Code: {{ script_output.rc }}"
Этот плейбук выполняет наш скрипт, а затем отображает:
- Стандартный вывод с использованием
script_output.stdout_lines - Стандартный вывод ошибок с использованием
script_output.stderr_lines - Код возврата с использованием
script_output.rc
Запуск улучшенного плейбука
Давайте запустим наш новый плейбук:
cd ~/project/ansible-output-demo
ansible-playbook -i inventory capture_all_output.yml
Вы должны увидеть все три типа вывода:
PLAY [Capture All Types of Script Output] *****************************
TASK [Execute the info.sh script] *************************************
changed: [localhost]
TASK [Display standard output] ****************************************
ok: [localhost] => {
"msg": "Standard Output (stdout):"
}
TASK [Display stdout content] *****************************************
ok: [localhost] => {
"script_output.stdout_lines": [
"=== System Information ===",
"Hostname: ubuntu",
"Date: Tue Oct 17 12:40:22 UTC 2023",
"Kernel: 5.15.0-1031-aws",
"Memory:",
" total used free shared buff/cache available",
"Mem: 7.7Gi 1.2Gi 5.2Gi 12Mi 1.3Gi 6.3Gi",
"Swap: 0B 0B 0B",
"=== Standard Output ===",
"This is standard output",
"Hello from the script!"
]
}
TASK [Display standard error] *****************************************
ok: [localhost] => {
"msg": "Standard Error (stderr):"
}
TASK [Display stderr content] *****************************************
ok: [localhost] => {
"script_output.stderr_lines": [
"=== Standard Error ===",
"This is standard error",
"An example error message"
]
}
TASK [Display return code] ********************************************
ok: [localhost] => {
"msg": "Return Code: 0"
}
PLAY RECAP **********************************************************
localhost : ok=6 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Теперь мы можем видеть все типы вывода из нашего скрипта:
- Стандартный вывод показывает информацию о системе и наши обычные сообщения
- Стандартный вывод ошибок показывает наши сообщения об ошибках
- Код возврата равен 0, что указывает на успешное выполнение
Создание скрипта с ошибками
Давайте создадим скрипт, который будет выдавать ошибку и возвращать ненулевой код выхода, чтобы увидеть, как Ansible обрабатывает это.
Создайте новый файл с именем error.sh в каталоге scripts:
- Нажмите на меню "File"
- Выберите "New File"
- Сохраните его как
scripts/error.shв каталоге~/project/ansible-output-demo
Добавьте следующее содержимое в файл error.sh:
#!/bin/bash
## Print some standard output
echo "Starting error demonstration script"
echo "This will appear in stdout"
## Print some standard error
echo "This will appear in stderr" >&2
echo "Error: Something went wrong!" >&2
## Exit with a non-zero code to indicate error
exit 1
Сделайте скрипт исполняемым:
chmod +x ~/project/ansible-output-demo/scripts/error.sh
Теперь давайте создадим плейбук для выполнения этого скрипта и обработки ошибки. Создайте новый файл с именем handle_errors.yml:
- Нажмите на меню "File"
- Выберите "New File"
- Сохраните его как
handle_errors.ymlв каталоге~/project/ansible-output-demo
Добавьте следующее содержимое в файл handle_errors.yml:
---
- name: Handle Script Errors
hosts: local
gather_facts: no
tasks:
- name: Execute the error script
command: "{{ playbook_dir }}/scripts/error.sh"
register: script_output
ignore_errors: yes
- name: Display standard output
debug:
var: script_output.stdout_lines
- name: Display standard error
debug:
var: script_output.stderr_lines
- name: Display return code
debug:
msg: "Return Code: {{ script_output.rc }}"
- name: Check if script failed
debug:
msg: "The script failed with return code {{ script_output.rc }}"
when: script_output.rc != 0
Обратите внимание на добавление ignore_errors: yes, которое указывает Ansible продолжать выполнение плейбука, даже если команда завершится неудачно (вернет ненулевой код выхода).
Давайте запустим этот плейбук:
ansible-playbook -i inventory handle_errors.yml
Вы должны увидеть вывод, похожий на следующий:
PLAY [Handle Script Errors] *******************************************
TASK [Execute the error script] ***************************************
changed: [localhost]
TASK [Display standard output] ****************************************
ok: [localhost] => {
"script_output.stdout_lines": [
"Starting error demonstration script",
"This will appear in stdout"
]
}
TASK [Display standard error] *****************************************
ok: [localhost] => {
"script_output.stderr_lines": [
"This will appear in stderr",
"Error: Something went wrong!"
]
}
TASK [Display return code] ********************************************
ok: [localhost] => {
"msg": "Return Code: 1"
}
TASK [Check if script failed] *****************************************
ok: [localhost] => {
"msg": "The script failed with return code 1"
}
PLAY RECAP **********************************************************
localhost : ok=5 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Этот пример демонстрирует, как:
- Захватывать вывод из скрипта, который выдает ошибку
- Продолжать выполнение плейбука, несмотря на ошибку
- Условно выполнять задачи на основе кода возврата скрипта
На следующем шаге мы рассмотрим более продвинутые варианты использования и лучшие практики работы с выводом скриптов в Ansible.
Расширенная обработка вывода и практические примеры использования
Теперь, когда мы понимаем, как захватывать различные типы вывода, давайте рассмотрим некоторые более продвинутые методы обработки и использования вывода скриптов в Ansible.
Разбор вывода с помощью фильтров
Ansible предоставляет различные фильтры, которые позволяют вам манипулировать и извлекать конкретную информацию из вывода скриптов. В этом разделе мы рассмотрим некоторые распространенные методы фильтрации.
Создайте новый файл с именем parse_output.yml в каталоге ~/project/ansible-output-demo:
- Нажмите на меню "File"
- Выберите "New File"
- Сохраните его как
parse_output.ymlв каталоге~/project/ansible-output-demo
Сначала давайте создадим скрипт, который генерирует структурированный вывод, который мы сможем разобрать. Создайте новый файл с именем system_stats.sh:
- Нажмите на меню "File"
- Выберите "New File"
- Сохраните его как
scripts/system_stats.shв каталоге~/project/ansible-output-demo
Добавьте следующее содержимое в файл system_stats.sh:
#!/bin/bash
## Display CPU info
echo "CPU_MODEL: $(grep 'model name' /proc/cpuinfo | head -1 | cut -d ':' -f2 | xargs)"
echo "CPU_CORES: $(grep -c 'processor' /proc/cpuinfo)"
## Display memory info in GB
mem_total=$(free -g | grep Mem | awk '{print $2}')
echo "MEMORY_GB: $mem_total"
## Display disk usage
disk_usage=$(df -h / | tail -1 | awk '{print $5}' | tr -d '%')
echo "DISK_USAGE_PCT: $disk_usage"
## Display load average
load_avg=$(uptime | awk -F'load average: ' '{print $2}' | cut -d, -f1)
echo "LOAD_AVG: $load_avg"
exit 0
Сделайте скрипт исполняемым:
chmod +x ~/project/ansible-output-demo/scripts/system_stats.sh
Теперь давайте создадим плейбук, который выполняет этот скрипт, захватывает его вывод и разбирает его для извлечения конкретной информации:
Добавьте следующее содержимое в файл parse_output.yml:
---
- name: Parse Script Output
hosts: local
gather_facts: no
tasks:
- name: Execute the system_stats.sh script
command: "{{ playbook_dir }}/scripts/system_stats.sh"
register: stats_output
- name: Display raw output
debug:
var: stats_output.stdout_lines
- name: Parse CPU model
set_fact:
cpu_model: "{{ stats_output.stdout | regex_search('CPU_MODEL: (.+)', '\\1') | first }}"
- name: Parse CPU cores
set_fact:
cpu_cores: "{{ stats_output.stdout | regex_search('CPU_CORES: (\\d+)', '\\1') | first }}"
- name: Parse memory
set_fact:
memory_gb: "{{ stats_output.stdout | regex_search('MEMORY_GB: (\\d+)', '\\1') | first }}"
- name: Parse disk usage
set_fact:
disk_usage: "{{ stats_output.stdout | regex_search('DISK_USAGE_PCT: (\\d+)', '\\1') | first }}"
- name: Parse load average
set_fact:
load_avg: "{{ stats_output.stdout | regex_search('LOAD_AVG: ([0-9.]+)', '\\1') | first }}"
- name: Display parsed information
debug:
msg: |
Parsed system information:
- CPU Model: {{ cpu_model }}
- CPU Cores: {{ cpu_cores }}
- Memory (GB): {{ memory_gb }}
- Disk Usage (%): {{ disk_usage }}
- Load Average: {{ load_avg }}
Этот плейбук:
- Выполняет наш скрипт
system_stats.sh - Отображает необработанный вывод
- Использует фильтр
regex_searchдля извлечения конкретных фрагментов информации из вывода - Сохраняет извлеченную информацию в переменные
- Отображает разобранную информацию в структурированном формате
Давайте запустим этот плейбук:
cd ~/project/ansible-output-demo
ansible-playbook -i inventory parse_output.yml
Вы должны увидеть вывод, похожий на следующий:
PLAY [Parse Script Output] ********************************************
TASK [Execute the system_stats.sh script] *****************************
changed: [localhost]
TASK [Display raw output] *********************************************
ok: [localhost] => {
"stats_output.stdout_lines": [
"CPU_MODEL: Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz",
"CPU_CORES: 2",
"MEMORY_GB: 7",
"DISK_USAGE_PCT: 58",
"LOAD_AVG: 0.08"
]
}
TASK [Parse CPU model] ************************************************
ok: [localhost]
TASK [Parse CPU cores] ************************************************
ok: [localhost]
TASK [Parse memory] ***************************************************
ok: [localhost]
TASK [Parse disk usage] ***********************************************
ok: [localhost]
TASK [Parse load average] *********************************************
ok: [localhost]
TASK [Display parsed information] *************************************
ok: [localhost] => {
"msg": "Parsed system information:\n- CPU Model: Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz\n- CPU Cores: 2\n- Memory (GB): 7\n- Disk Usage (%): 58\n- Load Average: 0.08"
}
PLAY RECAP ***********************************************************
localhost : ok=8 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Принятие решений на основе вывода
Одним из самых мощных аспектов захвата вывода скриптов является его использование для принятия решений в ваших плейбуках Ansible. Давайте создадим плейбук, который демонстрирует условное выполнение на основе вывода скрипта.
Создайте новый файл с именем conditional_actions.yml в каталоге ~/project/ansible-output-demo:
- Нажмите на меню "File"
- Выберите "New File"
- Сохраните его как
conditional_actions.ymlв каталоге~/project/ansible-output-demo
Добавьте следующее содержимое:
---
- name: Conditional Actions Based on Script Output
hosts: local
gather_facts: no
tasks:
- name: Execute the system_stats.sh script
command: "{{ playbook_dir }}/scripts/system_stats.sh"
register: stats_output
- name: Parse disk usage
set_fact:
disk_usage: "{{ stats_output.stdout | regex_search('DISK_USAGE_PCT: (\\d+)', '\\1') | first | int }}"
- name: Parse load average
set_fact:
load_avg: "{{ stats_output.stdout | regex_search('LOAD_AVG: ([0-9.]+)', '\\1') | first | float }}"
- name: Display system status
debug:
msg: "Current system status: Disk usage: {{ disk_usage }}%, Load average: {{ load_avg }}"
- name: Warn about high disk usage
debug:
msg: "WARNING: Disk usage is high at {{ disk_usage }}%. Consider cleaning up disk space."
when: disk_usage > 50
- name: Warn about high load average
debug:
msg: "WARNING: Load average is high at {{ load_avg }}. Check for resource-intensive processes."
when: load_avg > 1.0
- name: Report healthy system
debug:
msg: "System is healthy. All metrics within normal ranges."
when: disk_usage <= 50 and load_avg <= 1.0
Этот плейбук:
- Выполняет скрипт
system_stats.sh - Разбирает значения использования диска и средней нагрузки
- Отображает разные сообщения в зависимости от значений:
- Предупреждение, если использование диска превышает 50%
- Предупреждение, если средняя нагрузка превышает 1.0
- Сообщение "healthy system" (здоровая система), если все показатели находятся в нормальных пределах
Давайте запустим этот плейбук:
ansible-playbook -i inventory conditional_actions.yml
Вывод будет зависеть от текущего состояния вашей системы, но он должен включать условные сообщения на основе использования диска и средней нагрузки.
Эти примеры демонстрируют, как вы можете:
- Разбирать и извлекать конкретную информацию из вывода скрипта
- Использовать эту информацию для принятия решений в ваших плейбуках Ansible
- Выполнять различные действия на основе вывода скрипта
Эти методы необходимы для создания динамичных, отзывчивых рабочих процессов автоматизации, которые могут адаптироваться к различным условиям и сценариям.
Практический пример использования — проверка состояния системы
На этом заключительном шаге мы создадим полный реальный пример, который объединяет все, что мы узнали о захвате и обработке вывода скриптов с помощью Ansible. Мы создадим инструмент проверки состояния системы, который:
- Собирает различные системные метрики
- Анализирует метрики для выявления потенциальных проблем
- Генерирует отчет о состоянии
- Принимает корректирующие действия при необходимости
Создание скрипта проверки состояния
Сначала давайте создадим комплексный скрипт проверки состояния, который собирает различные системные метрики.
Создайте новый файл с именем health_check.sh в каталоге scripts:
- Нажмите на меню "File"
- Выберите "New File"
- Сохраните его как
scripts/health_check.shв каталоге~/project/ansible-output-demo
Добавьте следующее содержимое в файл health_check.sh:
#!/bin/bash
## System Health Check Script
echo "HEALTH_CHECK_START: $(date)"
## CPU load
cpu_load=$(uptime | awk -F'load average: ' '{print $2}' | cut -d, -f1)
echo "CPU_LOAD: $cpu_load"
if (($(echo "$cpu_load > 1.0" | bc -l))); then
echo "CPU_STATUS: WARNING"
else
echo "CPU_STATUS: OK"
fi
## Memory usage
mem_total=$(free | grep Mem | awk '{print $2}')
mem_used=$(free | grep Mem | awk '{print $3}')
mem_pct=$(echo "scale=2; $mem_used / $mem_total * 100" | bc)
echo "MEM_USAGE_PCT: $mem_pct"
if (($(echo "$mem_pct > 80" | bc -l))); then
echo "MEM_STATUS: WARNING"
else
echo "MEM_STATUS: OK"
fi
## Disk usage
disk_usage=$(df -h / | tail -1 | awk '{print $5}' | tr -d '%')
echo "DISK_USAGE_PCT: $disk_usage"
if [ "$disk_usage" -gt 80 ]; then
echo "DISK_STATUS: WARNING"
else
echo "DISK_STATUS: OK"
fi
## Check for zombie processes
zombie_count=$(ps aux | grep -c Z)
echo "ZOMBIE_PROCESSES: $zombie_count"
if [ "$zombie_count" -gt 0 ]; then
echo "ZOMBIE_STATUS: WARNING"
else
echo "ZOMBIE_STATUS: OK"
fi
## Check system uptime
uptime_days=$(uptime | awk '{print $3}')
echo "UPTIME_DAYS: $uptime_days"
## Check last 5 log entries for errors
echo "RECENT_ERRORS: $(grep -i error /var/log/syslog 2> /dev/null | tail -5 | wc -l)"
echo "HEALTH_CHECK_END: $(date)"
Сделайте скрипт исполняемым:
chmod +x ~/project/ansible-output-demo/scripts/health_check.sh
Создание плейбука проверки состояния
Теперь давайте создадим комплексный плейбук, который выполняет скрипт проверки состояния, анализирует результаты и предпринимает соответствующие действия на основе результатов.
Создайте новый файл с именем system_health_check.yml в каталоге ~/project/ansible-output-demo:
- Нажмите на меню "File"
- Выберите "New File"
- Сохраните его как
system_health_check.ymlв каталоге~/project/ansible-output-demo
Добавьте следующее содержимое в файл system_health_check.yml:
---
- name: System Health Check
hosts: local
gather_facts: no
tasks:
- name: Execute health check script
command: "{{ playbook_dir }}/scripts/health_check.sh"
register: health_check
- name: Display raw health check output
debug:
var: health_check.stdout_lines
## Parse metrics from the health check output
- name: Parse CPU load
set_fact:
cpu_load: "{{ health_check.stdout | regex_search('CPU_LOAD: ([0-9.]+)', '\\1') | first | float }}"
cpu_status: "{{ health_check.stdout | regex_search('CPU_STATUS: (\\w+)', '\\1') | first }}"
- name: Parse memory usage
set_fact:
mem_usage: "{{ health_check.stdout | regex_search('MEM_USAGE_PCT: ([0-9.]+)', '\\1') | first | float }}"
mem_status: "{{ health_check.stdout | regex_search('MEM_STATUS: (\\w+)', '\\1') | first }}"
- name: Parse disk usage
set_fact:
disk_usage: "{{ health_check.stdout | regex_search('DISK_USAGE_PCT: (\\d+)', '\\1') | first | int }}"
disk_status: "{{ health_check.stdout | regex_search('DISK_STATUS: (\\w+)', '\\1') | first }}"
- name: Parse zombie processes
set_fact:
zombie_count: "{{ health_check.stdout | regex_search('ZOMBIE_PROCESSES: (\\d+)', '\\1') | first | int }}"
zombie_status: "{{ health_check.stdout | regex_search('ZOMBIE_STATUS: (\\w+)', '\\1') | first }}"
## Generate a health status summary
- name: Generate health status summary
set_fact:
health_status:
cpu:
load: "{{ cpu_load }}"
status: "{{ cpu_status }}"
memory:
usage_percent: "{{ mem_usage }}"
status: "{{ mem_status }}"
disk:
usage_percent: "{{ disk_usage }}"
status: "{{ disk_status }}"
processes:
zombie_count: "{{ zombie_count }}"
status: "{{ zombie_status }}"
## Display health summary
- name: Display health summary
debug:
var: health_status
## Check overall system status
- name: Determine overall system status
set_fact:
overall_status: "{{ 'WARNING' if (cpu_status == 'WARNING' or mem_status == 'WARNING' or disk_status == 'WARNING' or zombie_status == 'WARNING') else 'OK' }}"
- name: Display overall system status
debug:
msg: "Overall System Status: {{ overall_status }}"
## Take remedial actions if necessary
- name: Recommend actions for CPU issues
debug:
msg: "Action recommended: Check for resource-intensive processes using 'top' or 'htop'"
when: cpu_status == "WARNING"
- name: Recommend actions for memory issues
debug:
msg: "Action recommended: Free up memory by restarting services or clearing cache"
when: mem_status == "WARNING"
- name: Recommend actions for disk issues
debug:
msg: "Action recommended: Clean up disk space using 'du -sh /* | sort -hr' to identify large directories"
when: disk_status == "WARNING"
- name: Recommend actions for zombie processes
debug:
msg: "Action recommended: Identify and restart parent processes of zombies"
when: zombie_status == "WARNING"
## Generate health report file
- name: Create health report directory
file:
path: "{{ playbook_dir }}/reports"
state: directory
- name: Get current timestamp
command: date "+%Y%m%d_%H%M%S"
register: timestamp
- name: Create health report file
copy:
content: |
System Health Report - {{ timestamp.stdout }}
----------------------------------------------
CPU:
Load Average: {{ cpu_load }}
Status: {{ cpu_status }}
Memory:
Usage: {{ mem_usage }}%
Status: {{ mem_status }}
Disk:
Usage: {{ disk_usage }}%
Status: {{ disk_status }}
Processes:
Zombie Count: {{ zombie_count }}
Status: {{ zombie_status }}
Overall Status: {{ overall_status }}
Recommendations:
{% if cpu_status == "WARNING" %}
- CPU: Check for resource-intensive processes using 'top' or 'htop'
{% endif %}
{% if mem_status == "WARNING" %}
- Memory: Free up memory by restarting services or clearing cache
{% endif %}
{% if disk_status == "WARNING" %}
- Disk: Clean up disk space using 'du -sh /* | sort -hr' to identify large directories
{% endif %}
{% if zombie_status == "WARNING" %}
- Processes: Identify and restart parent processes of zombies
{% endif %}
{% if overall_status == "OK" %}
- System is healthy. No actions required.
{% endif %}
dest: "{{ playbook_dir }}/reports/health_report_{{ timestamp.stdout }}.txt"
- name: Display report location
debug:
msg: "Health report saved to {{ playbook_dir }}/reports/health_report_{{ timestamp.stdout }}.txt"
Этот комплексный плейбук:
- Выполняет наш скрипт проверки состояния
- Разбирает различные метрики из вывода скрипта
- Создает структурированную сводку о состоянии системы
- Определяет общее состояние системы на основе статусов отдельных компонентов
- Предоставляет конкретные рекомендации по любым обнаруженным проблемам
- Генерирует файл подробного отчета о состоянии с меткой времени
Запуск проверки состояния
Давайте запустим наш плейбук проверки состояния системы:
cd ~/project/ansible-output-demo
ansible-playbook -i inventory system_health_check.yml
Вы должны увидеть подробный вывод, показывающий состояние системы, а также любые необходимые рекомендации по улучшению. Вывод будет варьироваться в зависимости от текущего состояния вашей системы.
После запуска плейбука проверьте каталог отчетов, чтобы увидеть сгенерированный отчет о состоянии:
ls -l ~/project/ansible-output-demo/reports/
Вы должны увидеть файл с именем health_report_[timestamp].txt. Просмотрите содержимое этого файла:
cat ~/project/ansible-output-demo/reports/health_report_*.txt
Краткое изложение того, что мы узнали
В ходе этого руководства мы узнали:
- Как захватывать различные типы вывода (stdout, stderr, коды возврата) из скриптов, выполняемых Ansible
- Как разбирать и извлекать конкретную информацию из вывода скриптов с помощью фильтров Ansible
- Как использовать вывод скриптов для принятия решений и выполнения условных действий
- Как реализовать полное реальное решение, которое использует вывод скриптов для мониторинга состояния системы
Эти методы являются мощными инструментами в вашем наборе инструментов автоматизации Ansible, позволяя вам создавать сложные, динамичные и отзывчивые рабочие процессы автоматизации.
Резюме
В этой лабораторной работе мы рассмотрели, как эффективно захватывать и использовать вывод скриптов, выполняемых через Ansible. Мы начали с базового захвата вывода с использованием ключевого слова register и перешли к более продвинутым методам, таким как разбор вывода с помощью фильтров и принятие решений на основе результатов скриптов.
Основные выводы из этого руководства включают:
- Возможность захвата различных типов вывода (stdout, stderr, коды возврата) из скриптов, выполняемых Ansible
- Методы разбора и извлечения конкретной информации из вывода скриптов
- Методы условного выполнения задач на основе вывода скриптов
- Комплексный реальный пример, демонстрирующий, как создать решение для мониторинга состояния системы с помощью Ansible
Освоив эти методы, вы сможете создавать более сложные, динамичные и отзывчивые рабочие процессы автоматизации, которые могут адаптироваться к различным условиям и сценариям. Эта возможность необходима для эффективного управления инфраструктурой, развертывания приложений и администрирования систем с использованием Ansible.
Продолжая свой путь с Ansible, помните, что захват вывода скриптов — это лишь одна из многих мощных функций, которые предлагает Ansible. Изучение других возможностей Ansible, таких как роли, шаблоны и vault, еще больше расширит ваш набор инструментов автоматизации.


