Я использую 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 для подмножества хостов ?
Невозможно достичь цели за одну игру. Если вы хотите обрабатывать группы параллельно, вам потребуется отдельный 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"