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

Я использую Ansible 2.9 и AWX 11. У меня есть парк серверов, некоторые из которых могут быть логически сегментированы с помощью тега, который следует шаблону вроде GUID_1234567890 . Каждый уникальный тег GUID _ * представляет произвольное количество серверов. В дополнение к тегу GUID _ * сервер будет иметь теги foo или bar .

Говоря более конкретно, у меня 2000 серверов, 1000 из них имеют 80 уникальных тегов GUID _ * . В каждой из этих 80 уникальных групп серверов GUID _ * я должен перезапустить серверы с тегами foo , но не серверы с тегами bar . Кроме того, мне нужно последовательно перезагружать серверы foo , если у них одинаковый тег GUID _ * .

Я могу запустить playbook с таким шаблоном хоста: hosts : GUID _ *: & foo и получите все GUID_ с тегами foo хостов. Однако, если для параметра playbook serial: указано любое значение, кроме 1 , серверы foo будут перезапущены параллельно, скорее всего, несколько серверов foo в одной группе тегов GUID_ . При последовательном выполнении сценария может потребоваться до дня. Я хотел бы использовать разветвление Ansible для запуска вилки playbook для каждой из 80 групп GUID _ * хостов, но каждая вилка должна вызывать playbook, который сам работает как serial: 1 против серверов foo .

Есть ли способ начать с большого набора хостов, но затем создать параллельные рабочие процессы, которые выполняют serial: 1 playbooks для подмножества хостов ?

2
задан 25 November 2020 в 00:24
1 ответ

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

" Меньшие подмножества хостов"

Учитывая инвентаризацию для упрощения тестирования

test_01
test_02
test_03
test_04
test_05
test_06

[GUID_01]
test_01
test_02
test_03

[GUID_02]
test_04
test_05
test_06

[foo]
test_01
test_02
test_04
test_05
srvX

[bar]
test_03
test_06
srvY

Создать словарь всех GUID_*и список хостов в частности GUID_xи группы foo. Например,

- hosts: GUID_*:&foo
  gather_facts: false
  tasks:
    - set_fact:
        my_groups: "{{ my_groups|default({})|
                       combine({item: my_hosts|dict2items|
                                      selectattr('value', 'eq', item)|
                                      map(attribute='key')|list}) }}"
      loop: "{{ my_guids|unique }}"
      vars:
        my_guids: "{{ ansible_play_hosts_all|
                      map('extract', hostvars, 'group_names')|
                      map('select', 'match', 'GUID')|
                      map('first')|flatten }}"
        my_hosts: "{{ dict(ansible_play_hosts_all|zip(my_guids)) }}"
      run_once: true
    - debug:
        var: my_groups
      run_once: true

дает

  my_groups:
    GUID_01:
    - test_01
    - test_02
    GUID_02:
    - test_04
    - test_05

Тот же словарь может быть создан без шаблонов

- hosts: all
  gather_facts: false
  tasks:
    - set_fact:
        my_groups: "{{ my_groups|default({})|
                       combine({item: groups[item]|
                                      intersect(groups['foo'])}) }}"
      loop: "{{ groups|select( 'match', 'GUID')|list }}"
      run_once: true

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

A: Используйте шаблоны Ansible для создания кода. Например, учитывая роль

shell> cat roles/reboot/tasks/main.yml
- command: date "+%H:%M:%S"
  register: result
- debug:
    msg: "{{ result.stdout }} {{ inventory_hostname }} Reboot"
- command: sleep 3
- command: date "+%H:%M:%S"
  register: result
- debug:
    msg: "{{ result.stdout }} {{ inventory_hostname }} Ready"

Шаблоны

shell> cat templates/my_hosts.j2
{{ lookup('file', 'hosts') }}

# ---------------------------------------------------------------------
# Groups for my_wrapper. See template my_hosts.j2

{% for group,hosts in my_groups.items() %}
[my_{{ group }}]
{% for host in hosts %}
{{ host }}
{% endfor %}

{% endfor %}
shell> cat templates/my_pb.j2
- hosts: my_{{ item }}
  gather_facts: false
  serial: 1
  roles:
    - reboot
shell> cat templates/my_wrapper.j2
#!/bin/bash
{% for group,hosts in my_groups.items() %}
nohup ansible-playbook -i my_hosts my_pb_{{ group }}.yml &
{% endfor %}

и плейбук

- hosts: all
  gather_facts: false
  tasks:
    - set_fact:
        my_groups: "{{ my_groups|default({})|
                       combine({item: groups[item]|
                                      intersect(groups['foo'])}) }}"
      loop: "{{ groups|select( 'match', 'GUID')|list }}"
      run_once: true
    - block:
        - template:
            src: my_hosts.j2
            dest: my_hosts
        - template:
            src: my_wrapper.j2
            dest: my_wrapper.sh
            mode: "a+x"
        - template:
            src: my_pb.j2
            dest: "my_pb_{{ item }}.yml"
          loop: "{{ my_groups.keys()|list }}"
      run_once: true
      delegate_to: localhost

создают файлы с кодом

shell> cat my_hosts

   ...

# ---------------------------------------------------------------------
# Groups for my_wrapper. See template my_hosts.j2

[my_GUID_01]
test_01
test_02

[my_GUID_02]
test_04
test_05
shell> cat my_wrapper.sh
#!/bin/bash
nohup ansible-playbook -i my_hosts my_pb_GUID_01.yml &
nohup ansible-playbook -i my_hosts my_pb_GUID_02.yml &
shell> cat my_pb_GUID_01.yml 
- hosts: my_GUID_01
  gather_facts: false
  serial: 1
  roles:
    - reboot

shell> cat my_pb_GUID_02.yml 
- hosts: my_GUID_02
  gather_facts: false
  serial: 1
  roles:
    - reboot

. Затем запуск обертки дает

shell> grep msg nohup.out 
    "msg": "13:03:51 test_01 Reboot"
    "msg": "13:03:51 test_04 Reboot"
    "msg": "13:03:56 test_01 Ready"
    "msg": "13:03:56 test_04 Ready"
    "msg": "13:03:58 test_02 Reboot"
    "msg": "13:03:58 test_05 Reboot"
    "msg": "13:04:04 test_02 Ready"
    "msg": "13:04:04 test_05 Ready"
2
ответ дан 25 November 2020 в 05:11

Теги

Похожие вопросы