问题描述
在使用 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 配置中设置 strategy
为 free
来启用这个策略。以下是一个示例:
---
- 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 实例是否已停止。
正文完