Ansible 回滚:即使其中一个主机发生故障,也会对主机列表运行一组任务



我有一个包含多个角色、主持人和组的剧本。我正在尝试开发一个回滚功能,该功能将在所有主机上运行。我目前的障碍是,我认为无法将角色、块或任务集委派给主机组

  • 我尝试在没有循环的情况下查找分组委托,因此它可以在一个块上工作。
  • import_role不接受循环
  • include_role不接受delegate_to
  • 与import_tasks/include_tasks相同

这是我现在作为剧本文件(缩短版本)的内容

- hosts: all
any_errors_fatal: true
vars_prompt:
- name: "remote_user_p"
prompt: "Remote user running the playbook"
default: "root"
private: no
- name: "service_user_p"
prompt: "Specify user to run non-root tasks"
default: "user"
private: no
tasks:
- set_fact:
playbook_type: "upgrade"
- import_role:
name: 0_pre_check
run_once: true
remote_user: "{{ remote_user_p }}"
become_user: "{{ service_user_p }}"
become_method: su
become: yes
- block:      
- import_role:
name: 1_os
- import_role:
name: 2_mysql
when: inventory_hostname in groups['mysql'] | default("")
- import_role:
name: 3_web
when: inventory_hostname in groups['web'] | default("") 
...
rescue:
- block:
- name: run rollback
import_tasks: ../common/roles/5_rollback/tasks/rollback.yml
remote_user: "{{ remote_user }}"
become_user: "{{ service_user }}"
become_method: su
become: yes

这是来自 rollback.yml 的一些示例代码:

- block:
- name: rollback symlinks to config dir
file:
src: "{{ current_config_path }}"
dest: "{{ install_dir }}/static/cfg"
owner: "{{ service_user }}"
group: "{{ service_user_primary_group }}"
state: link
when: current_new_configs | default("N") == "Y"
delegate_to: "{{ item }}"
with_items:
- "{{ ansible_play_hosts }}"
- block:           
- name: return config files
shell: test -f '{{ item.1.current_ver_file_path }}' && cp -p {{ item.1.current_ver_file_path }} {{ item.1.old_config_location }}
args:
warn: false
register: return_config_files
failed_when: return_config_files.rc >= 2
when:
- roolback_moved_cfg | default('N') == "Y"
- inventory_hostname in groups[item.0.group]
- item.1.old_config_location != ""
- item.1.current_ver_file_path != ""
with_subelements:
- "{{ config_files }}"
- files
become_user: root
become_method: sudo
become: yes
- name: systemctl daemon-reload  
shell: systemctl daemon-reload
failed_when: false
when: root_rights == "Y"
args:
warn: false
delegate_to: "{{ item }}"
with_items:
- "{{ ansible_play_hosts }}"
when: root_rights == "Y"
become_user: root
become_method: sudo
become: yes
- fail:
msg: "Upgrade failed. Symbolic links were set to the previous version. Fix the issues and try again. If you wish to cancel the upgrade, restore the database backup manually."

如您所见,现在我通过引入来使用蹩脚的解决方法

delegate_to: "{{ item }}"
with_items:
- "{{ ansible_play_hosts }}"

每次任务后。

这里有两个问题: 1.任务return config files后我不能使用相同的方法,因为它已经使用了一个循环 2.这通常是蹩脚的代码重复,我讨厌它

为什么我需要它:例如,如果 playbook 执行失败mysql角色中的某个地方,则rescue块将仅在该mysql角色的主机上执行(顺便说一句,下一个角色的任务的执行将在运行救援块时继续 - 尽管付出了所有努力,但仍有相同数量的任务),而我希望它运行所有主机。

我终于能够通过一个丑陋的黑客来解决这个问题。用过的戏剧而不仅仅是角色——现在有 10 多部戏剧。不要评判我,我花了很多精力试图让它变得漂亮):

示例播放后跟检查 - 与其他所有游戏相同。

- hosts: mysql
any_errors_fatal: true
tasks:
- block:              
- import_role:
name: 2_mysql
when: not rollback | default(false)
rescue:
- block:
- name: set fact for rollback
set_fact: 
rollback: "yes"
delegate_to: "{{ item }}"
delegate_facts: true
with_items: "{{ groups['all'] }}"
- hosts: all
any_errors_fatal: true
tasks:
- name: run rollback
import_tasks: ../common/roles/5_rollback/tasks/rollback.yml
when: rollback | default(false)
include_role不接受

delegate_to

事实上,确实如此。

使用ansible内核2.8:

- name: "call my/role with host '{{ansible_hostname}}' for hosts in '{{ansible_play_hosts}}'"
include_role:
name: my/role
apply:
delegate_to: "{{current_host}}"
with_items: "{{ansible_play_hosts}}"
loop_control:
loop_var: current_host

对于 ansible-core 2.5 到 2.7,请参阅 George Shuklinansible/ansibleissue 35398 中提到的 "2.5:delegate_to,include_role with loops">

- name: "call my/role with host '{{ansible_hostname}}' for items in '{{ansible_play_hosts}}'"
include_tasks: loop.yml
with_items: "{{ansible_play_hosts}}"
loop_control:
loop_var: current_host

loop.yml其自己的文件中的另一个任务:

- name: "Import my/role for '{{current_host}}'"
import_role: name=my/role
delegate_to: "{{current_host}}"

因此,在两个文件(使用 ansible 核心 2.7)或一个文件 (2.8)中,您可以使所有角色及其任务在委派服务器上运行。

最新更新