Skip to main content

Роли

Роль — способ организовать набор tasks, переменных, шаблонов, файлов и обработчиков в переиспользуемый модуль. Роли используются для конфигурации конкретных приложений. По умолчанию директория /etc/ansible/roles

Настраивается в cfg файле:

[defaults]
roles_path = ./roles

Также в переменной ANSIBLE_ROLES_PATH

Структура роли и добавление в playbook

  1. Создается папка roles, внутри папки с названиями ролей, внутри каждой папки - defaults files handlers meta templates tasks vars
  2. в playbook добавляется 
       roles:
        - имя

Назначения папок

Папка Назначение
defaults Устанавливает переменные по умолчанию для включенных ролей. Обычно defaults/main.yml 
---
# Used only for Debian/Ubuntu installation, as the -t option for apt.
nginx_default_release: ""

# Used only for Redhat installation, enables source Nginx repo.
nginx_yum_repo_enabled: true

# Use the official Nginx PPA for Ubuntu, and the version to use if so.
nginx_ppa_use: false
nginx_ppa_version: stable
files содержит статические файлы и файлы сценариев, которые могут быть скопированы на удалённый сервер или выполнены на нём.
handlers Обработчики, выполняемые  в самом конце
meta для метаданных роли, которые используются для управления зависимостями. Например, вы можете определить список ролей, которые должны быть применены до вызова текущей роли.
templates

Шаблоны генерации файлов на удалённых хостах. Шаблоны jinja2. 

Например нужно создать файл /etc/docker/daemon.json

Создаем шаблон в roles/docker/templates/daemon.json.j2

cat{
  templates/nginx.conf.j2"log-driver": user"json-file",
  "log-opts": {
    "max-size": "{{ nginx_userdocker_log_size }};",
    error_log"max-file": "{{ nginx_error_logdocker_log_files }};
pid        {{ nginx_pidfile }};

{% block worker %}
worker_processes  {{ nginx_worker_processes }};
{% endblock %}

{% if nginx_extra_conf_options %}
{{ nginx_extra_conf_options }}
{% endif %}

{% block events %}
events {
    worker_connections  {{ nginx_worker_connections }};
    multi_accept {{ nginx_multi_accept }};"
  }
{% endblock %}

http {
    {% block http_begin %}{% endblock %}

Добавляем переменные в roles/docker/defaults/main.yml 

docker_log_size: "10m"
docker_log_files: "3"

Создаем задачу 

- name: Deploy daemon.json
  ansible.builtin.template:
    src: daemon.json.j2
    dest: /etc/docker/daemon.json
    owner: root
    group: root
    mode: "0644"
  notify: Restart Docker

Создаем handlers roles/docker/handlers/main.yml 

- name: Restart Docker
  ansible.builtin.systemd:
    name: docker
    state: restarted

 В результате на сервере появится json файл.

tasks

Содержит файлы с задачами, которые определяются в разделе tasks обычного плейбука Ansible. Сначала просматривается файл tasks/main.yml В нем указывается условия импорта других файлов

---
# Variable setup.
- name: Include OS-specific variables.
  include_vars: "{{ ansible_os_family }}.yml"

- name: Define nginx_user.
  set_fact:
    nginx_user: "{{ __nginx_user }}"
  when: nginx_user is not defined

# Setup/install tasks.
- include_tasks: setup-RedHat.yml
  when: ansible_os_family == 'RedHat'

- include_tasks: setup-Ubuntu.yml
  when: ansible_distribution == 'Ubuntu'

- include_tasks: setup-Debian.yml
  when: ansible_os_family == 'Debian'

# Vhost configuration.
- import_tasks: vhosts.yml

# Nginx setup.
- name: Copy nginx configuration in place.
  template:
    src: "{{ nginx_conf_template }}"
    dest: "{{ nginx_conf_file_path }}"
    owner: root
    group: "{{ root_group }}"
    mode: 0644
  notify:
    - reload nginx

- name: Ensure nginx service is running as configured.
  service:
    name: nginx
    state: "{{ nginx_service_state }}"
    enabled: "{{ nginx_service_enabled }}"

Пути указываются относительно директории tasks

Эти задачи могут напрямую ссылаться на файлы и шаблоны, содержащиеся в соответствующих каталогах внутри роли, без необходимости указывать полный путь к файлу.

vars переменные для роли могут быть указаны в файлах внутри каталога, а затем ссылаться на них в другом месте роли.

Ссылки:

Пример преобразования одного файла в роль

Хранилище ролей

Есть сайт с ролями почти для всего. Сайт с ролями ansible Можно найти нужную роль на сайте, затем установить при помощи 

ansible-galaxy install current_role_name -p .

Создание роли:

ansible-galaxy init new_role_name

Пример создания новой роли

Пусть будет задача в установке docker. Реализуем из инструкции по Docker: общая информация и установка

Инициализируем новую роль 

ansible-galaxy init just_new_role

Структура директорий создана. Проанализируем инструкцию.

  • Написана для 3 вариаций ОС: Debian, Ubuntu, Alt.
  • Последовательность установки: 
    • Создание пользователя
    • Добавление сертификатов
    • Непосредственно установка пакетов
    • Дополнительные удобства

В константы будем постепенно добавлять нужные. Итоговый defaults/main.yml : 

---
# defaults file for just_new_role
docker_user: webadmin
packages_certificates:
  - ca-certificates
  - curl
  - gnupg
  - lsb-release
packages_docker_debian:
  - docker-ce
  - docker-ce-cli
  - containerd.io
  - docker-compose-plugin
packages_docker_alt:
  - docker-engine
  - docker-compose-v2

Начнем с установки sudo и добавления пользователя в группы, то есть реализуем следующие команды:

apt-get install sudo
sudo apt-get update
usermod -aG sudo docker_user

Файл задач tasks/01_create_user.yml : 

- name: Install sudo
  ansible.builtin.apt:
    name: sudo
    state: present
    update_cache: true
- name: Ensure user exists and is in sudo group
  ansible.builtin.user:
    name: "{{ docker_user }}"
    groups: sudo
    append: true
    state: present

Да, если сопоставить количество строк команд и того, что необходимо написать для их исполнения, возникает ощущение перебора (в 3 раза). Но это плата за индепотентность.

Добавим в файл tasks/main.yml задачу старта 01_create_user.yml 

---
# tasks file for just_new_role
- include_tasks: 01_create_user.yml

Запуск роли

Когда роль написана, нужно создать следующую структуру директорий для playbook 

project/
├── inventory.ini
├── playbook.yml
└── roles/
    └── just_new_role/
        ├── defaults/
        ├── tasks/
        ├── handlers/
        └── ...

Пример файла inventory.ini 

[docker_hosts]
192.168.1.100

[docker_hosts:vars]
ansible_user=webadmin

Пример playbook.yml 

---
- name: Install Docker
  hosts: all
  become: true

  roles:
    - just_new_role

Итоговые файлы:

main.yml 

---
# tasks file for just_new_role
- include_tasks: 01_create_user.yml
- include_tasks: 02_append_certs.yml

01_create_user.yml 

- name: Install sudo
  ansible.builtin.apt:
    name: sudo
    state: present
    update_cache: true
  when: ansible_distribution == "Debian"
- name: Ensure user exists and is in sudo group
  ansible.builtin.user:
    name: "{{ docker_user }}"
    groups: sudo
    append: true
    state: present
- name: Install required packages
  ansible.builtin.apt:
    name: "{{ packages_certificates }}"
    state: present
    update_cache: true
  when: ansible_distribution == "Debian"

02_append_certs.yml 

- name: Create apt keyrings directory
  ansible.builtin.file:
    path: /etc/apt/keyrings
    state: directory
    owner: root
    group: root
    mode: "0755"

- name: Download Docker GPG key
  ansible.builtin.get_url:
    url: https://download.docker.com/linux/debian/gpg
    dest: /etc/apt/keyrings/docker.asc
    mode: "0644"

- name: Create binary keyring
  ansible.builtin.command:
    cmd: >
      gpg --dearmor
      --output /etc/apt/keyrings/docker.gpg
      /etc/apt/keyrings/docker.asc
    creates: /etc/apt/keyrings/docker.gpg

- name: Add Docker repository
  ansible.builtin.apt_repository:
    repo: >-
      deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg]
      https://download.docker.com/linux/debian
      {{ ansible_distribution_release }} stable
    filename: docker
    state: present

- name: Update apt cache
  ansible.builtin.apt:
    update_cache: true

- name: Install required packages
  ansible.builtin.apt:
    name: "{{ packages_docker_debian }}"
    state: present
    update_cache: true
  when: ansible_distribution == "Debian"

- name: Ensure user exists and is in sudo group
  ansible.builtin.user:
    name: "{{ docker_user }}"
    groups: docker
    append: true
    state: present

- name: Enable and start Docker service
  ansible.builtin.systemd:
    name: docker
    enabled: true
    state: started