Сборка и запуск плейбука с пользовательскими ролями, ролями из Git и системными ролями
На этом шаге вы объедините все подготовленные компоненты: вашу пользовательскую роль, зависимость из Git и системную роль RHEL. Вы создадите основной плейбук, который будет оркестрировать эти роли для полной настройки сервера разработки веб-приложений.
Представьте этот шаг как сборку сложной машины из различных частей — каждая роль выполняет определенную функцию, и вместе они создают полноценную среду веб-сервера. Давайте разобьем это на управляемые части:
Сначала убедитесь, что вы находитесь в основной директории проекта.
cd ~/project
Прежде чем приступить к настройке, давайте разберемся, что мы создаем:
- Конфигурация Ansible: Настраивает поведение Ansible и места поиска файлов.
- Инвентарь (Inventory): Определяет, какими серверами управлять (в нашем случае, localhost).
- Переменные (Variables): Хранят данные, которые будут использоваться ролями (информация о разработчиках, настройки SELinux).
- Содержимое пользовательской роли: Фактические задачи, которые будут настраивать среду разработки.
- Основной плейбук (Main Playbook): Оркестратор, который выполняет все в правильном порядке.
1. Создание конфигурации Ansible и инвентаря
Файл ansible.cfg подобен конфигурационному файлу, который указывает Ansible, как ему следует работать. Без него вам пришлось бы указывать пути и опции в каждой команде. С ним Ansible автоматически знает, где искать ваши роли, коллекции и инвентарь.
Создайте файл ansible.cfg с помощью nano. Этот файл указывает Ansible, где искать ваши роли, коллекции и инвентарь.
nano ansible.cfg
Добавьте следующее содержимое. Давайте разберем каждую строку:
[defaults]
inventory = inventory
roles_path = roles
collections_paths = collections
host_key_checking = False
[privilege_escalation]
become = True
Что означает каждая настройка:
inventory = inventory: Вместо того чтобы каждый раз вводить -i inventory, Ansible будет автоматически использовать этот файл.
roles_path = roles: Ansible будет искать роли в директории roles.
collections_paths = collections: Здесь Ansible будет находить установленные вами коллекции.
host_key_checking = False: Предотвращает ошибки проверки SSH-ключей в лабораторных средах.
become = True: Автоматически выполняет задачи с повышенными привилегиями при необходимости.
Сохраните и выйдите из nano (Нажмите Ctrl+X, затем Y, затем Enter).
Файл инвентаря указывает Ansible, какими машинами управлять. В нашем случае мы настраиваем локальную машину.
nano inventory
Добавьте следующую строку:
localhost ansible_connection=local
Что это означает:
localhost: Имя нашей целевой машины.
ansible_connection=local: Вместо SSH используется локальное соединение (поскольку мы управляем той же машиной, на которой запускаем Ansible).
Сохраните и выйдите из nano.
2. Определение переменных роли
Переменные в Ansible — это как настройки, которые могут использовать ваши роли. Вместо того чтобы жестко кодировать значения, такие как имена пользователей или номера портов, в ваших задачах, вы определяете их в файлах переменных. Это делает вашу автоматизацию гибкой и повторно используемой.
Директория group_vars/all — это специальное место, где Ansible автоматически загружает переменные для всех хостов. Любой YAML-файл в этой директории становится доступным для ваших плейбуков и ролей.
Создайте структуру директорий для переменных, которые применяются ко всем хостам:
mkdir -p group_vars/all
Теперь создайте файл для определения информации о разработчиках. Эти данные будут использоваться вашей пользовательской ролью для создания учетных записей пользователей и конфигураций веб-сервера.
nano group_vars/all/developers.yml
Добавьте следующее содержимое:
---
web_developers:
- username: jdoe ## Первый разработчик
port: 9081 ## Пользовательский порт для веб-сайта этого разработчика
- username: jdoe2 ## Второй разработчик
port: 9082 ## Пользовательский порт для веб-сайта этого разработчика
Что означает эта структура данных:
web_developers: Список, содержащий информацию о разработчиках.
- У каждого разработчика есть
username и port.
- Ваша пользовательская роль будет перебирать этот список для создания конфигураций для каждого разработчика.
Сохраните и выйдите.
Далее создайте файл переменных для настройки SELinux. SELinux (Security-Enhanced Linux) — это модуль безопасности, который контролирует, что могут делать приложения.
nano group_vars/all/selinux.yml
Добавьте следующее содержимое:
---
selinux_state: enforcing ## Установить SELinux в режим enforcing (максимальная безопасность)
selinux_ports: ## Список портов, которые Apache разрешено использовать
- ports: "9081" ## Разрешить порт 9081
proto: "tcp" ## Протокол: TCP
setype: "http_port_t" ## Тип SELinux: HTTP порт
state: "present" ## Добавить это правило
- ports: "9082" ## Разрешить порт 9082
proto: "tcp" ## Протокол: TCP
setype: "http_port_t" ## Тип SELinux: HTTP порт
state: "present" ## Добавить это правило
Понимание настроек SELinux:
selinux_state: enforcing: SELinux будет активно блокировать несанкционированные действия.
selinux_ports: Список конфигураций портов.
http_port_t: Тип SELinux, который позволяет Apache привязываться к портам.
- По умолчанию Apache может использовать только порты 80 и 443; нам нужно явно разрешить порты 9081 и 9082.
Сохраните и выйдите.
3. Заполнение пользовательской роли
Ваша роль apache.developer_configs в настоящее время имеет структуру директорий, но без фактического содержимого. Нам нужно добавить:
- Шаблоны (Templates): Файлы, которые могут включать переменные (с использованием синтаксиса Jinja2).
- Задачи (Tasks): Фактическая работа, которую будет выполнять Ansible.
- Обработчики (Handlers): Специальные задачи, которые выполняются только при уведомлении (например, перезапуск служб).
- Метаданные (Metadata): Информация о зависимостях роли.
Шаблоны позволяют создавать файлы конфигурации, которые адаптируются на основе ваших переменных. Расширение .j2 указывает, что это шаблон Jinja2.
nano roles/apache.developer_configs/templates/developer.conf.j2
Добавьте следующее содержимое:
{% for dev in web_developers %}
Listen {{ dev.port }}
<VirtualHost *:{{ dev.port }}>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/{{ dev.username }}
<Directory /var/www/{{ dev.username }}>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
</VirtualHost>
{% endfor %}
Понимание синтаксиса шаблона:
{% for dev in web_developers %}: Начать цикл по списку разработчиков.
{{ dev.port }}: Вставить номер порта для этого разработчика.
{{ dev.username }}: Вставить имя пользователя для этого разработчика.
{% endfor %}: Завершить цикл.
- Результатом будут отдельные конфигурации виртуальных хостов для каждого разработчика.
Что это создает: Для наших двух разработчиков этот шаблон сгенерирует конфигурацию Apache, которая:
- Заставляет Apache слушать порты 9081 и 9082.
- Создает виртуальные хосты, которые обслуживают контент из
/var/www/jdoe и /var/www/jdoe2.
- Устанавливает соответствующие права доступа для каждой директории.
Сохраните и выйдите.
Задачи — это фактическая работа, которую выполняет Ansible. Каждая задача использует модуль Ansible для выполнения конкретной операции.
nano roles/apache.developer_configs/tasks/main.yml
Добавьте следующее содержимое и давайте разберем каждую задачу:
---
## Task 1: Create user accounts for each developer
- name: Create developer user accounts
ansible.builtin.user: ## Использовать модуль 'user'
name: "{{ item.username }}" ## Создать пользователя с этим именем
state: present ## Убедиться, что пользователь существует
loop: "{{ web_developers }}" ## Сделать это для каждого разработчика в списке
## Task 2: Create web directories for each developer
- name: Create developer web root directories
ansible.builtin.file: ## Использовать модуль 'file'
path: "/var/www/{{ item.username }}" ## Создать эту директорию
state: directory ## Убедиться, что это директория
owner: "{{ item.username }}" ## Установить владельца
group: "{{ item.username }}" ## Установить группу
mode: "0755" ## Установить права доступа (rwxr-xr-x)
loop: "{{ web_developers }}"
## Task 3: Create a sample webpage for each developer
- name: Create a sample index.html for each developer
ansible.builtin.copy: ## Использовать модуль 'copy'
content: "Welcome to {{ item.username }}'s dev space\n" ## Содержимое файла
dest: "/var/www/{{ item.username }}/index.html" ## Куда поместить файл
owner: "{{ item.username }}" ## Владелец файла
group: "{{ item.username }}" ## Группа файла
mode: "0644" ## Права доступа к файлу (rw-r--r--)
loop: "{{ web_developers }}"
## Task 4: Deploy the Apache configuration file
- name: Deploy developer apache configs
ansible.builtin.template: ## Использовать модуль 'template'
src: developer.conf.j2 ## Исходный файл шаблона
dest: /etc/httpd/conf.d/developer.conf ## Место назначения на сервере
mode: "0644" ## Права доступа к файлу
notify: restart apache ## Запустить обработчик restart при изменении этого файла
Понимание ключевых концепций:
loop: Повторяет задачу для каждого элемента в списке.
{{ item.username }}: Ссылается на имя пользователя текущего элемента в цикле.
notify: restart apache: Когда эта задача вносит изменения, она запускает обработчик с именем "restart apache".
- Права доступа к файлам:
0755 означает, что владелец может читать/писать/выполнять, остальные могут читать/выполнять; 0644 означает, что владелец может читать/писать, остальные могут только читать.
Сохраните и выйдите.
Обработчики — это специальные задачи, которые выполняются только при уведомлении от других задач. Они обычно используются для таких действий, как перезапуск служб.
nano roles/apache.developer_configs/handlers/main.yml
Добавьте следующее содержимое:
---
- name: restart apache ## Это имя должно совпадать с оператором notify:
ansible.builtin.service: ## Использовать модуль 'service'
name: httpd ## Имя службы (Apache называется 'httpd' в RHEL)
state: restarted ## Перезапустить службу
Зачем использовать обработчики?
- Эффективность: Служба перезапускается только в том случае, если конфигурация действительно изменилась.
- Порядок: Все задачи выполняются сначала, затем все обработчики выполняются в конце.
- Идемпотентность: Несколько задач могут уведомлять один и тот же обработчик, но он выполняется только один раз.
Сохраните и выйдите.
Наконец, нам нужно сообщить Ansible, что наша пользовательская роль зависит от роли infra.apache, которую мы установили ранее.
nano roles/apache.developer_configs/meta/main.yml
Замените содержимое файла на:
---
dependencies:
- role: infra.apache ## Эта роль должна быть выполнена перед нашей пользовательской ролью
Что это делает:
- Когда Ansible выполняет
apache.developer_configs, он сначала автоматически выполнит infra.apache.
- Это гарантирует, что Apache установлен и настроен до того, как мы добавим наши пользовательские конфигурации.
- Зависимости выполняются в том порядке, в котором они перечислены.
Сохраните и выйдите.
4. Сборка и запуск основного плейбука
Плейбук — это как рецепт, который указывает Ansible, что делать и в каком порядке. Наш плейбук будет:
- Настраивать параметры SELinux (pre_tasks).
- Выполнять наши роли (которые включают цепочку зависимостей).
Создайте файл основного плейбука:
nano web_dev_server.yml
Добавьте следующее содержимое с подробными объяснениями:
---
- name: Configure Dev Web Server ## Название плейбука
hosts: localhost ## Выполнять на localhost
pre_tasks: ## Задачи, которые выполняются перед ролями
## Task 1: Configure SELinux mode
- name: Set SELinux to enforcing mode
ansible.posix.selinux: ## Модуль из коллекции ansible.posix
policy: targeted ## Использовать политику SELinux 'targeted'
state: "{{ selinux_state }}" ## Использовать переменную, которую мы определили
when: selinux_state is defined ## Выполнять только если переменная определена
## Task 2: Configure SELinux ports
- name: Configure SELinux ports for Apache
community.general.seport: ## Модуль из коллекции community.general
ports: "{{ item.ports }}" ## Номер порта
proto: "{{ item.proto }}" ## Протокол (tcp)
setype: "{{ item.setype }}" ## Тип SELinux (http_port_t)
state: "{{ item.state }}" ## present или absent
loop: "{{ selinux_ports }}" ## Перебрать наш список портов
when: selinux_ports is defined ## Выполнять только если переменная определена
roles: ## Роли для выполнения
- apache.developer_configs ## Наша пользовательская роль (которая запустит infra.apache)
Понимание порядка выполнения:
pre_tasks: Сначала выполняется настройка SELinux.
roles: Сначала выполняются зависимости ролей (infra.apache), затем наша пользовательская роль.
handlers: Любые уведомленные обработчики выполняются в конце.
Почему этот порядок важен:
- SELinux должен быть настроен до того, как Apache попытается привязаться к пользовательским портам.
- Apache должен быть установлен до того, как мы сможем настроить виртуальные хосты.
- Перезапуск служб происходит после завершения всей конфигурации.
Сохраните и выйдите.
Теперь вы готовы выполнить вашу полную автоматизацию:
ansible-playbook web_dev_server.yml
Плейбук выполнится, и вы увидите подробный вывод. Вот что можно ожидать (например):
PLAY [Configure Dev Web Server] *************************************************
TASK [Gathering Facts] **********************************************************
ok: [localhost] ## Ansible собирает информацию о системе
TASK [Set SELinux to enforcing mode] *******************************************
changed: [localhost] ## Режим SELinux был изменен
TASK [Configure SELinux ports for Apache] **************************************
changed: [localhost] => (item={'ports': '9081', 'proto': 'tcp', 'setype': 'http_port_t', 'state': 'present'})
changed: [localhost] => (item={'ports': '9082', 'proto': 'tcp', 'setype': 'http_port_t', 'state': 'present'})
TASK [infra.apache : Ensure Apache is installed.] *******************************
changed: [localhost] ## Пакет Apache был установлен
TASK [apache.developer_configs : Create developer user accounts] ****************
changed: [localhost] => (item={'username': 'jdoe', 'port': 9081})
changed: [localhost] => (item={'username': 'jdoe2', 'port': 9082})
TASK [apache.developer_configs : Create developer web root directories] *********
changed: [localhost] => (item={'username': 'jdoe', 'port': 9081})
changed: [localhost] => (item={'username': 'jdoe2', 'port': 9082})
TASK [apache.developer_configs : Create a sample index.html for each developer] *
changed: [localhost] => (item={'username': 'jdoe', 'port': 9081})
changed: [localhost] => (item={'username': 'jdoe2', 'port': 9082})
TASK [apache.developer_configs : Deploy developer apache configs] ***************
changed: [localhost] ## Файл конфигурации был создан
RUNNING HANDLER [apache.developer_configs : restart apache] *********************
changed: [localhost] ## Apache был перезапущен
PLAY RECAP **********************************************************************
localhost : ok=17 changed=12 unreachable=0 failed=0 skipped=3 rescued=0 ignored=0
Вы успешно собрали и запустили сложный плейбук, который объединяет несколько ролей из разных источников для создания полноценной среды разработки веб-приложений!