Ansible如何有条件地委托本地或远程执行?

4

我有一些 ansible playbooks,有时候在本地上下文中很有意义,否则就会在远程执行。为了做到这一点,我使用 delegate_to 指令,但这也意味着我必须将所有任务都复制一遍:

---
- hosts: all
  gather_facts: no

  tasks:

  - name: Local command
    command: hostname
    register: target_host
    when: vhost is undefined
    delegate_to: 127.0.0.1

# ---    

  - name: Remote command
    command: hostname
    register: target_host
    when: vhost is defined

本地执行:

$ ansible-playbook -i inv.d/test.ini play.d/delegate.yml

PLAY [all] ******************************************************************** 

TASK: [Local command] ********************************************************* 
changed: [new-server -> 127.0.0.1]

TASK: [Remote command] ******************************************************** 
skipping: [new-server]

PLAY RECAP ******************************************************************** 
new-server                 : ok=1    changed=1    unreachable=0    failed=0

远程执行:

$ ansible-playbook -i inv.d/test.ini play.d/delegate.yml -e vhost=y

PLAY [all] ******************************************************************** 

TASK: [Local command] ********************************************************* 
skipping: [new-server]

TASK: [Remote command] ******************************************************** 
changed: [new-server]

PLAY RECAP ******************************************************************** 
new-server                 : ok=1    changed=1    unreachable=0    failed=0

有没有更聪明的方法告诉 ansible 何时回退到本地环境?目前我正在使用 ansible==1.9.2

1个回答

9

任务执行的位置不应该在任务中定义。当任务需要始终在本地或相关机器上(例如数据库主机或路由器)运行时,委托是有意义的,而playbook本身和因此大部分任务在playbook级别上定义的主机上运行。

但是,如果您的目标是在本地或一组远程主机上运行整个playbook,则应使用不同的清单文件或组。

如果您有两个不同的清单文件,在其中一个文件中定义localhost,在另一个文件中定义所有远程主机,则在调用ansible时应用您想要的清单,-i inv.d/local-i inv.d/remote

或者将所有内容放在一个清单中,并动态传递组。在您的清单中,您定义了两个组:

[local]
127.0.0.1

[remote]
host-1
host-2
host-N

然后将该组作为额外变量传递给ansible:-e "run=local"-e "run=remote"

在您的playbook中,您可以动态地设置hosts:

---
- hosts: "{{ run | mandatory }}"
  gather_facts: no
  tasks:
    ...

在您的示例中,似乎您只使用每个vhost额外变量定义了一个单独的远程主机。在这种情况下,最好的选择似乎是在hosts部分重复使用此变量,并将默认值设置为localhost。
---
- hosts: "{{ vhost | default('127.0.0.1') }}"
  gather_facts: no
  tasks:
    ...

如果定义了vhost,整个Playbook将在该主机上执行。如果未定义,则Playbook在本地运行。

最后,您仍然可以在单个任务中使用delegate_to选项,如下所示:

- name: Local AND remote command
  command: hostname
  delegate_to: "{{ '127.0.0.1' if vhost is undefined else omit }}"

omit是一个特殊变量,可以让Ansible忽略选项,就像它没有被定义一样。


这个是否有效:connection: "{{ 'ansible_host' | default('local') }}"文档看起来有些模棱两可,ansible_host被定义为“要连接的Docker容器的名称”。我愿意相信这只是文档中的一个错误。 - NarūnasK
我会在清单文件中设置连接,就像本节底部所描述的那样:http://docs.ansible.com/ansible/intro_inventory.html#hosts-and-groups - udondan
localhost ansible_connection=local - udondan
实际上我相信我需要的是这个:connection: "{{ omit | default('local') }}" - NarūnasK
只需将其设置为主机变量。connection是一种行为参数,不需要应用于playbook或任务。一旦在清单或主机变量中定义,Ansible将根据连接到的主机选择正确的连接类型。http://docs.ansible.com/ansible/intro_inventory.html#list-of-behavioral-inventory-parameters - udondan
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接