Ansible - начало работы

Майкл ДеХаан позаимствовал название Ansible из книги Орсона Скотта Карда «Игра Эндера». В этой книге Ansible использовался для одновременного контроля большого числа кораблей, удаленных на огромные расстояния.

Подготовка к работе

  1. Ставим ansible на машину управления (int-bak)
sudo apt update; sudo apt -y install ansible
curl -fsSL -o- https://bootstrap.pypa.io/pip/3.5/get-pip.py | python3.5
pip3 install ansible
  1. Готовим файл описания хостов /etc/ansible/hosts
....
[rabbits]
ansible-rabbit-1 ansible_ssh_host=10.0.4.132
ansible-rabbit-2 ansible_ssh_host=10.0.4.191
ansible-rabbit-3 ansible_ssh_host=10.0.4.112
ansible-rabbit-4 ansible_ssh_host=10.0.4.39 ansible_user=centos
ansible-rabbit-5 ansible_ssh_host=10.0.4.219 ansible_user=fedora

[rabbits_ubuntu]
ansible-rabbit-1 ansible_ssh_host=10.0.4.132
ansible-rabbit-2 ansible_ssh_host=10.0.4.191
ansible-rabbit-3 ansible_ssh_host=10.0.4.112

[rabbits_ubuntu:vars]
ansible_user=ubuntu
ansible_python_interpreter=/usr/bin/python3

Здесь хороший пример, как можно задать общие параметры для группы хостов rabbits_ubuntu. Для этого создается секция с именем группы и постфиксом :vars.

  1. Добавляем на все необходимые хосты публичную часть ключа (для примера getter.pub) Для этого хорошо подходит моя утилита saveprep из комплекта savior (https://git.gkomega.ru/sani/savior.git )

  2. Создаем папку /etc/ansible/keys и добавляем в нее приватную часть ключа getter.pem, по которому мы будем попадать во все наши контролируемые серверы (инстансы).

  3. Добавляем начальные настройки в файл /etc/ansible/ansible.cfg

[defaults]
inventory      = /etc/ansible/hosts
host_key_checking = False
log_path = /var/log/ansible/ansible.log
private_key_file = /etc/ansible/keys/getter.pem
[privilege_escalation]
[paramiko_connection]
[ssh_connection]
[accelerate]
[selinux]
  1. Теперь проверим подключение к удаленной машине:
ansible ansible-rabbit-2 -m ping -vvvv

Если в результате мы получаем ошибку, например, такую:

Using /etc/ansible/ansible.cfg as config file
10.0.4.132 | FAILED! => {
    "changed": false,
    "failed": true,
    "module_stderr": "",
    "module_stdout": "Traceback (most recent call last):\r\n  File \"/home/ubuntu/.ansible/tmp/ansible-tmp-1628577501.51-58083218354595/ping\", line 44, in <module>\r\n    import exceptions\r\nImportError: No module named 'exceptions'\r\n",
    "msg": "MODULE FAILURE",
    "parsed": false
}

Изначально возникает предположение, что на целевой машине не хватает python модуля exceptions. Но это неверно. На сервере управления ansible (int-bak) была установлена версия по-умолчанию python 2.7.12 и она не совпадала с той, что на управляемой машине (python 3.5). Но, на сервере и всех агентских машинах не обязательно должна быть одинаковая мажорная версия python! Причина этой ошибки в моем случае заключалась в том, что на сервере int-bak был некорректно установлен ansible и его пакеты. Когда я установил ansible на ВМ sakai с Python 3.9.4 и pip-модуль ansible, то все хорошо заработало и не пришлось “допиливать” целевые хосты.

Другая распространенная ошибка:

10.0.4.132 | UNREACHABLE! => {
    "changed": false,
    "msg": "ERROR! SSH encountered an unknown error during the connection. We recommend you re-run the command using -vvvv, which will enable SSH debugging output to help diagnose the issue",
    "unreachable": true
}

Проверьте, доступен ли тестируемый сервер, и корректность установки ключа.

Если на удаленном сервере все успешно отработало, то будет примерно такое сообщение:

Using /etc/ansible/ansible.cfg as config file
ansible-rabbit-2 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

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

$ ansible ansible-rabbit-4 -m command -a uptime
ansible-rabbit-4 | CHANGED | rc=0 >>
 09:45:56 up 19:40,  2 users,  load average: 0.00, 0.01, 0.05

Модуль command настолько часто используется, что сделан модулем по умолчанию, то есть его имя можно опустить в команде:

# ansible ansible-rabbit-4 -a who
ansible-rabbit-4 | CHANGED | rc=0 >>
centos   pts/0        2021-08-10 09:21 (192.168.64.3)
centos   pts/1        2021-08-10 09:49 (10.33.8.22)

Если команда использует аттрибуты, то ее нужно заключать в кавычки:

# ansible ansible-rabbit-4 -a 'sudo grep bash /etc/passwd'
ansible-rabbit-4 | CHANGED | rc=0 >>
root:x:0:0:root:/root:/bin/bash
centos:x:1000:1000:Cloud User:/home/centos:/bin/bash

Кроме того, надо помнить, что некоторые команды требуют привилегий суперпользователя и требуют добавления sudo, и отключения запроса пароля в файле /etc/sudoers.

Первое задание

## Если необходимо поправить python на целевой ВМ

Надо обеспечить функционирование исполнения программ на python, которые использует ansible при работе на подконтрольном сервере. Как выяснилось в процессе изучения, в этом нет необходимости. Все штатные образы openstack заработали сразу без напильника. Однако, в книге Хофштена “Запускаем ansible” сказано, что не целевой машине должен быть обязательно установлен python и модуль simplejson. Поначалу, это несколько сбило меня с толку, и я принялся доустанавливать некоторые компоненты python. Например, для штатного образа openstack ubuntu16 (python3.5), я установил дополнительно:

# правильная установка pip3 !
curl -fsSL -o- https://bootstrap.pypa.io/pip/3.5/get-pip.py | python3.5
pip install ansible
pip install python-docx
#x# pip install docx # этот модуль не надо ставить!
### apt install python3-simplejson

Это занимает довольно продолжительное время. В крупных проектах, целесообразно подготовить собственные шаблоны всех используемых операционных систем с заранее подготовленным python-окружением для ansible.

Исправляем, как обычно:

update-alternatives --list python
update-alternatives --install /usr/bin/python python /usr/bin/python3.5 1
update-alternatives --install /usr/bin/python python /usr/bin/python2.7 2
update-alternatives --config python
python -V