将变量传递给主机的 Ansible playbook:使用双引号

Posted

技术标签:

【中文标题】将变量传递给主机的 Ansible playbook:使用双引号【英文标题】:Issue passing variable to Ansible playbook for hosts: with double quotes 【发布时间】:2018-10-01 22:26:37 【问题描述】:

我正在尝试编写一个启动角色剧本并将主机列表传递给它的剧本。 “主”剧本中有一些负载平衡逻辑,我不想在每个角色剧本中重复,也不能放入 site.yml。

inventory.yml


[webservers]
Web1
Web2
Web3
Web4

master.yml

---
- name: Split Inventory into Odd/Even
  hosts: all
  gather_facts: false

  tasks:

    - name: Set Group Odd
      set_fact:
        group_type: "odd"
      when: (inventory_hostname.split(".")[0])[-1] | int is odd

    - name: Set Group Even
      set_fact:
        group_type: "even"
      when: (inventory_hostname.split(".")[0])[-1] | int is even 

    - name: Make new groups "odd" or "even"
      group_by:
        key: " group_type "

- name: Perform Roles on Odd 

  include: webservers.yml hosts= groups['odd'] | join(' ')


- name: Perform Roles on Even 

  include: webservers.yml hosts= groups['even'] | join(' ')

webservers.yml


- name: Perform Tasks on Webservers
  hosts: webservers:&" hosts | replace('\"','')"
  roles:
    - pause

join(' ') 将主机列表扁平化为一个字符串,每个主机之间用空格分隔。当我运行 playbook 时,它会将主机列表传递给 webservers.yml,但是它会在开头和结尾添加双引号,导致 webservers.yml 什么都不做,因为没有主机匹配。我假设 replace('\"','') 会删除字符串周围的引号,但似乎并非如此。这是 webservers.yml 的示例输出:

[WARNING]: Could not match supplied host pattern, ignoring: Web4"

[WARNING]: Could not match supplied host pattern, ignoring: "Web2

有什么想法吗? hosts: 处理过滤的方式不同吗?

【问题讨论】:

我认为replace('\"','') 没有任何理由。没有工作完全正常。你从哪里得到"?您的库存是什么样的? 我不明白。 “负载均衡逻辑”是干什么用的? @techraf 清单看起来像 [webservers] Web1 Web2 Web3 Web4 ,没有替换传递给 webservers.yml 的额外变量“hosts”打印为“Web2 Web4”,所以当它尝试正如您在警告中看到的那样,为它评估为“Web2 和 Web4”的主机解析该字符串。我尝试替换以删除“Web2 Web4”周围的引号,但它不起作用。 @Jack 负载均衡逻辑是从负载均衡器中删除所有奇数框,在奇数上运行 ansible 任务,将它们放回负载均衡器,对偶数重复。我从上面的剧本中省略了实际的 LB 任务,以使问题更容易识别。 您生成了一个不带引号的字符串,并且不需要删除引号。您在问题中发布的代码可以正常工作(尽管replace('\"','') 是不必要的)。这段代码唯一的事情是:你会收到一个警告,因为你会为变量名hosts 使用保留关键字。或者您正在使用一些带有错误的过时 Ansible 版本。 【参考方案1】:

我觉得你用错了角色和戏剧。当您执行任务时,您不应更改执行此任务或角色的主机列表。基本上,只有 play(带有'hosts:...,tasks:...,roles:...'的东西)可以控制运行的位置。

很少有例外,例如你可以玩代表团等等。但是对于您的情况,任何尝试使用任务或角色来控制主机列表只会带来痛苦和仇恨(对自己,对 ansible 等)。

要做到这一点,只需在您的剧本中添加另一个剧本(剧本是剧本的列表)。

这是您的代码,稍作修改。

---
- name: Split Inventory into Odd/Even
  hosts: all
  gather_facts: false

  tasks:

    - name: Set Group Odd
      set_fact:
        group_type: "odd"
      when: (inventory_hostname.split(".")[0])[-1] | int is odd

    - name: Set Group Even
      set_fact:
        group_type: "even"
      when: (inventory_hostname.split(".")[0])[-1] | int is even 

    - name: Make new groups "odd" or "even"
      group_by:
        key: " group_type "


- name: Doing odd things
  hosts: odd
  gather_facts: false
  tasks:
   - name: Perform Roles
     include: webservers.yml


- name: Doing even things
  hosts: even
  gather_facts: false
  tasks:
   - name: Perform Roles
     include: webservers.yml

您可以看到,我刚刚将剧本分配给两个组(“奇数”和“偶数”)。动态组在剧本中保留在剧本之间,在这件事上它们与任何其他组没有什么不同。

附:不要使用 'include',使用 'import_tasks' (包括在新版本的 ansible 中是危险的,如果可以的话,避免使用它们。)。

【讨论】:

以上是关于将变量传递给主机的 Ansible playbook:使用双引号的主要内容,如果未能解决你的问题,请参考以下文章

Ansible playboos 实现上传文件创建crontab

将 Terraform 变量中的数字传递给 Ansible Playbook

ansible PlayBook

将主机环境变量传递给 dockerfile

Ansible:从JSON响应创建变量

ansible——playbook剧本