Динамический Ansible inventory в zVirt
- Динамический inventory в Ansible
-
Механизм, который позволяет Ansible динамически находить и использовать инвентаризационные данные в реальном времени из внешних источников, таких как API, базы данных и другие источники данных, а не только из INI- YAML-файлов инвентаризации.
В zVirt динамический inventory реализован за счёт обращение к API и сбору информации о хостах, формировании системных переменные и группировке хостов на основе общих метаданных (принадлежность к кластеру или наличие тега).
1. Подготовка
Для того, чтобы можно было работать с динамическим inventory в zVirt, необходимо подготовить файлы ansible.cfg и сам динамический inventory.
динамический inventory обязательно должен иметь название ovirt.yaml, так как Python проводит валидацию названия файла. |
В файле ansible.cfg вам необходимо активировать плагин ovirt.ovirt.ovirt (этот плагин отвечает за работу динамического inventory) в секции [inventory].
Пример ниже:
[inventory]
enable_plugins = ovirt.ovirt.ovirt, yaml, ini
По-умолчанию используется следующие форматы: host_list, script, auto, yaml, ini, toml.
Если необходимо использовать иные плагины, помимо указанных в примере ansible.cfg, можно просто добавить их в список.
Далее нужно настроить сам inventory ovirt.yaml:
plugin: ovirt.ovirt.ovirt # Название плагина
ovirt_url: "https://zvirt.example.ru/ovirt-engine/api" # URL API zVirt
ovirt_cafile: "/root/zvirt/ca.cer" # Путь до корневого сертификат zVirt. Файл можно положить в любую директорию, путь рекомендуется указывать абсолютный
ovirt_username: admin@internal # Имя пользователя с указанием пространства имён. Локальные пользователи в zVirt находятся в пространстве @internal
ovirt_password: admin # Пароль учётной записи
ovirt_query_filter: # Указывается запрос для поиска хостов для Inventory
search: 'name=*' # Запрос 'name=*' выбирает ВМ с любым именем
# search: 'name=* AND cluster=SecondCluster' # Пример запроса, в котором выбираются ВМ с любым именем, состоящие в кластере SecondCluster
case_sensitive: no # Указание необходимости учитывать регистр
После создания файла, необходимо проверить работу. Для этого достаточно воспользоваться командой:
ansible-inventory --graph
Либо можно указать inventory файл прямо в CLI:
ansible-inventory -i /path/to/inventory/ovirt.yaml --graph
Команда должна обнаружить все ВМ:
@all:
|--@ungrouped:
| |--CentOS8Template
| |--my-zvirt-vm
| |--nginx
2. Группировка хостов
Динамический inventory позволяет также группировать хосты. Пример группировки по кластеру и тегу ниже:
plugin: ovirt.ovirt.ovirt
ovirt_url: "https://zvirt.example.ru/ovirt-engine/api"
ovirt_cafile: "/root/zvirt/ca.cer"
ovirt_username: admin@internal
ovirt_password: admin
ovirt_query_filter:
search: 'name=*'
case_sensitive: no
keyed_groups:
- key: cluster # Группировка по ключу cluster
prefix: "cluster" # Префикс группы. В название группы будет добавлен префикс, указанный здесь. Префикс и значение ключа будут разделены нижним прочерком.
- key: tags # Группировка по ключу tags
prefix: "tag"
Вывод такого inventory:
@all:
|--@ungrouped:
|--@cluster_Default:
| |--CentOS8Template
| |--my-zvirt-vm
| |--nginx
|--@tag_my_zvirt_tag:
| |--my-zvirt-vm
|--@tag_nginx:
| |--nginx
Все виртуальные машины попали в группу cluster_Default, ВМ nginx попала в группу tag_nginx, а ВМ my-zvirt-vm попала в группу tag_my_zvirt_tag.
3. Добавление переменной "ansible_host"
Чтобы хостам в inventory автоматически назначался ansible_host IP-адресом, можно воспользоваться compose в inventory-файле.
Для этого создайте следующий inventory:
plugin: ovirt.ovirt.ovirt
ovirt_url: "https://zvirt.example.ru/ovirt-engine/api"
ovirt_cafile: "/root/zvirt/ca.cer"
ovirt_username: admin@internal
ovirt_password: admin
ovirt_query_filter:
search: 'name=*'
case_sensitive: no
keyed_groups:
- key: cluster
prefix: "cluster"
compose:
ansible_host: devices["enp1s0"][0] # Будет произведена композиция переменной ansible_host по ключу devices, в котором выбирается устройство enp1s0 и выбирается первый элемент списка IP-адресов уйстройства
Проверка inventory:
"my-zvirt-vm": {
"ansible_host": "10.0.88.19",
"cluster": "Default",
"devices": {
"enp1s0": [
"10.0.88.19",
"fe80::546f:feff:feaa:2"
]
},
"name": "my-zvirt-vm",
"status": "up",
"tags": [
"my-zvirt-tag"
]
},
"nginx": {
"ansible_host": "10.0.88.18",
"cluster": "Default",
"devices": {
"enp1s0": [
"10.0.88.18",
"fe80::546f:feff:feaa:1"
]
},
"name": "nginx",
"status": "up",
"tags": [
"nginx"
]
}
Вывод выше неполный, так как помимо указанных переменных, есть и иные, однако, для упрощения понимания были выбраны лишь самые важные.
В compose мы указывали выбрать из devices устройство enp1s0 и уже из него выбрать первый элемент списка. В devices обоих хостов входит устройство enp1s0. У устройства есть список, в котором каждый элемент из себя представляет IP-адрес, в данном случае у обоих хостов у устройства enp1s0 сначала идёт IPv4, затем IPv6. Как раз первый элемент списка мы указывали в ovirt.yaml и переменной ansible_host присвоилось нужное значение.
Название устройств может разниться у разных ОС, перед указанием compose рекомендуем изучить вывод |
4. Тестирование
Для проверки был запущен модуль ping для различных групп, составленных с помощью динамического inventory
ansible-inventory --graph -i inventory/ovirt.yaml
Вывод:
@all:
|--@ungrouped:
|--@cluster_Default:
| |--CentOS8Template
| |--my-zvirt-vm
| |--nginx
|--@tag_my_zvirt_tag:
| |--my-zvirt-vm
|--@tag_nginx:
| |--nginx
[root@ansible ansible]$ ansible tag_nginx -m ping
nginx | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
[root@ansible ansible]$ ansible tag_my_zvirt_tag -m ping
my-zvirt-vm | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
[root@ansible ansible]$ ansible cluster_Default -m ping
nginx | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
my-zvirt-vm | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
CentOS8Template | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}