Предыдущий урок: Ansible практика – урок №1: Базовая настройка и первый запуск.
На данном этапе мы уже умеем выполнять простейшие команды с помощью Ansible. Но в чем смысл, если с таким же успехом эти команды можно было запускать на удаленных хостах через SSH? Сила Ansible не в исполнении отдельных команд, а в исполнении десятков и сотен команд объединенных в плейбук.
Что такое Ansible playbook?
Плейбук – это руководство для Ansible, в котором мы описываем какие действия, в какой последовательности и при каких условиях должен исполнить Ansible.
Например, каждый раз подготавливая новый сервер, администратор устанавливает ряд базовых программ и производит одни и те же настройки.
Все это можно легко описать в плейбуке. Тогда не нужно будет каждый новый сервер настраивать вручную, а оставить это Ansible.
Как запустить первый плейбук
Конечно, сегодня мы не создадим большой плейбук, который сам настроит весь сервер, но пару команд он точно исполнит.
Шаг 1: Создание плейбука
Допустим, мы часто подготавливаем веб сервера работающие на стеке LEMP. Чтобы не устанавливать каждый раз вручную пакеты NGINX, MariaDB и PHP, доверим это Ansible. Создадим на контрольной ноде файл install_lemp.yml следующего содержания:
---
- hosts: all
tasks:
- name: "Install PHP"
ansible.builtin.dnf:
name:
- php
- php-cli
- php-fpm
- php-common
- php-mbstring
- php-curl
- php-mysqlnd
- php-json
- php-xml
- php-phar
- php-pdo
- php-gd
state: latest
- name: "Install NGINX"
ansible.builtin.dnf:
name: nginx
state: latest
- name: "Ensure NGINX is started and enabled"
ansible.builtin.service:
name: nginx
state: started
enabled: true
- name: "Install MariaDB"
ansible.builtin.dnf:
name: mariadb-server
state: latest
- name: "Ensure MariaDB is started and enabled"
ansible.builtin.service:
name: mariadb
state: started
enabled: true
Плейбук использует YAML формат, данный формат чувствителен к отступам, поэтому будьте внимательны с пробелами. Лишний или недостающий отступ может сломать логику плейбука и сделать его нерабочим.
Первым делом мы задаем хосты (hosts: all), с которыми будет работать плейбук. Далее идет серия заданий (tasks), которые должен выполнить Ansible. Названия таскам можно давать любые, но старайтесь делать их понятными, описывающими суть задания.
В данном плейбуке мы используем два модуля Ansible.
ansible.builtin.dnf – это встроенный модуль для работы с пакетным менеджером DNF. Директива name указывает на имя пакета, а state на его состояние. state: latest говорит Ansible, что данный пакет должен присутствовать и быть последней версии. Подробнее о работе данного модуля и доступных параметрах вы можете узнать в официальной документации Ansible.
ansible.builtin.service – модуль для управления сервисами, используется для их запуска и остановки. Директива name задает имя сервиса, state – состояние, enabled – запуск по умолчанию. Страница руководства по данному модулю.
Шаг 2: Запуск Ansible плейбука
Наш первый плейбук готов. Давайте попробуем его запустить:
[root@Control-Node ansible]# ansible-playbook install_lemp.yml
PLAY [all] ******************************************************************************************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************************************************************************************
ok: [Managed-Node-2]
ok: [Managed-Node-1]
TASK [Install PHP] **********************************************************************************************************************************************************************************
changed: [Managed-Node-2]
changed: [Managed-Node-1]
TASK [Install NGINX] ********************************************************************************************************************************************************************************
changed: [Managed-Node-1]
changed: [Managed-Node-2]
TASK [Ensure NGINX is started and enabled] **********************************************************************************************************************************************************
changed: [Managed-Node-2]
changed: [Managed-Node-1]
TASK [Install MariaDB] ******************************************************************************************************************************************************************************
changed: [Managed-Node-1]
changed: [Managed-Node-2]
TASK [Ensure MariaDB is started and enabled] ********************************************************************************************************************************************************
changed: [Managed-Node-1]
changed: [Managed-Node-2]
PLAY RECAP ******************************************************************************************************************************************************************************************
Managed-Node-1 : ok=6 changed=5 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Managed-Node-2 : ok=6 changed=5 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@Control-Node ansible]#
По умолчанию, первым шагом (Gathering Facts) Ansible собирает информацию о хостах. Далее выполняет таски из нашего плейбука один за одни, при этом одновременно на обоих серверах. Для каждого сервера таски выполнены с результатом changed, это значит, что изменения были внесены.
Можно зайти на любую из Managed Node и убедиться, что сервисы установлены и запущены:
[root@Managed-Node-1 ~]# mariadb --version
mariadb Ver 15.1 Distrib 10.5.29-MariaDB, for Linux (x86_64) using EditLine wrapper
[root@Managed-Node-1 ~]# systemctl status mariadb
● mariadb.service - MariaDB 10.5 database server
Loaded: loaded (/usr/lib/systemd/system/mariadb.service; enabled; preset: disabled)
Active: active (running) since Mon 2025-12-08 12:22:29 +10; 30min ago
Docs: man:mariadbd(8)
https://mariadb.com/kb/en/library/systemd/
Process: 12248 ExecStartPre=/usr/libexec/mariadb-check-socket (code=exited, status=0/SUCCESS)
Process: 12270 ExecStartPre=/usr/libexec/mariadb-prepare-db-dir mariadb.service (code=exited, status=0/SUCCESS)
Process: 12367 ExecStartPost=/usr/libexec/mariadb-check-upgrade (code=exited, status=0/SUCCESS)
Main PID: 12352 (mariadbd)
Status: "Taking your SQL requests now..."
Tasks: 8 (limit: 11100)
Memory: 86.7M
CPU: 1.029s
CGroup: /system.slice/mariadb.service
└─12352 /usr/libexec/mariadbd --basedir=/usr
Dec 08 12:22:29 Managed-Node-1 mariadb-prepare-db-dir[12309]: The second is mysql@localhost, it has no password either, but
Dec 08 12:22:29 Managed-Node-1 mariadb-prepare-db-dir[12309]: you need to be the system 'mysql' user to connect.
Dec 08 12:22:29 Managed-Node-1 mariadb-prepare-db-dir[12309]: After connecting you can set the password, if you would need to be
Dec 08 12:22:29 Managed-Node-1 mariadb-prepare-db-dir[12309]: able to connect as any of these users with a password and without sudo
Dec 08 12:22:29 Managed-Node-1 mariadb-prepare-db-dir[12309]: See the MariaDB Knowledgebase at https://mariadb.com/kb
Dec 08 12:22:29 Managed-Node-1 mariadb-prepare-db-dir[12309]: Please report any problems at https://mariadb.org/jira
Dec 08 12:22:29 Managed-Node-1 mariadb-prepare-db-dir[12309]: The latest information about MariaDB is available at https://mariadb.org/.
Dec 08 12:22:29 Managed-Node-1 mariadb-prepare-db-dir[12309]: Consider joining MariaDB's strong and vibrant community:
Dec 08 12:22:29 Managed-Node-1 mariadb-prepare-db-dir[12309]: https://mariadb.org/get-involved/
Dec 08 12:22:29 Managed-Node-1 systemd[1]: Started MariaDB 10.5 database server.
[root@Managed-Node-1 ~]#
А что будет, если мы еще раз запустим тот же самый плейбук? Давайте попробуем:
[root@Control-Node ansible]# ansible-playbook install_lemp.yml
PLAY [all] ******************************************************************************************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************************************************************************************
ok: [Managed-Node-2]
ok: [Managed-Node-1]
TASK [Install PHP] **********************************************************************************************************************************************************************************
ok: [Managed-Node-2]
ok: [Managed-Node-1]
TASK [Install NGINX] ********************************************************************************************************************************************************************************
ok: [Managed-Node-1]
ok: [Managed-Node-2]
TASK [Ensure NGINX is started and enabled] **********************************************************************************************************************************************************
ok: [Managed-Node-2]
ok: [Managed-Node-1]
TASK [Install MariaDB] ******************************************************************************************************************************************************************************
ok: [Managed-Node-2]
ok: [Managed-Node-1]
TASK [Ensure MariaDB is started and enabled] ********************************************************************************************************************************************************
ok: [Managed-Node-1]
ok: [Managed-Node-2]
PLAY RECAP ******************************************************************************************************************************************************************************************
Managed-Node-1 : ok=6 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Managed-Node-2 : ok=6 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@Control-Node ansible]#
Все таски в состоянии ok и ни одного changed, значит, все они отработали штатно, но никаких изменений делать не потребовалось, так как все необходимые пакеты уже установлены, а сервисы запущены.
Такое поведение называется идемпотентностью – повторное выполнение плейбуков не вызывает изменений, если система уже находится в нужном состоянии.
Ansible автоматически определяет необходимость выполнения каждой задачи. Это позволяет экономить время, исключая повторное выполнение одних и тех же задач, если в том нет необходимости.
Итоги:
Мы составили наш первый плейбук и успешно его запустили. Разобрали результат работы плейбука и информационную выдачу Ansible. На примере работы нашего плейбука познакомились с принципом идемпотентности.
Следующий урок: Ansible практика – урок №3: Ограничение работы плейбука с помощью tags и limit.