Факты Ansible: сбор информации об узлах

Рейтинг: 61% · 6 голосов
Подробный курс по Ansible с прицелом на экзамен RHCE EX294: установка и инвентарь, плейбуки, переменные и факты, Vault, циклы и условия, шаблоны Jinja2, роли и коллекции, Execution Environments и ansible-navigator, управление системами (диски, LVM, cron, SELinux, firewalld). Примеры на RHEL/Fedora. Актуально на 2026.
Ответить
Аватара пользователя
Maksim_DevOps
Сообщения: 47
Зарегистрирован: 11 май 2026, 05:31

Факты Ansible: сбор информации об узлах

Сообщение Maksim_DevOps »

Оглавление курса (47)
  1. Что такое Ansible и зачем он нужен: автоматизация без агентов
  2. Сертификация RHCE и экзамен EX294: что внутри и как готовиться
  3. Архитектура Ansible: control node, узлы, модули и плагины
  4. Установка Ansible на control node: dnf, pip и версии ansible-core
  5. Подготовка управляемых узлов: SSH, пользователь и sudo
  6. Инвентарь Ansible: hosts, группы и переменные
  7. Настройка Ansible: файл ansible.cfg и приоритеты конфигурации
  8. Host patterns и инструменты командной строки Ansible
  9. Ad hoc команды Ansible: быстрые задачи без плейбука
  10. Ansible playbook: что это такое и как устроен
  11. Структура плейбука: play, task, модули и переменные
  12. Запуск плейбуков: проверка, теги, ограничения и отладка
  13. Параллелизм и порядок выполнения: forks, serial, strategy
  14. Факты Ansible: сбор информации об узлах (вы здесь)
  15. Переменные Ansible: типы, объявление и приоритет
  16. Регистрация результатов и специальные переменные
  17. Ansible Vault: шифрование паролей и секретов
  18. Организация инвентаря: group_vars, host_vars и вложенные группы
  19. Динамический инвентарь и инвентарные плагины
  20. Циклы в Ansible: loop, списки и словари
  21. Повтор задачи до условия: until, retries и delay
  22. Условия в Ansible: директива when и логика
  23. Jinja2 в Ansible: выражения, фильтры и подстановки
  24. Обработчики Ansible: handlers, notify и flush_handlers
  25. Обработка ошибок: failed_when, changed_when и ignore_errors
  26. Блоки в Ansible: block, rescue и always
  27. Управление файлами: модули file, copy, fetch и stat
  28. Архивы и сборка файлов: archive, unarchive, assemble
  29. Точечное редактирование файлов: lineinfile и blockinfile
  30. Шаблоны Jinja2: модуль template и динамические конфиги
  31. Jinja2 продвинуто: фильтры, циклы, макросы и lookup
  32. Модули Ansible: ansible-doc и поиск нужного модуля
  33. Разработка собственного модуля Ansible на Python
  34. Роли Ansible и Ansible Galaxy: переиспользование
  35. Разработка роли Ansible: создание с нуля
  36. Зависимости ролей и requirements.yml
  37. Коллекции Ansible: ansible.posix, community и своя коллекция
  38. Execution Environments: контейнеры для запуска Ansible
  39. Сборка Execution Environment с ansible-builder
  40. ansible-navigator: запуск плейбуков в Execution Environment
  41. Управление SSH-ключами через Ansible: authorized_key
  42. Управление дисками: filesystem, mount и parted
  43. LVM через Ansible: тома, группы и расширение
  44. Планировщик задач: cron и systemd timers через Ansible
  45. Безопасность: hardening SSH и репозитории dnf/yum
  46. SELinux через Ansible: булевы, контексты и порты
  47. Сквозной проект и подготовка к экзамену EX294
Представь задачу: один и тот же плейбук должен раскатиться на RHEL 9, на старую CentOS 7 и заодно на пару серверов под Ubuntu. На RHEL пакеты ставятся через dnf, на Ubuntu - через apt. Имя сервиса где-то httpd, где-то apache2. Зашивать эти различия руками через списки хостов - путь в ад: добавил новую машину, забыл вписать, всё развалилось. Ansible решает это иначе. Перед тем как выполнить хоть одну задачу, он сам идёт на узел и собирает кучу данных о нём: какая ОС, сколько памяти, какие диски, какой IP на основном интерфейсе. Эти данные называются фактами (facts), и научиться ими пользоваться - это половина успеха на практике и прямой пункт программы экзамена RHCE.

В этом уроке разберём, как устроен сбор фактов ansible, как достать конкретное значение, как ускорить плейбук отключением сбора, и как добавить свои собственные факты - и системные через файлы, и вычисляемые прямо на лету.

Что такое ansible facts и откуда они берутся

Когда ты запускаешь плейбук, в самом начале каждого play Ansible незаметно выполняет задачу Gathering Facts. Под капотом это вызов модуля ansible.builtin.setup, который заходит на управляемый узел и снимает с него слепок системы. Результат складывается в одну большую переменную ansible_facts - это словарь с сотнями ключей.

Чтобы своими глазами увидеть, что там собирается, не нужен плейбук. Достаточно одной команды ad-hoc, и это самый быстрый способ понять, какие данные доступны:

Код: Выделить всё

ansible localhost -m ansible.builtin.setup
Вывалится простыня JSON. Среди самого ходового:
  • ansible_facts['os_family'] - семейство ОS. Для RHEL, CentOS, Rocky, AlmaLinux, Fedora это RedHat; для Ubuntu и Debian - Debian. Главный ключ для кросс-дистрибутивных плейбуков.
  • ansible_facts['distribution'] - конкретный дистрибутив: RedHat, Fedora, Ubuntu, а для российских - тут окажется значение вроде RED OS или Astra.
  • ansible_facts['distribution_version'] - версия, например 9.4.
  • ansible_facts['default_ipv4'] - словарь про основной интерфейс с ключами address, interface, gateway.
  • ansible_facts['memtotal_mb'] - всего оперативки в мегабайтах.
  • ansible_facts['hostname'] и ansible_facts['fqdn'] - короткое и полное имя.
Тут есть тонкость с обращением к фактам, на которой спотыкаются почти все новички. Долгое время факты жили как отдельные переменные с префиксом ansible_: ansible_os_family, ansible_distribution, ansible_default_ipv4. Этот старый плоский стиль до сих пор работает по умолчанию. Но современный и рекомендованный способ - лезть внутрь словаря ansible_facts. То есть ansible_facts['os_family'] вместо ansible_os_family, и ansible_facts['default_ipv4']['address'] вместо ansible_default_ipv4.address. На свежих установках оба варианта живут параллельно, но если кто-то выставил inject_facts_as_vars = false в конфиге, плоские ansible_* пропадут и останется только словарь. Поэтому привыкай сразу к форме через ansible_facts.

Изображение

Сбор фактов ansible на практике: условия и фильтрация

Факты сами по себе бесполезны - ценность в том, чтобы строить на них условия. Связка факт плюс when - это базовый приём, и именно его любят гонять на экзамене EX294. Классический пример: установить нужный веб-сервер в зависимости от семейства ОС.

Код: Выделить всё

- name: Поставить веб-сервер под нужный дистрибутив
  hosts: all
  become: true
  tasks:
    - name: RHEL-семейство - ставим httpd
      ansible.builtin.dnf:
        name: httpd
        state: present
      when: ansible_facts['os_family'] == "RedHat"

    - name: Debian-семейство - ставим apache2
      ansible.builtin.apt:
        name: apache2
        state: present
      when: ansible_facts['os_family'] == "Debian"
Обрати внимание: внутри when значение факта пишется без фигурных скобок Jinja. Скобки {{ }} нужны там, где факт подставляется в строку (например в шаблоне или в name), а в условии when выражение и так вычисляется как Jinja. Если обернёшь когда-нибудь when в {{ }}, получишь предупреждение - частая мелкая ошибка.

Полный слепок системы огромный, и каждый раз листать его глазами утомительно. У setup есть фильтр по подмножеству. Хочешь только сетевые факты - не тащи всё:

Код: Выделить всё

ansible web1 -m ansible.builtin.setup -a "filter=ansible_default_ipv4"
ansible web1 -m ansible.builtin.setup -a "gather_subset=network"
Параметр filter принимает шаблон с маской по именам ключей, а gather_subset ограничивает категории сбора: network, hardware, virtual, min и так далее. Через gather_subset с восклицательным знаком можно наоборот исключить тяжёлые куски, например gather_subset=!hardware пропустит долгое сканирование дисков и заметно ускорит сбор на медленных машинах.

gather_facts: false - когда сбор фактов мешает

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

Код: Выделить всё

- name: Быстрый плейбук без фактов
  hosts: all
  gather_facts: false
  tasks:
    - name: Перезапустить сервис
      ansible.builtin.service:
        name: chronyd
        state: restarted
Параметр ansible gather_facts задаётся на уровне play. Поставил false - и задача Gathering Facts просто не выполняется, ansible_facts остаётся пустым. Если факты вдруг понадобились внутри такого плейбука, их можно собрать вручную отдельной задачей через тот же модуль ansible.builtin.setup. Обратная ситуация тоже встречается: gather_facts по умолчанию true, но иногда его явно прописывают, чтобы код читался однозначно.

Кастомные факты: set_fact и локальные .fact файлы

Встроенных фактов не всегда хватает. Бывает, нужно вычислить значение в процессе работы плейбука или хранить на самом узле какие-то метаданные - роль сервера, окружение, версию приложения. Для этого есть два механизма.

Первый - модуль ansible set_fact. Он создаёт переменную (по сути тот же факт) прямо во время выполнения, на основе других фактов или результатов предыдущих задач:

Код: Выделить всё

- name: Вычислить размер кеша как четверть памяти
  ansible.builtin.set_fact:
    cache_size_mb: "{{ (ansible_facts['memtotal_mb'] * 0.25) | int }}"

- name: Показать вычисленное значение
  ansible.builtin.debug:
    msg: "Под кеш выделим {{ cache_size_mb }} МБ"
Факт, созданный через set_fact, живёт в рамках текущего прогона и виден в последующих задачах этого хоста. Удобно для всего, что считается на лету: собрать строку подключения, выбрать имя пакета, развести логику без дублирования when.

Второй механизм - локальные (кастомные) факты, они же local facts. Это данные, которые лежат на самом управляемом узле в каталоге /etc/ansible/facts.d/. Любой файл там с расширением .fact Ansible подхватит при сборе фактов. Формат файла - либо INI, либо JSON, либо исполняемый скрипт, печатающий JSON в stdout. Заведём статический факт в формате INI:

Код: Выделить всё

# файл /etc/ansible/facts.d/server.fact на управляемом узле
[role]
type=database
environment=production
Раскатить такой файл удобно самим же Ansible через ansible.builtin.copy. После следующего сбора фактов содержимое окажется в ansible_facts['ansible_local']['server']['role']['type'] со значением database. Ключевой момент: всё, что пришло из facts.d, складывается под отдельным ключом ansible_local - так системные факты и твои собственные не перемешиваются и не перетирают друг друга. Проверить, что узел отдаёт локальные факты, можно тем же setup:

Код: Выделить всё

ansible db1 -m ansible.builtin.setup -a "filter=ansible_local"
Если хочешь динамику - сделай файл .fact исполняемым скриптом, который сам считает данные и выдаёт JSON. Тогда факт будет пересчитываться при каждом сборе.

Типичные грабли
  • Статический .fact файл случайно сделали исполняемым. Если на INI- или JSON-файле стоит бит +x, Ansible попытается запустить его как скрипт, получит мусор вместо JSON и сломает сбор. Статические файлы должны быть БЕЗ права на исполнение, а вот скрипты - наоборот, с ним.
  • Обращение к плоским ansible_* там, где их отключили. Если inject_facts_as_vars = false, переменная ansible_os_family не существует, и плейбук падает с undefined. Пиши через ansible_facts['os_family'].
  • gather_facts: false и тут же обращение к факту. Отключил сбор - не удивляйся, что ansible_facts['distribution'] пустой. Либо включай сбор, либо собирай факты явной задачей.
  • set_fact не сохраняется между запусками. Его факты живут только в текущем прогоне. Нужно постоянное хранилище на узле - используй facts.d.
  • Кеш фактов и устаревшие данные. Для ускорения можно включить кеширование фактов (fact_caching в ansible.cfg, например на jsonfile или redis). Но если узел изменился - добавили память, сменили IP - кеш отдаст старое значение, пока не истечёт срок. На отладке держи это в голове.
Мини-лаба

Руками, на тестовой RHEL/Fedora-машине (или в контейнере):
  • Выполни ansible localhost -m ansible.builtin.setup и найди в выводе os_family, distribution_version, default_ipv4 и memtotal_mb.
  • Прогони сбор с фильтром: filter=ansible_distribution* и отдельно gather_subset=network. Сравни объём вывода.
  • Напиши плейбук, который через when и ansible_facts['os_family'] ставит httpd на RedHat и apache2 на Debian.
  • Через set_fact вычисли половину памяти узла и выведи debug-ом.
  • Положи на узел /etc/ansible/facts.d/server.fact с секцией [role], собери факты и достань значение из ansible_local. Убедись, что файл не исполняемый.
Контрольные вопросы
  • Какой модуль отвечает за сбор фактов и в какой переменной лежит результат?
  • Чем ansible_facts['os_family'] отличается от ansible_facts['distribution'] и когда какой использовать?
  • Что делает gather_facts: false и в каком случае это оправдано?
  • Где лежат локальные факты, под каким ключом они доступны и почему статический .fact файл нельзя делать исполняемым?
Итог

Факты - это глаза Ansible. Модуль setup собирает слепок узла в ansible_facts, ты строишь на нём условия through when, при необходимости фильтруешь сбор или вовсе глушишь его gather_facts: false ради скорости. Свои значения добавляешь двумя путями: set_fact для вычислений на лету и .fact файлы в /etc/ansible/facts.d для постоянных метаданных на узле. На экзамене RHCE связка факт плюс условие всплывает постоянно - доведи её до автоматизма, и половина заданий по идемпотентной настройке решается без раздумий.
👍5 ❤️3 🔥3 😄 🤔
Аватара пользователя
sunglasses
Сообщения: 1
Зарегистрирован: 11 май 2026, 15:34

Re: Факты Ansible: сбор информации об узлах

Сообщение sunglasses »

Спасибо, наконец дошло зачем ansible_facts через словарь, а не плоские ansible_. У меня как раз inject_facts_as_vars=false стоял и плейбук падал с undefined, теперь понятно почему.
👍1 ❤️1 🔥 😄 🤔
Аватара пользователя
ralegg
Сообщения: 1
Зарегистрирован: 13 май 2026, 23:19

Re: Факты Ansible: сбор информации об узлах

Сообщение ralegg »

А кеширование фактов на jsonfile реально ускоряет на большом парке? У нас ~300 хостов, старт по минуте уходит только на gather. Думаю включить redis, но боюсь словить устаревший IP после переезда машины.
👍 ❤️1 🔥 😄 🤔
Ответить
← Предыдущая глава
Параллелизм и порядок выполнения: forks, serial, strategy
Следующая глава →
Переменные Ansible: типы, объявление и приоритет

Все главы курса «Ansible: автоматизация и подготовка к RHCE (EX294)»

Поделиться темой: ✈ Telegram VK
Похожие запросы: что такое ansible простыми словамиansible для начинающих с чего начатьустановка ansible на linuxansible inventory и hosts файлчто такое playbook в ansibleструктура ansible playbook из чего состоит

Вернуться в «Ansible: автоматизация и подготовка к RHCE (EX294)»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость