Ansible — один из наиболее часто используемых программных инструментов с открытым исходным кодом для управления конфигурацией, предоставления программного обеспечения и развертывания приложений в облачных и локальных средах. В этой статье мы поделимся Practices по настройке Ansible, предложим интересные подходы для эффективной работы с внутренними компонентами продукта.

Базовые Best Practices

Выбирайте YAML вместо JSON: Хотя Ansible позволяет использовать синтаксис JSON, с YAML читать файлы и проекты гораздо легче.

Используйте одинаковые пробелы: Чтобы красиво разделить объекты и улучшить читаемость, оставьте пустую строку между блоками, задачами или другими компонентами.

Используйте последовательную стратегию тегирования: Тегирование — это мощная функция в Ansible, поскольку она позволяет группировать задачи и детальнее ими управлять. Теги дают нам возможность добавлять тонкие элементы управления выполнением задач.

Добавляйте комментарии: Если вы считаете, что это необходимо, не стесняйтесь использовать комментарии, объясняющие цель и причину возникновения задач, переменных и так далее.

Используйте стратегию с последовательным именованием: Прежде, чем приступить к настройке своих проектов в Ansible, подумайте о применении последовательной стратегии именования для задач, плейбуков, переменных, ролей и модулей.

Определите руководство по стилю: Следуйте букве руководства — оно поможет последовательно выполнять задачи. Если вы ищете вдохновение, посмотрите на это руководство по стилю от OpenShift.

Будьте проще: Ansible предоставляет множество опций и расширенных возможностей, но это не значит, что мы должны использовать их все в один момент времени. Найдите те инструменты Ansible, которые подходят для вашего случая, и попытайтесь максимально упростите свой проект. Например, начните с простого плейбука и файла инвентаризации, а более сложные инструменты или рефакторинг добавьте позже.

Храните свои проекты в системе контроля версий (VCS): Сохраняйте файлы Ansible в репозитории кода и регулярно фиксируйте новые изменения.

Не храните конфиденциальные значения в обычном тексте: Для секретов и конфиденциальных значений используйте Ansible Vault для шифрования переменных и файлов и защиты любой конфиденциальной информации.

Тестируйте проекты: Используйте инструменты типа Ansible Lint и добавляйте этапы тестирования в конвейеры CI/CD для ваших репозиториев Ansible. Для тестирования ролей Ansible рекомендуем взглянуть на Molecule. Для тестирования вводимых данных или проверки пользовательских выражений можно использовать модуль assert.

Организуйте каталоги

Посмотрите, как выглядит хорошо организованная структура каталогов Ansible:

inventory/
    production                # inventory file for production servers
    staging                   # inventory file for staging environment
    testing                   # inventory file for testing environment
 
group_vars/
   group1.yml             # variables for particular groups
   group2.yml
host_vars/
  host1.yml               # variables for particular systems
  host2.yml
 
library/                  # Store here any custom modules (optional)
module_utils/             # Store here any custom module_utils to support modules (optional)
filter_plugins/           # Store here any filter plugins (optional)
 
master.yml                # master playbook
webservers.yml            # playbook for webserver tier
dbservers.yml             # playbook for dbserver tier
 
roles/
   example_role/               # 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 jinja2
       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
 
   monitoring/              # same kind of structure as "common" was above, done for the monitoring role

Best Practices инвентаризации

Best Practices

Используйте группы инвентаризации: Группируйте узлы на основе общих атрибутов, которые они могут разделять — расположение, цель, роли, среда.

Делайте отдельную инвентаризацию для каждой среды: Определите отдельный файл инвентаризации для каждой среды — производственной, промежуточной, тестовой и так далее, чтобы изолировать их друг от друга и избежать ошибок, связанных с неправильным выбором среды.

Проводите динамическую инвентаризацию: При работе с облачными провайдерами или быстро меняющимися средами ведение статических инвентаризаций может стать сложной задачей. 

Используйте динамическую группировку во время работы: Мы можем создавать динамические группы с помощью модуля `group_by` на основе заданного атрибута — к примеру, на основе их операционной системы — и выполнять различные задачи на каждом из них без определения таких групп в инвентаризации.

- name: Gather facts from all hosts
  hosts: all
  tasks:
    - name: Classify hosts depending on their OS distribution
      group_by:
        key: OS_{{ ansible_facts['distribution'] }}
 
# Only for the Ubuntu hosts
- hosts: OS_Ubuntu
  tasks:
    - # tasks that only happen on Ubuntu go here
    
# Only for the CentOS hosts
- hosts: OS_CentOS
  tasks:
    - # tasks that only happen on CentOS go here

Best Practices для плейбуков и сценариев

Всегда указывайте статус задач: Чтобы сделать ваши задачи более понятными, задавайте параметр state, даже если это не требуется из-за значения по умолчанию.

Размещайте каждый аргумент задачи в отдельной строке: Это помогает сделать файлы Ansible более удобными для чтения. Рассмотрим несколько примеров:

Это рабочий, но плохо читаемый вариант:

- name: Add the user {{ username }}
  ansible.builtin.user: name={{ username }} state=present uid=999999 generate_ssh_key=yes
  become: yes

Вместо этого вы можете использовать данный синтаксис: он улучшает читабельность и понятность задач и их аргументов:

- name: Add the user {{ username }}
  ansible.builtin.user:
     name: "{{ username }}"
     state: present
     uid: 999999
     generate_ssh_key: yes
  become: yes

Используйте плейбуки верхнего уровня для оркестровки плейбуков нижнего уровня: Вы можете логически сгруппировать задачи, сценарии и роли в низкоуровневых плейбуках и использовать плейбуки верхнего уровня для требуемой вам оркестровки. 

Группируйте задачи с помощью блочного синтаксиса: Задачи, которые связаны друг с другом и имеют общие атрибуты или теги, могут быть сгруппированы с помощью функции blok. Еще одним преимуществом этой опции является более простой задач, находящихся в одном блоке.

- name: Install, configure, and start an Nginx web server
  block:
    - name: Update and upgrade apt
      ansible.builtin.apt:
        update_cache: yes
        cache_valid_time: 3600
        upgrade: yes
 
    - name: "Install Nginx"
      ansible.builtin.apt:
        name: nginx
        state: present
 
    - name: Copy the Nginx configuration file to the host
      template:
        src: templates/nginx.conf.j2
        dest: /etc/nginx/sites-available/default
        
    - name: Create link to the new config to enable it
      file:
        dest: /etc/nginx/sites-enabled/default
        src: /etc/nginx/sites-available/default
        state: link
 
    - name: Create Nginx directory
      ansible.builtin.file:
        path: /home/ubuntu/nginx
        state: directory
 
    - name: Copy index.html to the Nginx directory
      copy:
        src: files/index.html
        dest: /home/ubuntu/nginx/index.html
      notify: Restart the Nginx service
  when: ansible_facts['distribution'] == 'Ubuntu'
  tags: nginx
  become: true
  become_user: root

Используйте контроллеры для запущенных задач: Контроллеры позволяют выполнить задачу после внесенных изменений. Контроллер будет запущен, когда произойдут изменения в файле index.html из приведенного выше примера.

handlers:
  - name: Restart the Nginx service
    service:
      name: nginx
      state: restarted
    become: true
    become_user: root

Best Practices для переменных

Переменные позволяют пользователям параметризовать различные компоненты Ansible и хранить значения, которые мы можем повторно использовать. 

Всегда задавайте значения по умолчанию для ваших переменных: Установите значения по умолчанию для всех групп в group_vars/all. Для каждой роли установите переменные по умолчанию в roles/<role_name>/defaults.main.yml.

Используйте каталоги groups_vars и host_vars: Чтобы файл инвентаризации был максимально аккуратным и лаконичным,  устанавливайте переменные групп и хостов в каталогах groups_vars и host_vars.

Ссылайтесь на роль в переменных в качестве префикса: Старайтесь быть четкими при определении имен переменных для ролей. 

nginx_port: 80
apache_port: 8080

Best Practices для модулей

Храните локальные модули рядом с плейбуками: Используйте каталог ./library каждого проекта Ansible для хранения соответствующих пользовательских модулей. Плейбуки, которые имеют каталог ./library относительно своего пути, могут напрямую ссылаться на любые модули внутри него.

Не используйте модули command и shell: Рекомендуем использовать их только тогда, когда нет другого выбора. Вместо этого выбирайте специализированные модули, которые обеспечивают отказоустойчивость и необходимую обработку ошибок.

Указывайте аргументы модуля, когда это имеет смысл: Во многих аргументах модулей значения по умолчанию могут быть опущены. Для удобства можно указать некоторые из этих аргументов, например, для определения статуса плейбука.

Отдавайте предпочтение многозадачности в модуле, а не циклам: Наиболее эффективным способом определения списка однотипных задач типа установки пакетов является использование нескольких задач в одном модуле.

- name: Install Docker dependencies
  ansible.builtin.apt:
     name:
       - curl
       - ca-certificates
       - gnupg
       - lsb-release
     state: latest

Документируйте и тестируйте пользовательские модули: Каждый пользовательский модуль должен содержать примеры, записанные настройки и описание полученных ответов. Новые модули следует тщательно тестировать перед выпуском. Вы можете создать плейбуки для тестирования пользовательских модулей и проверки различных сценариев для тестов.

Best Practices для ролей

Следуйте структуре каталога ролей Ansible Galaxy: Используйте команду ansible-galaxy init <role_name> для создания стандартного каталога ролей.

Сохраняйте назначение ролей: Каждая роль должна иметь отдельную ответственность и отдельную функциональность. Разделяйте роли на основе различных функциональных возможностей или технических областей задач.

Ограничивайте зависимости между ролями: Избегая большого количества зависимостей в ваших ролях, вы поддерживать их слабосвязанными, разрабатывать их независимо друг от друга и использовать их без заморочек со сложными зависимостями между ними.

Отдавайте предпочтение модулям import_role или include_role: Чтобы лучше контролировать порядок выполнения ролей и задач, используйте модули import_role или include_role, а не классические роли.

Будьте осторожны в отношении Ansible Galaxy Roles: При загрузке и использовании содержимого и ролей из Galaxy проверяйте содержимое файлов и выбирайте роли от надежных авторов.

Храните используемые роли Galaxy локально: Чтобы не зависеть от внешнего репозитория Ansible Galaxy, вы можете хранить любые роли из Galaxy в своих репозиториях кода и управлять ими как частью проекта.

Best Practices для развертывания среды

Сначала протестируйте изменения в staging: Это отличный способ убедиться в том, что изменения приведут к ожидаемому результату, а не к новым проблемам.

Ограничьте выполнение задач заданными узлами: Если вы хотите запустить плейбук на определенном хосте, вы можете использовать флаг --limit. Если вам нужно запустить только определенные задачи из плейбука на основе тегов, вы можете определить, какие теги будут выполняться, с помощью флага --tags.

Проверьте, какие задачи будут запущены перед выполнением: Вы можете использовать флаг --list-tasks для подтверждения того, какие задачи будут запущены без их фактического выполнения. Вы можете использовать флаг --list-hosts: так вы убедитесь в том, на какие хосты повлияет плейбук, но при этом не запустить его.

Убедитесь в том, что вы собрались менять, но при этом не запускайте обновления: Используйте флаг --check для прогнозирования изменений, которые могут произойти. Объедините его с флагом --diff, чтобы показать различия в измененных файлах.

Начните с конкретной задачи: Используйте флаг --start-at-task, чтобы плейбук начал работать с выбранной вами задачи.

Используйте Rolling Updates для контроля количества целевых машин: По умолчанию Ansible пытается запустить программу параллельно на всех хостах. Чтобы добиться непрерывных обновлений, вы можете использовать ключевое слово serial. Используя это ключевое слово, вы можете определить, на скольких хостах изменения могут выполняться параллельно.

Управляйте стратегией выполнения (запуска) playbook: По умолчанию Ansible завершает выполнение каждой задачи на всех хостах перед переходом к следующей задаче. Если вы хотите выбрать другую стратегию выполнения, ознакомьтесь с этой документацией

От редакции

С инструментами Ansible мы подробно знакомимся на курсе DevOps Upgrade — интенсивном курсе для тех, кто хочет стать DevOps-инженером. Поток стартует с практическими заданиями и поддержкой от спикеров курса стартует уже 15 мая — узнать подробнее о программе и присоединиться к группе вы можете на нашем сайте.

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


  1. Keirichs
    00.00.0000 00:00
    +1

    очередной компанейский выкидышь...