Используемые термины: Ansible , Bind , Prometheus , Grafana .
Мы рассмотрим простые примеры установки различных систем с помощью ролей Ansible. Инструкция больше имеет практическое применение с минимальным количеством пояснений и комментариев, но хорошо подойдет в качестве шпаргалки.
Подготовка к работе с ролями
Описание процесса
NGINX
BIND
Prometheus
Grafana
Vault
Kubernetes
Сборка NGINX из исходников
Обновление сертификатов
Работа с учетными записями пользователей
Подготовка к работе
Предполагается, что у нас уже есть сервер с установленным Ansible, например, по инструкции Установка и запуск Ansible на CentOS .
В файл hosts мы должны добавить серверы, на которые будем устанавливать наши сервисы:
vi /etc/ansible/hosts
[test_servers]
192.168.1.115
192.168.1.116
* в моем примере мы добавили тестовую группу test_servers , а в нее 2 сервера.
Мы будем работать относительно каталога с ролями, поэтому создадим его и перейдем в созданную директорию:
mkdir /etc/ansible/roles
cd /etc/ansible/roles
Можно приступать к созданию ролей.
Синтаксис и описание
Пару слов о том, как будем работать.
Каждую роль мы создаем с помощью команды ansible-galaxy. Синтаксис следующий:
ansible-galaxy init <Имя роли>
После ввода команды в текущем каталоге (в нашем примере, /etc/ansible/roles) будет создана папка с названием роли, а в ней следующая структура каталогов:
- defaults — переменные по умолчанию. У них самый низкий приоритет и их могут легко переопределить переменные в каталоге vars (ниже по списку).
- files — для файлов, которые могут быть скопированы на настраиваемый сервер.
- handlers — обработчики, которые могут запускаться при определенных обстоятельствах. Например, перезапуск сервиса в случае обновления конфигурационного файла.
- meta — добавление метаданных, например: автор, описание, среда и так далее.
- tasks — папка с описанием выполняемых задач.
- templates — файлы с шаблонами. Мы можем использовать переменные в данных шаблонах — тогда при копировании файлов, они будут заменяться значениями.
- tests — скрипты для выполнения тестов — ansible покажет результаты выполнения команд, но не применит их.
- vars — файлы с переменными. Имеют высокий приоритет.
После будем приступать к настройке роли, созданию и запуску плейбука.
NGINX
Установке и настройке NGINX с помощью Ansible я посвятил отдельную инструкцию .
Bind DNS
Инициализируем новую роль:
ansible-galaxy init Bind
* мы назвали нашу роль Bind .
Открываем основной файл для задачи:
vi Bind/tasks/main.yml
Добавляем:
—
— name: Include vars for os family
include_vars:
file: «{{ ansible_os_family }}.yml»
— name: Install Bind on RedHat Family
yum:
name: bind
state: present
when:
ansible_os_family == «RedHat»
notify:
— bind systemd
— name: Install Bind on Debian Family
apt:
name: «{{ item }}»
state: present
loop:
— bind9
— dnsutils
when:
ansible_os_family == «Debian»
notify:
— bind systemd
* в зависимости от типа операционной системы мы подгрузим разные переменные (так как в разных системах имя для bind разное), после чего устанавливаем bind с помощью yum (для систем на базе Red Hat) или apt (Debian). Обратите внимание, что для систем Debian мы выполняем установку двух пакетов, для перечисления которых используем цикл.
Создаем файл с переменными для debian:
vi Bind/vars/Debian.yml
—
service_name : bind9
* с переменной service_name и значением bind9.
Также создаем файл с переменными в роли Bind для систем на базе Red Hat:
vi Bind/vars/RedHat.yml
—
service_name : named
* во втором файле значение для переменной service_name будет named .
Редактируем файл для handlers:
vi Bind/handlers/main.yml
—
— name: bind systemd
systemd:
name: «{{ service_name }}»
enabled: yes
state: started
* после установки bind необходимо разрешить автозапуск сервиса и стартовать его. Имя сервиса подставляется из переменной и зависит от типа операционной системы Linux.
Создаем файл для плейбука:
vi start_role.yml
—
— hosts: test_servers
user: remontka
become: true
become_method: su
become_user: root
roles:
— Bind
* в данном примере мы запускаем выполнение роли Bind на серверы из группы test_servers .
Запускаем созданный плейбук:
ansible-playbook start_role.yml -kK
Prometheus
Создаем файлы для роли, которую назовем Prometheus:
ansible-galaxy init Prometheus
Открываем на редактирование файл с заданиями:
vi Prometheus/tasks/main.yml
Логически, мы поделим задачи на 3 файла:
—
— name: Prepare For Install Prometheus
include_tasks: tasks/prepare.yml
— name: Install Prometheus
include_tasks: tasks/install_prometheus.yml
— name: Install Alertmanager
include_tasks: tasks/install_alertmanager.yml
* в первом файле будут описаны задачи для подготовки системы к установке Prometheus; во втором файле мы выполним установку системы мониторинга; в третьем файле описание для установки alertmanager.
Создаем первый файл с задачами:
vi Prometheus/tasks/prepare.yml
—
— name: Security Settings For RedHat
block:
— name: Allow Ports
firewalld:
port: «{{ item }}»
permanent: true
state: enabled
loop: [ ‘9090/tcp’, ‘9093/tcp’, ‘9094/tcp’, ‘9100/tcp’, ‘9094/udp’ ]
notify:
— firewalld systemd restart
— name: Disable SELinux
selinux:
state: disabled
— name: Stop SELinux
shell: setenforce 0
ignore_errors: yes
when:
ansible_os_family == «RedHat»
— name: Security Settings For Debian
block:
— name: Allow TCP Ports
iptables:
chain: INPUT
rule_num: ‘1’
action: insert
protocol: tcp
jump: ACCEPT
destination_port: «{{ item }}»
loop: [ ‘9090’, ‘9093’, ‘9094’, ‘9100’ ]
— name: Allow UDP Ports
iptables:
chain: INPUT
rule_num: ‘1’
action: insert
protocol: udp
jump: ACCEPT
destination_port: ‘9094’
when:
ansible_os_family == «Debian»
* в данном примере будут открыты в брандмауэре порты для корректной работы prometheus и alertmanager, а также будет отключен SELinux. Мы используем условие when, чтобы применить нужные команды, разделенные блоками ( block ), к нужному типу дистрибутива Linux, однако, если в вашей среде не используется брандмауэр или на CentOS применяется iptables, необходимо внести коррекции.
Открываем файл с переменными:
vi Prometheus/vars/main.yml
Создаем две:
—
prometheus_version : 2.23.0
alertmanager_version : 0.21.0
* данным переменным в качестве значения присваиваем версии prometheus и alertmanager, которые необходимо установить. В нашем примере взяты последние версии на момент обновления инструкции. Актуальные версии можно посмотреть на странице загрузки .
Создаем файл с описанием задач по установке Prometheus:
vi Prometheus/tasks/install_prometheus.yml
—
— name: Create User prometheus
user:
name: prometheus
create_home: no
shell: /bin/false
— name: Create directories for prometheus
file:
path: «{{ item }}»
state: directory
owner: prometheus
group: prometheus
loop:
— ‘/tmp/prometheus’
— ‘/etc/prometheus’
— ‘/var/lib/prometheus’
— name: Download And Unzipped Prometheus
unarchive:
src: https://github.com/prometheus/prometheus/releases/download/v{{ prometheus_version }}/prometheus-{{ prometheus_version }}.linux-amd64.tar.gz
dest: /tmp/prometheus
creates: /tmp/prometheus/prometheus-{{ prometheus_version }}.linux-amd64
remote_src: yes
— name: Copy Bin Files From Unzipped to Prometheus
copy:
src: /tmp/prometheus/prometheus-{{ prometheus_version }}.linux-amd64/{{ item }}
dest: /usr/local/bin/
remote_src: yes
mode: preserve
owner: prometheus
group: prometheus
loop: [ ‘prometheus’, ‘promtool’ ]
— name: Copy Conf Files From Unzipped to Prometheus
copy:
src: /tmp/prometheus/prometheus-{{ prometheus_version }}.linux-amd64/{{ item }}
dest: /etc/prometheus/
remote_src: yes
mode: preserve
owner: prometheus
group: prometheus
loop: [ ‘console_libraries’, ‘consoles’, ‘prometheus.yml’ ]
— name: Create File for Prometheus Systemd
template:
src=templates/prometheus.service
dest=/etc/systemd/system/
notify:
— systemd reload
— name: Systemctl Prometheus Start
systemd:
name: prometheus
state: started
enabled: yes
* в данном примере мы:
- Создаем пользователя prometheus.
- Создаем каталоги, в которые будут помещены файлы сервиса.
- Скачиваем и распаковываем архив прометея с официального сайта.
- Копируем бинарники.
- Копируем конфигурационные файлы.
- Создаем юнит в systemd.
- Стартуем сервис.
Создаем yml-файл с задачами по установке и запуску alertmanager:
vi Prometheus/tasks/install_alertmanager.yml
—
— name: Create User Alertmanager
user:
name: alertmanager
create_home: no
shell: /bin/false
— name: Create Directories For Alertmanager
file:
path: «{{ item }}»
state: directory
owner: alertmanager
group: alertmanager
loop:
— ‘/tmp/alertmanager’
— ‘/etc/alertmanager’
— ‘/var/lib/prometheus/alertmanager’
— name: Download And Unzipped Alertmanager
unarchive:
src: https://github.com/prometheus/alertmanager/releases/download/v{{ alertmanager_version }}/alertmanager-{{ alertmanager_version }}.linux-amd64.tar.gz
dest: /tmp/alertmanager
creates: /tmp/alertmanager/alertmanager-{{ alertmanager_version }}.linux-amd64
remote_src: yes
— name: Copy Bin Files From Unzipped to Alertmanager
copy:
src: /tmp/alertmanager/alertmanager-{{ alertmanager_version }}.linux-amd64/{{ item }}
dest: /usr/local/bin/
remote_src: yes
mode: preserve
owner: alertmanager
group: alertmanager
loop: [ ‘alertmanager’, ‘amtool’ ]
— name: Copy Conf File From Unzipped to Alertmanager
copy:
src: /tmp/alertmanager/alertmanager-{{ alertmanager_version }}.linux-amd64/alertmanager.yml
dest: /etc/alertmanager/
remote_src: yes
mode: preserve
owner: alertmanager
group: alertmanager
— name: Create File for Alertmanager Systemd
template:
src=templates/alertmanager.service
dest=/etc/systemd/system/
notify:
— systemd reload
— name: Systemctl Alertmanager Start
systemd:
name: alertmanager
state: started
enabled: yes
* в данном примере мы:
- Создаем пользователя alertmanager.
- Создаем каталоги, в которые будут помещены файлы сервиса.
- Скачиваем и распаковываем архив alertmanager с официального сайта.
- Копируем бинарники.
- Копируем конфигурационные файлы.
- Создаем юнит в systemd.
- Стартуем сервис.
Создаем файл в шаблонах с юнитом systemd для prometheus:
vi Prometheus/templates/prometheus.service
[Unit]
Description=Prometheus Service
After=network.target
[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/prometheus
—config.file /etc/prometheus/prometheus.yml
—storage.tsdb.path /var/lib/prometheus/
—web.console.templates=/etc/prometheus/consoles
—web.console.libraries=/etc/prometheus/console_libraries
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
[Install]
WantedBy=multi-user.target
Создаем файл в шаблонах с юнитом systemd для alertmanager:
vi Prometheus/templates/alertmanager.service
[Unit]
Description=Alertmanager Service
After=network.target
[Service]
EnvironmentFile=-/etc/default/alertmanager
User=alertmanager
Group=alertmanager
Type=simple
ExecStart=/usr/local/bin/alertmanager
—config.file=/etc/alertmanager/alertmanager.yml
—storage.path=/var/lib/prometheus/alertmanager
$ALERTMANAGER_OPTS
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
[Install]
WantedBy=multi-user.target
Открываем на редактирование файл с обработчиками:
vi Prometheus/handlers/main.yml
Приводим его к виду:
—
— name: firewalld systemd restart
command: firewall-cmd —reload
— name: systemd reload
systemd:
daemon_reload: yes
* в данном примере мы будем перезапускать firewalld и перечитывать юниты в systemd.
Создаем плейбук:
vi start_role.yml
—
— hosts: test_servers
user: remontka
become: true
become_method: su
become_user: root
roles:
— role: Prometheus
tags: prom
* данный файл описывает плейбук для запуска роли Prometheus . Обратите внимание, что для примера мы добавили тег prom .
Запускаем наш плейбук для установки Prometheus + Alertmanager:
ansible-playbook —tags prom start_role.yml -kK
* в данном примере запуск вложенной роли запускается с тегом prom . Это ни на что не влияет, но, если бы у нас в плейбуке будет много ролей, с помощью тега мы можем запускать конкретную.
Grafana
Инициализируем файлы для роли Grafana:
ansible-galaxy init Grafana
Открываем на редактирование файл с заданиями:
vi Grafana/tasks/main.yml
Установка будет учитывать системы типа Debian или Red Hat с помощью блоков:
— name: Security Settings And Install Grafana For RedHat
block:
— name: Allow Ports
firewalld:
port: ‘3000/tcp’
permanent: true
state: enabled
notify:
— firewalld systemd restart
— name: Disable SELinux
selinux:
state: disabled
— name: Stop SELinux
shell: setenforce 0
ignore_errors: yes
— name: Add Repository
yum_repository:
name: Grafana
description: Grafana YUM repo
baseurl: https://packages.grafana.com/oss/rpm
gpgkey: https://packages.grafana.com/gpg.key
gpgcheck: yes
sslverify: yes
sslcacert: /etc/pki/tls/certs/ca-bundle.crt
— name: Install Grafana on RedHat Family
yum:
name: grafana
state: present
notify:
— grafana systemd
when:
ansible_os_family == «RedHat»
— name: Security Settings And Install Grafana For Debian
block:
— name: Allow TCP Ports
iptables:
chain: INPUT
rule_num: ‘1’
action: insert
protocol: tcp
jump: ACCEPT
destination_port: ‘3000’
— name: Import Grafana Apt Key
apt_key:
url: https://packages.grafana.com/gpg.key
state: present
— name: Add APT Repository
apt_repository:
repo: deb https://packages.grafana.com/oss/deb stable main
state: present
— name: Install Grafana on Debian Family
apt:
name: grafana
state: present
notify:
— grafana systemd
when:
ansible_os_family == «Debian»
* в нашем примере мы независимо от системы создаем правило в брандмауэре для порта 3000, добавляем репозиторий, устанавливаем графану.
Редактируем файл для handlers:
vi Grafana/handlers/main.yml
—
— name: firewalld systemd restart
command: firewall-cmd —reload
— name: grafana systemd
systemd:
name: grafana-server
enabled: yes
state: started
* в нашем handlers есть 2 задания:
- Перезапуск брандмауэра firewalld для применения настроек.
- Разрешение автозапуска сервиса grafana.
Создаем файл для плейбука:
vi start_role.yml
—
— hosts: test_servers
user: remontka
become: true
become_method: su
become_user: root
roles:
— Grafana
* в данном примере мы запускаем выполнение роли Grafana на серверы из группы test_servers .
Запускаем созданный плейбук:
ansible-playbook start_role.yml -kK
Hasicorp Vault
Подробнее об установке и настройке Hashicorp Vault .
Инициализируем файлы для роли Vault:
ansible-galaxy init Vault
Открываем на редактирование файл с заданиями:
vi Vault/tasks/main.yml
Разделим наше задание на два этапа — преднастройку системы и установку Vault:
—
— name: Prepare System
include_tasks: tasks/prepare.yml
— name: Install Vault
include_tasks: tasks/install_vault.yml
Создаем файл с задачами для преднастройки системы:
vi Vault/tasks/prepare.yml
—
— name: Prepare System For RedHat
block:
— name: Install Packages
yum:
name: «{{ item }}»
state: present
loop:
— wget
— chrony
— curl
— name: Allow Ports
firewalld:
port: «{{ item }}»
permanent: true
state: enabled
immediate: yes
loop: [ ‘8200/tcp’ ]
when:
ansible_os_family == «RedHat»
— name: Security Settings For Debian
block:
— name: Install Packages
apt:
name: «{{ item }}»
state: present
update_cache: yes
loop:
— wget
— chrony
— curl
— apt-transport-https
— iptables-persistent
— name: Allow TCP Ports
iptables:
chain: INPUT
rule_num: ‘1’
action: insert
protocol: tcp
jump: ACCEPT
destination_port: «{{ item }}»
loop: [ ‘8200’ ]
notify:
— iptables save
when:
ansible_os_family == «Debian»
Теперь создаем файл с заданиями по установке Vault:
vi Vault/tasks/install_vault.yml
— name: Install Hashicorp Vault For RedHat
block:
— name: Add Repository
get_url:
url: https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
dest: /etc/yum.repos.d/hashicorp.repo
— name: Install Vault
yum:
name: vault
state: present
notify:
— vault systemd
— name: Set Shell Enviroment
copy:
src: profile.d/vault.sh
dest: /etc/profile.d/vault.sh
when:
ansible_os_family == «RedHat»
— name: Install Hashicorp Vault For Debian
block:
— name: Import Vault Apt Key
apt_key:
url: https://apt.releases.hashicorp.com/gpg
state: present
— name: Add APT Repository
apt_repository:
repo: deb [arch=amd64] https://apt.releases.hashicorp.com {{ ansible_lsb.codename }} main
state: present
filename: hashicorp
— name: Install Vault
apt:
name: vault
state: present
notify:
— vault systemd
— name: Set Shell Enviroment
lineinfile:
path: /etc/environment
line: export VAULT_SKIP_VERIFY=true
create: yes
when:
ansible_os_family == «Debian»
Создаем хендлер для сохранения правил iptables и настройки сервиса vault:
vi Vault/handlers/main.yml
—
— name: iptables save
shell: netfilter-persistent save
— name: vault systemd
systemd:
name: «vault»
enabled: yes
state: started
Создаем каталог:
mkdir Vault/files/profile.d
Создадим в нем файл для настройки среды окружения для CentOS:
vi Vault/files/profile.d/vault.sh
export VAULT_SKIP_VERIFY=true
Создаем файл для плейбука:
vi start_role.yml
—
— hosts: test_servers
user: remontka
become: true
become_method: su
become_user: root
roles:
— Vault
* в данном примере мы запускаем выполнение роли Vault на серверы из группы test_servers .
Запускаем созданный плейбук:
ansible-playbook start_role.yml -kK
Кластер Kubernetes
В нашем примере мы создадим сценарий для настройки кластера под управлением Ubuntu Server. Подробнее о настройке Kubernetes на Ubuntu .
Для описания нод кластера мы будем использовать отдельный inventory файл:
mkdir /etc/ansible/inventory
vi /etc/ansible/inventory/kube_servers.yml
kube_servers:
vars:
ansible_python_interpreter: /usr/bin/python3
hosts:
server01:
ansible_host: master.remontka.local
ansible_ssh_host: 192.168.100.12
server02:
ansible_host: worker01.remontka.local
ansible_ssh_host: 192.168.100.13
server03:
ansible_host: worker02.remontka.local
ansible_ssh_host: 192.168.100.14
children:
master:
hosts:
server01:
worker:
hosts:
server02:
server03:
* в нашем примере установка будет выполнена на три сервера — один мастер и два воркера. Также мы выделили 2 группы — master и worker в которые вошли соответствующие серверы. Такая инвентаризация позволит нам точно указать, какие серверы мы планируем использовать в качестве мастера, а какие в качестве рабочих нод.
Инициализируем роль:
ansible-galaxy init Kubernetes
Откроем файл с задачами:
vi Kubernetes/tasks/main.yml
Пропишем следующее:
—
— name: Set hostname
hostname:
name: «{{ hostvars[inventory_hostname].ansible_host }}»
— name: Add to hosts file cluster machines
blockinfile:
path: /etc/hosts
block: |
{% for host in groups[‘kube_servers’] %}
{{ hostvars[host].ansible_ssh_host }} {{ hostvars[host].ansible_host }}
{% endfor %}
— name: Disable SWAP 1/2 (swapoff)
shell: swapoff -a
— name: Disable SWAP 2/2 (fstab)
replace:
path: /etc/fstab
regexp: ‘^([^#].*?sswaps+sws+.*)$’
replace: ‘# 1’
— name: Create File for modules load
file:
path: /etc/modules-load.d/k8s.conf
state: touch
owner: root
group: root
mode: 0644
— name: Add modules k8s
lineinfile:
path: /etc/modules-load.d/k8s.conf
line: «{{ item }}»
loop:
— br_netfilter
— overlay
— name: Add br_netfilter and overlay modules
modprobe:
name: «{{ item }}»
state: present
loop:
— br_netfilter
— overlay
— name: Set sysctl bridge-nf-call options
sysctl:
name: «{{ item }}»
value: ‘1’
state: present
reload: yes
sysctl_file: /etc/sysctl.d/k8s.conf
loop:
— net.bridge.bridge-nf-call-ip6tables
— net.bridge.bridge-nf-call-iptables
— name: Docker install
package:
name:
— docker
— docker.io
state: present
— name: Copy daemon.json config file
copy:
src: daemon.json
dest: /etc/docker/daemon.json
remote_src: no
mode: 0644
owner: root
group: root
— name: Docker systemctl enable and start
systemd:
name: docker
enabled: yes
state: restarted
— name: Import kubernetes repo key
apt_key:
url: https://packages.cloud.google.com/apt/doc/apt-key.gpg
state: present
— name: «Add kubernetes repository»
apt_repository:
repo: deb https://apt.kubernetes.io/ kubernetes-xenial main
filename: kubernetes
— name: kubernetes install
apt:
name:
— kubelet
— kubeadm
— kubectl
state: present
update_cache: yes
— name: Hold kubernetes to update
dpkg_selections:
name: «{{ item }}»
selection: hold
loop:
— kubelet
— kubeadm
— kubectl
— name: Master Settings
block:
— name: kubeadm init pod-network-cidr
shell: kubeadm init —pod-network-cidr=10.244.0.0/16
ignore_errors: yes
— name: Set KUBECONFIG system environment permanently
lineinfile:
path: /etc/environment
line: export KUBECONFIG=/etc/kubernetes/admin.conf
— name: Install CNI (Container Networking Interface)
shell: kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
— name: Get join command
shell: kubeadm token create —print-join-command
register: join_command
— name: Open ports on a firewall for Master
iptables:
action: insert
rule_num: 1
chain: INPUT
protocol: tcp
destination_port: «{{ item }}»
jump: ACCEPT
loop:
— «6443»
— «2379:2380»
— «10250:10252»
when: «‘master’ in group_names»
— name: Workers Settings
block:
— name: Open ports on a firewall for Worker
iptables:
action: insert
rule_num: 1
chain: INPUT
protocol: tcp
destination_port: «{{ item }}»
jump: ACCEPT
loop:
— «10250»
— «30000:32767»
— name: kubeadm init pod-network-cidr
shell: «{{ hostvars[groups[‘master’].0].join_command.stdout }}»
ignore_errors: yes
when: «‘worker’ in group_names»
-name: Install iptables-persistent
package:
name: iptables-persistent
state: present
— name: Save firewall rule
shell: netfilter-persistent save
Создаем конфигурационный файл daemon.json:
vi Kubernetes/files/daemon.json
{
«exec-opts»: [«native.cgroupdriver=systemd»],
«log-driver»: «json-file»,
«log-opts»: {
«max-size»: «100m»
},
«storage-driver»: «overlay2»,
«storage-opts»: [
«overlay2.override_kernel_check=true»
]
}
Создаем файл для плейбука:
vi start_role.yml
—
— hosts: kube_servers
user: root
gather_facts: true
become: true
become_method: su
become_user: root
roles:
— Kubernetes
* в данном примере мы запускаем выполнение роли Kubernetes на серверы из группы kube_servers .
Запускаем созданный плейбук:
ansible-playbook -i /etc/ansible/inventory/test_servers.yml start_role.yml
* обратите внимание, что с помощью опции -i мы указываем путь до инвентарного файла, который создали специально для данного примера.
Сборка из исходников NGINX
Ранее была указана ссылка на страницу с описанием установки NGINX из пакетов при помощи Ansible. Но если нам нужно добавить дополнительный модуль, необходима сборка веб-сервера из исходников. Данный пример, в большей степени, можно использовать для сборки и других пакетов.
В нашем примере мы соберем NGINX и добавим в него модуль SPNEGO. Модуль может быть любым — главное, понять принцип.
Создаем новую роль с любым названием, например, Nginx_Make:
ansible-galaxy init Nginx_Make
Открываем файл с переменными:
vi Nginx_Make/vars/main.yml
—
nginx_ver : 1.19.3
* нам нужна одна переменная для указания конкретной версии NGINX, которую мы хотим установить.
Открываем на редактирование файл с заданиями:
vi Nginx_Make/tasks/main.yml
—
— name: Security Settings For RedHat
block:
— name: Allow Ports
firewalld:
port: ‘{{ item }}/tcp’
permanent: true
state: enabled
immediate: true
loop: [ ’80’, ‘443’ ]
notify:
— firewalld systemd restart
— name: Disable SELinux
selinux:
state: disabled
— name: Stop SELinux
shell: setenforce 0
ignore_errors: yes
when:
ansible_os_family == «RedHat»
— name: Security Settings For Debian
block:
— name: Allow TCP Ports
iptables:
chain: INPUT
rule_num: ‘1’
action: insert
protocol: tcp
jump: ACCEPT
destination_port: ‘{{ item }}’
loop: [ ’80’, ‘443’ ]
when:
ansible_os_family == «Debian»
— name: Installing NGINX Dependencies On Debian
apt:
name: «{{ item }}»
update_cache: yes
state: present
loop:
— git
— build-essential
— libpcre++-dev
— zlib1g-dev
— libkrb5-dev
— libssl-dev
— libxslt-dev
— libgd-dev
when:
ansible_os_family == «Debian»
— name: Installing NGINX Dependencies On Red Hat
yum:
name: «{{ item }}»
state: present
loop:
— epel-release
— git
— pcre-devel
— openssl-devel
— libxml2-devel
— libxslt-devel
— gd-devel
— perl-ExtUtils-Embed
— gperftools-devel
when:
ansible_os_family == «RedHat»
— name: Unpacking Nginx Source
unarchive:
src: «http://nginx.org/download/nginx-{{ nginx_ver }}.tar.gz»
dest: /tmp/
remote_src: yes
creates: /tmp/nginx-{{ nginx_ver }}.tar.gz
register: nginx_source_unpack
— name: Clone Nginx Module From GitHub
git:
repo: «https://github.com/stnoonan/spnego-http-auth-nginx-module.git»
dest: /tmp/nginx-{{ nginx_ver }}/spnego-http-auth-nginx-module
register: module_source_clone
— name: Configuring NGINX Source With Custom Modules For Debian
command: «./configure —prefix=/usr/share/nginx —sbin-path=/usr/sbin/nginx —conf-path=/etc/nginx/nginx.conf —http-log-path=/var/log/nginx/access.log —error-log-path=/var/log/nginx/error.log —lock-path=/var/lock/nginx.lock —pid-path=/run/nginx.pid —modules-path=/usr/lib/nginx/modules —http-client-body-temp-path=/var/lib/nginx/body —http-fastcgi-temp-path=/var/lib/nginx/fastcgi —http-proxy-temp-path=/var/lib/nginx/proxy —http-scgi-temp-path=/var/lib/nginx/scgi —http-uwsgi-temp-path=/var/lib/nginx/uwsgi —with-debug —with-compat —with-pcre-jit —with-http_ssl_module —with-http_stub_status_module —with-http_realip_module —with-http_auth_request_module —with-http_v2_module —with-http_dav_module —with-http_slice_module —with-threads —with-http_addition_module —with-http_gunzip_module —with-http_gzip_static_module —with-http_image_filter_module=dynamic —with-http_sub_module —with-http_xslt_module=dynamic —with-stream=dynamic —with-stream_ssl_module —with-mail=dynamic —with-mail_ssl_module —add-module=spnego-http-auth-nginx-module»
args:
chdir: «/tmp/nginx-{{ nginx_ver }}»
when: nginx_source_unpack.changed or module_source_clone.changed
register: nginx_configure
— name: Installing NGINX
shell: make && make install
args:
chdir: «/tmp/nginx-{{ nginx_ver }}»
when: nginx_configure.changed
register: installed_nginx
— name: Create Nginx User For Red Hat
user:
name: nginx
create_home: no
shell: /bin/false
when:
ansible_os_family == «RedHat»
— name: Create Folder /var/lib/nginx
file:
path: «/var/lib/nginx»
state: directory
— name: Create File for Nginx Systemd
copy:
src: files/nginx.service
dest: /lib/systemd/system
notify:
— systemd reload
register: create_nginx_systemd
— name: Systemctl Nginx Restart
systemd:
name: nginx
state: restarted
enabled: yes
when: create_nginx_systemd.changed or installed_nginx.changed
* обратите внимание:
- необходимый набор зависимостей может оказаться индивидуальным, так как при добавлении других модулей система будет требовать других компонентов — лучшим решением будет собрать вручную nginx на тестовом сервере и определить точный набор пакетов для установки.
- в данном примере для добавления модуля SPNEGO необходимо его клонировать с GitHub и разместить в каталоге с исходником. Для установки другого модуля могут понадобиться другие действия. Необходимо изучить документацию для каждого конкретного модуля.
- опции конфигурирования индивидуальны и зависят от ваших потребностей. В данном примере используется общий набор опций.
Открываем файл для notify:
vi Nginx_Make/handlers/main.yml
—
— name: firewalld systemd restart
command: firewall-cmd —reload
— name: systemd reload
systemd:
daemon_reload: yes
Создаем файл для юнита systemd:
vi Nginx_Make/files/nginx.service
[Unit]
Description=A high performance web server and a reverse proxy server
Documentation=man:nginx(8)
After=network.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -q -g ‘daemon on; master_process on;’
ExecStart=/usr/sbin/nginx -g ‘daemon on; master_process on;’
ExecReload=/usr/sbin/nginx -g ‘daemon on; master_process on;’ -s reload
ExecStop=-/sbin/start-stop-daemon —quiet —stop —retry QUIT/5 —pidfile /run/nginx.pid
TimeoutStopSec=5
KillMode=mixed
Restart=on-failure
[Install]
WantedBy=multi-user.target
Создаем файл для плейбука:
vi start_role.yml
—
— hosts: test_servers
user: remontka
become: true
become_method: su
become_user: root
roles:
— Nginx_Make
* в данном примере мы запускаем выполнение роли Nginx_Make на серверы из группы test_servers .
Запускаем созданный плейбук:
ansible-playbook start_role.yml -kK
Обновление сертификата
Так как большинство современных сервисов требуют для своей работы сертификат, рассмотрим пример централизованного их обновления.
Предположим, что у нас есть сертификат wildcard и необходимо его копировать на все серверы компании. Если серверов много, делать это вручную при очередном его обновлении неудобно.
И так, создаем новую роль:
ansible-galaxy init Update_Certs
Открываем на редактирование файл с заданиями:
vi Update_Certs/tasks/main.yml
—
— name: Register System Services
service_facts:
register: services_state
— name: Create Directories For Certs
file:
path: ‘/etc/ssl/dmoks’
state: directory
owner: root
group: root
mode: 0755
— name: Copy Cert File If Different
copy:
src: «{{ item }}»
dest: /etc/ssl/remontka
remote_src: no
mode: 0644
owner: root
group: root
with_fileglob:
— files/*
notify:
— reload httpd
— reload nginx
— reload apache2
* будут выполняться следующие задачи:
- Register System Services — получаем список всех служб, которые работают на целевом компьютере
- Create Directories For Certs — создаем каталог /etc/ssl/dmoks, в который будем копировать сертификаты
- Copy Cert File If Different — копируем сертификаты в целевой каталог. Если были изменения в любом из файлов, по очереди запускаем 3 задачи в handlers для перезагрузки сервисов. Здесь нам нужно самостоятельно перечислить все службы, которые вам нужно перезагружать.
Открываем на редактирование файл в каталоге handlers:
vi Update_Certs/handlers/main.yml
Добавим строки:
—
— name: reload httpd
systemd:
name: httpd
state: restarted
when:
services_state.ansible_facts.services[‘httpd.service’].state == ‘running’
ignore_errors: yes
— name: reload nginx
systemd:
name: nginx
state: restarted
when:
services_state.ansible_facts.services[‘nginx.service’].state == ‘running’
ignore_errors: yes
— name: reload apache2
systemd:
name: apache2
state: restarted
when:
services_state.ansible_facts.services[‘apache2.service’].state == ‘running’
ignore_errors: yes
* в задачах, в случае изменения сертификатов, мы выполняем задания reload httpd , reload nginx и reload apache2 . Все задания описаны в данном файле. В данном примере мы проверяем, что сервисы запущены и если это так, перезапускаем их. Нам необходимо перезапускать все службы, которые используют сертификаты (в противном случае, обновленные сертификаты не будут использоваться). При необходимости дописать службы, делаем это по аналогии.
В каталог Update_Certs/files/ помещаем наши сертификаты — все содержимое данного каталога будет копироваться на целевые компьютеры в каталог /etc/ssl/remontka .
Создаем файл для плейбука:
vi start_role.yml
—
— hosts: test_servers
user: remontka
become: true
become_method: su
become_user: root
roles:
— Update_Certs
* в данном примере мы запускаем выполнение роли Update_Certs на серверы из группы test_servers .
Запускаем созданный плейбук:
ansible-playbook start_role.yml -kK
Создание пользователя
Это довольно типичная задача для возможности контролировать на своих серверах учетные записи пользователей. Рассмотрим пример централизованного создания нескольких аккаунтов. Подробная инструкция на официальном сайте .
И так, создаем новую роль:
ansible-galaxy init Local_Users
Предположим, мы создадим пользователей user1 и user2. Сгенерируем хэши для их паролей:
openssl passwd -salt ‘AnySalt’ -1
* где AnySalt — произвольный текст для соли.
После ввода команды система запросит ввести пароль — вводим и получаем хэш, например:
Password:
$1$AnySalt$J1MdB0X9KWZBg7BxeC9Ee0
Копируем его — он понадобиться позже. После повторяем команду, вводим новый пароль и генерируем хэш для второго пользователя.
Открываем на редактирование файл с заданиями:
vi Local_Users/tasks/main.yml
—
— name: Add User For Servers
user:
name: ‘{{ item.name }}’
password: ‘{{ item.password }}’
state: present
update_password: on_create
loop:
— { name: ‘user1’, password: ‘$1$AnySalt$J1MdB0X9KWZBg7BxeC9Ee0’ }
— { name: ‘user2’, password: ‘$1$AnySalt$It8oyh2yAISnUqI4jK5VR0’ }
* в данном примере будут созданы пользователи из цикла loop , в котором перечислены связки логин и пароль — конкретно, в нашем случае, это user1 и user2 ; state: present говорит, что пользователь должен присутствовать в системе; update_password: on_create установит наш пароль только при создании пользователя, ползволив ему самому сменить данные для аутентификации.
Создаем файл для плейбука:
vi start_role.yml
—
— hosts: test_servers
user: remontka
become: true
become_method: su
become_user: root
roles:
— Local_Users
* в данном примере мы запускаем выполнение роли Local_Users на серверы из группы test_servers .
Запускаем созданный плейбук:
ansible-playbook start_role.yml -kK