Ansible
Quick start#
- Устанавливаем ansible на машину (Ansible Master)
- Создаём инветарный файл в котором описываются хосты (сервера), которыми будет управлять ansible
Про инвентарный файл (что можно делать?)#
-
Разбивать сервера на группы
[dev_servers] — это группа серверов, которая представляет собой логическую коллекцию хостов -
Создавать групповые переменные
Это задаст пользователя и порт по умолчанию для всех серверов в группе web_servers - Параметры подключения: Можно управлять параметрами подключения для отдельных серверов или групп:
ansible_user
: имя пользователя для SSHansible_port
: порт для SSH-подключенияansible_host
: IP-адрес или имя хостаansible_ssh_private_key_file
: путь к файлу с приватным ключом для SSHansible_become
: определяет, нужно ли использовать привилегированные права (sudo) для выполнения задач
- Группы групп
-
Команды:
ansible-inventory -i hosts.ini --list
- отображает список хостов, распределение хостов по группам в json-овидном форматеansible-inventory -i hosts.ini --graph
- отображает список хостов, распределение хостов по группам в древовидном формате
Ansible case sensetive!
По умолчанию любой сервер входит в 2 группы: 1) all 2) ungrouped или пользовательская группа
Про конфигурационный файл ansible.cfg
#
-
Ansible ищет конфигурационный файл в нескольких местах, в следующем порядке при запуске:
- Файл ANSIBLE_CONFIG в переменной окружения
- В текущем каталоге — если существует файл ansible.cfg в директории, из которой запускается Ansible.
- В домашней директории пользователя — файл ~/.ansible.cfg.
- В системной директории — обычно /etc/ansible/ansible.cfg.
Ansible будет использовать первый найденный конфигурационный файл. Это позволяет иметь разные конфигурации для разных проектов.
Файл ansible.cfg лучше хранить в проекте, инфраструктуру когорого менеджерит ansible, а вот инвентарный файл hosts.ini можно хранить где угодно на Ansible-Master хосте, главное в .cfg задать путь к hosts.ini
Основные секции ansible.cfg
#
- [defaults] - Это основная секция для установки параметров по умолчанию
Создание retry-файла: Если во время выполнения плейбука Ansible сталкивается с ошибкой на одном или нескольких серверах, он автоматически создаёт retry-файл. По умолчанию этот файл создаётся в директории, где был запущен плейбук, и имеет формат имя_плейбука.retry
[defaults] inventory = ./hosts # Указывает путь к инвентарному файлу remote_user = ubuntu # Пользователь для подключения по умолчанию host_key_checking = False # Отключение проверки ключей SSH хоста retry_files_enabled = False # Отключение создания файлов retry timeout = 10 # Время ожидания для SSH-соединения forks = 10 # Количество параллельных задач retry_files_enabled = True retry_files_save_path = ~/ansible-retries
Повторный запуск плейбука: Можно использовать retry-файл, чтобы запустить плейбук только на тех серверах, которые указаны в файле. Для этого нужно указать имя retry-файла с опцией --limit.
ansible-playbook site.yml --limit @site.retry
- [privilege_escalation] - Эта секция управляет параметрами для выполнения команд от имени суперпользователя (с помощью sudo)
[privilege_escalation]
become = True # Включение использования sudo (become)
become_method = sudo # Метод получения привилегий (по умолчанию sudo)
become_user = root # Пользователь, от имени которого выполняются команды
become_ask_pass = False # Отключение запроса пароля при использовании sudo
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
pipelining = True
control_path = %(directory)s/%%h-%%r
ssh_args
: Дополнительные параметры для команды ssh. В данном примере включена поддержка многократного использования одного SSH-соединения (ControlMaster).
pipelining
: Опция для ускорения выполнения команд за счёт уменьшения количества вызовов SSH.
control_path
: Путь для хранения файлов управления соединением SSH.
- [log] - Настройка логирования
Ad-Hoc команды#
ansible [опции] <группа-хостов> -m <модуль> -a <аргументы>
- структура Ad-Hoc команд
ansible -i hosts.ini all -m setup
- модуль, который собирает детальную информацию о системе каждого хоста (например, информацию о процессоре, операционной системе, памяти, сетевых интерфейсах и т.д.). Эта информация затем может быть использована в плейбуках или для отладкиansible -i hosts.ini all -m ping
- проверка доступности хостовansible -i hosts.ini all -m shell -a "rm -rf /"
- запускает команду в кавычках на хостах, выводит вывод команды со всех хостов в консоль.ansible -i hosts.ini all -m command -a "rm -rf /"
- команда не будут обрабатываться через shell, поэтому переменные типа $HOSTNAME и операции типа "*", "<", ">", "|", ";" и "&" не будут работать. модуль ansible.builtin.shell, если нужны эти функции, command более секьюрная.ansible -i hosts.ini all -m copy -a "src=filename.txt dest=/home mode=777" -b
- ну тут понятно что команда делает, флаг-b
- это выполнить от суперпользователяansible -i hosts.ini all -m file -a "path=/home/privet.txt state=absent" -b
- удаляет файлansible -i hosts.ini all -m get_url -a "url=https://link/on/download/file dest=/home" -b
- скачивает файл из интернетаansible -i hosts.ini all -m apt -a "name=nginx state=present" --become
- устанаваливает пакет на Ubuntu/Debian (-b и --become эквивалентны)ansible -i hosts.ini all -m uri -a "url=https://www.content.ru return_content=yes"
- Модуль uri в Ansible используется для взаимодействия с веб-сервисами через HTTP или HTTPS. Этот модуль позволяет выполнять запросы к REST API, загружать данные, отправлять данные на удалённый сервер и проверять доступность веб-сервисов.
group_vars#
Директория group_vars
должна находиться в директории с инвентарным файлом.
├── ansible.cfg
├── inventory/
│ ├── hosts
├── group_vars/
│ ├── all.yml
│ ├── web_servers.yml
│ └── db_servers.yml
└── playbook.yml
group_vars
могут находиться файлы с именами групп из инвентаря. Эти файлы содержат переменные, которые будут применяться ко всем хостам, принадлежащим к соответствующей группе.
-
Файл
web_servers.yml
содержит переменные, которые будут применяться ко всем серверам группы web_servers. -
Файл
all.yml
содержит переменные для всех хостов, независимо от группы.
Основные моменты#
-
Приоритеты: Если переменные определены в нескольких местах, например, в файлах group_vars, host_vars или playbook, Ansible применяет переменные в следующем порядке:
-
Переменные, определённые внутри задач в плейбуке (самый высокий приоритет).
-
Переменные, указанные для конкретных хостов (host_vars).
-
Переменные из группы хостов (group_vars).
-
Переменные для всех хостов (например, файл group_vars/all.yml).
-
Значения по умолчанию.
-
-
Наследование переменных: Переменные, определённые в файле для всех хостов (например,
group_vars/all.yml
), могут быть переопределены переменными, определёнными в группе конкретных хостов (например,group_vars/web_servers.yml
). -
Формат файлов: Файлы в директории
group_vars
могут быть в формате YAML или INI, хотя YAML используется чаще.
host_vars#
- Ansible автоматически подгружает переменные для конкретного хоста из файла, если этот файл находится в специальной директории
host_vars
- На уровне директории, где находится ваш инвентарь (файл
inventory
), вы создаёте каталог с именемhost_vars
- Переменные из файлов
host_vars
будут доступны при выполнении плейбука на соответствующих хостах
Флаги#
-b
- от суперюзера-k
---ask-pass
: ask for connection password-K
---ask-become-pass
: ask for privilege escalation password-v
,-vv
,-vvv
,-vvvv
- подробный вывод для дебага
Плейбуки#
-
Hosts (хосты) - это часть плейбука, которая указывает, на каких серверах выполнять задачи
-
all
означает, что команды будут выполняться на всех хостах из инвентаря. -
Также можно указывать конкретные группы или отдельные хосты.
- Tasks (задачи) - Каждая задача в плейбуке представляет собой отдельное действие (например, установка пакета, редактирование файла, запуск сервиса). Задачи выполняются по порядку, сверху вниз.
- Vars (переменные) - Можно использовать переменные для хранения данных, таких как имена пользователей, порты, пути к файлам и так далее.
- hosts: web_servers become: true vars: http_port: 8080 document_root: /var/www/html tasks: - name: Установить Apache ansible.builtin.apt: name: apache2 state: present - name: Настроить Apache на нужный порт ansible.builtin.lineinfile: path: /etc/apache2/ports.conf regexp: '^Listen' line: "Listen {{ http_port }}" # Использование переменной - name: Создать директорию DocumentRoot ansible.builtin.file: path: "{{ document_root }}" # Использование переменной state: directory
- Handlers (обработчики) - это специальные задачи, которые выполняются только в случае, если их вызвали. Их часто используют для таких задач, как перезагрузка сервиса после изменения конфигурационного файла.
- Become (повышение привилегий) - Некоторые команды требуют прав администратора (sudo). Для этого используется
become
. - Loops (циклы) - Ansible поддерживает выполнение задач в цикле
- Conditions (условия) - Ansible позволяет выполнять задачи только при выполнении определённых условий с помощью
when
.
-
Блоки#
Для чего блоки:
-
Группировка задач: Несколько связанных задач можно объединить для удобства
-
Управление ошибками: Можно задать специальную логику для обработки ошибок с помощью блоков
rescue
(обработчики ошибок) иalways
(выполняются всегда, независимо от успеха или неудачи) -
Условия и циклы: Можно использовать блоки для использования
when
,loop
илиwith_items
(утстарел) и тп
# Пример с rescue и always
- name: Основной блок
block:
- name: Первая задача
ansible.builtin.shell: echo "Running task 1"
- name: Вторая задача
ansible.builtin.shell: echo "Running task 2"
rescue:
- name: Обработка ошибок
ansible.builtin.debug:
msg: "Произошла ошибка!"
always:
- name: Выполняется всегда
ansible.builtin.debug:
msg: "Этот шаг выполнится всегда, даже если были ошибки."
block
: — основной блок, в котором определяются задачи. Если в нём произойдёт ошибка, выполнение перейдёт в секцию rescue.
2. rescue
: — блок для обработки ошибок. Выполняется, если одна из задач в блоке завершилась с ошибкой.
3. always
: — блок для задач, которые должны выполняться всегда, вне зависимости от того, произошла ошибка или нет (например, очистка или уведомления).
4. rescue
и always
используются только с блоками и относятся к конкретному блоку
# Пример блока с условием
- hosts: localhost
tasks:
- name: Пример блока с условием
block:
- name: Выполнить команду echo
ansible.builtin.command: echo "Hello, World!"
when: ansible_facts['os_family'] == "Debian"
# Блок с циклом
- hosts: localhost
tasks:
- name: Установить несколько пакетов
block:
- name: Установить пакеты
ansible.builtin.apt:
name: "{{ item }}"
state: present
loop:
- git
- vim
- htop
when: ansible_facts['os_family'] == "Debian"
# Пример использования блоков с условиями
- hosts: all
tasks:
- name: Проверка системы и установка пакетов
block:
- name: Установить curl
ansible.builtin.apt:
name: curl
state: present
- name: Установить git
ansible.builtin.apt:
name: git
state: present
when: ansible_facts['os_family'] == "Debian"
- name: Установить пакеты для RedHat
block:
- name: Установить curl
ansible.builtin.yum:
name: curl
state: present
- name: Установить git
ansible.builtin.yum:
name: git
state: present
when: ansible_facts['os_family'] == "RedHat"
- name: Add several users
ansible.builtin.user:
name: "{{ item.name }}"
state: present
groups: "{{ item.groups }}"
loop:
- { name: 'testuser1', groups: 'wheel' }
- { name: 'testuser2', groups: 'root' }
Хендлеры (Handlers)#
Это специальные задачи, которые выполняются только при вызове через notify
. Обычно они используются для выполнения действий, которые должны происходить после того, как одна или несколько задач изменили состояние системы. Например, изменение конфигурации сервиса.
-
Запускаются один раз за плейбук: Если хендлер был вызван несколько раз в одном плейбуке, он выполнится только один раз, после выполнения всех остальных задач, изменивших состояние.
-
Выполняются в конце выполнения задач: Хендлеры выполняются после того, как все основные задачи завершились.
-
Хендлеры выполняются по требованию: Если задача не изменила состояние, хендлер не вызовется, даже если есть директива
notify
. -
Внутри хендлера можно использовать
when
- hosts: all
tasks:
- name: Обновить конфигурацию приложения
ansible.builtin.copy:
src: /path/to/config.yml
dest: /etc/myapp/config.yml
notify:
- Restart App
- Send Notification
handlers:
- name: Restart App
ansible.builtin.systemd:
name: myapp
state: restarted
- name: Send message
ansible.builtin.debug:
msg: "Конфигурация приложения обновлена, уведомление."
Модули#
Модуль file - С помощью этого модуля можно изменять права доступа, владельцев, группы, создавать или удалять файлы и директории, а также устанавливать символические ссылки.
path
: путь к файлу или директории, с которыми нужно работать.state
: определяет, что должно быть сделано с файлом или директорией. Возможные значения:touch
: создать пустой файл, если он не существует, или обновить время доступа и модификации, если файл уже существует.absent
: удалить файл или директорию.directory
: создать директорию.file
: создать файл.link
: создать символическую ссылку.hard
: создать жесткую ссылку.
owner
: владелец файла или директории.group
: группа файла или директории.mode
: права доступа к файлу или директории, указанные в виде числового значения (например, 0644).-
recurse
: рекурсивно изменяет права, владельцев или группы для директорий и их содержимого (поддиректорий и файлов). -
Модуль service - в Ansible используется для управления системными сервисами на удалённых хостах. Он позволяет запускать, останавливать, перезапускать и изменять состояние сервисов, а также управлять их включением при загрузке системы.
-
name
: Название сервиса, который нужно управлять. Например, apache2, nginx, ssh, и т. д. state
: Указывает желаемое состояние сервиса. Возможные значения:started
: Запустить сервис.stopped
: Остановить сервис.restarted
: Перезапустить сервис.reloaded
: Перезагрузить конфигурацию сервиса без остановки.enabled
: Включить сервис при загрузке системы.disabled
: Отключить сервис от автозагрузки.
enabled
: Указывает, должен ли сервис автоматически запускаться при загрузке системы. Значения могут быть true или false.-
ansible -i hosts.ini all -m service -a "name=nginx state=started enabled=yes" -b
Все демоны могут считаться сервисами, но не все сервисы являются демонами
-
Модуль Dedug - Модуль debug в Ansible используется для вывода отладочной информации во время выполнения плейбуков. Он помогает отображать значения переменных, выводить сообщения.
-
Модуль set_fact - для всяких разных операций с переменными в плейбуке
-
Модуль template - Используется для создания конфигурационных файлов и других текстовых файлов на целевых хостах на основе шаблонов Jinja2. Это позволяет динамически генерировать файлы с переменными, которые могут меняться в зависимости от окружения или настроек. Модуль
template
читает шаблон, подставляет значения переменных и создает итоговый файл на целевом хосте.Боевой ример исользования# Пример синтаксиса модуля - name: Копировать шаблон конфигурационного файла ansible.builtin.template: src: /path/to/template.j2 # Путь к шаблону на Ansible Master dest: /path/to/destination.conf # Путь, куда будет записан итоговый файл на целевом хосте
template
# Файл-шаблон nginx.conf.j2 server { listen {{ http_port }}; server_name {{ server_name }}; location / { proxy_pass http://{{ backend_service }}; } }
Таска- hosts: web_servers vars: http_port: 80 server_name: example.com backend_service: backend:5000 tasks: - name: Копировать шаблон конфигурации Nginx ansible.builtin.template: src: nginx.conf.j2 dest: /etc/nginx/conf.d/example.conf notify: - перезапустить nginx handlers: - name: перезапустить nginx ansible.builtin.service: name: nginx state: restarted
Копировать шаблон конфигурации Nginx
берет шаблонnginx.conf.j2
, рендерит его с подстановкой переменных и записывает в файл/etc/nginx/conf.d/example.conf
на целевом хосте.
ansible-galaxy collection install ansible.<collection_name>
- установить модуль
Директивы#
-
register - используется для сохранения результатов выполнения задачи в переменной. Это позволяет вам использовать результаты задачи в последующих задачах внутри playbook.
После выполнения задачи,- name: Register loop output as a variable ansible.builtin.shell: "echo {{ item }}" loop: - "one" - "two" register: echo
echo
будет содержать информацию о каждой итерации, включая стандартный вывод, статус выполнения и другие данные. После выполнения задачи, можно использовать зарегистрированную переменную в следующих задачахПримерная структура переменной в{ "changed": true, "msg": "All items completed", "results": [ { "changed": true, "cmd": "echo \"one\" ", "delta": "0:00:00.003110", "end": "2013-12-19 12:00:05.187153", "invocation": { "module_args": "echo \"one\"", "module_name": "shell" }, "item": "one", "rc": 0, "start": "2013-12-19 12:00:05.184043", "stderr": "", "stdout": "one" }, { "changed": true, "cmd": "echo \"two\" ", "delta": "0:00:00.002920", "end": "2013-12-19 12:00:05.245502", "invocation": { "module_args": "echo \"two\"", "module_name": "shell" }, "item": "two", "rc": 0, "start": "2013-12-19 12:00:05.242582", "stderr": "", "stdout": "two" } ] }
register
-
until - конструкция, которая используется для повторного выполнения задачи до тех пор, пока не будет выполнено определенное условие
# Основной синтаксис - name: Task description # Условие, при выполнении которого задача завершится ansible.builtin.module_name: parameters register: result_variable # Сохраняет результат выполнения задачи в указанной переменной, которая затем используется в условии until. until: result_variable.condition # Условие, при выполнении которого задача завершится. retries: number_of_retries # Общее количество повторных попыток, которые будут сделаны, если условие until не выполнено delay: delay_in_seconds # Время (в секундах) для ожидания между попытками выполнения задачи
# Пример - name: Start a service ansible.builtin.systemd: name: my_service state: started - name: Wait for the service to be active ansible.builtin.shell: "systemctl is-active my_service" register: result until: result.stdout == "active" retries: 5 delay: 2 - name: Notify that the service is active ansible.builtin.debug: msg: "The service is now active."
- with_fileglob - используется для итерации по файлам в директории, соответствующим определённому шаблону
- Работает только с файлами на локальном хосте (где запущен Ansible).
- Если в шаблоне не найдено ни одного файла, Ansible просто пропустит задачу.
- Путь в
with_fileglob
должен быть абсолютным.- hosts: all become: true tasks: - name: Копировать конфигурационные файлы и установить правильные разрешения ansible.builtin.copy: src: "{{ item }}" # Локальный путь к файлам dest: /etc/myapp/configs/ mode: '0644' with_fileglob: - "/etc/myapp/configs/*.conf"
# Можно использовать несколько шаблонов - hosts: webservers become: true tasks: - name: Копировать конфигурационные и скриптовые файлы ansible.builtin.copy: src: "{{ item }}" dest: /etc/myapp/ with_fileglob: # Можно использовать несколько шаблонов - "/etc/myapp/configs/*.conf" - "/etc/myapp/scripts/*.sh"
- any_errors_fatal : (true || false) - прекращает выполнение плейбука, если хоть одна таска на одном из хостов падает с ошибкой
-
ignore_errors : (yes || no) - если таска падает с ошибкой, плейбук продолжает выполняться
-
failed_when - таска падает или не падает в зависимости от условия.
failed_when
принимает логическое выражение. Если это выражение истинно (true), задача считается неудачной, даже если команда выполнена успешно (с кодом возврата 0)- name: Example task command: /path/to/some/command register: result failed_when: result.rc != 0 and result.stdout != "expected output"
-
changed_when - позволяет кастомно определить условие
changed
, не останавливает выполнение задачи, влияет только на вывод работы плейбука. благодаряchanged_when
можно контролировать, как Ansible оценивает, изменила ли таска что-либо в системе. - group_by - в Ansible используется для динамического создания групп хостов на основе определённых условий. Модуль
group_by
может создавать группы на основе любых фактов, доступных черезansible_facts
, а также на основе данных из инвентаря или других переменных.group_by
не изменяет инвентарь# Синтаксис - name: Group hosts by operating system group_by: key: "os_{{ ansible_facts['distribution'] }}"
-
tags - теги (tags) позволяют управлять выполнением отдельных задач или целых плейбуков, предоставляя возможность запускать только те части плейбука, которые вам нужны, вместо выполнения всех задач. Теги особенно полезны для ускорения процесса, когда нужно протестировать только определенные задачи или фрагменты плейбука
- Управление выполнением задач: Вы можете назначать тег задачам или блокам задач, а затем запускать playbook с флагом
--tags
, чтобы выполнить только эти задачи. - Исключение задач: С помощью
--skip-tags
можно исключать выполнение задач с определенными тегами.
- Управление выполнением задач: Вы можете назначать тег задачам или блокам задач, а затем запускать playbook с флагом
# Теги тасок
- name: Install Nginx
apt:
name: nginx
state: present
tags:
- install
- webserver
- name: Copy configuration file
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
tags:
- config
# Теги плейбука
- hosts: webservers
tags:
- setup
tasks:
- name: Install Apache
apt:
name: apache2
state: present
- name: Start Apache service
service:
name: apache2
state: started
ansible-playbook site.yml --tags "install,config"
- поддерживается работа с несколькими тегами
- ansible-playbook site.yml --tags "install" --skip-tags "config"
- выполнить только установку серверов пропуская конфигурацию (пример использования)
Секреты (Ansible Vault)#
Позволяет шифровать конфиденциальные данные, такие как файлы с переменными, плейбуки, конфигурации или любые другие файлы, требующие защиты
- ansible-vault create secret.yml
- создание зашифрованного файла
- ansible-vault edit secret.yml
- редактирование зашифрованного файла
- ansible-vault encrypt secret.yml
- шифрование уже сущ. файла
- ansible-vault decrypt secret.yml
- расшифровка файла
- ansible-vault view secret.yml
- cat для зашифрованного файла
- ansible-vault rekey secret.yml
- поменять пароль для зашифрованного файла
- ansible-playbook playbook_vault.yml --vault-password-file mypassword.txt
- пароль для запуска плейбука берётся из файла
- ansible-playbook playbook.yml --ask-vault-pass
- запуск плейбука с расшифровкой
- ansible-vault encrypt_string --stdin-name
"MyPassword" - зашифровать строку
- echo -n "MyPassword" | ansible-vault encrypt_string
- зашифровать строку
ansible all -m ping -b --extra-vars '@vault.yml' --extra-vars "ansible_become_pass={{ vault_sudo_passwords[inventory_hostname] }}" --ask-vault-pass
- пинг хостов с разными паролями юзеров
Роли#
# Структура роли
└── first_role
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── README.md
├── tasks
│ └── main.yml
├── templates
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
[defaults]
roles_path = ./roles:/etc/ansible/roles:/another/path/to/roles # : - это разделение нескольких путей
Можно закинуть роль в глобальный каталог
tasks/main.yml
: Здесь находятся задачи, которые выполняет роль. Это основной файл задач, аналогичный тем, что вы пишете в плейбуках. Можно разделить задачи по отдельным файлам и включать их в main.yml.
handlers/main.yml
: Хендлеры, которые вызываются при изменении состояния задач. Они перезапускают сервисы, если это необходимо.
files/
: В эту папку вы кладете файлы, которые должны быть скопированы на удаленные хосты с помощью модуля copy.
templates/
: Здесь хранятся шаблоны Jinja2, которые можно использовать для создания динамических файлов конфигурации, применяя переменные.
vars/main.yml
: Здесь определяются переменные для роли. Эти переменные имеют более высокий приоритет по сравнению с переменными из defaults.
defaults/main.yml
: Здесь определяются переменные с наименьшим приоритетом. Они могут быть переопределены переменными из других файлов.
meta/main.yml
: В этом файле содержатся метаданные роли, такие как ее зависимости от других ролей.
tests/
: Папка для тестирования роли. Здесь можно хранить тестовые плейбуки и инвентарь.
Приоритет переменных
1. Переменные командной строки (-e
или --extra-vars
)
2. Переменные, объявленные в vars
внутри плейбука.
3. Переменные, определенные в host_vars
.
4. Переменные, определенные в group_vars
.
5. Переменные, объявленные в vars
внутри роли.
6. Переменные, объявленные в defaults
внутри роли.
Зависимости можно указать в файле meta/main.yml
. Например, если роль зависит от другой роли, то она будет автоматически вызвана:
Роль можно протестировать с помощью специального тестового плейбука. Например, в папке tests/
может быть файл test.yml
, который проверяет работу роли:
Разница между defaults/
и vars/
-
defaults/
может содержать такие переменные, как версии ПО, которые можно легко изменить для разных окружений. -
vars/
будет содержать важные и фиксированные настройки, такие как адреса серверов или пути к файлам, которые редко меняются.
# Пример плейбука
- name: Playbook
hosts: all
become: yes
roles:
- { role: my_role, when: ansible_system == "Linux" }
and
, or
и not (!=)
)
- { role: my_role, when: ansible_distribution == "Ubuntu" and ansible_distribution_version == "20.04" }
extra-vars#
Как передать переменную в плейбук? Можно писать: - --extra-var - --extra-vars - -eextra-var
имеет наивысший приоритет и переопределяет все остальные переменные, т.к. это по сути переменная внутри плейбука
import и include#
import_*
- загружает все задачи из указанного файла на этапе разбора плейбука (parse time), то есть перед выполнением задачinclude_*
- Загружает задачи динамически на этапе выполнения (runtime)include_tasks
import_playbook
- загружает целый плейбук на этапе разбора (parse time)include_playbook
- устарелаimport_role
Когда использовать import
, а когда include
?
import
:
- Когда нужно загрузить фиксированный набор задач, плейбуков или ролей.
- Когда условия и переменные известны на этапе разбора (parse time).
include
:
- Когда требуется динамическое выполнение в зависимости от условий.
- Когда необходимо передать переменные или использовать цикл для включения.
Best practice#
- Писать
hosts : all
, а потом юзать в таскахwhen
- bad practice - Инвентарь в
yml
формате host_vars
- это временное решение (на хостах завязываться не стоит), лучше объединить в группу с одним хостом в инвентаре и прописывать переменные вgroup_vars
- Можно писать переменные внутри инвентаря, если это общая переменная для многих хостов, чтобы не создавать лишние
group_vars
и не плодить сущности - Не управляем пользователями и контейнерами с помощью
Ansible
для этого есть специализированные инструменты. -
Писать роль отвечающую за компонент целиком (например, роль для NGINX)
-
Разные инвентари для разные сред (инвентарь для прода, дева и тд)
- Группируй однотипные задачи с помощью
block
- Роли долнжны быть слабосвязаны, избегать зависимости между ролями
- Проверьте, какие задачи будут запущены перед выполнением: Вы можете использовать флаг
--list-tasks
для подтверждения того, какие задачи будут запущены без их фактического выполнения. Вы можете использовать флаг--list-hosts
: так вы убедитесь в том, на какие хосты повлияет плейбук, но при этом не запустить его - Убедитесь в том, что вы собрались менять, но при этом не запускайте обновления: Используйте флаг
--check
для прогнозирования изменений, которые могут произойти. Объедините его с флагом--diff
, чтобы показать различия в измененных файлах. - Пример архитектуры
production # inventory file for production servers staging # inventory file for staging environment group_vars/ group1.yml # here we assign variables to particular groups group2.yml host_vars/ hostname1.yml # here we assign variables to particular systems hostname2.yml library/ # if any custom modules, put them here (optional) module_utils/ # if any custom module_utils to support modules, put them here (optional) filter_plugins/ # if any custom filter plugins, put them here (optional) site.yml # master playbook webservers.yml # playbook for webserver tier dbservers.yml # playbook for dbserver tier roles/ common/ # this hierarchy represents a "role" tasks/ # main.yml # <-- tasks file can include smaller files if warranted handlers/ # main.yml # <-- handlers file templates/ # <-- files for use with the template resource ntp.conf.j2 # <------- templates end in .j2 files/ # bar.txt # <-- files for use with the copy resource foo.sh # <-- script files for use with the script resource vars/ # main.yml # <-- variables associated with this role defaults/ # main.yml # <-- default lower priority variables for this role meta/ # main.yml # <-- role dependencies library/ # roles can also include custom modules module_utils/ # roles can also include custom module_utils lookup_plugins/ # or other types of plugins, like lookup in this case webtier/ # same kind of structure as "common" was above, done for the webtier role monitoring/ # "" fooapp/ # ""
- Пример архитектуры
inventories/ production/ hosts # inventory file for production servers group_vars/ group1.yml # here we assign variables to particular groups group2.yml host_vars/ hostname1.yml # here we assign variables to particular systems hostname2.yml staging/ hosts # inventory file for staging environment group_vars/ group1.yml # here we assign variables to particular groups group2.yml host_vars/ stagehost1.yml # here we assign variables to particular systems stagehost2.yml library/ module_utils/ filter_plugins/ site.yml webservers.yml dbservers.yml roles/ common/ webtier/ monitoring/ fooapp/
- Пример статического инвентаря
# file: production [atlanta_webservers] www-atl-1.example.com www-atl-2.example.com [boston_webservers] www-bos-1.example.com www-bos-2.example.com [atlanta_dbservers] db-atl-1.example.com db-atl-2.example.com [boston_dbservers] db-bos-1.example.com # webservers in all geos [webservers:children] atlanta_webservers boston_webservers # dbservers in all geos [dbservers:children] atlanta_dbservers boston_dbservers # everything in the atlanta geo [atlanta:children] atlanta_webservers atlanta_dbservers # everything in the boston geo [boston:children] boston_webservers boston_dbservers
- В
site.yml
мы импортируем плейбуки, которые определяют всю нашу инфраструктуру - Идея здесь в том, что мы можем выбрать настройку всей нашей инфраструктуры, «запустив»
site.yml
, или мы могли бы просто выбрать запуск подмножества, запустивwebservers.yml
. Это аналогично параметру«–limit» в ansible
, но немного более явно - Только для серверов в Бостоне
- Для первых 10, потом следущие 10
ansible-playbook -i production webservers.yml --limit boston[0:9] ansible-playbook -i production webservers.yml --limit boston[10:19]
- Как также упоминалось выше, хороший способ разделить среды подготовки (или тестирования) и производства - использовать отдельный файл инвентаризации для dev и prod. Таким образом, вы выбираете с помощью
-i
на инвентарь. Хранение их всех в одном файле может привести к непрогнозируемому поведению! Тестирование промежуточной среде перед тем, как выкатывать на prod, всегда является отличной практикой. Ваши среды не обязательно должны быть одинакового размера, и вы можете использовать групповые переменные для управления различиями между этими средами. - Параметр
'state'
является необязательным для многих модулей. Будь то'state=present'
или'state=absent'
, всегда лучше оставить этот параметр в своих плейбуках, чтобы сделать его понятным, особенно потому, что некоторые модули поддерживают дополнительные состояния. - Если вам приходится иметь дело с параметром, который отличается в двух разных операционных системах, отличным способом решения этой проблемы является использование модуля
group_by
. Это создает динамическую группу хостов, соответствующих определенным критериям, даже если эта группа не определена в файле инвентаризации. Это позволит объединить все системы в динамическую группу на основе имени операционной системы.Если необходимы настройки, специфичные для группы, это также можно сделать. Например:- name: talk to all hosts just so we can learn about them hosts: all tasks: - name: Classify hosts depending on their OS distribution group_by: key: os_{{ ansible_facts['distribution'] }} # now just on the CentOS hosts... - hosts: os_CentOS gather_facts: False tasks: - # tasks that only happen on CentOS go here
- Используй
name
в тасках -
Используйте контроль версий. Храните ваши плейбуки и файл
inventory
вgit
(или другой системе контроля версий) и фиксируйте изменения, когда вносите в них изменения. Таким образом, у вас будет аудиторский след, описывающий, когда и почему вы изменили правила, автоматизирующие вашу инфраструктуру. -
Переменные и секреты: начнём с
group_vars/
подкаталога, названного в честь группы. Внутри этого подкаталога создайте два файла с именамиvars
иvault
. Внутри файлаvars
определите все необходимые переменные, включая любые конфиденциальные. Затем скопируйте все конфиденциальные переменные в файлvault
и добавьте к этим переменным префиксvault_
. Вам следует настроить переменные вvars
файле так, чтобы они указывали на соответствующиеvault_переменные
, используя синтаксисjinja2
, и убедиться, чтоvault
файл зашифрован с помощью хранилища.
Опять про роли#
# roles/example/tasks/main.yml
- name: added in 2.4, previously you used 'include'
import_tasks: redhat.yml
when: ansible_facts['os_family']|lower == 'redhat'
- import_tasks: debian.yml
when: ansible_facts['os_family']|lower == 'debian'
# roles/example/tasks/redhat.yml
- yum:
name: "httpd"
state: present
# roles/example/tasks/debian.yml
- apt:
name: "apache2"
state: present
import_role
или include_role
:
- hosts: webservers
tasks:
- debug:
msg: "before we run our role"
- import_role:
name: example
- include_role:
name: example
- debug:
msg: "after we ran our role"
# Можно переопределять переменные
- hosts: webservers
roles:
- common
- role: foo_app_instance
vars:
dir: '/opt/a'
app_port: 5000
- role: foo_app_instance
vars:
dir: '/opt/b'
app_port: 5001
# playbook.yml
- hosts: webservers
roles:
- foo
- foo
# roles/foo/meta/main.yml
allow_duplicates: true
allow_duplicates: true
- В этом примере foo
будет выполнено дважды, поскольку мы явно включили эту функцию