Введение в Ansible

Ansible — это отличная штука для того чтобы работать с серверами. Если вы иногда заходите по ssh на сервер чтобы там что-нибудь выполнить, то вам стоит посмотреть на Ansible и, возможно, начать его использовать.

Сначала нужно поставить Ansible. Если вы работаете на маке, то он устанавливается с помощью стандартного:

brew install ansible

После того как Ansible установлен, можно начинать его использовать. Специально для написания этой статьи я поднял 2 тестовые машинки. Я не хочу показывать свои настоящие сервера, поэтому я запустил несколько docker контейнеров (можно было бы взять какой-нибудь VirtualBox и поднять несколько виртуалок, но докер для меня удобнее). В реальной жизни я управляю серверами, которые живут на digitalocean.com. Я настроил эти тестовые докер контейнеры так что я могу зайти на них с помощью команд:

ssh root@192.168.99.100 -p 2014
ssh root@192.168.99.100 -p 2016

Т.е. обе эти машинки живут на одном и том же айпишнике (айпишник докера), но на разных портах.

Ansible начинается с inventory файла. Это файл в котором записаны все сервера, которыми нужно управлять через Ansible. Обычно этот файл называется hosts. Чаще всего hosts файл — это просто перечисление hostname серверов:

server_a
server_b

Но в моем экспериментальном примере у моих машинок нет хостнеймов, плюс ssh работает не на стандартном 22 порту, и подключаюсь я не под своим пользователем, а под root. Так что мой inventory файл получает дополнительные параметры:

server_a ansible_host=192.168.99.100 ansible_port=2014 ansible_user=root
server_b ansible_host=192.168.99.100 ansible_port=2016 ansible_user=root

В данном случае имена server_a и server_b — это просто алиасы для Ansible, ничто больше в системе не знает про эти алиасы, но Ansible когда их видит понимает что нужно зайти по ssh на ip/порт и использовать указанное имя пользователя.

Все =) Ansible установлен, inventory файл написан, теперь можно начать использовать Ansible.

Самое простое что можно сделать — это проверить что все машины доступны

$ ansible -i hosts all -m ping
server_b | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
server_a | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

Вот что означают параметры, которые мы указали для программы ansible:

-i hosts    # указали где находится invetory файл
all         # паттерн для выбора хоста. `all` — это специально слово,
            # означает что нужно взять все хосты
-m ping     # модуль который нужно выполнить

При запуске этой команды, Ansible прочитал inventory файл, создал список хостов, которые попадают под указанный паттерн и для каждого хоста выполнил следующие действия:

Несмотря на название модуль ping никак не связан с командой ping — этот модуль ничего не пингует — он просто проверят что на указанные машинки можно зайти по ssh и что на этой машинке можно запустить этот python скрипт ping.

Модуль ping вполне может выдать ошибки. Например, если на машинке нет python, то мы получим:

$ ansible -i hosts server_b -m ping
server_b | FAILED! => {
    "changed": false,
    "failed": true,
    "module_stderr": "",
    "module_stdout": "/bin/sh: 1: /usr/bin/python: not found\r\n",
    "msg": "MODULE FAILURE",
    "parsed": false
}

А если машинка не доступна по сети, или не пускает по ssh, то ошибка будет:

$ ansible -i hosts server_a -m ping
server_a | UNREACHABLE! => {
    "changed": false,
    "msg": "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
}

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

Давайте попробуем что-нибудь более интересное чем модуль ping.

Вот как запустить на всех машинках из inventory файла команду:

$ ansible -i hosts all -m shell -a 'cat /etc/lsb-release | grep DISTRIB_RELEASE'
server_b | SUCCESS | rc=0 >>
DISTRIB_RELEASE=16.04

server_a | SUCCESS | rc=0 >>
DISTRIB_RELEASE=14.04

Тут мы использовали модуль shell и передали ему аргумент — строку которую нужно выполнить в консоли. Ansible выполнил эту команду на обоих машинках, и показал их вывод. Вот так с помощью запуска одной команду на локальной машине мы получили информацию про версию ubuntu на двух серверах.

Команда ansible — это очень удобная штука для одноразового запуска команд на удаленных серверах. Даже если сервер один, иногда удобнее использовать команду ansible для того чтобы быстро что-нибудь сделать с этим сервером (ansible особенно помогает, когда до сервера плохая связь — тогда на удаленный машине неудобно работать — из-за сети все тормозит, поэтому набрать команду на локальном ноутбуке быстрее и приятнее).

Но самая мощь Ansible — это команда ansible-playbook — с ее помощью можно накатывать определенный набор команд для полной настройки серверов. С помощью плейбуков получается хранить изменения инфраструктуры в репозитории — и это волшебно прекрасно: есть вся история изменений, всегда можно откатиться на прошлую версию настроек, видно кто и когда что сделал с серверами. Но про ansible-playbook — в следующий раз.

Иван Бессарабов
ivan@bessarabov.ru

29 апреля 2017