Что такое Ansible?
Ansible - это система управления конфигурациями, с помощью которой можно эффективно управлять
большим количеством серверов.
Что такое система управления конфигурациями?
Это инструмент в помощь системным администраторам и DevOps инженерам для быстрого выполнения команд
и управления состоянием большого количества серверов. Среди известных можно назвать
Puppet, Chef, fabrica и, собственно, Ansible.
Обычно их делят на реализующие
pull-модель и
push-модель.
Pull-модель преполагает, что управляемые хосты подтягивают инструкции с мастер-сервера.
Push-модель реализует подход, когда инструкции по желанию или по событию доставляются с управляющего на управляемые хосты.
Ansible чаще всего используется для push-модели управления, но умеет и pull-модель.
У меня всё заскриптовано bash скриптами. Чем какая-то система будет лучше?
Системы управления конфигурациями позволяют гибко описывать шаблоны конфигурационных файлов, выполнять сценарии параллельно на группах серверов,
быстрее адаптировать сценарии к разным условиям - разные дистрибутивы, версии ПО и т.д.
Кроме того, описать состояние большого окружения на bash так, чтобы это было понятно коллегам, задача очень непростая.
Такие системы побуждают инженеров содержать описание большой инфраструктуры в опрятном виде, более подходящем для командной работы.
А чем Ansible лучше остальных?
Выгодные отличия Ansible от других систем управления конфигурациями:
- быстро осваивается, достаточно поверхностного понимания синтаксиса YAML и Jinja
- нет необходимости устанавливать специальное ПО на хосты, нужен только SSH и python
- подробная и наглядная документация
- большое количество модулей
- позволяет реализовать принцип идемпотентности в управлении состояниями хостов
Что такое идемпотентность?
Это важный момент, разберем подробно.
Идемпотентность - это такая характеристика действия, согласно которой повторное
выполнение этого действия будет давать тот же результат, что и первый запуск.
В контексте систем управления конфигурациями это означает, что сценарии, написанные с соблюдением такого подхода, не изменят,
не сломают и не выдадут ошибок на управляемом хосте при повторном запуске.
Например, нам нужно добавить пользователя на хост, для bash это будет выглядеть так:
useradd newuser -ms /bin/bash
Но если мы запустим команду второй раз, то получим ошибку
useradd newuser -ms /bin/bash
useradd: user 'newuser' already exists
Поэтому нам нужно дополнительно добавлять проверку, например так:
id newuser || useradd newuser -ms /bin/bash
В случае Ansible мы только декларируем состояние, например:
- hosts: localhost
gather_facts: no
tasks:
- user:
name: newuser
shell: /bin/bash
state: present
При первом запуске плейбук Ansible ответит:
TASK [user] ***
changed: [localhost] => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"comment": "",
"create_home": true,
"group": 1001,
"home": "/home/newuser",
"name": "newuser",
"shell": "/bin/bash",
"state": "present",
"system": false,
"uid": 1001
}
При повторном:
TASK [user] ***
ok: [localhost] => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"append": false,
"changed": false,
"comment": "",
"group": 1001,
"home": "/home/newuser",
"move_home": false,
"name": "newuser",
"shell": "/bin/bash",
"state":
"present",
"uid": 1001
}
Обратите внимание, что статус задания сменился с `changed` на `ok` и повторный запуск вернул значение `"changed": false`
Таким образом, сценарии, написанные с учетом идемпотентности, реализуют ту самую декларативность в описании состояния инфраструктуры,
а инфраструктура соответствует состоянию, описанному в коде нашего скрипта.
Это и есть
Iac - Infrastructure as Code - инфраструктура как код.
Основная терминология Ansible
Инвентарь (Inventory) - cписок хостов, может быть статичным в виде текcтового файла в формате ini или динамическим в
виде скрипта или плагина, который подгружает структуру данных из стороннего источника, например, Openstack API или база LDAP.
$ cat hosts
[web]
nginx01
nginx02
nginx03
[mysql]
mysql01
mysql02
mysql03
[prod:children]
web
mysql
[devel]
dev-nginx01
dev-mysql01
Данный пример описывает группы хостов web, mysql, prod и devel, группа prod наследует содержимое групп web и mysql.
Задание (Task) - атомарная операция, выполняемая на управляемом хосте, например:
apt:
package: nginx
state: present
Данный пример аналогичен команде `apt install nginx`
Сценарий (Play) или
Плейбук (Playbook) - сценарий или скрипт, содержащий одну или несколько заданий на выполнение, например:
$ cat prod-playbook.yml
---
- hosts: nginx
tasks:
- apt:
package: nginx
state: present
- shell: whoami
Роль (Role) - более сложная абстракция, выглядит как структура директорий и файлов, которые описывают набор дефолтных переменных,
зависимостей от других ролей, может содердать содержит файлы, темплейтов и задания.
Факты (Facts) - структура данных, которая содержит информацию о хосте, например, версию дистрибутива, IP адреса и файловые системы.
Ansible забирает эту информацию с хоста, и на нее можно ссылаться в коде плейбуков и ролей.
Сбор фактов хоста занимает некоторое время, поэтому их можно кэшировать или отключить их сбор при выполнении плейбука.
Структура проекта Ansible
В общем случае структура файлов и директорий выглядит примерно таким образом:
.
├── ansible.cfg
├── group_vars
│ └── all.yml
├── host_vars
├── hosts
│ ├── all.yml
│ ├── localhost.yml
│ └── openstack.yml
├── playbook_01.yml
├── playbook_02.yml
└── roles
└── nginx
├── defaults
├── handlers
├── tasks
└── templates
ansible.cfg - файл конфигурации
group_vars - переменные, которые являются атрибутами групп хостов
host_vars - переменные, которые являются атрибутами хостов
hosts - инвентарь со списками хостов
roles - директория, содержащая роли
playbook_0[12].yml - плейбуки для выполнения
group_vars, host_vars, hosts могут быть файлами или директориями, содержащими какую-то семантическую человекочитаемую иерархию, например:
group_vars/
├── all.yml
├── mysql
├── nginx
└── users
Основные команды
Их две:
anible и
ansible-playbook
Команда ansible служит для вызова отдельных модулей, например:
ansible all -m shell -a "lscpu"
Здесь мы вызываем модуль shell для выполнения команды на всех хостах и аргументом передаем команду, которую хотим запустить.
Для запуска сценария передаем файл команде ansible-playbook:
ansible-playbook playbook_01.yml -D -vv -C
Параметр -C/--check запускает плейбук в режиме check_mode, в тестовом режиме прогонит задания, не выполняя их фактически.
Здесь следует иметь в виду, что некоторые модули, например, shell или command не умеют отрабатывать check_mode, о чем сообщают в выводе
при запуске с -C/--check, поэтому следует ими пользоваться только в особых случаях.
Параметр -D/--diff покажет в diff формате разницу старого и нового состояния файлов.
Теперь, познакомившить с основными принципами и понятиями Ansible, можно
установить виртуальный
сервер из шаблона 'Openstack & Ansible shellbox' с готовой к работе структурой файлов Ansible, и попробовать его на практике.