Модуль Ansible Command

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

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

В этом лабораторном занятии (lab) вы познакомитесь с модулем Ansible Command, мощным инструментом для выполнения команд на удаленных хостах. Модуль Command позволяет взаимодействовать с командной строкой непосредственно из ваших Ansible-плейбуков и задач, предоставляя гибкий способ управления удаленными системами. В рамках этого лабораторного занятия вы научитесь использовать модуль Ansible Command для выполнения различных команд, работы с переменными и аргументами, а также для захвата вывода команд.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL linux(("Linux")) -.-> linux/FileandDirectoryManagementGroup(["File and Directory Management"]) ansible(("Ansible")) -.-> ansible/PlaybookEssentialsGroup(["Playbook Essentials"]) linux(("Linux")) -.-> linux/SystemInformationandMonitoringGroup(["System Information and Monitoring"]) linux(("Linux")) -.-> linux/BasicFileOperationsGroup(["Basic File Operations"]) ansible(("Ansible")) -.-> ansible/ModuleOperationsGroup(["Module Operations"]) linux/BasicFileOperationsGroup -.-> linux/ls("Content Listing") ansible/ModuleOperationsGroup -.-> ansible/command("Execute Commands") ansible/ModuleOperationsGroup -.-> ansible/debug("Test Output") linux/BasicFileOperationsGroup -.-> linux/tail("File End Display") linux/FileandDirectoryManagementGroup -.-> linux/pwd("Directory Displaying") ansible/PlaybookEssentialsGroup -.-> ansible/playbook("Execute Playbook") linux/SystemInformationandMonitoringGroup -.-> linux/df("Disk Space Reporting") linux/SystemInformationandMonitoringGroup -.-> linux/service("Service Managing") subgraph Lab Skills linux/ls -.-> lab-290161{{"Модуль Ansible Command"}} ansible/command -.-> lab-290161{{"Модуль Ansible Command"}} ansible/debug -.-> lab-290161{{"Модуль Ansible Command"}} linux/tail -.-> lab-290161{{"Модуль Ansible Command"}} linux/pwd -.-> lab-290161{{"Модуль Ansible Command"}} ansible/playbook -.-> lab-290161{{"Модуль Ansible Command"}} linux/df -.-> lab-290161{{"Модуль Ansible Command"}} linux/service -.-> lab-290161{{"Модуль Ansible Command"}} end

Создание простого Ansible-плейбука

На этом шаге вы создадите свой первый Ansible-плейбук, используя модуль Command для выполнения простой команды.

Сначала перейдите в директорию проекта:

cd ~/project

Теперь создайте новый файл с именем simple_command.yml с помощью текстового редактора по вашему выбору. Например, вы можете использовать редактор nano:

nano simple_command.yml

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

---
- name: Execute a simple command
  hosts: localhost
  tasks:
    - name: Run 'ls' command
      command: ls -l

Разберем этот плейбук:

  • Строка hosts: localhost указывает, что плейбук будет выполняться на локальной машине.
  • Раздел tasks содержит список задач, которые должны быть выполнены.
  • Строка command: ls -l использует модуль Command для выполнения команды ls -l, которая выводит список файлов и директорий в длинном формате.

Сохраните файл и выйдите из редактора (в nano нажмите Ctrl+X, затем Y, а затем Enter).

Теперь запустите плейбук с помощью следующей команды:

ansible-playbook simple_command.yml

Вы должны увидеть вывод, похожий на следующий:

PLAY [Execute a simple command] ************************************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [Run 'ls' command] ********************************************************
changed: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Этот вывод показывает, что плейбук был успешно выполнен, и команда ls -l была выполнена на вашей локальной машине.

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

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

Создайте новый файл с именем variable_command.yml:

nano variable_command.yml

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

---
- name: Use variables with the Command module
  hosts: localhost
  vars:
    file_path: /etc/passwd
    line_count: 5
  tasks:
    - name: Display the last few lines of a file
      command: "tail -n {{ line_count }} {{ file_path }}"
      register: command_output

    - name: Show the command output
      debug:
        var: command_output.stdout_lines

В этом плейбуке представлены несколько новых концепций:

  • Раздел vars определяет переменные, которые можно использовать в рамках всего плейбука.
  • Мы используем синтаксис {{ variable_name }} для обращения к переменным внутри команды.
  • Ключевое слово register сохраняет вывод команды в переменную с именем command_output.
  • Модуль debug используется для отображения содержимого переменной command_output.

Сохраните файл и выйдите из редактора.

Теперь запустите плейбук:

ansible-playbook variable_command.yml

Вы должны увидеть вывод, похожий на следующий:

PLAY [Use variables with the Command module] ***********************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [Display the last few lines of a file] ************************************
changed: [localhost]

TASK [Show the command output] *************************************************
ok: [localhost] => {
    "command_output.stdout_lines": [
        "games:x:5:60:games:/usr/games:/usr/sbin/nologin",
        "man:x:6:12:man:/var/cache/man:/usr/sbin/nologin",
        "lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin",
        "mail:x:8:8:mail:/var/mail:/usr/sbin/nologin",
        "news:x:9:9:news:/var/spool/news:/usr/sbin/nologin"
    ]
}

PLAY RECAP *********************************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Этот вывод показывает последние 5 строк файла /etc/passwd, демонстрируя, как можно использовать переменные с модулем Command.

Захват и обработка вывода команды

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

Создайте новый файл с именем process_output.yml:

nano process_output.yml

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

---
- name: Capture and process command output
  hosts: localhost
  tasks:
    - name: Get disk usage information
      command: df -h
      register: df_output

    - name: Display all partitions
      debug:
        msg: "{{ df_output.stdout_lines }}"

    - name: Find root partition
      set_fact:
        root_partition: "{{ df_output.stdout_lines | select('match', '\\s+/$') | first | default('') }}"

    - name: Display root partition information
      debug:
        msg: "Root partition: {{ root_partition }}"
      when: root_partition!= ''

    - name: Extract usage percentage
      set_fact:
        root_usage: "{{ root_partition.split()[-2].rstrip('%') | int }}"
      when: root_partition!= ''

    - name: Display root partition usage
      debug:
        msg: "Root partition is {{ root_usage }}% full"
      when: root_partition!= ''

    - name: Check if root partition is over 80% full
      fail:
        msg: "Warning: Root partition is over 80% full!"
      when: root_partition!= '' and root_usage > 80

    - name: Display message if root partition not found
      debug:
        msg: "Root partition (/) not found in df output"
      when: root_partition == ''

Этот плейбук более надежен и обрабатывает случаи, когда корневая раздел (root partition) может быть трудно обнаружена:

  • Мы выводим все разделы, чтобы увидеть, какие из них доступны.
  • Мы используем более гибкий шаблон для поиска корневой раздела.
  • Мы добавляем проверки для обработки случаев, когда корневая раздела не найдена.
  • Мы используем фильтр default(''), чтобы избежать ошибок, когда корневая раздела не найдена.

Сохраните файл и выйдите из редактора.

Теперь запустите плейбук:

ansible-playbook process_output.yml

Вы должны увидеть вывод, похожий на следующий:

PLAY [Capture and process command output] ************************************************

TASK [Gathering Facts] *******************************************************************
ok: [localhost]

TASK [Get disk usage information] ********************************************************
changed: [localhost]

TASK [Display all partitions] ************************************************************
ok: [localhost] => {
    "msg": [
        "Filesystem      Size  Used Avail Use% Mounted on",
        "overlay          20G  618M   20G   4% /",
        "tmpfs            64M     0   64M   0% /dev",
        "tmpfs           3.9G     0  3.9G   0% /sys/fs/cgroup",
        "shm              64M  128K   64M   1% /dev/shm",
        "/dev/vdb        100G   17G   84G  17% /etc/hosts"
    ]
}

TASK [Find root partition] ***************************************************************
ok: [localhost]

TASK [Display root partition information] ************************************************
skipping: [localhost]

TASK [Extract usage percentage] **********************************************************
skipping: [localhost]

TASK [Display root partition usage] ******************************************************
skipping: [localhost]

TASK [Check if root partition is over 80% full] ******************************************
skipping: [localhost]

TASK [Display message if root partition not found] ***************************************
ok: [localhost] => {
    "msg": "Root partition (/) not found in df output"
}

PLAY RECAP *******************************************************************************
localhost                  : ok=7    changed=1    unreachable=0    failed=1    skipped=1    rescued=0    ignored=0

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

Работа с параметрами модуля Command

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

Создайте новый файл с именем command_options.yml:

nano command_options.yml

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

---
- name: Explore Command module options
  hosts: localhost
  tasks:
    - name: Run a command with a specific working directory
      command: pwd
      args:
        chdir: /tmp

    - name: Run a command with environment variables
      command: echo $MY_VAR
      environment:
        MY_VAR: "Hello from Ansible"

    - name: Run a command and ignore errors
      command: ls /nonexistent_directory
      ignore_errors: yes

    - name: Run a command with a timeout
      command: sleep 2
      async: 5
      poll: 0
      register: sleep_result

    - name: Check sleep command status
      async_status:
        jid: "{{ sleep_result.ansible_job_id }}"
      register: job_result
      until: job_result.finished
      retries: 5
      delay: 1

В этом плейбуке демонстрируются различные параметры модуля Command:

  • chdir: Изменяет текущую рабочую директорию перед выполнением команды.
  • environment: Устанавливает переменные окружения для команды.
  • ignore_errors: Продолжает выполнение плейбука, даже если команда завершилась с ошибкой.
  • async и poll: Запускает команду асинхронно с установкой таймаута.

Сохраните файл и выйдите из редактора.

Теперь запустите плейбук:

ansible-playbook command_options.yml

Вы должны увидеть вывод, похожий на следующий:

PPLAY [Explore Command module options]

TASK [Gathering Facts]
ok: [localhost]

TASK [Run a command with a specific working directory]
changed: [localhost]

TASK [Run a command with environment variables]
changed: [localhost]

TASK [Run a command and ignore errors]
fatal: [localhost]: FAILED! => {"changed": true, "cmd": ["ls", "/nonexistent_directory"], "delta": "0:00:00.006113", "end": "2024-09-06 09:40:43.373350", "msg": "non-zero return code", "rc": 2, "start": "2024-09-06 09:40:43.367237", "stderr": "ls: cannot access '/nonexistent_directory': No such file or directory", "stderr_lines": ["ls: cannot access '/nonexistent_directory': No such file or directory"], "stdout": "", "stdout_lines": []}
...ignoring

TASK [Run a command with a timeout]
changed: [localhost]

TASK [Check sleep command status]
FAILED - RETRYING: Check sleep command status (10 retries left).
FAILED - RETRYING: Check sleep command status (9 retries left).
FAILED - RETRYING: Check sleep command status (8 retries left).
FAILED - RETRYING: Check sleep command status (7 retries left).
FAILED - RETRYING: Check sleep command status (6 retries left).
FAILED - RETRYING: Check sleep command status (5 retries left).
FAILED - RETRYING: Check sleep command status (4 retries left).
FAILED - RETRYING: Check sleep command status (3 retries left).
FAILED - RETRYING: Check sleep command status (2 retries left).
FAILED - RETRYING: Check sleep command status (1 retries left).
fatal: [localhost]: FAILED! => {"ansible_job_id": "5877920468.2517", "attempts": 10, "changed": false, "finished": 0, "started": 1}

PLAY RECAP

Этот вывод демонстрирует различные поведения параметров модуля Command, которые мы рассмотрели.

Использование модуля Command в сценарии, совместимом с Docker

На этом последнем шаге вы будете использовать модуль Ansible Command в более реалистичном сценарии, совместимом с Docker: проверять статус службы SSH и управлять ею при необходимости.

Создайте новый файл с именем check_service_docker.yml:

nano check_service_docker.yml

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

---
- name: Check and manage SSH service in Docker
  hosts: localhost
  become: yes ## Это позволяет Ansible использовать sudo
  tasks:
    - name: Check SSH service status
      command: service ssh status
      register: ssh_status
      ignore_errors: yes

    - name: Display SSH service status
      debug:
        msg: "SSH service status: {{ ssh_status.stdout }}"

    - name: Start SSH service if not running
      command: service ssh start
      when: ssh_status.rc!= 0

    - name: Verify SSH service is running
      command: service ssh status
      register: ssh_status_after

    - name: Display final SSH service status
      debug:
        msg: "SSH service status is now: {{ ssh_status_after.stdout }}"

    - name: Check if SSH port is listening
      command: netstat -tuln | grep :22
      register: ssh_port_check
      ignore_errors: yes

    - name: Display SSH port status
      debug:
        msg: "SSH port 22 is {{ 'open' if ssh_port_check.rc == 0 else 'closed' }}"

Этот плейбук выполняет следующие действия:

  1. Проверяет статус службы SSH с использованием команды service.
  2. Отображает текущий статус службы.
  3. Запускает службу, если она не запущена.
  4. Проверяет статус службы после возможного запуска.
  5. Отображает итоговый статус службы.
  6. Проверяет, прослушивается ли порт SSH (22).
  7. Отображает статус порта SSH.

Сохраните файл и выйдите из редактора.

Теперь запустите плейбук с привилегиями sudo:

sudo ansible-playbook check_service_docker.yml

Вы должны увидеть вывод, похожий на следующий:

PLAY [Check and manage SSH service in Docker] *****************************************

TASK [Gathering Facts] ****************************************************************
ok: [localhost]

TASK [Check SSH service status] *******************************************************
changed: [localhost]

TASK [Display SSH service status] *****************************************************
ok: [localhost] => {
    "msg": "SSH service status: * sshd is running"
}

TASK [Start SSH service if not running] ***********************************************
skipping: [localhost]

TASK [Verify SSH service is running] **************************************************
changed: [localhost]

TASK [Display final SSH service status] ***********************************************
ok: [localhost] => {
    "msg": "SSH service status is now: * sshd is running"
}

TASK [Check if SSH port is listening] *************************************************
changed: [localhost]

TASK [Display SSH port status] ********************************************************
ok: [localhost] => {
    "msg": "SSH port 22 is open"
}

PLAY RECAP ****************************************************************************
localhost                  : ok=6    changed=3    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

Этот вывод показывает, что служба SSH уже была запущена, поэтому ее не нужно было запускать. Плейбук успешно проверил и подтвердил статус службы, а также убедился, что порт SSH открыт.

Итог

В этом лабораторном занятии вы познакомились с универсальностью и мощностью модуля Ansible Command. Вы научились:

  1. Создавать простые плейбуки Ansible с использованием модуля Command для выполнения базовых команд.
  2. Использовать переменные с модулем Command, чтобы сделать ваши плейбуки более гибкими и повторно используемыми.
  3. Захватывать и обрабатывать вывод команд, что позволяет принимать решения на основе результатов выполнения команд.
  4. Работать с различными параметрами модуля Command для управления его поведением, например, изменять директорию, устанавливать переменные окружения и обрабатывать ошибки.
  5. Применять модуль Command в реальном сценарии, проверяя и управляя системной службой.

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

Не забывайте, что хотя модуль Command мощный, часто лучше использовать специализированные модули Ansible (например, модуль service для управления службами), если они доступны. Эти специализированные модули обеспечивают лучшую идемпотентность и могут обрабатывать более сложные сценарии сразу.

Продолжайте практиковаться и изучать возможности Ansible, чтобы дополнительно улучшить свои навыки автоматизации и упростить свои IT-операции.