You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Ansible Handlers实现SSM与CloudWatch Agent安装失败回滚?

Ansible SSM/CloudWatch Agent安装失败回滚及Handlers使用问题

我最近写了个Ansible任务文件用来安装SSM和CloudWatch Agent,本来想在安装过程中任何步骤失败时自动回滚,但试了fail模块根本没生效,想请教下怎么解决这个问题,另外也想搞清楚怎么用Handlers来处理失败场景下的回滚操作。

我的任务文件代码如下:

# tasks file for SSMAgnetInstall
- name: status check
  command: systemctl status amazon-ssm-agent
  register: s_status
- debug:
    msg: "{{ s_status }}"
- name: Get CPU architecture
  command: getconf LONG_BIT
  register: cpu_arch
  changed_when: False
  check_mode: no
  when: s_status.stdout == ""
  ignore_errors: true
- name: Install rpm file for Redhat Family (Amazon Linux, RHEL, and CentOS) 32/64-bit
  yum:
    name: "https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_386/amazon-ssm-agent.rpm"
    state: present
  when: s_status.stdout == ""
  become: yes
  ignore_errors: true
- name: cloud status check
  command: systemctl status amazon-cloudwatch-agent
  register: cld_status
  become: yes
- debug:
    msg: "{{ cld_status }}"
- name: Register to cloud watch service
  become: yes
  become_user: root
  service:
    name: amazon-ssm-agent
    enabled: yes
    state: started
- name: copy the output to a local file
  copy:
    content: "{{ myshell_output.stdout }}"
    dest: "/home/ansible/rama/output.txt"
  delegate_to: localhost

一、解决回滚不生效的核心问题

首先看你原代码里的关键问题:多处添加的ignore_errors: true会让Ansible直接跳过错误,根本不会触发后续的失败检测和回滚逻辑,这就是fail模块没生效的原因。另外你没有明确的错误捕获分支,Ansible里处理这种场景最常用的是**block/rescue/always结构**,相当于编程语言里的try-catch-finally。

我给你修改后的任务文件,加入了完整的回滚逻辑:

# tasks file for SSMAgentInstall
- name: 处理SSM和CloudWatch Agent安装及回滚流程
  block:
    - name: 检查SSM Agent当前状态
      command: systemctl status amazon-ssm-agent
      register: s_status
      changed_when: false  # 状态检查不标记为changed
      failed_when: false   # 即使状态查询失败(比如未安装),也不触发任务失败

    - name: 打印SSM Agent状态
      debug:
        msg: "{{ s_status }}"

    - name: 获取CPU架构(仅当SSM未安装时执行)
      command: getconf LONG_BIT
      register: cpu_arch
      changed_when: false
      check_mode: no
      when: s_status.stdout == ""

    - name: 安装Redhat系SSM Agent(匹配对应架构)
      yum:
        name: "https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_{{ cpu_arch.stdout }}/amazon-ssm-agent.rpm"
        state: present
      become: yes
      when: s_status.stdout == ""
      # 这里去掉ignore_errors,让安装失败时直接进入rescue

    - name: 检查CloudWatch Agent状态
      command: systemctl status amazon-cloudwatch-agent
      register: cld_status
      become: yes
      changed_when: false
      failed_when: false

    - name: 打印CloudWatch Agent状态
      debug:
        msg: "{{ cld_status }}"

    - name: 启用并启动SSM Agent服务
      become: yes
      service:
        name: amazon-ssm-agent
        enabled: yes
        state: started

    - name: 复制状态输出到本地文件
      copy:
        content: "SSM Agent状态: {{ s_status.stdout }}\nCloudWatch Agent状态: {{ cld_status.stdout }}"
        dest: "/home/ansible/rama/output.txt"
      delegate_to: localhost

  rescue:
    # 安装失败时执行回滚操作
    - name: 回滚SSM Agent安装(仅针对之前未安装的情况)
      yum:
        name: amazon-ssm-agent
        state: absent
      become: yes
      when: s_status.stdout == ""

    - name: 停止并禁用SSM Agent服务(如果已启动)
      become: yes
      service:
        name: amazon-ssm-agent
        enabled: no
        state: stopped

    - name: 输出回滚完成提示
      debug:
        msg: "安装流程失败,已执行回滚操作"

    - name: 强制终止Playbook并返回失败状态
      fail:
        msg: "SSM/CloudWatch Agent安装失败,回滚完成"

这个结构的逻辑是:

  • block块里放所有正常的安装流程,任何任务失败都会立刻跳转到rescue块
  • rescue块里执行回滚:卸载刚装的SSM Agent、清理服务配置
  • 最后用fail模块明确标记Playbook失败,避免Ansible返回错误的成功状态

二、用Handlers处理失败场景的回滚

Handlers的优势是可以把重复的操作封装起来,复用性更强。不过Handlers默认只在任务changed时触发,而且要等到所有任务执行完才会运行,所以要在失败场景下用Handlers,需要做两个关键配置:

1. 开启强制触发Handlers

在你的Playbook开头加上force_handlers: yes,确保即使任务失败,Handlers依然会被执行:

- name: 安装SSM和CloudWatch Agent
  hosts: your_target_hosts
  force_handlers: yes  # 关键配置:失败时不跳过Handlers
  tasks:
    # 这里放你的任务代码

2. 定义回滚用的Handlers

在任务文件末尾添加Handlers:

handlers:
  - name: 回滚SSM Agent安装
    yum:
      name: amazon-ssm-agent
      state: absent
    become: yes

  - name: 清理SSM Agent服务配置
    service:
      name: amazon-ssm-agent
      enabled: no
      state: stopped
    become: yes

3. 在rescue块中触发Handlers

修改之前的rescue块,用notify触发Handlers,再用meta: flush_handlers立即执行(不然Handlers会等到所有任务结束才跑):

rescue:
  - name: 触发回滚Handlers
    debug:
      msg: "开始执行回滚操作"
    notify:
      - 回滚SSM Agent安装
      - 清理SSM Agent服务配置

  - name: 立即执行Handlers(不等待任务结束)
    meta: flush_handlers

  - name: 终止Playbook
    fail:
      msg: "安装失败,已通过Handlers完成回滚"

这样,失败时就会调用预定义的Handlers完成回滚,逻辑更清晰,后续如果要修改回滚操作,只需要调整Handlers即可。


内容的提问来源于stack exchange,提问作者Ram Krishna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:09:47