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.

Комментарии (0)