Spec-Zone.ru › Ansible 2.5

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

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

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

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

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

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

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

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

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

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

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

- name: test play
  hosts: webservers
  serial: 2
  gather_facts: False
  tasks:
  - name: task one
    comand: hostname
  - name: task two
    command: hostname

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

PLAY [webservers] ****************************************

TASK [task one] ******************************************
changed: [web2]
changed: [web1]

TASK [task two] ******************************************
changed: [web1]
changed: [web2]

PLAY [webservers] ****************************************

TASK [task one] ******************************************
changed: [web3]
changed: [web4]

TASK [task two] ******************************************
changed: [web3]
changed: [web4]

PLAY RECAP ***********************************************
web1      : ok=2    changed=2    unreachable=0    failed=0
web2      : ok=2    changed=2    unreachable=0    failed=0
web3      : ok=2    changed=2    unreachable=0    failed=0
web4      : ok=2    changed=2    unreachable=0    failed=0

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

- 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 или больше.

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

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

- hosts: webservers
  max_fail_percentage: 30
  serial: 10

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

Примечание

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

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

Это на самом деле не специфично для поэтапного обновления, но часто встречается в таких случаях.

Если вы хотите выполнить задачу на одном хосте со ссылкой на другие хосты, используйте ключевое слово ‘delegate_to’ в задаче. Это идеально подходит для размещения узлов в пуле балансировщиков нагрузки или их удаления. Также это очень полезно для управления окнами простоев. Обратите внимание, что не имеет смысла делегировать все задачи; отладка, добавление хоста, включение и т. д. всегда выполняются на контроллере. Также рекомендуется использовать это с ключевым словом ‘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-агента, иначе 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) отражает хост, на который делегируется задача.

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

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

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

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

Выполнить один раз

В некоторых случаях может потребоваться запустить задачу только один раз и только на одном хосте. Этого можно добиться, настроив «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. Если важно, чтобы задача выполнялась только один раз независимо от режима «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

Примечание

Если вы установили подключение на локальное и не задано ansible_python_interpreter, модули будут выполняться в /usr/bin/python, а не в {{ ansible_playbook_python }}. Убедитесь, что вы установили ansible_python_interpreter: “{{ ansible_playbook_python }}” в host_vars/localhost.yml, например. Вы можете избежать этой проблемы, используя local_action или delegate_to: localhost вместо этого.

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

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

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

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

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

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

Для центра обработки данных «A» плейбуке может быть написан так:

---
- 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
#ansible IRC чат-канал

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

Spec-Zone.ru

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