Ansible:测试多个 RDS 实例是否全部停止

69次阅读
没有评论

问题描述

在使用 Ansible 停止多个 RDS (也可以是 EC2) 实例后,希望只有当所有实例的状态都为 “stopped” 时才继续执行下一步。他目前使用了如下任务来实现这个需求,但代码只在测试第一个元素的状态。

- name: Wait for RDS modify to finish
  rds_instance_facts:
    aws_access_key: "{{ assumed_role.sts_creds.access_key }}"
    aws_secret_key: "{{ assumed_role.sts_creds.secret_key }}"
    security_token: "{{ assumed_role.sts_creds.session_token }}"
    db_instance_identifier: "{{ item }}"
    region: "{{ region }}"
  loop: "{{ vars[ 'list_rds_resources_ids1_' ] + vars[ 'list_rds_resources_ids2_' ] }}"
  register: aws_rds_facts
  until: aws_rds_facts[0].db_instance_status == "stopped"
  retries: 90
  delay: 10

解决方案

请注意以下操作可能因版本差异或风险而需要适当调整,务必做好备份。

最佳方案

为了实现同时测试所有实例是否已停止的目标,可以使用 Ansible 的 free strategy。这个策略会尽快运行所有任务,而不会等待任何内容完成。但要注意,这可能会导致日志变得混乱。

你可以在 Ansible 配置中设置 strategyfree 来启用这个策略。以下是一个示例:

---
- hosts: your_hosts
  strategy: free
  tasks:
    # 你的任务在这里

请注意,虽然 free strategy 可以快速运行任务,但在处理大量任务时,日志可能会变得难以管理。

方案2

用户在评论中提到了另一种解决方案,将 until 条件放到外部循环中。这样,所有 RDS 实例的停止操作会在外部循环之前启动,从而节省时间。只有当所有数据库都停止后,外部循环才会结束。

以下是用户提供的示例代码,演示了如何实现这个解决方案:

在主任务文件 main.yml 中:

---
- include: wait_rds_are_stopped.yml
  when: chosen_action == "stop"
  loop: "{{ vars[ 'list_rds_resources_ids1_' + environment ] + vars[ 'list_rds_resources_ids2_' + environment ] }}"
  loop_control:
    loop_var: outer_item

wait_rds_are_stopped.yml 任务文件中:

---
- name: Wait for RDS stop to finish
  rds_instance_facts:
    aws_access_key: "{{ assumed_role.sts_creds.access_key }}"
    aws_secret_key: "{{ assumed_role.sts_creds.secret_key }}"
    security_token: "{{ assumed_role.sts_creds.session_token }}"
    db_instance_identifier: "{{ outer_item }}"
    region: "{{ region }}"
  register: aws_rds_facts
  until: aws_rds_facts.instances[0].db_instance_status == "stopped"
  retries: 90
  delay: 10

在上面的示例中,外部循环 loop 控制着 RDS 实例的停止操作,而 until 条件确保只有当所有实例都已停止时,外部循环才会结束。

这种方法的好处在于能够在外部循环中同时运行所有停止操作,从而提高效率。

结论

根据用户的需求,我们提供了两种解决方案。你可以根据实际情况选择合适的方法来测试并确保所有 RDS 实例是否已停止。

正文完