
У меня есть более 80 хостов, на которых работает мое приложение, и я обновляю давно существующий ansible playbook, чтобы изменить наш балансировщик нагрузки. В нашей текущей настройке балансировщика нагрузки хосты можно добавлять/удалять из балансировщика нагрузки за одну ansible play, обращаясь к AWS CLI. Однако мы переключаемся на балансировщик нагрузки, настроенный на нескольких наших собственных хостах, и будем вводить и выводить хосты, манипулируя текстовыми файлами на этих хостах с помощью ansible. По сути, мне нужен внутренний цикл по разным хостам в playbook, при этом используя Serial.
У меня возникли проблемы со структурированием сценария таким образом, чтобы можно было разослать blockinfile
команды хостам в группе, tag_Type_edge
одновременно выполняя развертывание на 80 tag_Type_app
хостах с последовательным портом: 25%.
Вот что я хочу уметь делать:
---
- hosts: tag_Type_app
serial: "25%"
pre_tasks:
- name: Gathering ec2 facts
action: ec2_metadata_facts
- name: Remove from load balancers
debug:
msg: "This is where I'd fan out to multiple different hosts from group tag_Type_edge to manipulate
text files to remove the 25% of hosts from tag_Type_app from the load balancer"
tasks:
- name: Do a bunch of work to upgrade the app on the tag_Type_app machines while out of the load balancer
debug:
msg: "deploy new code, restart service"
post_tasks:
- name: Put back in load balancer
debug:
msg: "This is where I'd fan out to multiple different hosts from group tag_Type_edge to manipulate
text files to *add* the 25% of hosts from tag_Type_app back into the load balancer"
Как мне структурировать это так, чтобы обеспечить внутренний цикл tag_Type_edge
при использовании serial: 25% на всех tag_Type_app
ящиках?
решение1
В Ansible, для фактического запуска задачи на одном хосте, но от имени другого, может потребоваться использование умной вещи, называемойделегация. Пример в документации действительно заключается в исключении хостов из балансировщика нагрузки.
Как и любая задача, она может быть запущена несколько раз в цикле на некоторых именах хостов. Не цикл воспроизведения, а цикл задачи. Помогает пример, принимая ваш скелет:
---
- name: Example loop over load balancers for each app server
hosts: tag_Type_app
serial: "25%"
pre_tasks:
- name: Gathering ec2 facts
action: ec2_metadata_facts
- name: Remove from load balancers
debug:
msg: "Remove app instance {{ inventory_hostname }} from edge node {{ item }}"
delegate_to: "{{ item }}"
loop: "{{ query('inventory_hostnames', 'tag_Type_edge') }}"
tasks:
- name: Do a bunch of work to upgrade the app on the tag_Type_app machines while out of the load balancer
debug:
msg: "deploy new code, restart service"
post_tasks:
- name: Put back in load balancer
debug:
msg: "Add app instance {{ inventory_hostname }} to edge node {{ item }}"
delegate_to: "{{ item }}"
loop: "{{ query('inventory_hostnames', 'tag_Type_edge') }}"
inventory_hostnames — это плагин поиска, который выполняет шаблоны инвентаризации, туда можно добавить любой шаблон.
Пара сложных моментов. Любой сбой в цикле "edge" приведет к сбою хоста "app". Что оставит частичное состояние некоторых хостов edge включенным, а некоторых нет. Если только у вас нет какого-то механизма отката, например, блока со спасательным средством, которое его отменяет.
Как цикл задач, некоторые функции, связанные с инвентарем и игрой, не будут применяться. Вы не можете ограничить хосты Edge еще больше с помощью --limit
командной строки. Вы также не можете использовать serial
их для пакетирования, это уже в игре.
Также он будет запускать относительно большое количество задач, по крайней мере app ✕ edge ✕ 2. Это может быть немного медленно. Можно было бы немного смягчить, увеличив количество форков.
Если бы ваш балансировщик нагрузки с несколькими хостами имел одну плоскость управления, не нужно было бы затрагивать так много хостов. Выполнение одной задачи на сервер приложений. Возможно, вы не настроены на это в данный момент, но это следует учитывать.