Файл inventory
Список хостов с тэгами (группами), на которые впоследствии ссылаются в задачах.
Последовательность поиска файла
По умолчанию: /etc/ansible/hosts
Однако проще указывать файл при запуске playbook
ansible-playbook -i my_inventory.ini playbook.yml
Форматы файлов:
Есть динамический, ini и yaml формат. Определяет формат по содержанию файла, расширение файла (.ini, .yaml, .yml) не играет роли. Порядок анализа:
- Является ли файл исполняемым — если да, то запускает его как динамический inventory
- Пытается распарсить как INI — если получается, использует INI-формат
- Пытается распарсить как YAML — если получается, использует YAML-формат
- Если ничего не подошло — выдает ошибку
Важно:
- Нельзя смешивать форматы в одном файле
- Способ отличия форматов:
INI-формат: начинается с секций в квадратных скобках [group]
YAML-формат: начинается с --- (опционально) или со слова all: / children: / hosts: - Автодетект может ошибаться. Если будет файл, валидный как INI и как YAML, то Ansible выберет INI.
Проверка, как Ansible интерпретирует ваш файл:
# Покажет структуру inventory в JSON
ansible-inventory -i ваш_файл --list
# Покажет в удобном для человека виде
ansible-inventory -i ваш_файл --graph
Можно в директории хранить несколько файлов и использовать их по необходимости.
# Посмотреть все хосты из inventory
ansible all -i inventory.ini --list-hosts
# Посмотреть переменные конкретного хоста
ansible -i inventory.ini web1 -m debug -a "var=hostvars[inventory_hostname]"
# Выполнить команду на группе серверов
ansible web_servers -i inventory.ini -m command -a "df -h"
ini формат:
Ожидается, что hosts в формате ini.
[example]
www.example.com
192.168.0.1
192.168.0.2:2222
Внутри [] название группы, далее состав этой группы (доменное имя или IP). Указание порта определяет порт ssh сервера.
Вложенные группы
При указании :children создается метагруппа. То есть
[staging:children]
web_servers
db_servers
создаст группу staging, которая будет состоять из хостов группы web_servers и db_servers. Это именно группы, хосты указывать в метагруппе нельзя. Можно городить любую иерархию, одна метагруппа внутри другой.
Диапазоны
web[01:05].example.com
Переменные
Для хоста переменные через пробел в одной строке
[databases]
192.168.1.20 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/ubuntu-key.pem
При помощи :vars задаются переменные для группы
[staging:vars]
ansible_user=staging_user
env=staging
app_version=latest
yaml формат
| Когда использовать YAML | Когда проще INI |
|
Сложная иерархия групп (3+ уровня) Много переменных со сложными типами (списки, словари) Храните инвентарь в Git (лучше для code review) Команда привыкла к YAML |
Мало хостов (<20) Простая структура (1-2 уровня групп) Быстрые временные инвентари |
Корневая группа одна — all. Группа all является специальной встроенной группой Ansible:
- в неё входят все хосты inventory
- все группы являются её потомками (напрямую или косвенно)
Поддерживает диапазоны аналогично ini
Если будет несколько корневых групп, то будет ошибка. Структура файла настроек:
all:
hosts:
vars:
children:
Хосты:
Внутри hosts указываются переменные для хоста.
all:
hosts:
server1:
ansible_host: 192.168.1.10
server2:
ansible_host: 192.168.1.11
Переменные:
vars:
http_port: 80
app_user: nginx
Переменные из all.vars наследуются всеми хостами
Теперь переменные доступны в playbook
- name: Show port
debug:
msg: "{{ http_port }}"
Переменные переопределяются по иерархии.
Создание дальнейшей вложенной структуры создает вложенную структуру переменной:
all:
hosts:
db-master:
replication:
role: master
sync_mode: synchronous
То есть у хоста db-master переменные replication.role и replication.sync_mode. Можно также использовать списки:
vars:
allowed_ips:
- 192.168.1.0/24
- 10.0.0.0/8
Группы:
Внутри children указываются имена дочерних групп и их настройки. Структура дочерних групп аналогичная. Допускается множественное вложение.
all:
children:
webservers:
hosts:
web1:
ansible_host: 10.0.0.10
web2:
ansible_host: 10.0.0.11
dbservers:
hosts:
db1:
ansible_host: 10.0.0.20
Множественное вложение:
all:
children:
msk_web:
hosts:
msk-web-01:
msk-web-02:
msk_db:
hosts:
msk-db-01:
spb_web:
hosts:
spb-web-01:
spb_db:
hosts:
spb-db-01:
msk:
children:
msk_web
msk_db
vars:
datacenter: moscow
region: central
spb:
children:
spb_web
spb_db
vars:
datacenter: st_petersburg
region: north-west
russia:
children:
msk
spb
production:
children:
russia
vars:
env: production
monitoring_enabled: true
Однако при усложнении правил (субъективно) теряется сама идея простоты настройки. То есть приходится объяснять правила объединения, рисовать зависимости, ... А когда переменные еще и отличаются для разных групп, и этих групп много, то все становится совсем плохо.
Выполнение playbook только для группы:
ansible-playbook -i inventory.yml site.yml --limit webservers
Можно использовать якоря
defaults: &defaults
ansible_user: admin
ansible_port: 22
webservers:
hosts:
web1:
<<: *defaults
ansible_host: 192.168.1.10
web2:
<<: *defaults
ansible_host: 192.168.1.11
Разделение данных на файлы
Предыдущий текст относится к ситуации, когда хосты и переменные расположены в одном файле. Есть возможность разбить проект на специально названные файлы. Например:
inventory/
└── testing/
├── hosts.yml
├── group_vars/
│ ├── all.yml
└── production/
├── hosts.yml
├── group_vars/
│ ├── all.yml
│ ├── webservers.yml
│ └── dbservers.yml
└── host_vars/
├── web1.yml
└── db1.yml
Создана директория inventory, внутри окружения testing и production, в каждом окружении файл hosts.yml и директории group_vars и host_vars. Запуск playbook будет выглядеть так:
ansible-playbook -i inventory/production/hosts.yml site.yml
hosts.yml: только хосты/группы, стандартная структура без переменных.
all:
children:
webservers:
hosts:
web1:
web2:
dbservers:
hosts:
db1:
group_vars/all.yml: Переменные для всех групп, все пишется на одном уровне
ansible_user: ubuntu
timezone: Europe/Amsterdam
group_vars/<group_name>.yml: Переменные для группы group_name, все пишется на одном уровне
host_vars/<host_name>.yml: Переменные только для хоста <host_name>
Динамический файл