Ansible не ставит на управляемые машины никакого агента. Это его главная фишка и одновременно источник большинства проблем у новичков. Вместо демона он подключается к серверу по обычному SSH, копирует туда временный модуль на Python, выполняет его, забирает результат и стирает за собой. Из этого выводится весь список того, что должно быть на узле, чтобы плейбук вообще запустился.
Подготовка узлов ansible сводится к трём вещам. Первое - туда должен пускать SSH без интерактивного ввода пароля, то есть по ключу. Второе - на узле должен быть интерпретатор Python, потому что почти все модули написаны на нём. Третье - у тебя должна быть возможность поднять права до root, потому что устанавливать пакеты или править firewalld от обычного юзера не выйдет.
Звучит просто, но именно на этом этапе спотыкается половина людей, которые потом пишут "ansible ssh не работает" в поиске. Разберём по шагам, как сделать так, чтобы первый же ping прошёл с первого раза, а не на десятой попытке.

Отдельный пользователь автоматизации и раздача SSH-ключей
Заходить под root по SSH - плохая идея, и на экзамене, и в жизни. Правильный паттерн такой: на каждом узле живёт отдельный пользователь автоматизации (назовём его ansible), у него есть твой публичный ключ в authorized_keys, и он умеет делать sudo. Управляющая нода ходит на узлы под этим пользователем.
Сначала на управляющей машине генерируем пару ключей, если её ещё нет. Современный алгоритм - ed25519, он короче и быстрее RSA.
Код: Выделить всё
# на управляющем узле, под пользователем ansible
ssh-keygen -t ed25519 -C "ansible control node"
# просто Enter на все вопросы: путь по умолчанию ~/.ssh/id_ed25519,
# для лабы можно без passphrase
Код: Выделить всё
# первый раз - по паролю, чтобы закинуть ключ
ssh-copy-id ansible@node1.example.com
# проверяем беспарольный вход
ssh ansible@node1.example.com 'hostname; id'
Когда узлов много, раскладывать ключи руками неудобно. Тут уже сам Ansible помогает: модуль ansible.posix.authorized_key добавляет публичный ключ нужному пользователю идемпотентно. Запускать такой плейбук придётся либо по уже разложенному ключу, либо разово по паролю с флагом -k (--ask-pass).
Код: Выделить всё
---
- name: Раздать ключ автоматизации на узлы
hosts: all
become: true
tasks:
- name: Создать пользователя ansible
ansible.builtin.user:
name: ansible
shell: /bin/bash
state: present
- name: Положить публичный ключ пользователю ansible
ansible.posix.authorized_key:
user: ansible
key: "{{ lookup('file', '~/.ssh/id_ed25519.pub') }}"
state: present
Privilege escalation: ansible become и sudo
Ходим мы под обычным пользователем ansible, а делать надо рутовые вещи. За это отвечает механизм повышения прав, который в Ansible называется become. Это ключевая тема, и без понимания ansible become на EX294 делать нечего - повышение прав там нужно почти в каждой задаче.
Три главных ключевых слова:
- become: true - включить повышение прав для задачи, плея или всего плейбука.
- become_user - до какого пользователя поднимаемся. По умолчанию root, но можно указать любого, например become_user: postgres.
- become_method - каким способом. По умолчанию sudo, что нам и нужно на RHEL.
Код: Выделить всё
---
- name: Установка веб-сервера
hosts: webservers
become: true # весь плей идёт под root через sudo
tasks:
- name: Поставить пакет
ansible.builtin.dnf:
name: httpd
state: present
- name: Запустить и включить службу
ansible.builtin.service:
name: httpd
state: started
enabled: true
- name: Открыть порт в firewalld
ansible.posix.firewalld:
service: http
permanent: true
immediate: true
state: enabled
Вариант NOPASSWD - пользователь делает sudo вообще без пароля. Удобно для автоматизации, типично для лаб и для экзамена. Кладём отдельный файл в /etc/sudoers.d/, а не правим основной sudoers.
Код: Выделить всё
# /etc/sudoers.d/ansible (права 0440)
ansible ALL=(ALL) NOPASSWD: ALL
Код: Выделить всё
# запуск с запросом become-пароля
ansible-playbook site.yml -K
# а -k (маленькая) - это запрос SSH-пароля, не путай их
Проверка связи: ansible ping
Когда ключи разложены и become настроен, надо убедиться, что всё живо. Для этого есть модуль ansible.builtin.ping. Это НЕ сетевой ICMP-пинг. Модуль подключается по SSH, запускает на узле минимальный Python-код и возвращает pong. То есть ansible ping проверяет сразу три вещи: что SSH пускает, что Python на месте и что модуль отрабатывает.
Код: Выделить всё
# ad-hoc проверка всех узлов из инвентаря
ansible all -m ansible.builtin.ping
Код: Выделить всё
node1.example.com | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3.9"
},
"ping": "pong"
}
Типичные грабли
Host key checking. При первом подключении SSH спрашивает "точно доверяешь этому хосту?". В интерактиве ты жмёшь yes, а Ansible на этом молча зависает или падает с "Host key verification failed". Лечится либо предварительным сбором ключей через ssh-keyscan в known_hosts, либо отключением проверки в ansible.cfg:
Код: Выделить всё
# ansible.cfg
[defaults]
host_key_checking = False
Нет Python на узле. Симптом - ошибка вроде "/usr/bin/python: No such file or directory". Голый минимальный образ может приехать без интерпретатора. Решение - поставить python3 через модуль raw до основного плея, или указать путь явно через ansible_python_interpreter.
Права sudo. Ошибка "Missing sudo password" значит, что ты не дал NOPASSWD и не передал -K. Ошибка "sudo: a password is required" - то же самое с другой стороны. А если become просто не срабатывает, проверь, что файл в /etc/sudoers.d имеет права 0440 и проходит проверку visudo - битый файл sudoers игнорируется целиком.
Не тот пользователь. Ansible по умолчанию подключается под тем же юзером, под которым ты сидишь на управляющей ноде. Если на узлах пользователь называется иначе, задай его в инвентаре через ansible_user=ansible, иначе будешь долго думать, почему ключ "не подходит".
Мини-лаба
Подними две виртуалки с RHEL/Fedora (или AlmaLinux) и проделай руками весь цикл:
- Сгенерируй ключ ed25519 на управляющей ноде через ssh-keygen.
- Заведи пользователя ansible на обоих узлах и разложи ему ключ через ssh-copy-id.
- Проверь беспарольный вход обычным ssh - без этого дальше не идём.
- Положи правило NOPASSWD в /etc/sudoers.d/ansible с правами 0440.
- Прогони ansible all -m ansible.builtin.ping и добейся pong на обоих узлах.
- Напиши маленький плейбук с become: true, который ставит httpd и открывает порт в firewalld.
- Чем флаг -k отличается от -K при запуске ansible-playbook?
- Что именно проверяет модуль ansible.builtin.ping и почему это не ICMP?
- Какие три ключевых слова отвечают за повышение прав и какие у них значения по умолчанию?
- Почему правило для sudo лучше класть в /etc/sudoers.d/, а не в основной /etc/sudoers, и какие права должны быть у файла?
Управляемый узел готов, когда туда пускает SSH по ключу, на нём есть Python и пользователь автоматизации умеет делать sudo. Раздаёшь ключи через ssh-copy-id или ansible.posix.authorized_key, повышаешь права через become с become_user и become_method, проверяешь всё одной командой ansible ping. Это та самая база, на которой держится весь остальной курс и без которой на EX294 не сдвинуться с места.