问题描述
在使用Ansible时,有一个需求是希望在一组主机中找到第一个运行特定Docker容器的主机。他创建了一个包含一系列任务的playbook,最终执行一个curl命令。他只想在一个主机上执行该命令,但首先必须根据主机是否运行特定的Docker镜像来找到该主机。他使用一个shell任务来执行docker ps | grep my-filter
命令,以查看主机是否有名为”my-filter”的Docker容器。一旦在特定主机上找到该容器,他希望在该主机上执行其余的任务。
解决方案
请注意以下操作注意版本差异及修改前做好备份。
方案1
为了在找到第一个主机后跳过其他主机,可以使用block
和when
语句来实现。以下是一个示例playbook:
- hosts: test
tasks:
- block:
- shell: docker ps | grep my-filter
register: result
delegate_to: "{{ item }}"
ignore_errors: true
when: (result|default({})).rc == 0
- set_fact:
my_host: "{{ result.results|json_query('[?rc == `0`].item')|first }}"
- debug:
var: my_host
- add_host:
name: "{{ my_host }}"
groups: my_group
run_once: true
- hosts: my_group
tasks:
- debug:
var: inventory_hostname
在上面的示例中,我们首先在test
组的所有主机上执行一个shell命令来检查是否有名为”my-filter”的Docker容器。如果命令返回0(即找到了容器),我们将该主机添加到my_group
组中。然后,我们在my_group
组的主机上执行其他任务。
请注意,delegate_to
参数用于将任务委派给特定的主机,以便在该主机上执行命令。ignore_errors
参数用于忽略命令执行的错误,以便在找到容器的主机上继续执行任务。
方案2
另一种方法是使用with_first_found
循环来找到第一个满足条件的主机,并将其添加到一个新的组中。以下是一个示例playbook:
- hosts: test
tasks:
- set_fact:
my_host: "{{ item }}"
with_first_found:
- command: docker ps | grep my-filter
delegate_to: "{{ item }}"
ignore_errors: true
run_once: true
- add_host:
name: "{{ my_host }}"
groups: my_group
run_once: true
- hosts: my_group
tasks:
- debug:
var: inventory_hostname
在上面的示例中,我们使用with_first_found
循环来执行一个命令来检查是否有名为”my-filter”的Docker容器。一旦找到满足条件的主机,我们将其添加到my_group
组中。然后,我们在my_group
组的主机上执行其他任务。
请注意,delegate_to
参数用于将命令委派给特定的主机,以便在该主机上执行命令。ignore_errors
参数用于忽略命令执行的错误,以便在找到容器的主机上继续执行任务。
以上是两种解决方案,你可以根据自己的需求选择其中一种。