Описание
Playbook — это сценарий, описывающий действия, которые нужно выполнить на управляемых хостах.
- Особенности:
- Пишется на YAML;
- Действия выполняются последовательно в том порядке, в котором написаны;
- Идемпотентность - проверяется, достигнуто ли желаемое конечное состояние, и если это состояние достигнуто работа завершается без выполнения каких-либо действий, так что повторение задачи не изменяет конечное состояние;
- Начинается с трех тире (---), обозначающих начало документа;
- Комментарии обозначаются решеткой #;
- Отступ - 2 пробела.
ansible-playbook main.yaml
Структура файла playbook
--- #Начинается всегда с трех тире
- name: test-playbook #Имя playbook (любое)
hosts: servers #Группа хостов, на которых будет происходить выполнение (своя группа, all, ungroupt, localhost)
become: true #Запускать все задачи с правами суперпользователя (true или false, по умолчанию - false)
gather_facts: true #Осуществлять или нет сбор фактов (данных об управляемых хостах) (true или false, по умолчанию - true)
vars: #Список переменных для этого сценария
owner: root
custom_var: 42
vars_files: #Файлы с переменными
- vars.yaml
tasks: #Список задач
- name: block examples tasks #Объединенный блок нескольких задач, для которого можно задать условие, теги и.т.д.
block:
- name: Установка apache в centos
yum:
name: httpd
update_cache: true
state: present
- name: Запуск apache в centos
service:
name: httpd
state: started
enabled: true
tags: tag1, tag2 #Теги
when: ansible_os_family == "RedHat" #Условие выполнения
- name: Создание файла #Имя задачи
file: #Модуль
dest: /var/www/html/index.html #Аргументы
state: touch
owner: "{{ owner }}" #Использование переменной, всегда выделяется кавычками
group: "{{ owner }}"
mode: 0644
tags: tag1, tag2
notify: Restart httpd #Вызывается handlers только если произошли изменения
handlers:
- name: Restart httpd
service:
name: httpd
state: restarted
- Основными группами простого сценария являются:
- hosts — управляемые узлы или группы узлов, к которым нужно применить изменения, можно указать список;
- tasks — задачи описывающие состояние, в которое необходимо привести управляемый узел, могут быть выделены в роли;
- roles — объединение содержимого, такого как файлы, шаблоны, задачи и т.д. в одну роль для ее последующего вызова
- gather_facts — собирать или нет информацию об узлах перед выполнением задач, по умолчанию — да;
- vars — переменные, которые будут использованы при выполнении сценария;
- block — объединение нескольких задач в блок для которого можно указать условие и теги
- vars_files — список файлов с переменными
- pre_tasks — список задач, выполняемых перед другими задачами
- post_tasks — список задач, выполняемых после других задач
- handlers — список задач, выполняемых после вызова из другой задачи
Задачи в блоке handlers называются обработчиками и выполняются в тех случаях, если в результате выполнения вызывающей их задачи произошли изменения. Обработчики выполняются только после завершения задач и только один раз. Обработчики выполняются в порядке следования в разделе handlers. В основном обработчики используются для перезапуска служб после изменения конфигурационных файлов.
- Основными параметрами простого сценария являются:
- connection — можно указать метод соединения с узлами: pure ssh, paramiko, fireball, chroot, jail, local, accelerate (применимо также для выполнения отдельного модуля);
- sudo — после установления соединения выполнять задачу с привилегиями другого пользователя, по умолчанию другой пользователь — root;
- sudo_user — в сочетании с предыдущим параметром можно указать с привилегиями какого именно пользователя будет выполнена задача;
- vars_prompt — перед выполнением playbook'а Ansible в интерактивном режиме может уточнить указанные в этом разделе параметры;
- remote_user — имя пользователя для авторизации на удалённом узле;
- become — выполнить от имени привилегированного пользователя;
- become_user — имя привилегированного пользователя;
- when — условие выполнения;
- tags — теги, могут быть указаны при запуске playbook'а для выполнения конкретных задач;
- ignore_errors — игнорировать ошибки выполнения задачи и продолжать дальше.
Debug и register
- Модуль debug имеет два возможных аргумента
- var — выводит значение переменной;
- msg — выводит текст, а также можно выводить значение переменной, в том числе встроенных в ansible, например owner. Все встроенные переменные можно посмотреть командой ansible group -m setup.
---
- name: test-playbook
hosts: localhost
vars:
msg1: 123
msg2: 456
path: /home/123
tasks:
- debug:
var: path
- debug:
var: ansible_os_family #выводит семейство ос
- debug:
msg: "string {{ owner }}"
#Объединить переменные в новую переменную и вывести
- set_fact: full_message="{{ msg1 }} {{ msg2 }} {{ owner }}"
- debug:
msg: full_message
Модуль register сохраняет выходные данные команд, он регистрирует в отдельный словарь с информацией о задаче, которую можно использовать дальше, всякая задача, выполняемая при запуске, может сохранить результаты в переменной. Для вывода информации в консоль можно использовать модуль debug.
---
- name: test-playbook
hosts: localhost
tasks:
- shell: uptime
register: results
- debug:
var: results
- debug:
var: results.stdout #выведет только вывод команды uptime
Условия
Для условия используется слово when
---
- name: test-playbook
hosts: localhost
vars:
var1: true
var2: false
tasks:
- name: Установка apache в centos
yum:
name: httpd
update_cache: true
state: present
when: var1
- name: Установка nginx в centos
yum:
name: httpd
update_cache: true
state: present
when: var2
Будет выполнена только первая задача.---
- name: test-playbook
hosts: servers
tasks:
- name: Установка apache в centos
yum:
name: httpd
update_cache: true
state: present
when: ansible_os_family == "RedHat" #ansible_os_family - встроенная переменная
- name: Установка apache в ubuntu
apt:
name: apache2
update_cache: true
state: present
when: ansible_os_family == "Debian" #или when: ansible_os_family != "RedHat"
- name: Запуск apache в centos
service:
name: httpd
state: started
enabled: true
when: ansible_os_family == "RedHat"
- name: Запуск apache в ubuntu
service:
name: apache2
state: started
enabled: true
when: ansible_os_family == "Debian" #или (when: ansible_os_family != "RedHat")
---
- name: test-playbook
hosts: servers
tasks:
- block:
- name: Установка apache в centos
yum:
name: httpd
update_cache: true
state: present
- name: Запуск apache в centos
service:
name: httpd
state: started
enabled: true
when: ansible_os_family == "RedHat"
- block:
- name: Установка apache в ubuntu
apt:
name: apache2
update_cache: true
state: present
- name: Запуск apache в ubuntu
service:
name: apache2
state: started
enabled: true
when: ansible_os_family == "Debian"
Шаблоны Jinja2
Шаблоны позволяют задавать переменные в файлах, которые будут скопированы на хосты. При копировании переменная заменяется значением.
Hostname: {{ ansible_hostname }} #встроенные переменные
OS family: {{ ansible_os_faminy }}
IP: {{ ansible_default_ipv4.address }}
my_var: {{ my_var}} #своя переменная
---
- name: test-playbook
hosts: servers
vars: #своя переменная
my_var: example1
tasks:
- name: Копирование файла с подстановкой переменных
template:
src: /home/test1/template1.j2
dest: /home/test2/file1.txt #из шаблона получается файл с именем file1.txt с подставленными переменными
mode: 0644
Циклы
- Есть несколько вариантов цикла
- loop - цикл по количеству элементов списка;
- with_fileglob - цикл использующий файлы, которые соответствуют регулярному выражению;
- until - цикл с условием выхода.
Цикл имеет зарезервированную переменную item, значение которой меняется каждую итерацию цикла.
---
- name: test-playbook
hosts: servers
tasks:
- name: Вывод 4 строк с цифрами
debug:
msg: "string {{ item }}" #item - это зарезервированное для цикла слово
loop:
- "1"
- "2"
- "3"
- "4"
loop_control:
pause: 3 #пауза в 3 секунды между итерациями цикла, можно не указывать
- name: Копирование нескольких файлов
copy:
src: "/home/test1/{{ my_files }}"
dest: /home/test2
mode: 0644
loop:
- "file1.txt"
- "file5.txt"
- "file6.txt"
loop_control:
loop_var: my_files #замена стандартной переменной item на свою
---
- name: test-playbook
hosts: servers
tasks:
- name: Копирование файлов по регулярному выражению
copy:
src: "/home/test1/{{ item }}"
dest: /home/test2
mode: 0644
with_fileglob: "*.txt"
- name: Копирование файлов по регулярному выражению
copy:
src: "{{ item }}"
dest: /home/test2
mode: 0644
with_fileglob: "/home/test1/*.txt"
Эти две задачи выполнят одно и тоже.---
- name: test-playbook
hosts: servers
tasks:
- name: Второй вариант
shell: echo -n "123-" >> file1.txt && cat file1.txt #запись строки в файл и вывод в консоль
register: output #вывод предыдущей команды записывается в переменную output
delay: 2 #задержка 2 секунды между итерациями цикла, необязательно
retries: 10 #максимальное количество итераций цикла, необязательно, по умолчанию 3
until: output.stdout.find("123-123-123-") == false #условие выхода из цикла
- name: Вывод output
debug:
var: output.stdout
Import и include
Для разделения playbook'а используются import и include. Они позволяют в отдельном файле написать задачи на определенную тему, затем импортировать их в основной файл.
При использовании import - ansible берет текст файла перед запуском и проверяет на ошибки.
При использовании include содержимое файла берется только в момент прохода по этой команде, поэтому если используются переменные взятые из фактов нужно использовать include.
---
- name: create file
file:
dest: /home/file.txt
state: touch
owner: root
group: root
mode: 0644
---
- name: test-playbook
hosts: servers
tasks:
include: task_create.yaml #вместо include можно использовать import
myvar: "string" #можно передавать переменные в подключаемый файл
Роли
Роли позволяют автоматически загружать связанные переменные, файлы, задачи, обработчики и другие артефакты Ansible на основе известной файловой структуры.
ansible-galaxy initили создать каталоги самостоятельно
Части playbook'а переносятся в соответствующие каталоги, затем в главной файле вызывается роль.
- Список каталогов роли и их назначение
- tasks — задачи;
- handlers — задачи handlers;
- templates — шаблоны j2;
- files — файлы для копирования;
- vars — переменные, связанные с этой ролью;
- defaults — переменные по умолчанию, имеют самый низкий приоритет;
- meta — метаданные для роли, включая зависимости от роли;
- library — пользовательские модули;
- module_utils — пользовательские module_utils;
- lookup_plugins — дополнительные плагины.
---
- name: test-playbook
hosts: servers
roles:
- role_name_1
- role_name_2
Внешние переменные
Переменные, переданные в playbook через extra-var имеют наивысший приоритет. Передача значения переменной в playbook осуществляется с помощью ключа -e или --extra-var, например -e "message1=Hello".
---
- name: test-playbook
hosts: "{{ hosts_run }}"
tasks:
- name: Создание файла
file:
dest: /home/file.txt
state: touch
owner: "{{ owner }}"
group: "{{ owner }}"
mode: 0644
И при запуске указывать значение переменной
ansible-playbook main.yaml --extra-var "hosts_run=servers owner=root"
Теги
Ansible позволяет применять теги для выполнения определенных сценариев или задач к которым они привязаны. Для указания тегов при запуске playbook'а необходимо использовать ключ tags, за которым следует список нужных тегов.
- ansible-playbook main.yaml --tags=test запуск сценария с передачей тега
- ansible-playbook main.yaml --skip-tags=test пропустить задачи с определенным тегом
- ansible-playbook main.yaml --list-tags проверить доступные теги
- Ansible имеет специальные теги:
- always - задача, помеченная этим тегом, всегда будет выполняться, даже если она не соответствует списку тегов, переданных в опции --tags. Единственное исключение ― когда он явно пропускается с помощью опции --skip-tags=always.
- never - задача, помеченная этим тегом, не выполняется, за исключением случая, когда выполняется набор сценариев с опцией --tags, в которой указано значение never или один из тегов, связанных с задачей.
- tagged - запускает любую задачу с явным тегом
- untagged - запускает любую задачу не имеющую явного тега
- all - включает все задачи в сценарии независимо от того, есть у них теги или нет. Это поведение Ansible по умолчанию.
Выполнение задачи только на одном сервере
Нужно написать у задачи delegate_to: server1 тогда задача выполнится только на указанном сервере.
---
- name: test-playbook
hosts: servers
tasks:
- name: Создание файла
file:
dest: /home/file.txt
state: touch
owner: root
group: root
mode: 0644
delegate_to: server1
---
- name: test-playbook
hosts: servers
tasks:
- name: text
shell: echo "Server {{ inventory_hostname }} - node name {{ ansible_nodename }}" >> /home/log.txt
delegate_to: localhost
При выполнении на мастере создаться файл в который будут записаны значения переменных с других серверов.---
- name: test-playbook
hosts: servers
tasks:
- name: Создание файла
file:
dest: /home/file.txt
state: touch
owner: root
group: root
mode: 0644
run_once: true
Перехват и контроль ошибок
При запуске playbook, если на одном из серверов какая-либо задаче не выполнилась, то все последующие задачи на этом сервере не будут выполнены, чтобы этого не произошло нужно добавить флаг ignore_errors: yes, тогда если в этой задаче произойдет ошибка последующие все равно будут выполняться.
---
- name: test-playbook
hosts: servers
tasks:
- name: Создание файла
file:
dest: /home/file.txt
state: touch
owner: root
group: root
mode: 0644
ignore_errors: yes
---
- name: test-playbook
hosts: servers
tasks:
- name: Создание файла
file:
dest: /home/file.txt
state: touch
owner: root
group: root
mode: 0644
register: results
failed_when: "'text' is results.stdout"
В этом случае будет ошибка выполнения задачи, если в выводе будет слово text---
- name: test-playbook
hosts: servers
tasks:
- name: Создание файла
file:
dest: /home/file.txt
state: touch
owner: root
group: root
mode: 0644
register: results
failed_when: results.rc == 0
---
- name: test-playbook
hosts: servers
any_errors_fatal: true
tasks:
- name: Создание файла
file:
dest: /home/file.txt
state: touch
owner: root
group: root
mode: 0644
Шифрование файлов
ansible-vault позволяет создавать и редактировать зашифрованный файл, который playbook будет автоматический распознавать и расшифровывать с помощью пароля.
- ansible-vault create secrets.yaml создание файла для сохранения секретных данных, будет запрошен пароль
- ansible-vault view secrets.yaml посмотреть содержимое зашифрованного файла, будет запрошен пароль
- ansible-vault edit secrets.yaml редактировать содержимое зашифрованного файла, будет запрошен пароль
- ansible-vault encrypt secrets.yaml шифрование уже созданного файла с секретными данными
- ansible-vault decrypt secrets.yaml расшифровка файла с секретными данными
- ansible-vault rekey secrets.yaml сменить пароль файла с секретными данными
- ansible-playbook main.yaml --ask-vault-pass при запуске playbook'а выводить запрос пароля для расшифровки файла
- ansible-playbook main.yaml --vault-password-file pass_file.txt при запуске playbook'а взятие пароля из файла
К файлу, зашифрованному таким образом можно обращаться в секции vars_files. Если в playbook'е есть обращение к зашифрованному файлу, то при запуске playbook'а нужно указывать ключ --ask-vault-pass для запроса пароля, при этом пароль может сохраниться в логах ansible, чтобы это не произошло, в playbook'е перед блоком задач нужно указать no_log: true
ansible-vault encrypt_stringПосле выполнения этой команды нужно будет ввести пароль и саму зашифровываемую строку, в результате на экране отобразиться зашифрованная строка, которую можно вставить в playbook. При запуске playbook'а нужно будет добавлять ключ --ask-vault-pass для запроса пароля расшифровки.
---
- name: test-playbook
hosts: servers
tasks:
- name: create file
file:
dest: /home/file.txt
state: touch
owner: root
group: root
mode: 0644
- name: install git
yum:
name: git
update_cache: true
state: present
- name: install vim and nano
yum:
name:
- vim
- nano
update_cache: true
state: present