Ansible — топовое решение для управления парком геораспределенных серверов и позволяет конфигурировать нужные состояния с помощью кода. Но даже несмотря на популярность решения, в том числе среди российских разработчиков, не все знают, как оптимизировать работу с этим инструментом, из-за чего вынуждены работать с «костылями».
Делимся советами, как «выжать» из Ansible по-максимуму, не сталкиваясь с проблемами.
1. Всегда присваивайте названия
Ansible позволяет запускать сценарии и задачи даже без названия. Например:
---
- hosts: local
tasks:
- user:
name: testuser1
state: present
groups: wheel
В таком случае на выходе можно получить:
PLAY****************************************************************
TASK [user]****************************************************[...]
Но при работе с большим количеством логов отсутствие даже базового описания сильно усложняет работу. Поэтому, названия лучше присваивать и делать их максимально понятными. Например:
---
- name: "Prepare localhost"
hosts: local
tasks:
- name: "Create testuser1"
user:
name: testuser1
state: present
groups: wheel
В таком случае вывод будет:
PLAY [Prepare localhost] *****************************************
TASK [Create testuser1] *************************************[...]
Это гораздо удобнее и понятнее.
Помимо этого, в имена задач можно добавлять больше информации DEBUG. Например:
- name: "Create folder {{ target_folder }}"
file:
path: "{{ target_folder }}"
recurse: yes
state: directory
При этом надо понимать — чем подробнее информация DEBUG, тем легче находить и устранять ошибки.
2. Используйте синтаксис YAML
Ansible — позволяет использовать разные синтаксисы или их комбинации: Ansible, YAML или их сочетание.
Например, код на YAML будет выглядеть следующим образом:
- name: add user testuser1
user:
name: testuser1
state: present
groups: wheel
В случае комбинирования YAML/Ansible:
- name: add user testuser1
user: name=testuser1 state=present groups=wheel
В первом случае Ansible проанализирует документ YAML, а затем запустит код. Во втором случае Ansible также будет анализировать name=testuser1 state=present groups=wheel
перед запуском задачи user.
Работать с YAML в чистом виде сложнее, так как нужна дополнительная проверка и проработка состояний. Но изменение синтаксиса на YAML дает важное преимущество — помогает обнаруживать ошибки до запуска кода и делает его более удобным для чтения.
3. Документируйте свои переменные
В Ansible можно переопределять переменные практически в любом месте кода. Перечень довольно длинный:
role defaults
inventory vars
inventory group_vars
inventory host_vars
playbook group_vars
playbook host_vars
host facts
play vars
play vars_prompt
play vars_files
registered vars
set_facts
role and include vars
block vars (only for tasks in block)
task vars (only for the task)
extra vars (always win precedence)
Но, чтобы не создавать проблем и путаницы, лучше соблюдать несколько правил:
не «раскидывайте» переменные по коду — их лучше сгруппировать;
документируйте все переменные, которые вы используете.
Лучше использовать групповые и ролевые переменные, не прибегая к другим уровням.
Также можно документировать настройки. Например:
---
# file: group_vars/all
# For data synchronisation from the server to localhost
local_source_folder: /Users/octplane/src/wiseman_r
remote_production_folder: /home/oct/prod
# app name to look for in the local registry
app_name: wiseman
# image name to search for in the local image registry
image_name: "octplane/{{ app_name }}"
# version to search for in the local image registry
version: 4
# where to export the docker image
export_folder: /tmp
# Exported file from docker after zipping
artefact_name: "{{ app_name }}-{{ version }}.docker.gz"
# where to copy the data on the remote server
# where is deployed the test application
remote:
landing_folder: /home/oct/tmp
test_folder: /home/oct/data/wiseman.test/
При таком подходе легче читать код и понять, как он работает.
4. Пишите значимые сообщения об ошибках
Подробное документирование позволяет проверять параметры перед запуском кода и уже на этапе подготовки исключать большинство ошибок. Например:
- name: "Validate version is a number, > 0«
assert:
that:
- "{{ version | int }} > 0"
msg: "'version' must be a number and > 0, is \"{{version}}\""
Кроме того, лучше прописывать свое уточнение в уведомлениях об ошибках — это будет гораздо информативнее и полезнее, чем работа со стандартными сообщениями об ошибках от Ansible. Используйте, например: 'version' must be a number and > 0, got "coucou"
.
5. Измените stdout регистратор
В Ansible довольно неудобный стандартный stdout регистратор. В нем банально нет полезной информации, да и места на экране он занимает неоправданно много. Но это не приговор — Ansible позволяет изменить stdout регистратор на любой другой по своему усмотрению.
Вариантов регистраторов много, часто они лежать в открытом доступе на Github. Например, один из них — https://github.com/octplane/ansible_stdout_compact_logger.
6. Пишите роли под каждый компонент
При работе с Ansible главное не идти по пути упрощения — порой заманчиво создать роль, которая станет многоразовым набором инструментов. Но лучше разделять содержимое ролей по назначению, например присваивая разные роли для:
MongoDB;
HAProxy;
Tomcat.
То есть: один технический компонент — одна роль.
Такой подход позволяет объединить все административные задачи, которые могут потребоваться для данного компонента: установка, настройка, запуск, остановка, обновление, обслуживание и одновременно с этим снизить зависимость между ролями и техническими продуктами, уменьшая количество переменных, необходимых для его запуска.
7. Используйте одну роль для нескольких задач
Технически роль представляет собой единственную точку входа tasks/main.yml
, которую без присвоения тегов сложно применять для разных задач. Но на практике это возможно, если добавить разные переменные. Их использование позволит получить небольшой операционный маршрутизатор внутри своей роли:
---
# roles/service/vars/main.yml
# by default, we ensure that service is present, configured and running.
# allowed values: present, absent, install, configure, start, stop
state: present
---
# roles/service/tasks/main.yml
- include: "{{ state }}.yml"
---
# roles/service/tasks/present.yml
- include: "install.yml"
- include: "configure.yml"
- include: "start.yml"
---
# roles/service/tasks/install.yml
- name: add user testuser1
user:
name: testuser1
state: present
groups: wheel
8. Ограничьте использование set_fact
set_fact
позволяет динамически создавать переменные в скриптах Ansible. Это очень полезно, если новые данные нужно внести в процессе выполнения, не тратя время на этапе проработки. Но у переменных, создаваемых «на лету», есть несколько недостатков:
высокий приоритет;
риск сбоев из-за отсутствия предварительного тестирования переменной;
невозможность переопределения переменной.
Поэтому, лучше применять set_fact
ограничено и только там, где без этого не обойтись.
9. Используйте теги с умом
При использовании ролей под несколько задач или вариантов использования, многие начинают применять и теги для фильтрации задач во время выполнения. В большинстве случае это удобно и оправданно, но такой подход сопряжен с риском получения проблем. Так:
если одинаковый тег используется в разных ролях, может возникнуть внутренний конфликт и использовать его будет просто невозможно;
чем больше тегов, тем сложнее понять, что они делают.
При этом, безусловно, теги — удобный инструмент, который упрощает жизнь, если применять его в «умеренных» количествах.
10. Не стесняйтесь конфигурировать Ansible
В ansible.cfg
можно легко изменить конфигурацию Ansible под свои запросы и задачи. Для этого достаточно создать ansible.cfg
файл, в котором запускаются сценарии, чтобы Ansible мог автоматически извлекать и объединять его содержимое с глобальной конфигурацией. Приоритет следующий:
ANSIBLE_CONFIG (переменная окружения)
ansible.cfg (в текущем каталоге)
.ansible.cfg (в домашнем каталоге пользователя)
/etc/ansible/ansible.cfg
Благодаря этому Ansible можно легко настроить под себя.
Главное по теме
Ansible — классный инструмент для удаленного управления конфигурациями. Но даже несмотря на его популярность, не все знают, как работать с этим программным решением, чтобы «получить от него по-максимуму». Приведенный набор рекомендаций — не панацея, но придерживаясь их, можно значительно упростить себе работу и избежать ряда распространенных проблем.
12 октября стартует поток курса Ansible: Infrastructure as Code
Курс дает базу, которая помогает экономить время и силы. Это не только теория, это опыт спикера, его набитые шишки, кейсы, а также 78 тестовых и 46 практических заданий на стендах в личном кабинете.
На курсе вы:
— Узнаете как работать с переменными, как писать плейбуки и роли;
— Развернете LEMP стек, PostgreSQL и Mongo кластеры,
задеплоите Flask приложение;
— Напишите свой модуль для Ansible;
— Настроите IaC в Gitlab;
— Разберетесь с работой с облаками и enterprise решениями.
Посмотреть программу и записаться: https://slurm.io/ansible
Материал написан на основе статьи 10 Ansible tips and tricks.