Spec-Zone.ru › Ansible 2.4

Делегирование, поэтапные обновления и локальные действия

  • Размер пакета поэтапного обновления
  • Максимальный процент сбоев
  • Делегирование
  • Делегированные факты
  • Выполнение один раз
  • Локальные плейбуки
  • Прерывание выполнения при любой ошибке

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

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

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

В этом разделе рассматриваются все эти возможности. Примеры использования этих элементов можно найти в репозитории ansible-examples. Там есть множество примеров процедур поэтапных обновлений без простоев для различных типов приложений.

Также следует обратиться к разделу О модулях, различные модули, такие как ‘ec2_elb’, ‘nagios’, ‘bigip_pool’ и ‘netscaler’, гармонично сочетаются с понятиями, упомянутыми здесь.

Также вам необходимо ознакомиться с Ролями, так как понятия ‘pre_task’ и ‘post_task’ — это места, где вы обычно вызываете эти модули.

Обратите внимание, что некоторые задачи невозможно делегировать, например, include, add_host, debug, и т. д., так как они всегда выполняются на контроллере.

Размер пакета поэтапного обновления

Новая версия 0.7.

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

- name: test play
  hosts: webservers
  serial: 3

В приведенном выше примере, если у нас было 100 хостов, 3 хоста в группе ‘webservers’ полностью завершат плейбуки перед переходом к следующим 3 хостам.

Ключевое слово ‘’serial’’ также может быть указано в виде процента в Ansible 1.8 и более поздних версиях, которое будет применено к общему числу хостов в плейбуке, чтобы определить количество хостов за один проход:

- name: test play
  hosts: webservers
  serial: "30%"

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

Начиная с Ansible 2.2, размеры пакетов могут быть указаны в виде списка, как показано ниже:

- name: test play
  hosts: webservers
  serial:
  - 1
  - 5
  - 10

В приведенном выше примере первый пакет будет содержать один хост, следующий — 5 хостов, а (если остались хосты) каждый последующий пакет будет содержать 10 хостов, пока не будут использованы все доступные хосты.

Также можно перечислить несколько размеров пакетов в процентах:

- name: test play
  hosts: webservers
  serial:
  - "10%"
  - "20%"
  - "100%"

Вы также можете смешивать значения:

- name: test play
  hosts: webservers
  serial:
  - 1
  - 5
  - "20%"

Примечание

Независимо от того, насколько мал процент, количество хостов за один проход всегда будет равно 1 или больше.

Максимальный процент сбоев

Новая версия 1.3.

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

- hosts: webservers
  max_fail_percentage: 30
  serial: 10

В приведенном выше примере, если более 3 из 10 серверов в группе выйдут из строя, остальная часть плейбука будет прервана.

Примечание

Установленный процент должен быть превышен, а не равен. Например, если serial был установлен в 4, и вы хотели, чтобы задача прервалась, когда 2 системы вышли из строя, процент должен быть установлен в 49, а не 50.

Делегирование

Новая версия 0.7.

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

Если вам нужно выполнить задачу на одном хосте, ссылаясь на другие хосты, используйте ключевое слово ‘delegate_to’ в задаче. Это идеально подходит для размещения узлов в пуле балансировщиков нагрузки или для их удаления. Это также очень полезно для управления временными окнами простоев. Имейте в виду, что не имеет смысла делегировать все задачи, debug, add_host, include и т. д. всегда выполняются на контроллере. Также рекомендуется использовать это с ключевым словом ‘serial’ для управления количеством хостов, выполняющих задачи одновременно:

---

- hosts: webservers
  serial: 5

  tasks:

  - name: take out of load balancer pool
    command: /usr/bin/take_out_of_pool {{ inventory_hostname }}
    delegate_to: 127.0.0.1

  - name: actual steps would go here
    yum: name=acme-web-stack state=latest

  - name: add back to load balancer pool
    command: /usr/bin/add_back_to_pool {{ inventory_hostname }}
    delegate_to: 127.0.0.1

Эти команды будут выполняться на 127.0.0.1, что является машиной, на которой работает Ansible. Также есть сокращенная синтаксическая конструкция, которую вы можете использовать для каждой задачи: ‘local_action’. Ниже приведен тот же плейбук, что и выше, но с использованием сокращенной синтаксической конструкции для делегирования на 127.0.0.1:

---

# ...

  tasks:

  - name: take out of load balancer pool
    local_action: command /usr/bin/take_out_of_pool {{ inventory_hostname }}

# ...

  - name: add back to load balancer pool
    local_action: command /usr/bin/add_back_to_pool {{ inventory_hostname }}

Распространенный паттерн — использовать локальное действие для вызова ‘rsync’ для рекурсивной копии файлов на управляемые серверы. Вот пример:

---
# ...
  tasks:

  - name: recursively copy files from management server to target
    local_action: command rsync -a /path/to/files {{ inventory_hostname }}:/path/to/target/

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

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

---
# ...
  tasks:

  - name: Send summary mail
    local_action:
      module: mail
      subject: "Summary Mail"
      to: "{{ mail_recipient }}"
      body: "{{ mail_body }}"
    run_once: True

Переменная ansible_host (ansible_ssh_host в 1.x или специфичная для плагинов ssh/paramiko) отражает хост, на который делегирована задача.

Делегированные факты

Новая версия 2.0.

По умолчанию любые собранные фактами делегированной задачи присваиваются inventory_hostname (текущий хост), а не хосту, который фактически их произвел (хосту, на который делегирована задача). В версии 2.0 директива delegate_facts может быть установлена в True, чтобы назначать собранные фактами задачи хосту, на который делегирована задача, а не текущему:

- hosts: app_servers
  tasks:
    - name: gather facts from db servers
      setup:
      delegate_to: "{{item}}"
      delegate_facts: True
      with_items: "{{groups['dbservers']}}"

В приведенном выше примере будут собраны факты для машин в группе dbservers и факты будут присвоены этим машинам, а не app_servers. Таким образом, вы можете обратиться к hostvars[‘dbhost1’][‘default_ipv4’][‘address’], даже если dbservers не входили в плейбук или были исключены с помощью –limit.

Выполнение один раз

Новая версия 1.7.

В некоторых случаях может потребоваться выполнить задачу только один раз и только на одном хосте. Это можно сделать, настроив “run_once” в задаче:

---
# ...

  tasks:

    # ...

    - command: /opt/application/upgrade_db.py
      run_once: true

    # ...

Это можно дополнительно использовать с “delegate_to”, чтобы указать отдельный хост для выполнения:

- command: /opt/application/upgrade_db.py
  run_once: true
  delegate_to: web01.example.org

Если “run_once” не используется с “delegate_to”, он будет выполняться на первом хосте, определенном в инвентаре, в группе(ах) хостов, на которые нацелен плейбук - например, webservers[0], если плейбук нацелен на “hosts: webservers”.

Этот подход аналогичен применению условия к задаче, например:

- command: /opt/application/upgrade_db.py
  when: inventory_hostname == webservers[0]

Примечание

При совместном использовании с “serial”, задачи, помеченные как “run_once”, будут выполняться на одном хосте в каждом пакете выполнения. Если крайне важно, чтобы задача выполнялась только один раз независимо от режима “serial”, используйте конструкцию when: inventory_hostname == ansible_play_hosts[0].

Локальные плейбуки

Иногда полезно использовать плейбук локально, а не подключаясь через SSH. Это может быть полезно для проверки конфигурации системы, размещая плейбук в crontab. Это также может быть использовано для выполнения плейбука внутри установщика ОС, например, Anaconda kickstart.

Чтобы выполнить весь плейбук локально, просто установите строку “hosts:” на “hosts: 127.0.0.1”, а затем запустите плейбук следующим образом:

ansible-playbook playbook.yml --connection=local

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

- hosts: 127.0.0.1
  connection: local

Прерывание выполнения при любой ошибке

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

Иногда выполнение ‘’serial’’ не подходит; количество хостов непредсказуемо (из-за динамического инвентаря), а скорость критически важна (требуется одновременное выполнение), но все задачи должны быть на 100% успешными, чтобы продолжить выполнение плейбука.

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

  • отключение трафика на балансировщиках нагрузки (должны быть выключены одновременно)
  • безопасная остановка сервиса
  • обновление программного обеспечения (этот шаг включает тесты и запуск сервиса)
  • включение трафика на балансировщиках нагрузки (которые должны быть включены одновременно)

Сервис не может быть остановлен с «активными» балансировщиками нагрузки; они должны быть отключены в первую очередь. Из-за этого второй этап не может быть выполнен, если какой-либо сервер завершился ошибкой на первом этапе.

Для дата-центра «А» плейбук может быть написан следующим образом:

---
- hosts: load_balancers_dc_a
  any_errors_fatal: True
  tasks:
  - name: 'shutting down datacenter [ A ]'
    command: /usr/bin/disable-dc

- hosts: frontends_dc_a
  tasks:
  - name: 'stopping service'
    command: /usr/bin/stop-software
  - name: 'updating software'
    command: /usr/bin/upgrade-software

- hosts: load_balancers_dc_a
  tasks:
  - name: 'Starting datacenter [ A ]'
    command: /usr/bin/enable-dc

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

См. также

Плейбуки
Вводный курс по плейбукам
Примеры Ansible на GitHub
Многие примеры полномасштабных развертываний
Список рассылки пользователей
Есть вопрос? Заходите в группу Google!
irc.freenode.net
Канал IRC-чата #ansible

© 2012–2018 Michael DeHaan
© 2018–2019 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/ansible/2.4/playbooks_delegation.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API