На чем было опробовано:
- Ansible 2.9.18
- Hyper-V на Windows 10 Pro.
- Сервер Ansible: CentOS Linux release 7.9.2009 (Core).
- Node 1: CentOS Linux release 7.9.2009 (Core).
- Node 2: CentOS Linux release 7.9.2009 (Core).
- Node 3: CentOS Linux release 7.9.2009 (Core).
1. Введение.
Официальную документацию с официальными примерами всегда можно почитать на сайте разработчиков Ansible.
Ссылка: docs.ansible.com.
Раздел: «ansible-playbook».
Как установить и первоначально настроить Ansible описано здесь:
Ссылка: «Ansible: Часть 1. Описание, установка и первоначальная настройка.»
Так как простые задачи для Ansible реально простые, в буквальном смысле слова, то я принял решение вынести их в отдельную инструкцию:
Ссылка: «Ansible: Часть 2. Примеры простых задач.»
По данной ссылке я создам небольшую подборку самых интересных и типовых плейбуков, которые могут пригодиться вам в повседневной работе.
Ссылка: «Ansible: Часть 4. Практические примеры плейбуков.»
Как настраивать защищенные плейбуки описано в этом разделе.
Ссылка: «Ansible: Часть 5. Настройка защищенных плейбуков.»
2. Сценарии — playbooks.
Ansible позволяет не только выполнять единичные задачи, но и писать сценарии, которые необходимо выполнить на управляемых узлах.
Рассмотрим структуру и правила написания таких сценариев более подробно.
Все сценарии в Ansible пишутся на YAML — это удобный для человека формат данных, гораздо более простой, чем XML или JSON.
Чтобы выполнить сценарий используется команда ansible-playbook
со следующим синтаксисом:
# ansible-playbook <имя_файла_сценария.yml> ... [другие параметры]
Для Ansible практически каждый YAML файл начинается со списка. Каждый элемент списка — список пар «ключ-значение», часто называемая словарем.
В начале сценария обязательно должна присутствовать последовательность символов ‘---
‘ (так в YAML обозначается начало документа).
Перед каждым новым разделом списка ставится дефис ( -
):
---
- name: Операции с SELinux
hosts: webservers
become_method: sudo
become_user: root
tasks:
- name: Отключаем SELinux
selinux:
state: disabled
Основными параметрами/группами простого сценария являются:
hosts
— в нем указываются управляемые узлы или группы узлов, к которым нужно применить изменения;tasks
— здесь описывается состояние, в которое необходимо привести управляемый узел, альтернативой этому могут служить роли;
Также в сценарии перед непосредственным описанием задач могут быть указаны следующие параметры или группы параметров:
gather_facts
— собирать или нет информацию об узлах перед выполнением задач, по умолчанию —да
;vars
— в нем указываются различные переменные, которые будут использованы при выполнении сценария;connection
— можно указать метод соединения с узлами:pure ssh
,paramiko
,fireball
,chroot
,jail
,local
,accelerate
(применимо также для выполнения отдельного модуля);sudo
— после установления соединения выполнять задачу с привилегиями другого пользователя, по умолчанию другой пользователь — root;sudo_user
— в сочетании с предыдущим параметром можно указать с привилегиями какого именно пользователя будет выполнена задача;vars_prompt
— перед выполнением плейбука Ansible в интерактивном режиме может уточнить указанные в этом разделе параметры;remote_user
(в предыдущих версиях — просто user) — имя пользователя для авторизации на удалённом узле.
Рассмотрим все эти разделы более подробно.
В разделе hosts
указывается группа управляемых узлов, к которой будут применены описываемые в сценарии изменения.
Так, строка формата:
hosts: webservers
Это означает, что изменения будут применены к узлам из группы webservers
.
Сценарии могут выполняться не только от имени пользователя, под именем которого установлено соединение, но и любого другого.
В следующем примере авторизация на узле будет произведена с именем yourname
, но задачи будут выполняться от имени пользователя root (если, конечно, этому пользователю это разрешено):
---
- name: Операции с SELinux
hosts: webservers
become_method: sudo
become_user: yourname
Если добавить параметр ‘user: postgres
‘, то все действия будут выполняться с привилегиями пользователя postgres.
В разделе vars
указываются переменные, которые будут использованы в сценарии, и их значения:
- hosts: webservers
vars:
http_port: 80
max_clients: 200
Список изменений, которые необходимо произвести на управляемом узле, приводится в разделе tasks
. Каждой задаче (task
) присваивается имя (name
).
Далее указываются модули Ansible, которые будут задействованы при ее выполнении:
---
- hosts: webservers
user: yourname
tasks:
- service:
name: nginx
state: started
Для каждой задачи можно указывать пользователя, от имени которого она будет выполнена:
---
- hosts: webservers
user: yourname
tasks:
- service:
name: nginx
state: started
sudo: yes
Еще некоторые примеры.
Все члены списка должны находится с одинаковым отступом от начала строки, и должны начинаться с пробела или «-
». Комментарии начинаются с «#
».
Например:
---
# Message
- Hosting
Cloud
Словарь представлен в виде «ключ:
» (двоеточие и пробел) «значение
»:
---
# Message
site: habr
blog: infobox
При необходимости словари могут быть представлены в сокращенной форме:
--
# Comment
{site: habr, blog: infobox}
Можно указать логические значение (истина/ложь) так:
---
need_access: no
use_service: yes
file_conf: TRUE
read_value: True
kill_process: false
Целиком наш пример YAML–файла будет выглядеть так:
---
# About blog
site: hamstersen.ru
blog: infobox
must_read: true
themes:
- hosting
- cloud
- it
- geeks
brands:
- infobox
- infoboxcloud
Для переменных Ansible использует «{{ var }}
». Если значение после двоеточия начинается с «{
», то YAML будет думать, что это словарь.
Для использования переменных нужно заключить скобки в кавычки:
word: "{{ variable }}"
Этого достаточно для начала написания playbooks.
По данной ссылке я создам небольшую подборку самых интересных и типовых плейбуков, которые могут пригодиться вам в повседневной работе.
Ссылка: «Ansible: Часть 4. Практические примеры плейбуков.»
3. Обработчики событий — handlers.
Ansible не просто выполняет задачи в указанном порядке, но и проверяет их состояние на наличие изменений. Если при выполнении сценария требовалось, например, добавить строку в конфигурационный файл, и в результате выполнения он изменился (необходимой строки действительно не было), то Ansible может выполнить специальную задачу, описанную как обработчик события (handler
). Если при выполнении строка уже была в конфигурационном файле, то обработчик выполнен не будет. Обработчики событий описываются в конце сценария. В описании задачи они указываются через параметр notify
.
Приведём пример:
---
- hosts: webservers
vars:
max_clients: 200
tasks:
# генерируем файл конфигурации на основе шаблона
# и укажем, что требуется выполнить задачу “restart apache”
# если файл изменился
- name: write the apache config file
template:
src: /srv/httpd.j2
dest: /etc/httpd.conf
notify:
- restart apache
- name: ensure apache is running
service:
name: httpd
state: started
# раздел описания обработчиков
handlers:
- name: restart apache
# используем модуль service для перезапуска веб-сервера
service:
name: httpd
state: restarted
4. Контроль выполнения.
Допустим, что при выполнении сценария нам нужно проверять определённые переменные или состояния и, в зависимости от них, выполнять или не выполнять какие-либо задачи.
Для этого можно использовать оператор «when
»:
tasks:
# сохраняем файл шаблона и сохраняем результат задачи
# в переменную last_result
- template:
src: /templates/foo.j2
dest: /etc/foo.conf
register: last_result
# проверяем переменную last_result.changed и если она имеет
# значение true - задача будет выполнена, иначе - будет пропущена
- command:
echo 'the file has changed'
when: last_result.changed
5. Шаблонизация.
В Ansible используется шаблонизатор Jinja2.
Приведём пример шаблона (часть конфигурации powerdns):
# пароль для подключения к базе данных
gpgsql-password={{ lookup('password', 'credentials/' + inventory_hostname + '/postgresql/powerdns', length=15) }}
# IPv4-адрес, который будет “слушать” powerdns
local-address={{ ansible_default_ipv4.address }}
# IPv6-адрес, который будет “слушать” powerdns
local-ipv6={{ ansible_default_ipv6.address }}
# nsid dns-сервера (EDNS option 3, rfc5001)
server-id={{ ansible_hostname }}
В приведённом примере мы подставляем в шаблон следующие значения:
- из заранее собранных фактов об узле:
ansible_default_ipv4.address
— основной IPv4-адрес узла;ansible_default_ipv6.address
— основной IPv6-адрес узла;ansible_hostname
— имя узла (результат выполнения командыhostname
).
inventory_hostname
— имя узла в инвентарном файле;- пароль пользователя powerdns из внешнего источника данных (в данном случае файл) для подключения к базе Postgresql , полученный с помощью lookup-плагина password из стандартной поставке. Особенность некоторых lookup-плагинов — если данных нет, то они могут их генерировать и сохранить для последующего использования.
Обработку шаблонов и, в данном случае, генерацию конфигурационного файла выполняет модуль template
; он же может задать необходимые права доступа и изменить владельца/группу:
- name: generate powerdns config
template: src=pdns.conf.j2 dest=/etc/powerdns/pdns.conf owner=powerdns group=powerdns mode=600
Внимание! Файл шаблона и файл с паролем пользователя базы данных находятся на машине управления, а результатом будет файл на удалённом узле.
6. Делегирование задачи другому узлу.
Иногда требуется выполнить задачу на определённом узле, но в контексте другого узла.
Например, во время обновления узла может возникнуть необходимость отключить для него мониторинг, находящийся на отдельном сервере. Для этого используется управляющая директива delegate_to
.
Приведём пример:
- name: disable nagios alerts for this host webserver service
nagios:
action: disable_alerts
host: {{inventory_hostname}}
services: dnsserver
delegate_to: mon_host.example.com
Результатом выполнения этой задачи будет отключение сообщений для сервиса dnsserver
в Nagios
.
7. Роли.
Ролью называется типовой набор переменных и задач, назначаемых для одного или нескольких серверов. Если вам нужно применить к серверу или группе серверов типовой набор операций, вам достаточно просто назначить ему роль. Предварительно в проекте каталоге проекта должна быть создана соответствующая структура.
В сценариях роли назначаются следующим образом:
---
- name: check and apply basic configuration to all hosts
hosts: all
roles:
- common
- name: check and apply configuration to group1
hosts: group1
roles:
- pgsql
- name: check and apply configuration to group2
hosts: group2
roles:
- fooapp
8. Структура проекта.
9. Пишем первые playbook’и.
Playbook может состоять из списка обслуживаемых серверов, переменных пользователя, задач, обработчиков (хендлеров) и так далее. Большинство настроек конфигурации можно переопределить в playbook. Каждый playbook состоит из одного или более действия (игры) в списке.
Цель игры — связать группу хостов с предопределенными ролями, представленными как вызов задач Ansible.
В качестве другого примера давайте рассмотрим процесс установки nginx.
Создадим директорию, где будут хранится playbooks:
# mkdir ~/ansible/playbooks
Создадим файл setup_nginx.yml
в директории playbooks со следующим содержанием:
---
- hosts: experiments
tasks:
- name: Install nginx package
apt:
name: nginx
update_cache: yes
sudo: yes
- name Starting nginx service
service:
name: nginx
state: started
sudo: yes
Давайте рассмотрим содержимое:
hosts:
Список узлов или группа, на которой вы запускаете задачу.
Это поле обязательное и каждый playbook должен иметь его, за исключением ролей. Если указана узловая-группа, сначала Ansible ее ищет в playbook, а затем в файле inventory
.
Узнать, на каких узлах будет происходить работа, можно командой:
# ansible-playbook --list-host
где – путь к вашему playbook (playbooks/setup_nginx.yml
).
tasks:
Задачи. Все playbooks содержат задачи.
Задача — это список действий, которые вы хотите выполнить. Поле задачи содержит имя задачи (справочная информация о задаче для пользователя playbook), модуль, который должен быть выполнен и аргументы, требуемые для модуля. Параметр «name
» может добавляться опционально, но, в целом, рекомендуемый.
10. Пример сценария.
В этом примере первое воспроизведение предназначено для web-серверов, а второе — для серверов баз данных:
Пример сценария:
---
- name: update web servers
hosts: webservers
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum:
name: httpd
state: latest
- name: write the apache config file
template:
src: /srv/httpd.j2
dest: /etc/httpd.conf
- name: update db servers
hosts: databases
remote_user: root
tasks:
- name: ensure postgresql is at the latest version
yum:
name: postgresql
state: latest
- name: ensure that postgresql is started
service:
name: postgresql
state: started
11. Практические примеры плейбуков.
По данной ссылке я создам небольшую подборку типовых плейбуков, которые могут пригодиться вам в повседневной работе.
Ссылка: «Ansible: Часть 4. Практические примеры плейбуков.»
12. Запуск плейбуков.
Чтобы запустить плейбук и выполнить все определенные в нем задачи, используйте команду ansible-playbook:
# ansible-playbook myplaybook.yml
Чтобы перезаписать в плейбуке опцию hosts по умолчанию и ограничить выполнение определенной группой или узлом, включите в команду опцию -l
:
# ansible-playbook -l server1 myplaybook.yml
13. Запрос информации о play.
Опция --list-tasks
используется для перечисления всех задач, которые будут выполнены в play, при этом не внося никаких изменений на удаленные серверы:
# ansible-playbook myplaybook.yml --list-tasks
Точно так же можно запросить все узлы, которые будут затронуты выполнением play, без запуска каких-либо задач на удаленных серверах:
# ansible-playbook myplaybook.yml --list-hosts
Вы можете использовать теги, чтобы ограничить выполнение play.
Чтобы вывести список всех тегов, доступных в play, используйте параметр --list-tags
:
# ansible-playbook myplaybook.yml --list-tags
14. Управление выполнением плейбука.
Вы можете использовать опцию --start-at-task
, чтобы определить новую точку входа вашего плейбука. Затем Ansible пропустит все, что предшествует указанной задаче, выполнив оставшуюся часть play с заданного момента.
Эта опция в качестве аргумента требует правильное имя задачи:
# ansible-playbook myplaybook.yml --start-at-task="Set Up Nginx"
Чтобы выполнять только задачи, связанные с конкретными тегами, вы можете использовать опцию --tags
.
Например, если вы хотите выполнить только задачи, помеченные как nginx или mysql, вы можете использовать:
# ansible-playbook myplaybook.yml --tags=mysql,nginx
Если вы хотите пропустить все задачи, которые находятся под определенными тегами, используйте --skip-tags
.
Следующая команда будет выполнять myplaybook.yml, пропуская все задачи, помеченные как mysql
:
# ansible-playbook myplaybook.yml --skip-tags=mysql
15. Настройка защищенных плейбуков.
Если ваши плейбуки Ansible содержат конфиденциальные данные, такие как пароли, ключи API и учетные данные, важно обеспечить их безопасность с помощью шифрования. Ansible предоставляет ansible-vault для шифрования файлов и переменных.
Несмотря на то, что любой файл данных Ansible, а также двоичные файлы, возможно зашифровать изначально, чаще для шифрования переменных файлов, содержащих конфиденциальные данные, используется ansible-vault. После шифрования файла с помощью этого инструмента вы сможете выполнять, редактировать или просматривать его, только предоставив соответствующий пароль, указанный при первом шифровании файла.
Ссылка: «Ansible: Часть 5. Настройка защищенных плейбуков.»
16. Оригиналы источников информации.
- selectel.ru «Система управления конфигурацией Ansible».
- dmosk.ru «Инструкция по установке и запуску Ansible на CentOS».
- dmosk.ru «Что такое ansible».
- 8host.com «Как работать с Ansible: простая удобная шпаргалка».
- habr.com «Автоматизируем и ускоряем процесс настройки облачных серверов с Ansible. Часть 1: Введение».
- kamaok.org.ua «Установка и использование Ansible на Centos7».
- Источник: https://hamsterden.ru/ansible-playbooks/