Факты: что Ansible знает о хосте

Урок 12 - используем факты: автоматически собранную информацию о каждом сервере.

«Не спрашивай у пользователя, сколько на сервере ядер. Ansible уже знает - это факт».

Факты (facts) - это переменные, которые Ansible сам собирает о каждом хосте перед выполнением задач: ОС и её семейство, число процессоров, объём памяти, IP-адреса, имя хоста, версия дистрибутива и сотни других параметров. Они доступны через ansible_facts.

Откуда берутся факты

В начале каждого плея, если не отключено явно, Ansible запускает модуль setup - он и собирает факты. Их можно посмотреть ad-hoc командой:

# Показать все факты о хосте
ansible web1.example.com -m setup

# Только факты про память
ansible web1.example.com -m setup -a "filter=ansible_memory_mb"

Применение фактов

- name: Поставить пакет в зависимости от ОС
  ansible.builtin.package:
    name: "{{ 'apache2' if ansible_facts['os_family'] == 'Debian' else 'httpd' }}"
    state: present

- name: Задать число воркеров по числу ядер
  ansible.builtin.set_fact:
    workers: "{{ ansible_facts['processor_vcpus'] }}"

Факты особенно полезны в when и в Jinja2-шаблонах: одна и та же роль адаптируется под разные ОС и железо без ручных настроек.

Как работает под капотом

Сбор фактов - это запуск модуля setup на хосте, который опрашивает систему (через /proc, системные утилиты) и возвращает большой JSON. Этот JSON и становится словарём ansible_facts. Сбор занимает время, поэтому на больших инвентарях его иногда отключают через gather_facts: false или кешируют между запусками.

Смоделируем выбор пакета по факту ОС - типовая логика «адаптации под систему».

# Выбор имени пакета по факту об ОС
def pick_package(facts):
    family = facts.get("os_family")
    table = {"Debian": "apache2", "RedHat": "httpd"}
    return table.get(family, "apache2")

debian_host = {"os_family": "Debian", "processor_vcpus": 4}
rhel_host   = {"os_family": "RedHat", "processor_vcpus": 8}

print("Debian ->", pick_package(debian_host))  # apache2
print("RedHat ->", pick_package(rhel_host))    # httpd
print("Воркеров на RHEL:", rhel_host["processor_vcpus"])

Попробуй сам ▶ Один и тот же код выбирает разные пакеты в зависимости от факта об ОС. Так роли становятся переносимыми между дистрибутивами без правок.

Кеширование и gather_facts

- name: Быстрый плей без сбора фактов
  hosts: web
  gather_facts: false      # факты не нужны - экономим время
  tasks:
    - name: Просто перезапустить сервис
      ansible.builtin.service:
        name: nginx
        state: restarted

Если факты не используются, gather_facts: false ускоряет плей. Если используются часто - настраивают кеш фактов (fact caching), чтобы не пересобирать их каждый раз.

Частые ошибки

  • Использовать факт при gather_facts: false. Если сбор отключён, ansible_facts пуст - переменная будет undefined.
  • Старый синтаксис фактов. Раньше писали ansible_os_family; современная форма - ansible_facts['os_family'].
  • Опираться на факт, которого нет на этой ОС. Набор фактов разный; проверяй через setup.

Best practices

  • Используй факты для переносимости ролей между дистрибутивами и железом.
  • Отключай gather_facts там, где факты не нужны - это ускоряет прогон.
  • На больших инвентарях настрой кеш фактов, чтобы не пересобирать их каждый раз.

В реальной работе

Факты делают роли по-настоящему переносимыми. Одна и та же роль ставит веб-сервер и на Debian (пакет apache2), и на RHEL (пакет httpd), выбирая нужное по факту os_family - без ветвления вручную под каждый сервер. Кроме встроенных фактов, можно заводить кастомные: положить на хост файл в /etc/ansible/facts.d/, и его содержимое появится среди фактов под ключом ansible_local. Так на сервере хранят, например, метку «этот хост обслуживает такого-то клиента», и playbook'и адаптируются под неё. А на больших инвентарях обязательно настраивают кеш фактов: пересобирать сотни параметров с каждого из трёхсот серверов на каждом прогоне - дорого, кеш экономит минуты.

Итоги

Факты - автоматически собранная информация о хостах (ОС, железо, сеть), доступная через ansible_facts. Они делают роли адаптивными. Сбор можно отключать или кешировать ради скорости. Дальше превратим переменные и факты в реальные конфиги через Jinja2.

Проверьте себя
1. Что такое факты (facts) в Ansible?
AПеременные, которые пишет пользователь вручную
BИнформация о хосте (ОС, железо, сеть), автоматически собранная Ansible и доступная в ansible_facts
CЛоги выполнения задач
DИмена групп инвентаря
2. Зачем ставить gather_facts: false?
AЧтобы скрыть хосты
BЧтобы ускорить плей, когда факты в нём не используются
CЧтобы факты собирались дважды
DЧтобы включить отладку