【问题标题】:Specifying multiple groups as hosts from different inventories in an Ansible playbook在 Ansible playbook 中将多个组指定为来自不同清单的主机
【发布时间】:2023-03-04 08:14:05
【问题描述】:

当组位于不同的清单中时,我正在寻找一种方法来将多个组指定为 Ansible 剧本中的主机(这类似于 this question,但不同,因为该问题假设一个清单)。

假设我有一本名为 change_things.yml 的剧本。有时我想更改development,有时qa,有时production等中的内容:

ansible-playbook -i development -i production change_things.yml.

假设有单独的清单大致如下所示:

# development inventory

[development]
10.0.0.1
10.0.0.2

如果未明确指定 hosts,上述 playbook 将无法运行。

我有几个问题:

  1. 使用hosts: all 似乎有害。如果用户忘记显式声明清单,我会想象 Ansible 继承自 /etc/ansible/hosts 中的任何内容。
  2. 硬编码主机组 (hosts: development:production) 是不可取的,因为我将来可能想运行类似 ansible-playbook -i development -i qa change_things.yml 的东西。

我正在寻找一种方法来维护单独的主机清单,但要以这样的方式创建剧本,以便它们可以针对主机组的多个组合执行。我不知道如何告诉 Ansible“使用这些清单中的这些组”。

【问题讨论】:

  • 隔离开发和生产。身体上!通过版本系统共享通用工件(剧本、角色、库存、变量...)。
  • @VladimirBotka 这只是一个人为的例子来说明我绝对想强制执行这种隔离 - 你可以将它们视为red 服务器和green 服务器。我不想维护多个具有不同默认主机但内容完全相同的剧本。 Ansible 的版本系统是什么?

标签: ansible


【解决方案1】:

问:告诉 Ansible '使用这些清单中的这些组'

A:在第一次播放时动态创建一个新的主机组,然后使用它。例如

shell> cat pb.yml
- hosts: localhost
  tasks:
    - add_host:
        name: "{{ item }}"
        groups: my_group
      loop: "{{ my_groups|from_yaml|map('extract', groups)|flatten }}"

- hosts: my_group
  tasks:
    - debug:
        var: inventory_hostname

鉴于库存

shell> cat hosts_prod
[prod]
prod1
prod2
prod3

shell> cat hosts_qa
[qaA]
qa1
qa2

[qaB]
qa3

shell> cat hosts_devel 
[develA]
devel1
devel2

[develB]
devel3

命令

ansible-playbook pb.yml -i hosts_prod -i hosts_qa -i hosts_devel -e "my_groups=[develA,qaB]"

给予(删节)

PLAY [my_group] **********************************************

TASK [debug] **************************************************
ok: [devel2] => 
  inventory_hostname: devel2
ok: [devel1] => 
  inventory_hostname: devel1
ok: [qa3] => 
  inventory_hostname: qa3

在命令行上定义清单和 my_groups 的任意组合。

【讨论】:

  • 谢谢 - 这是一个非常有趣的方法。
【解决方案2】:

如果您确实将不同的服务器分隔在不同的库存中,那么您可以使用常见的名称为组命名,例如 servers

然后您的库存将随之而来

## this is development inventory 
[servers]
node1.dev.example.org
node2.dev.example.org
## this is qa inventory 
[servers]
node1.qa.example.org
node2.qa.example.org

所以你的剧本将从

开始
- hosts: servers

你可以运行它

ansible-playbook -i development -i qa playbook.yml

另一种方法,但我不得不说,我觉得这是一个过于复杂的场景,是使用 ansible_inventory_sources 特殊变量,然后将清单文件的名称与主机组对齐:

## this is development inventory 
[development]
node1.dev.example.org
node2.dev.example.org
## this is qa inventory 
[qa]
node1.qa.example.org
node2.qa.example.org

所以剧本会有一个可怕的:

- hosts: "{{ ansible_inventory_sources | map('basename') | map('regex_replace', '^([^\\.]*).*', '\\1') | list | join(':') }}"

在哪里

  • basename 会得到文件名,例如inventory.yml
  • regex_replace,在您的用例中并不是真正需要的,而是由@Zeitounator 从this answer 借用的,如果您有库存文件扩展名,则允许删除任何文件扩展名,例如development.yml。由于我的库存确实有 .yml 扩展名,因此值得注意。
  • 然后该列表是 join'ed 与冒号 (:) 以回退到您的其他问题

然后运行它,再次使用

ansible-playbook -i development -i qa playbook.yml

将生成主机组模式development:qa


这是一个演示(为了演示,使用debug,但是,因为变量也可以在host 中使用,所以这是一样的):

- hosts: localhost
  gather_facts: no
      
  tasks:
    - debug:
        msg: "{{ ansible_inventory_sources | map('basename') | map('regex_replace', '^([^\\.]*).*', '\\1') | list | join(':') }}"

回顾一下:

PLAY [localhost] **************************************************************************************************

TASK [debug] ******************************************************************************************************
ok: [localhost] => {
    "msg": "developement:qa"
}

PLAY RECAP ********************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

【讨论】:

  • 非常感谢! [servers] 的想法非常优雅。附带说明一下,我实际上最终完全走了一条单独的路线,只是在运行时提示主机/组。鉴于隔离主机/库存的必要性,我认为提示可以作为额外的故障保护。
猜你喜欢
  • 1970-01-01
  • 2017-09-08
  • 2015-11-17
  • 1970-01-01
  • 2020-05-22
  • 2019-11-11
  • 1970-01-01
  • 2018-12-08
  • 2017-06-04
相关资源
最近更新 更多