Предыдущий урок: Ansible практика – урок №4: Использование условий when в плейбуке.
В прошлый раз мы прописали в наш плейбук условия when, а до этого добавляли теги. С каждым разом плейбук становится все больше, а читать его все сложнее. Чтобы успешно работать с большими плейбуками их надо уметь делить на небольшие роли.
Какова роль ролей?
Задача плейбука – подготовить сервер по заданной инструкции. Роль – часть общей задачи, обычно объединенная по логическому принципу и выделенная отдельную подзадачу. Например, роль, объединяющая всю установку пакетов или таски связанные с одним сервисом.
Роли создание и применение
Роли могут иметь разнообразные названия и содержать различные задачи, но главное правило Ansible – чем понятнее и логичнее, тем лучше.
Шаг 1: Выделяем таски в отдельные роли
У нас сейчас присутствует два вида задач – на установку и на запуск сервисов. В данном случае сервис – отличный общий признак, по которому таски можно выделить в роли.
Создадим директорию roles и поддиректории roles/php, roles/nginx и roles/mariadb, а в каждой поддиректории еще одну директорию tasks:
[root@Control-Node ansible]# mkdir roles
[root@Control-Node ansible]# mkdir -p roles/php/tasks roles/nginx/tasks roles/mariadb/tasks
[root@Control-Node ansible]#
Ранее мы уже делили таски по такому же признаку, когда присваивали теги. Вынесем соответствующие задачи в файл main.yml внутри каждой директории tasks.
Таски PHP в файл roles/php/tasks/main.yml:
---
- name: "Install PHP on CentOS"
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
tags:
- installation
- php
when: ansible_distribution == "CentOS"
- name: "Install PHP on Ubuntu"
ansible.builtin.apt:
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
tags:
- installation
- php
when: ansible_distribution == "Ubuntu"
Задачи, связанные с NGINX в roles/nginx/tasks/main.yml:
---
- name: "Install NGINX on CentOS"
ansible.builtin.dnf:
name: nginx
state: latest
tags:
- installation
- nginx
when: ansible_distribution == "CentOS"
- name: "Install NGINX on Ubuntu"
ansible.builtin.apt:
name: nginx
state: latest
tags:
- installation
- nginx
when: ansible_distribution == "Ubuntu"
- name: "Ensure NGINX is started and enabled"
ansible.builtin.service:
name: nginx
state: started
enabled: true
tags:
- start
- nginx
MariaDB в roles/mariadb/tasks/main.yml:
---
- name: "Install MariaDB on CentOS"
ansible.builtin.dnf:
name: mariadb-server
state: latest
tags:
- installation
- mariad
when: ansible_distribution == "CentOS"
- name: "Install MariaDB on Ubuntu"
ansible.builtin.apt:
name: mariadb-server
state: latest
tags:
- installation
- mariad
when: ansible_distribution == "Ubuntu"
- name: "Ensure MariaDB is started and enabled"
ansible.builtin.service:
name: mariadb
state: started
enabled: true
tags:
- start
- mariadb
Мы вынесли таски в отдельные роли. Название ролей соответствуют названиям поддиректорий внутри директории roles.
Шаг 2: Проверяем плейбук
Теперь поправим плейбук, удалим уз него все таски и заменим их ролями. Обновленный файл install_lemp.yml будет иметь следующий вид:
---
- hosts: all
roles:
- php
- nginx
- mariadb
Запустим Ansible и проверим работу плейбука:
[root@Control-Node ansible]# ansible-playbook install_lemp.yml
PLAY [all] ******************************************************************************************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************************************************************************************
ok: [Managed-Node-1]
ok: [Managed-Node-3]
ok: [Managed-Node-2]
TASK [php : Install PHP on CentOS] ******************************************************************************************************************************************************************
skipping: [Managed-Node-3]
ok: [Managed-Node-1]
ok: [Managed-Node-2]
TASK [php : Install PHP on Ubuntu] ******************************************************************************************************************************************************************
skipping: [Managed-Node-1]
skipping: [Managed-Node-2]
ok: [Managed-Node-3]
TASK [nginx : Install NGINX on CentOS] **************************************************************************************************************************************************************
skipping: [Managed-Node-3]
ok: [Managed-Node-2]
ok: [Managed-Node-1]
TASK [nginx : Install NGINX on Ubuntu] **************************************************************************************************************************************************************
skipping: [Managed-Node-1]
skipping: [Managed-Node-2]
ok: [Managed-Node-3]
TASK [nginx : Ensure NGINX is started and enabled] **************************************************************************************************************************************************
ok: [Managed-Node-1]
ok: [Managed-Node-2]
ok: [Managed-Node-3]
TASK [mariadb : Install MariaDB on CentOS] **********************************************************************************************************************************************************
skipping: [Managed-Node-3]
ok: [Managed-Node-1]
ok: [Managed-Node-2]
TASK [mariadb : Install MariaDB on Ubuntu] **********************************************************************************************************************************************************
skipping: [Managed-Node-1]
skipping: [Managed-Node-2]
ok: [Managed-Node-3]
TASK [mariadb : Ensure MariaDB is started and enabled] **********************************************************************************************************************************************
ok: [Managed-Node-1]
ok: [Managed-Node-2]
ok: [Managed-Node-3]
PLAY RECAP ******************************************************************************************************************************************************************************************
Managed-Node-1 : ok=6 changed=0 unreachable=0 failed=0 skipped=3 rescued=0 ignored=0
Managed-Node-2 : ok=6 changed=0 unreachable=0 failed=0 skipped=3 rescued=0 ignored=0
Managed-Node-3 : ok=6 changed=0 unreachable=0 failed=0 skipped=3 rescued=0 ignored=0
[root@Control-Node ansible]#
Как видим, Ansible отработал без проблем. Самый внимательные заметили, что ход раскатки никак не изменился по сравнению с плейбуком без ролей. Оно и верно, мы изменили структуру самого плейбука, но не исполняемые задачи.
Мы сделали структуру более сегментированной и если Ansible сфейлит на какой либо задаче мы будем искать причину в отдельной роли, а не во всем плейбуке целиком.
Шаг 3: Создаем новую роль
Давайте, в качестве закрепления материала, создадим новую роль с нуля. Мы подготавливаем веб сервера, а значит, посетители должны иметь доступ к основным портам – 80 (http) и 443 (https).
На CentOS они обычно закрыты файерволом. А на минимальной установке Ubuntu файрвол по дефолту не установлен. Нам не нужно гадать, установлен файервол или нет, открыты порты или нет, пусть Ansible просто обеспечит нам желаемый результат.
Создадим поддиректории roles/firewalld и roles/firewalld/tasks:
[root@Control-Node ansible]# mkdir roles/firewalld roles/firewalld/tasks
[root@Control-Node ansible]#
Далее создаем файл roles/firewalld/tasks/main.yml следующего содержания:
---
- name: "Install firewalld on CentOS"
ansible.builtin.dnf:
name: firewalld
state: latest
tags:
- installation
- firewalld
when: ansible_distribution == "CentOS"
- name: "Install firewalld on Ubuntu"
ansible.builtin.apt:
name: firewalld
state: latest
tags:
- installation
- firewalld
when: ansible_distribution == "Ubuntu"
- name: "Ensure Firewalld is started and enabled"
ansible.builtin.service:
name: firewalld
state: started
enabled: yes
tags:
- start
- firewalld
- name: "Open SSH service permanently in public zone"
ansible.posix.firewalld:
zone: public
service: ssh
permanent: true
state: enabled
tags:
- firewalld
- name: "Open HTTP service permanently in public zone"
ansible.posix.firewalld:
zone: public
service: http
permanent: true
state: enabled
tags:
- firewalld
- name: "Open HTTPS service permanently in public zone"
ansible.posix.firewalld:
zone: public
service: https
permanent: true
state: enabled
tags:
- firewalld
- name: "Reload Firewalld to apply changes"
ansible.builtin.service:
name: firewalld
state: restarted
tags:
- firewalld
Первым делом мы должны быть уверены, что файрвол присутствует, для этого сначала идут таски по его установке. Далее запускаем файрвол и добавляем в публичный доступ сервисы SSH, HTTP и HTTPS.
В реальных условиях, для повышения безопасности SSH лучше выносить из публичной зоны и ограничивать доступ. Но в рамках нашей практики это излишне, а ошибка в плейбуке может отрезать вам доступ до хоста.
Добавим роль в плейбук:
---
- hosts: all
roles:
- php
- nginx
- mariadb
- firewalld
Запустим плейбук с тегом firewalld, так мы исключим из раскатки таски, которые ранее уже неоднократно исполнялись:
[root@Control-Node ansible]# ansible-playbook install_lemp.yml --tags firewalld
PLAY [all] ******************************************************************************************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************************************************************************************
ok: [Managed-Node-2]
ok: [Managed-Node-1]
ok: [Managed-Node-3]
TASK [firewalld : Install firewalld on CentOS] ******************************************************************************************************************************************************
skipping: [Managed-Node-3]
changed: [Managed-Node-1]
changed: [Managed-Node-2]
TASK [firewalld : Install firewalld on Ubuntu] ******************************************************************************************************************************************************
skipping: [Managed-Node-1]
skipping: [Managed-Node-2]
changed: [Managed-Node-3]
TASK [firewalld : Ensure Firewalld is started and enabled] ******************************************************************************************************************************************
ok: [Managed-Node-1]
ok: [Managed-Node-2]
ok: [Managed-Node-3]
TASK [firewalld : Open SSH service permanently in public zone] **************************************************************************************************************************************
ok: [Managed-Node-3]
ok: [Managed-Node-2]
ok: [Managed-Node-1]
TASK [firewalld : Open HTTP service permanently in public zone] *************************************************************************************************************************************
changed: [Managed-Node-1]
changed: [Managed-Node-3]
changed: [Managed-Node-2]
TASK [firewalld : Open HTTPS service permanently in public zone] ************************************************************************************************************************************
changed: [Managed-Node-1]
changed: [Managed-Node-3]
changed: [Managed-Node-2]
TASK [firewalld : Reload Firewalld to apply changes] ************************************************************************************************************************************************
changed: [Managed-Node-3]
changed: [Managed-Node-1]
changed: [Managed-Node-2]
PLAY RECAP ******************************************************************************************************************************************************************************************
Managed-Node-1 : ok=7 changed=4 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
Managed-Node-2 : ok=7 changed=4 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
Managed-Node-3 : ok=7 changed=4 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
[root@Control-Node ansible]#
Ansible успешно отработал. Firewalld был обнавлен/установлен на хостах, а доступ к сервисам открыт. Теперь наши сервера готовы принимать запросы, можете проверить с помощью curl:
[root@Control-Node ansible]# curl -I 192.168.151
HTTP/1.1 200 OK
Server: nginx/1.20.1
Date: Wed, 10 Dec 2025 10:30:24 GMT
Content-Type: text/html
Content-Length: 2713881
Last-Modified: Tue, 04 Jun 2024 22:57:12 GMT
Connection: keep-alive
ETag: "665f9bc8-296919"
Accept-Ranges: bytes
[root@Control-Node ansible]#
Или вбив IP адрес хоста в браузере.
Итоги:
Мы разобрались, как работают роли и переделали наш плейбук, чтобы он был более структурированным и легко читаемым. Благодаря ролям можно писать плейбуки на сотни задач и не теряться в нем.
Следующий урок: Ansible практика – урок №6 Оптимизация плейбука с помощью block.