Ansible практика – урок №11: Шаблоны и их применение.

Предыдущий урок: Ansible практика – урок №10: Больше переменных в host vars.

В прошлом уроке мы изучили механизм host vars позволяющий массово использовать переменные, сегодня эти переменные помогут нам разобраться с концепцией шаблонов в Ansible.

Зачем нужны шаблоны?

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

Шаблоны и их применение.

Разные веб сервера могут иметь одинаковые настройки PHP и MariaDB, но одинаковых настроек NGINX у них не будет. Каждый сервер работает для своего сайта, со своим доменным именем. Давайте реализуем динамическое задание доменного имени в настройках NGINX с помощью шаблона.

Шаг 1: Подготавливаем шаблон

Создадим поддиректорию templates в директории роли nginx:

[root@Control-Node ansible]# mkdir roles/nginx/templates
[root@Control-Node ansible]#

А в ней файл nginx.conf.j2, содержание файла конфигурации можно скопировать с любого управляемого хоста.

Я оставлю только часть для 80 порта, так как на тестовом окружении мы не будем использовать SSL сертификаты, если вы адаптируете плейбук под реальный веб сервер, не забудьте добавить 443 порт.

В конечном итоге файл roles/nginx/templates/nginx.conf.j2 будет выглядеть следующим образом:

worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 4096;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80;
        listen       [::]:80;
        server_name  {{ domain_name }};
        root         /usr/share/nginx/html;

        include /etc/nginx/default.d/*.conf;

        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
    }
} 

Мы использовали переменную domain_name (ее мы добавили в прошлом уроке)в директиве server_name, отвечающей в NGINX за то, какие адреса обслуживает веб сервер.

Шаг 2: Добавляем шаблон в плейбук

Отредактируем роль nginx, добавим задачу на использование шаблона. Модифицированный файл roles/nginx/tasks/main.yml имеет следующий вид:

---
- name: "Role: NGINX | Block: Installation"
  tags:
    - installation
    - nginx
  block:
    - name: "Install NGINX on CentOS"
      ansible.builtin.dnf:
        name: nginx
        state: latest
      when: ansible_distribution == "CentOS"

    - name: "Install NGINX on Ubuntu"
      ansible.builtin.apt:
        name: nginx
        state: latest
      when: ansible_distribution == "Ubuntu"

- name: "Ensure NGINX is started and enabled"
  ansible.builtin.service:
    name: nginx
    state: started
    enabled: true
  tags:
    - start
    - nginx

- name: "Deploy nginx.conf from template"
  ansible.builtin.template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
    mode: '0644'
    owner: root
    group: root
  notify: restart_nginx
  tags:
    - nginx

Для работы с шаблонами используется модуль ansible.builtin.template (документация по модулю).

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

Создадим директорию:

[root@Control-Node ansible]# mkdir roles/nginx/handlers
[root@Control-Node ansible]#

И файл roles/nginx/handlers/main.yml со следующим содержанием:

---
- name: restart_nginx
  ansible.builtin.service:
    name: nginx
    state: restarted

Шаблон создан, таск добавлен. Переходим к запуску плейбука.

Шаг 3: Проверяем плейбук

Запустим Ansible ограничив его работу тегами, чтобы не катать лишние таски:

[root@Control-Node ansible]# ansible-playbook install_lemp.yml --tags nginx --skip-tags installation,start

PLAY [all] ******************************************************************************************************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************************************************************************************
ok: [Managed-Node-2]
ok: [Managed-Node-1]
ok: [Managed-Node-3]

TASK [nginx : Deploy nginx.conf from template] ******************************************************************************************************************************************************
changed: [Managed-Node-2]
changed: [Managed-Node-1]
changed: [Managed-Node-3]

RUNNING HANDLER [nginx : restart_nginx] *************************************************************************************************************************************************************
changed: [Managed-Node-1]
changed: [Managed-Node-2]
changed: [Managed-Node-3]

PLAY RECAP ******************************************************************************************************************************************************************************************
Managed-Node-1             : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
Managed-Node-2             : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
Managed-Node-3             : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

[root@Control-Node ansible]#

Плейбук отработал без ошибок, пройдем по управляемым нодам и проверим получил ли каждый сервер свой индивидуальный домен:

Managed-Node-1:

[root@Managed-Node-1 ~]# grep server_name /etc/nginx/nginx.conf
        server_name  example-1.com;
[root@Managed-Node-1 ~]#

Managed-Node-2:

[root@Managed-Node-2 ~]# grep server_name /etc/nginx/nginx.conf
        server_name  example-2.com;
[root@Managed-Node-2 ~]#

Managed-Node-3:

root@Managed-Node-3:~# grep server_name /etc/nginx/nginx.conf
        server_name  example-3.com;
root@Managed-Node-3:~#

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

Итоги:

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

Следующий урок: в процессе