Автор статьи: Рустем Галиев

IBM Senior DevOps Engineer & Integration Architect. Официальный DevOps ментор и коуч в IBM

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

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

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

Допустим у нас есть плейбук, который проверяет состояние сервисов на хосте

service_status.yaml

---
- hosts: web-server
  become: true
  gather_facts: false
  tasks:
   - name: verify nginx service
     command: service nginx status

   - name: verify if nginx is listening on 80
     wait_for: port=80 timeout=1

У нас есть быстрая проверка, и мы отключаем сбор фактов с помощью gather_facts со значением false. Говоря по простому gather_facts в Ansible - это параметр, который определяет, должен ли Ansible собирать факты (информацию о целевых хостах) перед выполнением задач. Факты - это данные о системе и окружении целевого хоста, такие как операционная система, аппаратное оборудование, переменные среды и многое другое. Сбор фактов полезен, когда вам нужно знать о состоянии целевой системы перед выполнением задач, чтобы принять решение о том, какие задачи выполнять или какие конфигурации применять. В данном плейбуке оно нам не нужно, поэтому ставим значение false.

Также мы можем использовать это в плейбуке, который отвечает за перезагрузку сервисов

service_restart.yml

---
- hosts: web-server
  become: true
  gather_facts: false
  tasks:
   - service: name=nginx state=stopped
     wait_for: port=80 state=drained

- hosts: db-server
  become: true
  tasks:
   - service: name=mysql state=restarted
     wait_for: host={{ansible_eth0.ipv4.address}} port=3306

- hosts: web-server
  become: true
  gather_facts: false
  tasks:
   - service: name=nginx state=started
     wait_for: port=80

Также для ускорения работы плейбуков мы можем использовать параметр cache_valid_time.

cache_valid_time - это параметр, используемый в Ansible для управления временем действительности кэша фактов (facts cache). Кэш фактов - это механизм, который позволяет Ansible сохранять информацию о фактах, собранных о целевых хостах, и повторно использовать ее в будущих запусках плейбуков или задач.

Для использования параметра cache_valid_time с, например, тем же плейбуком установки Nginx, можно будет включить его в раздел ansible.cfg проекта Ansible. Этот параметр устанавливается на уровне конфигурации Ansible и определяет, сколько времени информация в кэше фактов о хостах считается действительной.

ansible.cfg

[defaults]
inventory = /path/to/inventory
cache_valid_time = 3600  # Кэш фактов действителен в течение 1 часа (3600 секунд)


В этом примере cache_valid_time установлен на 3600 секунд (1 час). Это означает, что информация о фактах будет кэшироваться в течение часа и, если вы запустите плейбук повторно в течение этого времени, Ansible будет использовать кэшированные факты, если они все еще действительны.

Еще один вариант использования:

- hosts: all
  become: true
  gather_facts: false
  tasks:
   - name: update apt cache
     apt: update_cache=yes cache_valid_time=3600


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

  • hosts: all: Указывает, что этот плейбук будет применяться ко всем хостам, определенным в вашем инвентаризационном файле. Все задачи, включенные в этот плейбук, будут выполнены на всех хостах.

  • become: true: Эта строка говорит Ansible использовать привилегии суперпользователя (обычно root) при выполнении задач. Обновление кэша APT обычно требует прав суперюзера, поэтому здесь используется become, чтобы получить необходимые права.

  • gather_facts: false: Этот параметр отключает сбор фактов о целевых хостах перед выполнением задач. Факты - это информация о системе и окружении хостах, и в данном случае они не собираются.

  • tasks: Это секция, где определены задачи, которые будут выполнены на целевых хостах.

  • name: update apt cache: Это имя задачи, которое будет отображаться в выводе Ansible для идентификации задачи.

  • apt: update_cache=yes cache_valid_time=3600: Эта задача использует модуль apt для выполнения операции обновления кэша APT на хосте. Вот что делает каждая опция:

    • update_cache=yes: Эта опция указывает модулю apt выполнить обновление кэша APT. Кэш APT содержит информацию о доступных пакетах и их версиях.

    • cache_valid_time=3600: Эта опция устанавливает время действия кэша фактов для этой задачи в 3600 секунд (1 час). Это означает, что Ansible не будет обновлять кэш APT на этом хосте в течение 1 часа после выполнения этой задачи. Это может помочь ускорить выполнение плейбука, если он запускается несколько раз в течение короткого времени, поскольку обновление кэша APT - это операция, которая может занимать время, особенно при большом количестве пакетов.

Таким образом, этот плейбук выполняет задачу обновления кэша APT с привилегиями суперпользователя на всех целевых хостах и кэширует факты операции в течение 1 часа, что может помочь оптимизировать процесс выполнения плейбука.

Но это еще не все, что мы можем сделать. Есть еще один параметр Hosts: limit, который поможет нам ускорить процесс.

Параметр --limit или --limit-hosts в Ansible используется для ограничения выполнения тасок только на определенных целевых хостах или группах хостов из инвентаризационного файла или же по простому инветаря. Это позволяет нам выбирать конкретные хосты, на которых мы хотим выполнить задачи из плейбука или командной строки Ansible, вместо применения их ко всем хостам, определенным в инвентаризационном файле.

ansible-playbook -i inventory.ini network_services_update.yml --limit myserver

В этом примере:

  • inventory.ini - это инвентаризационный файл, который определяет хосты и их группы.

  • network_services_update.yml - плейбук Ansible.

  • --limit myserver - это параметр, который указывает Ansible выполнить плейбук только на хосте с именем myserver.

Можно использовать --limit для указания группы хостов:

ansible-playbook -i inventory.ini network_services_update.yml --limit web_servers

В этом случае Ansible выполнит плейбук только на хостах, включенных в группу web_servers из вашего инвентаризационного файла.

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

Еще одним способом ускорения работы плейбуков может быть использовани метки (tags). Метки позволяют назначать идентификаторы (теги) к задачам в нашем плейбуке и затем выполнять только задачи с определенными тегами вместо выполнения всех задач из плейбука. Это может быть полезно, когда мы хотим выборочно выполнять только определенные части плейбука, особенно если плейбук содержит множество задач.

Чтобы добавить метку к задаче в плейбуке, используем параметр tags в определении задачи:

---
- name: Install Nginx
  hosts: myserver
  tasks:
    - name: install Nginx
      apt:
        name: nginx
        state: present
      tags:
        - nginx_install
    - name: Nginx_conf
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
      tags:
        - nginx_configure

В этом примере две задачи связаны с установкой и настройкой Nginx. Каждая из них имеет свою метку (tags):

Первая задача имеет метку nginx_install.

Вторая задача имеет метку nginx_configure.

Теперь мы можем выполнить только задачи с определенными метками, используя параметр --tags или --skip-tags при запуске плейбука:

# Запустить только задачи с меткой "nginx_install"
ansible-playbook myplaybook.yml --tags nginx_install

# Пропустить задачи с меткой "nginx_configure"
ansible-playbook myplaybook.yml --skip-tags nginx_configure

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

Ну и конечно же можно ускорить плейбук основываясь на основном принципе Ansible и в целом IaaC: Идемпотентность.

Idempotence (Идемпотентность) - это важный концепт в Ansible, который обозначает, что выполнение плейбуков и задач должно быть безопасным и предсказуемым, даже если они выполняются несколько раз. В контексте Ansible, выполнение задач и плейбуков с идемпотентностью означает, что:

  • Если задача уже выполнена и текущее состояние системы соответствует желаемому состоянию (как описано в задаче), Ansible не будет повторно выполнять эту задачу. Это означает, что задача не вносит изменения в систему.

  • Если задача уже выполнена, но текущее состояние системы не соответствует желаемому состоянию, Ansible выполнит эту задачу только один раз, чтобы привести систему в желаемое состояние.

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

changed_when и failed_when - это параметры, которые позволяют настраивать условия, при которых Ansible будет считать задачу измененной (changed) или завершившейся с ошибкой (failed). Мы можем использовать их для достижения идемпотентности и оптимизации плейбуков.

changed_when: параметр, который позволяет нам определить условия, при которых Ansible будет считать, что задача изменила систему. Если условие истинно, Ansible отметит задачу как "changed" (изменившую систему), даже если никакие фактические изменения не были внесены. Используется для управления тем, когда Ansible должен отмечать задачу как "changed".

---
- hosts: web-server
  become: true
  gather_facts: false
  tasks:
   - name: verify nginx service
     command: service nginx status
     changed_when: false


В данном случае, использование changed_when: false означает, что статус службы Nginx (service nginx status) не имеет значения для целей плейбука, и даже если Ansible получит сообщение о том, что служба изменилась (что может произойти, например, при рестарте), это не должно считаться фактическим изменением состояния системы.

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

Таким образом, параметр changed_when: false в данном контексте помогает предотвратить ложные срабатывания и сохранить плейбук в идемпотентном (безопасном и предсказуемом) состоянии, что важно для автоматизации конфигурации и управления системами.

Ну и последнее в списке, но не по значимости это Accelerated Mode и Pipelining

Accelerated Mode:

Ускоренный режим - это оптимизация, предназначенная для снижения задержек при выполнении задач на удаленных хостах. Он активируется по умолчанию, начиная с Ansible 2.0. Этот режим позволяет Ansible эффективнее отправлять задачи на удаленные хосты и получать результаты выполнения задач.

Основная особенность ускоренного режима - это уменьшение числа отдельных SSH-сеансов, устанавливаемых между управляющим хостом Ansible и целевыми хостами. Вместо открытия нового SSH-сеанса для каждой задачи, ускоренный режим поддерживает постоянное соединение SSH, что уменьшает накладные расходы на установку и разрыв соединения SSH.

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

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

 Pipelining (Пайплайнинг):

Пайплайнинг (Pipelining) - это оптимизация, которая позволяет уменьшить количество SSH-запросов между управляющим хостом и целевыми хостами. Пайплайнинг позволяет объединить несколько задач в один SSH-сеанс, что уменьшает задержки и улучшает производительность при выполнении нескольких задач на одном хосте.

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

[all]
ansible_ssh_pipelining=True

Установка ansible_ssh_pipelining=True для группы хостов позволит использовать пайплайнинг для всех хостов в этой группе.

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

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

Всем быстрых и оптимизированных пайплайнов!

А больше практических навыков вы можете получить на онлайн-курсах от ведущих экспертов отрасли. Заглядывайте в каталог и выбирайте подходящий курс. Также напоминаю о том, что в рамках каждого курса мы проводим бесплатные вебинары, на которые можно зарегистрироваться прямо на странице курса.

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


  1. TomskDiver
    20.09.2023 16:27
    +3

    Простите меня, но я в заголовке увидел Asnible и дальше не стал читать. Я понимаю что можно сделать ошибки в большом тексте, но сделать ошибку в маааленьком заголовке лично для меня это эпик фейл.


    1. marks
      20.09.2023 16:27

      Когда выкладываешь по 5-6 статей в день, ради рейтинга, и не такое бывает


    1. moderator
      20.09.2023 16:27
      +1

      Исправили


    1. MaxRokatansky Автор
      20.09.2023 16:27
      +1

      Действительно опечатались. Будем внимательнее.