HostiServer
2026-11-09 11:20
Ansible: архітектура, встановлення, inventory, ad-hoc команди
📚 Серія «Ansible», частина 1 з 10:
- Ansible: архітектура, встановлення, inventory та перші ad-hoc команди ← ви тут
- Ansible playbooks: tasks, modules, handlers, loops і теги
- Змінні та шаблони Jinja2 в Ansible: host_vars, group_vars, precedence
- Ansible на практиці: nginx, firewall, SSH-ключі та користувачі на реальному VPS
- Ansible roles: структура, includes/imports і best practices
- Ansible Galaxy та Collections: requirements.yml і встановлення
- Ansible Vault: секрети, vault-id та інтеграція з playbooks
- Ansible у масштабі: forks, serial, pipelining і SSH multiplexing для 100+ нод
- Динамічний inventory в Ansible: плагіни для Hetzner, AWS і GCP
- Ansible + CI/CD: ansible-lint та автодеплой через Forgejo і GitHub Actions
Ansible: архітектура, встановлення, inventory та перші ad-hoc команди
У серії про Docker на VPS ми встановлювали Docker, налаштовували Compose, піднімали Nginx із SSL і навіть зібрали кластер Docker Swarm з кількох нод. Кожен із цих кроків ми виконували вручну: зайти по SSH, ввести команди, перевірити результат. Для одного сервера це нормально. Для трьох уже відчутно нудно. Для тридцяти це вже окрема робота: тридцять терміналів, тридцять разів однакові команди, і гарантія, що на якомусь сервері щось піде не так, а ви дізнаєтесь про це лише згодом.
Ansible вирішує саме цю задачу. Ви один раз описуєте бажаний стан серверів (які пакети встановлені, які сервіси працюють, які файли лежать на місці), а Ansible сам приводить до цього стану будь-яку кількість машин і за потреби повторює це щоразу однаково. Це перша стаття серії з десяти: ми розберемо, як Ansible влаштований, як його встановити, як описати свої сервери та як виконувати перші команди без жодного playbook. Далі серія пройде шлях від простих playbook до ролей, секретів, великих інфраструктур і автоматичного деплою з CI/CD.
1.1 Задача: десятки чи сотні серверів без ручної роботи
Адміністрування кількох серверів руками має три хронічні проблеми. По-перше, швидкість: кожна зміна множиться на кількість машин. По-друге, дрейф: сервери, налаштовані у різний час різними людьми, поступово стають різними, і ніхто вже не пам'ятає чому. По-третє, відтворюваність: коли потрібен ще один такий самий сервер, інструкція існує лише в чиїйсь голові чи в застарілому текстовому файлі.
Автоматизація конфігурації замінює ручні кроки описом, який можна зберегти в git, перевірити, переглянути й повторити.
1.2 Скрипти, Ansible чи Chef/Puppet/Salt
Є три типові підходи до цієї задачі, і вони відрізняються моделлю роботи, а не лише синтаксисом.
| Підхід | Як працює | Агент на серверах | Де виграє, де програє |
|---|---|---|---|
| Bash-скрипти | Послідовність команд: «зроби це, потім це» | Не потрібен | Швидкий старт. Але повторний запуск часто ламає стан, а обробку помилок і різниці між дистрибутивами доводиться писати самому |
| Ansible | Опис бажаного стану в YAML; модулі самі перевіряють, чи потрібна зміна | Не потрібен: працює через SSH | Низький поріг входу, нічого не треба встановлювати на сервери. Для дуже великих парків потрібне налаштування продуктивності (частина 8 серії) |
| Chef / Puppet / Salt | Центральний сервер, на нодах працює агент, який сам регулярно звіряє стан | Зазвичай потрібен (у Salt є і режим salt-ssh) | Постійна самоперевірка стану і масштаб. Але своя мова чи DSL, окрема інфраструктура керування й агенти, які самі треба підтримувати |
Для більшості команд із десятками серверів, VPS чи виділених машин, саме Ansible дає найкращий баланс між зусиллями на старті й користю від автоматизації.
1.3 Чотири ключові властивості
- Agentless. На керованих серверах не потрібно нічого встановлювати: ні агента, ні демона. Достатньо SSH та Python.
- Звичайний SSH як транспорт. Ansible використовує те, що вже є на кожному Linux-сервері. Для Windows-машин як керованих вузлів використовується WinRM (або SSH).
- Ідемпотентність. Повторне виконання тієї самої задачі не ламає стан. Модуль перевіряє поточний стан, і якщо він уже відповідає бажаному, нічого не змінює й повідомляє «ok» замість «changed».
- YAML як мова. Опис автоматизації читається без спеціальних знань, а отже його може прочитати й перевірити колега, який Ansible не писав.
Ідемпотентність варто розібрати на прикладі, бо саме вона відрізняє Ansible від скриптів. Команда echo "line" >> /etc/file у скрипті додасть рядок при кожному запуску, і після п'яти запусків файл матиме п'ять однакових рядків. Модуль Ansible, що описує «цей рядок має бути в цьому файлі», перевірить наявність рядка і додасть його лише один раз. Те саме з пакетами: state=present означає «має бути встановлений», а не «встановити ще раз».
⚠️ Ідемпотентність не безумовна. Вона є властивістю модулів, а не самого Ansible. Модулі command і shell виконують довільну команду і не можуть знати, чи змінила вона щось, тому щоразу звітують «changed». Для таких задач у Ansible є параметри creates і removes. Докладніше про вибір модулів поговоримо в частині 2.
ℹ️ Звідки ми прийшли: якщо ви ще не проходили серію про контейнери, її початок описаний у статті «Docker на VPS: встановлення і перший контейнер». Для Ansible вона не обов'язкова, але саме на її прикладі добре видно, скільки однакових ручних кроків накопичується, коли серверів кілька.
2. Архітектура: як це працює
2.1 Три компоненти
- Control node. Машина, з якої ви запускаєте Ansible: ноутбук, CI-сервер або bastion host. Тут установлений Ansible, лежать inventory, playbook і SSH-ключі. Control node працює на Linux чи macOS; Windows підтримується лише через WSL.
- Managed nodes. Цільові сервери, якими ви керуєте. На них потрібні тільки Python і доступ по SSH до звичайної POSIX-оболонки.
- Inventory. Список і опис managed nodes: які в них імена та адреси, як до них підключатись і як вони згруповані.
2.2 Що відбувається під час виконання
Кожне завдання проходить однаковий цикл:
- Control node підключається до сервера по SSH.
- Копіює на нього невеликий Python-модуль з потрібною логікою (у тимчасову директорію).
- Виконує модуль і збирає результат у JSON.
- Прибирає тимчасові файли.
- Повертає результат на control node, де Ansible показує вам статус: ok, changed чи failed.
Звідси випливає цікавий наслідок: оскільки модуль щоразу доставляється на сервер заново, на управлінні версіями жодних проблем не виникає. На самих серверах немає нічого, що довелося б оновлювати.
2.3 Чого на керованих серверах не потрібно
Ні агента, ні постійно працюючого демона, ні відкритого порту, окрім SSH. Це і спрощує підтримку (нічого оновлювати), і зменшує поверхню атаки (немає ще одного слухача на мережевому порту).
2.4 Зворотний бік: control node треба захищати
Control node тримає ключі від усього парку серверів, тож це критичний вузол. Практичні правила: використовуйте окремий SSH-ключ для автоматизації, захищайте його паролем (passphrase) чи тримайте в ssh-agent, обмежте, хто може входити на control node, і не зберігайте його приватний ключ на спільних машинах. Про управління секретами пізніше окремо поговоримо в частині 7 серії (Ansible Vault).
2.5 Вимоги до Python на керованих серверах
Модулі Ansible виконуються на сервері, тому потрібен Python. На більшості серверних образів Debian, Ubuntu, AlmaLinux чи Rocky він є з коробки. У мінімальних образах (контейнерах, деяких хмарних образах) його може не бути, і тоді доведеться поставити його до першого запуску. Виняток становлять мережеві модулі (вони працюють на боці control node, без Python на пристрої) та модуль raw, який виконує команду без Python і саме тому часто використовується для початкового встановлення Python.
3. Встановлення Ansible на control node
3.1 Два пакети: ansible і ansible-core
Перш ніж ставити, варто знати, що існує два пакети. ansible-core — мінімальний: сама мова, середовище виконання й вбудовані модулі. ansible — повніший пакет «з батарейками»: те саме плюс набір колекцій, відібраних спільнотою. Колекціям присвячена окрема частина серії (Ansible Galaxy та Collections, частина 6), а для початку підійде будь-який із двох; повний пакет зручніший, бо одразу містить більшість потрібних модулів.
3.2 Способи встановлення
| Система | Спосіб | Примітки |
|---|---|---|
| Будь-який Linux, macOS (для CI-сервера та VPS: основний варіант) | pipx install --include-deps ansible |
Ізольоване середовище, просте оновлення, не чіпає системний Python |
| Ubuntu | Офіційний PPA ppa:ansible/ansible |
Містить новіші версії, ніж стандартні репозиторії |
| Debian | Пакет ansible зі стандартного репозиторію або з Ubuntu PPA |
Версія зі стандартного репозиторію може бути застарілою |
| AlmaLinux / Rocky / CentOS Stream | dnf після підключення EPEL |
Перевірте, яку версію надає EPEL, перед використанням у проєкті |
| Fedora | dnf install ansible чи ansible-core |
Доступні обидва пакети |
| macOS | brew install ansible |
Або через pipx, як і на Linux |
| Windows | Лише в WSL | Нативно як control node не підтримується |
3.3 Рекомендація: pipx
Для CI-сервера та VPS ми радимо pipx. Це практичний вибір: Ansible ставиться в окреме віртуальне середовище, не конфліктує із системним Python і оновлюється однією командою. Офіційна документація називає основним способом pip, а pipx — поширеною альтернативою для випадків, коли pip недоступний через політику ОС. А на сучасних Debian та Ubuntu якраз так і буває: системний Python позначений як «externally managed», і pip install без додаткових прапорців там відмовляється працювати. Тому pipx тут природний вибір.
# Ubuntu / Debian
sudo apt update
sudo apt install -y pipx
pipx ensurepath
# AlmaLinux / Rocky (після підключення EPEL)
sudo dnf install -y pipx
pipx ensurepath
# Власне встановлення
pipx install --include-deps ansible
Після pipx ensurepath відкрийте новий термінал, щоб оновився PATH. Оновлення пізніше:
pipx upgrade --include-injected ansible
3.4 Установка з Ubuntu PPA
sudo apt update
sudo apt install -y software-properties-common
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install -y ansible
Для Debian новіша версія ставиться з того самого PPA, але через ручне підключення репозиторію з ключем у /usr/share/keyrings/; точні кроки з відповідністю кодових імен Debian і Ubuntu є на офіційній сторінці установки для окремих ОС.
3.5 Перевірка
ansible --version
python3 --version
Команда ansible --version показує версію ansible-core, шлях до конфігураційного файлу, шлях до модулів і версію Python, під якою вона працює. Версію повного пакета ansible показує окрема команда ansible-community --version.
3.6 Версії та вимоги до Python
Станом на листопад 2026 поточна гілка повного пакета — ansible 14.x, що працює на ansible-core 2.21. Для цієї версії на control node потрібен Python 3.12–3.14, а на керованих серверах — Python 3.9–3.14. З цього випливають дві практичні речі:
- Старий Python на control node. У деяких поширених дистрибутивах системний Python старший за 3.12 (наприклад, Ubuntu 22.04 чи Debian 12). Тоді варто встановити окремий новіший Python і вказати його pipx (
pipx install --python python3.12 --include-deps ansible) або взяти старішу гілку ansible-core. - Дуже старі керовані сервери. Якщо на цільовій системі Python старший за 3.9, поточна версія ansible-core не зможе з нею працювати, і для таких машин потрібна старіша версія ansible-core.
Версії змінюються кілька разів на рік, тож перед установкою варто звірити таблицю підтримки на сторінці релізів офіційної документації Ansible.
⚠️ Не змішуйте способи встановлення. Якщо Ansible встановлений і через apt, і через pipx, у вас буде дві копії, і команда ansible запускатиме ту, що першою трапилась у PATH. Це типове джерело дивних помилок («у документації є цей параметр, а в мене немає»). Обирайте один спосіб і перевіряйте ansible --version після зміни.
4. SSH-ключі: безпарольний доступ
4.1 Чому паролі не працюють у масштабі
Ansible виконує дії на багатьох серверах одночасно, і запитувати пароль для кожного з'єднання неможливо. До того ж паролі для SSH гірші за ключі й з погляду безпеки: їх можна підібрати, вони потрапляють у історію команд і їх складно змінювати централізовано. Тому стандартний підхід — SSH-ключі.
4.2 Генерація ключової пари
Якщо окремого ключа для автоматизації ще немає, створіть його на control node:
ssh-keygen -t ed25519 -C "ansible-control" -f ~/.ssh/ansible_ed25519
Тип ed25519 — сучасний, короткий і швидкий. Утиліта запропонує задати passphrase. Для ключа, який керує всім парком серверів, passphrase бажаний: щоб не вводити його щоразу, додайте ключ в ssh-agent (ssh-add ~/.ssh/ansible_ed25519). На CI-сервері, де ключ використовується без участі людини, його зазвичай зберігають у секретах платформи, про що йтиметься в частині 10.
4.3 Розповсюдження публічного ключа
ssh-copy-id -i ~/.ssh/ansible_ed25519.pub admin@192.0.2.11
Цю команду треба виконати для кожного керованого сервера. Для початку підійде будь-який існуючий обліковий запис із правами sudo (у прикладі admin). Пізніше, у частині 4, ми створимо окремого користувача для автоматизації самим Ansible, а зараз головне — налаштувати доступ.
4.4 Перевірка вручну перед першим запуском
ssh -i ~/.ssh/ansible_ed25519 admin@192.0.2.11 "hostname && sudo -n true && echo sudo-ok"
Ця команда відповідає на три запитання одразу: чи працює вхід за ключем без пароля, чи правильне ім'я хоста і чи може користувач виконувати sudo без запиту пароля. Прапор -n змушує sudo завершитись помилкою замість запиту. Якщо вручну все працює, Ansible також запрацює. Якщо ні, проблему треба вирішувати зараз, а не посеред виконання завдання.
4.5 Привілеї: sudo без пароля чи з паролем
Більшість адміністративних задач потребують root-прав, які Ansible отримує через sudo (параметр become). Є два підходи:
- Запитувати пароль sudo щоразу: додавайте до команд
--ask-become-pass(-K). Безпечніше, але незручно для автоматизації. - Дозволити sudo без пароля для автоматизаційного користувача: зручно для CI і автоматичного деплою, але зменшує захист: хто отримає ключ, отримає й root.
echo 'admin ALL=(ALL) NOPASSWD:ALL' | sudo tee /etc/sudoers.d/ansible
sudo chmod 440 /etc/sudoers.d/ansible
sudo visudo -cf /etc/sudoers.d/ansible
Остання команда перевіряє синтаксис файлу: помилка в sudoers здатна заблокувати доступ до sudo, тому перевіряти варто завжди. Тримайте сесію з правами root відкритою, доки не переконаєтесь, що нове правило працює.
⚠️ Не використовуйте для Ansible прямий вхід під root. Звичайний обліковий запис із sudo залишає слід у журналах (видно, хто саме і що виконав) і дозволяє заборонити вхід root по SSH. Ця заборона — одне із завдань, які ми автоматизуємо в частині 4.
4.6 Параметри підключення
Якщо імена користувачів, порти чи ключі відрізняються між серверами, це описується параметрами хоста: ansible_user (хто підключається), ansible_port (нестандартний порт SSH), ansible_ssh_private_key_file (який ключ використати). Їх задають у inventory або в конфігурації, і про це йдеться далі.
4.7 Перше підключення і known_hosts
При першому підключенні SSH питає, чи довіряєте ви відбитку ключа сервера. В автоматизації це питання зупиняє виконання. Правильний вихід — додати відбитки заздалегідь:
ssh-keyscan -H 192.0.2.11 192.0.2.12 198.51.100.21 >> ~/.ssh/known_hosts
Зверніть увагу: ssh-keyscan довіряє тому, що відповів сервер у момент запиту. Для чутливих систем звірте відбитки (ssh-keygen -lf) з тими, що показує панель провайдера чи консоль сервера. Вимикати перевірку ключів хоста замість цього не варто, чому саме, розглянемо в розділі про ansible.cfg.
5. Inventory: описуємо інфраструктуру
Inventory — це «карта» вашого парку: які сервери є, як вони називаються, як до них підключитись і як вони згруповані. Ansible не вгадує, куди підключатись: він працює лише з тими вузлами, які описані в inventory.
5.1 Два формати: INI і YAML
Ansible підтримує обидва формати «з коробки». INI простіший і коротший, YAML краще масштабується й зручніший, коли в хостів багато змінних. Один і той самий парк в INI:
[webservers]
web1 ansible_host=192.0.2.11
web2 ansible_host=192.0.2.12
[databases]
db1 ansible_host=198.51.100.21 ansible_port=2222
[production:children]
webservers
databases
[all:vars]
ansible_user=admin
ansible_python_interpreter=/usr/bin/python3
І в YAML:
all:
vars:
ansible_user: admin
ansible_python_interpreter: /usr/bin/python3
children:
webservers:
hosts:
web1:
ansible_host: 192.0.2.11
web2:
ansible_host: 192.0.2.12
databases:
hosts:
db1:
ansible_host: 198.51.100.21
ansible_port: 2222
production:
children:
webservers:
databases:
Адреси в прикладах — із діапазонів, зарезервованих для документації (192.0.2.0/24 і 198.51.100.0/24), підставте свої.
5.2 Групи нод
Групи — головний інструмент inventory: вони дозволяють звертатись до багатьох серверів однією назвою. Дві групи є завжди без жодного опису: all (усі хости) і ungrouped (хости, які не входять до жодної іншої групи). Кожен хост належить принаймні до однієї з них.
5.3 Вкладені групи
В INI вкладеність задається суфіксом :children у заголовку групи (як у прикладі [production:children]), у YAML — ключем children. Хост із дочірньої групи автоматично належить і батьківській: web1 входить і до webservers, і до production. Це зручно для того, щоб описувати окремі середовища: наприклад, групи staging і production, кожна зі своїми webservers. Циклічні зв'язки між групами заборонені.
5.4 Змінні рівня inventory
Параметри, що визначають, як підключатись:
ansible_host— реальна адреса чи DNS-ім'я, якщо воно відрізняється від імені хоста в inventory (у прикладіweb1— це просто зручна назва);ansible_port— порт SSH, якщо він не 22;ansible_user— користувач для підключення;ansible_python_interpreter— шлях до Python на сервері. Явне значення прибирає попередження про автоматично знайдений інтерпретатор і запобігає помилкам на системах із кількома версіями Python.
Змінні, оголошені в секції [all:vars], діють для всіх хостів; змінні групи (наприклад, [webservers:vars]) — лише для її членів; змінні в рядку хоста мають найвищий пріоритет серед цих трьох. Повну систему пріоритетів змінних ми розберемо в частині 3.
5.5 Діапазони хостів
Для однотипних серверів не треба перелічувати кожен: запис web[01:50].example.com створить п'ятдесят хостів від web01 до web50. Крок задається третім числом (web[01:50:2] дасть лише непарні), підтримуються й літерні діапазони (db-[a:f].example.com).
5.6 Де зберігати inventory
- Один файл — достатньо для невеликого парку. Просто, видно все й одразу.
- Директорія (наприклад,
inventory/з кількома файлами): Ansible читає всі файли в ній за алфавітом. Зручно, коли парк росте або коли частина inventory генерується автоматично (до цього ми дійдемо в частині 9 про динамічний inventory). Якщо одна змінна визначена у кількох файлах, виграє остання за алфавітним порядком, тому порядок файлів можна контролювати префіксами (01-,02-).
У будь-якому випадку зберігайте inventory в git разом з іншим кодом автоматизації, але без паролів і ключів у відкритому вигляді.
5.7 Перевірка inventory
ansible-inventory -i inventory/hosts.ini --list
ansible-inventory -i inventory/hosts.ini --graph
Перша команда виводить усе, що Ansible «розуміє» про ваші хости, у форматі JSON, включно зі змінними. Друга показує дерево груп. Для прикладу вище воно виглядатиме приблизно так:
@all:
|--@production:
| |--@databases:
| | |--db1
| |--@webservers:
| | |--web1
| | |--web2
|--@ungrouped:
Звикайте виконувати цю перевірку після кожної зміни inventory: вона одразу показує помилки в групах і змінних, до того як вони обернуться «чужою» поведінкою на серверах.
6. ansible.cfg: базова конфігурація
6.1 Де Ansible шукає конфіг
Ansible перебирає чотири місця в такому порядку й використовує перший знайдений файл. Інші файли ігноруються, їх вміст не зливається:
- Файл, вказаний у змінній середовища
ANSIBLE_CONFIG, якщо вона задана; ansible.cfgу поточній директорії (проєктний конфіг);~/.ansible.cfgу домашній директорії;/etc/ansible/ansible.cfg(загальносистемний).
Для проєктів майже завжди найкращий варіант — другий: ansible.cfg лежить у корені репозиторію разом з inventory і playbook, і всі, хто працює з репозиторієм, отримують однакові налаштування. Яку саме конфігурацію Ansible зараз використовує, показує рядок config file у виводі ansible --version.
⚠️ Конфіг із каталогу, доступного всім на запис, ігнорується. Ansible не завантажує ansible.cfg з поточної директорії, якщо вона world-writable: інакше інший користувач системи міг би підкласти свій файл і керувати вашими запусками. Якщо ваш конфіг «не підхоплюється», перевірте права на каталог (ls -ld .).
6.2 Ключові параметри
[defaults]
inventory = ./inventory/hosts.ini
remote_user = admin
private_key_file = ~/.ssh/ansible_ed25519
host_key_checking = True
inventory— шлях до inventory за замовчуванням, щоб не вказувати-iу кожній команді;remote_user— користувач для підключення, якщо він не вказаний у inventory;private_key_file— ключ за замовчуванням;host_key_checking— перевірка відбитків ключів хостів (за замовчуванням увімкнена).
Перевірити, які параметри ви змінили відносно значень за замовчуванням, можна командою ansible-config dump --only-changed.
6.3 Чому host_key_checking = False тільки для тестів
Багато інструкцій радять вимкнути перевірку ключів хостів, щоб прибрати питання про довіру при першому підключенні. Це працює, але повністю знімає захист від підміни сервера (man-in-the-middle): Ansible погодиться підключитись до будь-кого, хто відповість за потрібною адресою, і передасть йому все, що ви надсилаєте на сервер, включно з файлами й змінними. Для експериментів на тимчасових віртуальних машинах це прийнятно. Для production правильний шлях — розділ 4.7: заздалегідь додати відбитки у known_hosts і залишити перевірку ввімкненою.
7. Ad-hoc команди: Ansible без playbook
Ad-hoc команда — це одна дія, виконана на одному чи кількох серверах прямо з командного рядка, без написання playbook. Для разових операцій це найшвидший спосіб.
7.1 Синтаксис
ansible <pattern> -m <module> -a "<аргументи>"
Три частини: pattern (до кого застосувати), модуль (що зробити) і аргументи модуля. Якщо модуль не вказано, використовується ansible.builtin.command.
7.2 Pattern: на які хости діяти
| Pattern | Що означає |
|---|---|
all |
Усі хости з inventory |
webservers |
Усі хости групи |
web1 |
Один конкретний хост |
web* |
Wildcard: усі, чиї імена починаються з «web» |
webservers:databases |
Об'єднання груп (або одна, або інша) |
production:&webservers |
Перетин: хости, що входять в обидві групи |
webservers:!web2 |
Виключення: усі з групи, крім web2 |
Для виключення в оболонці bash символ ! зазвичай треба брати в одинарні лапки: ansible 'webservers:!web2' -m ping, інакше оболонка спробує розкрити його як посилання на історію команд. Додатково будь-який pattern можна звузити опцією --limit (-l), наприклад -l web1.
7.3 Корисні модулі для щоденних задач
| Модуль | Призначення | Приклад аргументів |
|---|---|---|
ping |
Перевірка, що Ansible може підключитись і виконати Python на сервері | без аргументів |
command |
Виконати команду без оболонки (без каналів і перенаправлень) | -a "uptime" |
shell |
Виконати команду через оболонку (дозволені |, >, змінні) |
-a "df -h | head -5" |
copy |
Скопіювати файл із control node на сервер | -a "src=./motd dest=/etc/motd mode=0644" |
fetch |
Забрати файл із сервера на control node | -a "src=/etc/os-release dest=./fetched/" |
service |
Керувати сервісами | -a "name=nginx state=restarted" |
apt / dnf |
Керувати пакетами на Debian/Ubuntu або RHEL-подібних | -a "name=nginx state=present" |
Модуль ping не має нічого спільного з ICMP-пінгом: він справді входить на сервер по SSH, запускає невеликий Python-код і повертає «pong». Тому вдала відповідь означає, що працюють і SSH-доступ, і Python, і права, і це набагато більше, ніж «сервер відповідає на мережу».
7.4 Приклади
# Чи доступні всі сервери
ansible all -m ping
# Аптайм усіх вебсерверів (command за замовчуванням)
ansible webservers -a "uptime"
# Вільне місце, пайп потребує shell
ansible all -m ansible.builtin.shell -a "df -h / | tail -1"
# Перезапуск Nginx з правами root
ansible webservers -b -m ansible.builtin.service -a "name=nginx state=restarted"
# Факти про систему (фільтр за назвою)
ansible web1 -m ansible.builtin.setup -a "filter=ansible_distribution*"
Опція -b (--become) вмикає підвищення привілеїв через sudo. Додатково знадобляться -u (підключитись іншим користувачем), -i (вказати inventory, якщо його немає в конфігурації) та -K (запитати пароль sudo).
7.5 Режим перевірки: --check
Прапор --check (-C) запускає «репетицію»: Ansible показує, що зробив би, але нічого на серверах не змінює. Він добре працює з модулями, які вміють передбачати результат (apt, copy, service та інші). Але command і shell у режимі перевірки зазвичай пропускаються, бо Ansible не може знати, що зробить довільна команда. Тому репетиція не є універсальною гарантією безпеки, її корисно застосовувати разом із перевіркою на одному сервері.
7.6 Паралелізм: forks
За замовчуванням Ansible працює з п'ятьма серверами одночасно (параметр forks). Для парку з сотні машин це означає двадцять послідовних «хвиль». Збільшити паралелізм для окремого запуску можна опцією -f:
ansible all -f 20 -m ping
Більше — не завжди краще: кожен fork споживає пам'ять і з'єднання на control node, а надто агресивне значення може впертись в ліміти SSH чи в мережу. Тонке налаштування продуктивності (forks, pipelining, SSH multiplexing) ми розберемо в частині 8.
8. Перший реальний сценарій
Зведемо розібране в один практичний сценарій: перевірити парк, подивитись стан і безпечно оновити пакети на вебсерверах.
8.1 Крок 1: чи все доступне
ansible all -m ping
Успішна відповідь виглядає так:
web1 | SUCCESS => {
"changed": false,
"ping": "pong"
}
Поки ping не проходить на всіх вузлах, далі йти немає сенсу.
8.2 Крок 2: перевірка uptime на всіх нодах
ansible all -a "uptime"
web1 | CHANGED | rc=0 >>
12:41:03 up 12 days, 3:07, 1 user, load average: 0.08, 0.03, 0.01
Зверніть увагу на слово CHANGED, хоча команда uptime нічого не змінила. Це та сама властивість модуля command із розділу 1: він не знає, чи змінила команда стан, тому завжди звітує «changed». Це не помилка, а нагадування, що для справді ідемпотентних дій потрібні профільні модулі, а не command.
8.3 Крок 3: оновлення пакетів на вебсерверах
Спершу репетиція на одному сервері, потім реальний запуск на ньому ж, і лише після цього на всіх:
# Debian / Ubuntu: репетиція на одному хості
ansible webservers -l web1 -b -m ansible.builtin.apt -a "update_cache=yes upgrade=dist" --check
# Реальний запуск на одному хості
ansible webservers -l web1 -b -m ansible.builtin.apt -a "update_cache=yes upgrade=dist"
# Після перевірки: на всіх вебсерверах
ansible webservers -b -m ansible.builtin.apt -a "update_cache=yes upgrade=dist"
# Для RHEL-подібних систем
ansible webservers -b -m ansible.builtin.dnf -a "name='*' state=latest"
Така послідовність («canary»: спочатку один, потім усі) — звичка, яка рятує від ситуації, коли проблемне оновлення одночасно кладе весь парк. Для production-серверів у частині 8 ми розберемо директиву serial, що автоматизує поступове оновлення групами.
8.4 Як читати вивід
| Статус | Що означає | Що робити |
|---|---|---|
SUCCESS (ok) |
Завдання виконане, стан уже відповідав бажаному, змін немає | Нічого |
CHANGED |
Завдання виконане і щось змінило (або модуль не може цього визначити) | Переконатись, що це змінення очікуване |
UNREACHABLE |
Не вдалось підключитись до сервера | Перевірити мережу, порт, ключ, користувача, відбиток у known_hosts; спробувати той самий ssh вручну |
FAILED |
Підключення є, але завдання завершилось помилкою | Прочитати поле msg: типові причини — відсутній -b для задач, які потребують root, не встановлений Python, помилка в аргументах модуля |
Найчастіша плутанина в початківців: UNREACHABLE означає проблему з доступом (SSH), а FAILED — проблему з виконанням (модуль, права, Python). Це різні класи несправностей, і діагностика починається з різних місць.
9. Обмеження ad-hoc і що далі
9.1 Де ad-hoc закінчується
Ad-hoc команди ідеальні для разових операцій: перевірити доступність, подивитись версію, перезапустити сервіс, зібрати факти. Але вони не підходять для повторюваних сценаріїв: послідовність дій не зберігається, логіка («якщо сталась зміна, перезапусти сервіс») не виражається, а результат неможливо перевірити чи переглянути в git. Як тільки ви ловите себе на тому, що вводите ту саму довгу команду втретє, настав час для playbook.
9.2 Що ми зробили в цій статті
- Зрозуміли, як влаштований Ansible: control node, managed nodes, inventory, виконання через SSH без агента.
- Встановили його на control node і розібрались у версіях та вимогах до Python.
- Налаштували безпарольний доступ за ключами та підготували сервери до автоматизації.
- Описали парк серверів в inventory з групами і змінними.
- Налаштували
ansible.cfg, не вимикаючи перевірку ключів хостів. - Виконали перші ad-hoc команди і навчились читати їхній вивід.
9.3 Що далі в серії
Наступна стаття присвячена playbook: файлам, які описують послідовність завдань, дозволяють використовувати handlers (перезапуск сервісу лише після зміни конфігурації), цикли й теги. Саме там з'явиться справжня ідемпотентна автоматизація. Далі серія піде від змінних і шаблонів Jinja2 до практичного налаштування реального VPS (частина 4: nginx, firewall, SSH-ключі, користувачі), ролей, Ansible Galaxy, Vault для секретів, масштабування до сотень вузлів, динамічного inventory й, нарешті, автоматичного деплою через Forgejo чи GitHub Actions. Для тих, хто захоче заздалегідь познайомитись із CI/CD, початок цієї теми розібраний у статті «Що таке CI/CD: від ручного deploy до автоматизованих pipelines».
📚 Навігація серії:
Ви читаєте частину 1 з 10 «Ansible: архітектура, встановлення, inventory та перші ad-hoc команди».
Далі: Частина 2. Ansible playbooks: tasks, modules, handlers, loops і теги →
🚀 Сервери для вашого Ansible-парку
Для старту з Ansible потрібні лише дві речі: невеликий сервер під control node і одна-дві машини, якими він керуватиме. Hostiserver дає ресурси, на яких можна безпечно експериментувати і з яких пізніше виростає повноцінна інфраструктура.
🖥️ Виділені Сервери
- Від $90/міс, повний контроль над залізом для важких навантажень
- Без сусідів по ресурсах: передбачувана продуктивність для баз даних і build-вузлів
- 24/7 підтримка: допоможемо з мережею та SSH-доступом між вашими серверами
💻 Cloud (VPS) Хостинг
- Від $19.95/міс, KVM-ізоляція, виділені vCPU і RAM
- Повний root-доступ: Ansible отримує потрібні права без обхідних шляхів
- Однакові тарифи на кілька VPS: зручно створювати тестовий парк з однотипних нод
- Легко масштабувати: додали ще один сервер у inventory, і він під керуванням
💬 Не впевнені, який варіант потрібен?
💬 Напишіть нам — допоможемо з вибором!
Часті запитання
- Чим Ansible кращий за звичайні bash-скрипти?
Скрипт описує послідовність дій, а Ansible — бажаний стан. Модуль Ansible спершу перевіряє, чи потрібна зміна, тому повторний запуск не ламає систему й не дублює результат (ідемпотентність). Крім того, один і той самий опис працює на різних дистрибутивах: модулі самі враховують відмінності, які в скрипті довелося б обробляти вручну. Скрипти лишаються доречними для дуже простих разових задач.
- Чи потрібно щось встановлювати на керованих серверах?
Ні агента, ні демона. Потрібні лише SSH-доступ і Python (для більшості модулів). На стандартних серверних образах Debian, Ubuntu, AlmaLinux чи Rocky Python вже є. Якщо його немає, початкове встановлення можна виконати модулем
raw, який працює без Python:ansible all -m raw -a "apt install -y python3" -b. Мережеві модулі виконуються на боці control node й Python на самому пристрої не потребують.
- Чи можна запускати Ansible з Windows?
Нативно Windows як control node не підтримується. Варіант — WSL (Windows Subsystem for Linux), у якому Ansible працює як на звичайному Linux. Керувати Windows-серверами як managed nodes можна, але для них використовується WinRM (або SSH), і це окрема тема, яку в цій серії ми не розглядаємо.
- Ansible повертає UNREACHABLE. З чого почати діагностику?
Спробуйте те саме підключення вручну:
ssh -i ключ користувач@адреса. Якщо вручну не працює, проблема в мережі, порту, ключі чи користувачі, і Ansible тут нічого не вирішить. Якщо вручну працює, а в Ansible ні, перевіртеansible_user,ansible_portіansible_hostу inventory (командаansible-inventory --listпокаже, що Ansible «бачить»), а також наявність відбитка хоста вknown_hosts. Для детальної діагностики додайте до команди прапор-vvv.
- Pipx, apt чи pip: як краще встановити Ansible?
Для CI-сервера і VPS ми радимо pipx: ізольоване середовище, просте оновлення, жодних конфліктів із системним Python (на сучасних Debian і Ubuntu
pip installбез додаткових прапорців там блокується). Пакет із PPA чи репозиторію ОС теж допустимий, особливо якщо ви хочете оновлення разом з іншими пакетами системи. Головне правило: обрати один спосіб і не змішувати, інакше у вас опиниться дві копії Ansible.
- Чи безпечно давати користувачу sudo без пароля для Ansible?
Це компроміс. Sudo без пароля потрібне для автоматичного запуску без участі людини (CI/CD), але той, хто отримає SSH-ключ цього користувача, отримує й root. Зменшують ризик так: окремий ключ лише для автоматизації, захист ключа passphrase чи сховищем секретів, обмеження доступу до control node, доступ по SSH тільки з потрібних адрес. Для ручних запусків можна обійтись паролем: опція
--ask-become-pass(-K).
- Чи потрібен окремий сервер під control node?
Ні, на початку підійде ваш ноутбук чи будь-яка Linux-машина з доступом до серверів. Окремий сервер (bastion чи CI-вузол) має сенс, коли з Ansible працює кілька людей або запуски відбуваються автоматично. Тоді він стає єдиною точкою, де зберігаються ключі та inventory, і її легше захистити й контролювати. Невеликий VPS для цього зазвичай достатньо.