Как захватить вывод скрипта, выполненного Ansible

AnsibleBeginner
Практиковаться сейчас

Введение

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 файл инвентаризации определяет хосты и группы хостов, на которых выполняются команды, модули и задачи в плейбуке.

Создайте файл инвентаризации, используя редактор кода:

  1. Нажмите на меню "File" в верхнем левом углу IDE
  2. Выберите "New File"
  3. Сохраните его как inventory в каталоге ~/project/ansible-output-demo

Добавьте следующее содержимое в файл inventory:

[local]
localhost ansible_connection=local

Этот файл инвентаризации указывает, что мы будем запускать Ansible на локальной машине.

Далее давайте создадим простой скрипт, который будет генерировать некоторый вывод для захвата. Этот скрипт:

  1. Выведет некоторую информацию о системе
  2. Сгенерирует стандартный вывод
  3. Сгенерирует стандартный вывод об ошибках

Создайте новый файл в каталоге scripts с именем info.sh:

  1. Нажмите на меню "File"
  2. Выберите "New File"
  3. Сохраните его как 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:

  1. Нажмите на меню "File"
  2. Выберите "New File"
  3. Сохраните его как 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

Давайте рассмотрим этот плейбук:

  1. Плейбук нацелен на группу local, определенную в нашей инвентаризации.
  2. Первая задача выполняет наш скрипт info.sh с помощью модуля command.
  3. Ключевое слово register сохраняет вывод команды в переменную с именем script_output.
  4. Вторая задача использует модуль 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!"
    ]
}

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

Захват различных типов вывода

На предыдущем шаге мы захватили и отобразили стандартный вывод нашего скрипта. Однако при выполнении скриптов существует несколько типов вывода, которые мы можем захотеть захватить:

  1. Стандартный вывод (stdout): Обычный вывод скрипта
  2. Стандартный вывод ошибок (stderr): Сообщения об ошибках и предупреждения
  3. Код возврата (rc): Статус завершения скрипта (0 обычно означает успех, ненулевые значения указывают на ошибки)

Давайте создадим новый плейбук, который захватывает и отображает все три типа вывода.

Создайте новый файл с именем capture_all_output.yml в каталоге ~/project/ansible-output-demo:

  1. Нажмите на меню "File"
  2. Выберите "New File"
  3. Сохраните его как 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 }}"

Этот плейбук выполняет наш скрипт, а затем отображает:

  1. Стандартный вывод с использованием script_output.stdout_lines
  2. Стандартный вывод ошибок с использованием script_output.stderr_lines
  3. Код возврата с использованием 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:

  1. Нажмите на меню "File"
  2. Выберите "New File"
  3. Сохраните его как 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:

  1. Нажмите на меню "File"
  2. Выберите "New File"
  3. Сохраните его как 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

Этот пример демонстрирует, как:

  1. Захватывать вывод из скрипта, который выдает ошибку
  2. Продолжать выполнение плейбука, несмотря на ошибку
  3. Условно выполнять задачи на основе кода возврата скрипта

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

Расширенная обработка вывода и практические примеры использования

Теперь, когда мы понимаем, как захватывать различные типы вывода, давайте рассмотрим некоторые более продвинутые методы обработки и использования вывода скриптов в Ansible.

Разбор вывода с помощью фильтров

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

Создайте новый файл с именем parse_output.yml в каталоге ~/project/ansible-output-demo:

  1. Нажмите на меню "File"
  2. Выберите "New File"
  3. Сохраните его как parse_output.yml в каталоге ~/project/ansible-output-demo

Сначала давайте создадим скрипт, который генерирует структурированный вывод, который мы сможем разобрать. Создайте новый файл с именем system_stats.sh:

  1. Нажмите на меню "File"
  2. Выберите "New File"
  3. Сохраните его как 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 }}

Этот плейбук:

  1. Выполняет наш скрипт system_stats.sh
  2. Отображает необработанный вывод
  3. Использует фильтр regex_search для извлечения конкретных фрагментов информации из вывода
  4. Сохраняет извлеченную информацию в переменные
  5. Отображает разобранную информацию в структурированном формате

Давайте запустим этот плейбук:

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:

  1. Нажмите на меню "File"
  2. Выберите "New File"
  3. Сохраните его как 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

Этот плейбук:

  1. Выполняет скрипт system_stats.sh
  2. Разбирает значения использования диска и средней нагрузки
  3. Отображает разные сообщения в зависимости от значений:
    • Предупреждение, если использование диска превышает 50%
    • Предупреждение, если средняя нагрузка превышает 1.0
    • Сообщение "healthy system" (здоровая система), если все показатели находятся в нормальных пределах

Давайте запустим этот плейбук:

ansible-playbook -i inventory conditional_actions.yml

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

Эти примеры демонстрируют, как вы можете:

  1. Разбирать и извлекать конкретную информацию из вывода скрипта
  2. Использовать эту информацию для принятия решений в ваших плейбуках Ansible
  3. Выполнять различные действия на основе вывода скрипта

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

Практический пример использования — проверка состояния системы

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

  1. Собирает различные системные метрики
  2. Анализирует метрики для выявления потенциальных проблем
  3. Генерирует отчет о состоянии
  4. Принимает корректирующие действия при необходимости

Создание скрипта проверки состояния

Сначала давайте создадим комплексный скрипт проверки состояния, который собирает различные системные метрики.

Создайте новый файл с именем health_check.sh в каталоге scripts:

  1. Нажмите на меню "File"
  2. Выберите "New File"
  3. Сохраните его как 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:

  1. Нажмите на меню "File"
  2. Выберите "New File"
  3. Сохраните его как 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"

Этот комплексный плейбук:

  1. Выполняет наш скрипт проверки состояния
  2. Разбирает различные метрики из вывода скрипта
  3. Создает структурированную сводку о состоянии системы
  4. Определяет общее состояние системы на основе статусов отдельных компонентов
  5. Предоставляет конкретные рекомендации по любым обнаруженным проблемам
  6. Генерирует файл подробного отчета о состоянии с меткой времени

Запуск проверки состояния

Давайте запустим наш плейбук проверки состояния системы:

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

Краткое изложение того, что мы узнали

В ходе этого руководства мы узнали:

  1. Как захватывать различные типы вывода (stdout, stderr, коды возврата) из скриптов, выполняемых Ansible
  2. Как разбирать и извлекать конкретную информацию из вывода скриптов с помощью фильтров Ansible
  3. Как использовать вывод скриптов для принятия решений и выполнения условных действий
  4. Как реализовать полное реальное решение, которое использует вывод скриптов для мониторинга состояния системы

Эти методы являются мощными инструментами в вашем наборе инструментов автоматизации Ansible, позволяя вам создавать сложные, динамичные и отзывчивые рабочие процессы автоматизации.

Резюме

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

Основные выводы из этого руководства включают:

  1. Возможность захвата различных типов вывода (stdout, stderr, коды возврата) из скриптов, выполняемых Ansible
  2. Методы разбора и извлечения конкретной информации из вывода скриптов
  3. Методы условного выполнения задач на основе вывода скриптов
  4. Комплексный реальный пример, демонстрирующий, как создать решение для мониторинга состояния системы с помощью Ansible

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

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