问题描述
在使用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
参数用于忽略命令执行的错误,以便在找到容器的主机上继续执行任务。
以上是两种解决方案,你可以根据自己的需求选择其中一种。