Знакомство с Ansible. Часть 2. Командный интерфейс Ansible

В предыдущей публикации я рассказывал о файлах инвентаризации Ansible. Теперь вооружившись предыдущими знаниями мы с вами можем перейти к следующей теме – Командный интерфейс Ansible. В англоязычной литературе его еще часто называют ad-hoc. У него тоже есть свои сценарии применения. Например, когда мы с вами тестировали файлы инвентаризации то сами того не подозревая использовали именно командный интерфейс.

Командный интерфейс Ansible

Зачем вообще нужен командный интерфейс Ansible? По большей части для тестирования/отладки и выполнения каких разовых единичных задач. Например, посмотреть имени хостов из группы, время или информацию об IP-адресах.

В последующих примерах я буду использовать файл инвентаризации из примера №3 моей предыдущей публикации.

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

ansible all -i inv.ini -a "date"
roman@ansible:~$ ansible all -i inv.ini -a "date"
tst1 | CHANGED | rc=0 >>
Wed Jun 28 02:39:02 PM UTC 2023
tst2 | CHANGED | rc=0 >>
Wed Jun 28 02:39:02 PM UTC 2023
roman@ansible:~$ 

Здесь:

  • ansible – это имя утилиты командного интерфейса Ansible.
  • all – имя группы, для которой необходимо выполнить действие.
  • -i – имя файла инвентаризации.
  • -a – передача аргументов модулю. Если модуль не указан (параметр -m), то аргументы будут переданы модулю shell. Я передал команду отображения текущей даты и времени.

Аналогично вы можете выполнить любую другую команду:

ansible all -i inv.ini -a "free -m"
roman@ansible:~$ ansible all -i inv.ini -a "free -m"
tst1 | CHANGED | rc=0 >>
               total        used        free      shared  buff/cache   available
Mem:            3877        2277         455          49        1145        1265
Swap:           3890           0        3890
tst2 | CHANGED | rc=0 >>
               total        used        free      shared  buff/cache   available
Mem:            3877         325        3223           1         328        3333
Swap:           3890           0        3890
roman@ansible:~$ 

У Ansible довольно большой набор модулей. В командном интерфейсе вы можете использовать любой нужный вам модуль. Давайте, например, установим curl на все сервера группы front. Для этого нам нужно использовать модуль apt. В качестве параметров модулю необходимо передать имя пакета (параметр name) и состояние (state=present), чтобы Ansible убедился в том, что модуль присутствует в системе.

ansible front -i inv.ini -m apt -a "name=curl state=present"
roman@ansible:~$ ansible front -i inv.ini -m apt -a "name=curl state=present"
tst1 | FAILED! => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "msg": "'/usr/bin/apt-mark manual curl' failed: E: Could not create temporary file for /var/lib/apt/extended_states - mkstemp (13: Permission denied)\nE: Failed to write temporary StateFile /var/lib/apt/extended_states\n",
    "rc": 100,
    "stderr": "E: Could not create temporary file for /var/lib/apt/extended_states - mkstemp (13: Permission denied)\nE: Failed to write temporary StateFile /var/lib/apt/extended_states\n",
    "stderr_lines": [
        "E: Could not create temporary file for /var/lib/apt/extended_states - mkstemp (13: Permission denied)",
        "E: Failed to write temporary StateFile /var/lib/apt/extended_states"
    ],
    "stdout": "",
    "stdout_lines": []
}

Как любит уведомлять один из браузеров – “Опаньки… Что-то пошло не так.”. Хотя из описания ошибки уже должна быть понятна причина – у учетной записи нет достаточных привилегий. Давайте повысим привилегии через sudo и повторим попытку. Для запроса выполнения команды через sudo необходимо указать параметр -b:

ansible front -i inv.ini -m apt -a "name=curl state=present" -b
roman@ansible:~$ ansible front -i inv.ini -m apt -a "name=curl state=present" -b
tst1 | FAILED! => {
    "msg": "Missing sudo password"
}
roman@ansible:~$

Снова что-то пошло не так. Хотя уже определенно мы с вами сделали шаг вперед. Судя по всему необходимо явно указать пароль при использовании sudo. Для этого есть отдельный параметр -K. Добавим его:

ansible front -i inv.ini -m apt -a "name=curl state=present" -b -K
roman@ansible:~$ ansible front -i inv.ini -m apt -a "name=curl state=present" -b -K
BECOME password: 
tst1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "cache_update_time": 1687965135,
    "cache_updated": false,
    "changed": false
}
roman@ansible:~$ 

Теперь все получилось. Обратите внимание вот на эту строчку:

"changed": false

Это значит, что никаких изменений не было внесено в конфигурацию сервера. На сервере уже была установлена утилита curl.

Какие есть альтернативы интерактивному запросу пароля для sudo? Из наиболее распространенных и безопасных вариантов – использовать Ansible Vault.

Примеры использования командного интерфейса

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

В примерах ниже я буду использовать вот этот файл инвентаризации.

Пример 1. Выполнение команды в shell

Команда может быть любая. Например, давайте проверим сколько у нас свободного места на серверах. Модуль shell используется по умолчанию. Дополнительно передавать название модуля через параметр -m нет необходимости. Достаточно только передать параметры модулю через -a:

ansible all -i inv.ini -a "df -h"
roman@ansible:~$ ansible all -i inv.ini -a "df -h"
tst1 | CHANGED | rc=0 >>
Filesystem                         Size  Used Avail Use% Mounted on
tmpfs                              388M  1.6M  387M   1% /run
/dev/mapper/ubuntu--vg-ubuntu--lv   57G   14G   41G  25% /
tmpfs                              1.9G  152K  1.9G   1% /dev/shm
tmpfs                              5.0M     0  5.0M   0% /run/lock
/dev/sda2                          2.0G  130M  1.7G   8% /boot
tmpfs                              388M  4.0K  388M   1% /run/user/1000
tst2 | CHANGED | rc=0 >>
Filesystem                         Size  Used Avail Use% Mounted on
tmpfs                              388M  1.3M  387M   1% /run
/dev/mapper/ubuntu--vg-ubuntu--lv   57G  6.8G   48G  13% /
tmpfs                              1.9G     0  1.9G   0% /dev/shm
tmpfs                              5.0M     0  5.0M   0% /run/lock
/dev/sda2                          2.0G  130M  1.7G   8% /boot
tmpfs                              388M  4.0K  388M   1% /run/user/1000
roman@ansible:~$ ansible 

Пример 2. Установка приложения

Для установки приложения в большинстве случаев используются два модуля – apt и yum. Для Debian и CentOS подобных систем, соответственно.

Например, установим nginx на сервер frontend. В процессе установки мы запросим дополнительные привилегии через sudo (параметр -b) и интерактивно укажем пароль для sudo (параметр -K):

ansible front -i inv.ini -m apt -a "name=nginx state=present" -b -K
roman@ansible:~$ ansible front -i inv.ini -m apt -a "name=nginx state=present" -b -K
BECOME password: 
tst1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "cache_update_time": 1687965135,
    "cache_updated": false,
    "changed": true,
    "stderr": "",
    "stderr_lines": [],
<....>
        "NEEDRESTART-KCUR: 5.15.0-75-generic",
        "NEEDRESTART-KEXP: 5.15.0-75-generic",
        "NEEDRESTART-KSTA: 1"
    ]
}

Обратите внимание вот на эту строчку:

"changed": true

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

Пример 3. Запуск сервиса

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

Для этого нам потребуется модуль service:

ansible front -i inv.ini -m service -a "name=nginx state=started enabled=true" -b -K
roman@ansible:~$ ansible front -i inv.ini -m service -a "name=nginx state=started enabled=true" -b -K
BECOME password: 
tst1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "enabled": true,
    "name": "nginx",
    "state": "started",
    "status": {
        "ActiveEnterTimestamp": "Thu 2023-06-29 16:02:52 UTC",
        "ActiveEnterTimestampMonotonic": "2576195565",
<.....>
        "WatchdogSignal": "6",
        "WatchdogTimestamp": "n/a",
        "WatchdogTimestampMonotonic": "0",
        "WatchdogUSec": "0"
    }
}

Нас не интересует весь рулон вывода на консоль. Нас интересует только вот эти строчки:

    "enabled": true,
    "name": "nginx",
    "state": "started"

т.е. сервис запущен и настроен его автоматический запуск при старте системы.

Пример 4. Создание пользователя

Командный интерфейс Ansible не ограничивается только выполнение shell команд и управления сервисами. Вы также можете, например, создавать пользователей. Предварительно нужно установить модуль passlib для python:

python3 -m pip install passlib

Вот теперь мы можем создать пользователя:

ansible front -b -K -m user -a "name=usr createhome=yes password={{ 'Qwerty123' | password_hash('sha512') }}"
roman@ansible:~$ ansible front -b -K -m user -a "name=usr createhome=yes password={{ 'Qwerty123' | password_hash('sha512') }}"
BECOME password: 
tst1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "append": false,
    "changed": true,
    "comment": "",
    "group": 1001,
    "home": "/home/usr",
    "move_home": false,
    "name": "usr",
    "password": "NOT_LOGGING_PASSWORD",
    "shell": "/bin/sh",
    "state": "present",
    "uid": 1001
}

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

password={{ 'Qwerty123' | password_hash('sha512') }}

Модуль user может сразу задать пароль для пользователя. Но пароль не может быть передан открытым текстом – необходимо передать хэш пароля. Все то, что указано вот в этой конструкции со скобками {{ … }} является ни чем иным, как шаблоном jinja2. О шаблонах мы с вами поговрим в следующих публикациях. Пока достаточно знать того, что содержимое шаблона заменяется определенным текстом. В нашем случе берется текст пароля (Qwerty123) и берется хэш этого пароля. Именно хэш и будет передан параметру password.

Пример 5. Установка обновлений на сервер

Вы также можете запускать обновления в фоновом режиме через командный интерфейс Ansible. Примерно вот так:

ansible back -i inv.ini -b -K -B 3600 -P 0 -a "apt upgrade -y"
roman@ansible:~$ ansible back -i inv.ini -b -K -B 3600 -P 0 -a "apt upgrade -y"
BECOME password: 
tst2 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "ansible_job_id": "j95838861652.2020",
    "changed": true,
    "finished": 0,
    "results_file": "/root/.ansible_async/j95838861652.2020",
    "started": 1
}
roman@ansible:~$ 

Я приведу дополнительные пояснения только по новым параметрам:

  • -B – максимальное время в секундах, которое фоновому заданию можем выполняться.
  • – P – время в секундах, через которое происходит повторный опрос задания со стороны сервера Ansible.

Запросить статус задания можно через модуль async_status. В качестве параметра необходимо передать идентификатор задания:

ansible back -i inv.ini -b -K -m async_status -a "jid=j95838861652.2020"
roman@ansible:~$ ansible back -i inv.ini -b -K -m async_status -a "jid=j95838861652.2020"
BECOME password: 
tst2 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "ansible_job_id": "j95838861652.2020",
    "changed": true,
    "cmd": [
        "apt",
        "upgrade",
        "-y"
    ],
    "delta": "0:00:53.638043",
    "end": "2023-06-29 16:56:59.430687",
    "finished": 1,
    "msg": "",
    "rc": 0,
<....>

Это будет очень длинный вывод, но в нем нас интересуют следующие строки:

tst2 | CHANGED => {
    "changed": true,
    "finished": 1,
    "rc": 0,

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

На этом я завершаю публикацию про командный интерфейс Ansible. В следующей статье мы поговорим про Ansible playbook.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *