管理 Ansible YAML 库存文件中的“嵌套”组

lar*_*sks 3 ansible ansible-inventory

我正在管理多个集群,并且希望将多个清单文件合并到一个清单中,该清单实际上如下所示:

all:
  children:
    cluster_one:
      children:
        controller:
          hosts:
            host1:
            host2:
            host3:
        compute:
          hosts:
            host4:
            host5:
            host6:
    cluster_two:
      children:
        controller:
          hosts:
            host11:
            host12:
            host13:
Run Code Online (Sandbox Code Playgroud)

我期待这最终会像这样解析:

[cluster_one]
host1
host2
host3
host4
host5
host6

[cluster_two]
host11
host12
host13

[controller]
host1
host2
host3
host11
host12
host13

[compute]
host4
host5
host6
Run Code Online (Sandbox Code Playgroud)

通过这种结构,我将能够使用主机模式请求“cluster_one 中的控制器” cluster_one:&controller,或者如果我想要所有集群中的所有控制器,我可以只请求 controller. 方便的!

不幸的是,它实际上是这样解析的:

[cluster_one]
host1
host2
host3
host4
host5
host6

[cluster_two]
host11
host12
host13

[controller]
host1
host2
host3
host11
host12
host13

[compute]
host4
host5
host6

[cluster_one:children]
controller
compute

[cluster_two:children]
controller
Run Code Online (Sandbox Code Playgroud)

请注意底部的两个额外条目,它们使YAML 文件中的“父级”的子级成为controllercompute组的子级,而不是仅使它们的主机成为父级的成员。

例如,如果我运行ansible -i example.yml --list-hosts cluster_one,我会得到:

  hosts (9):
    host1
    host2
    host3
    host11
    host12
    host13
    host4
    host5
    host6
Run Code Online (Sandbox Code Playgroud)

这是出乎我意料的,让我感到难过。显然,我可以重组清单以使其正常工作(例如,通过使用此处显示的 INI 格式清单,或为类似的结构重新构建 YAML),但这些解决方案涉及多次列出每个主机,这意味着事情是可能的失去同步。

有没有一种方法可以构建清单,让我获得所需的分组,而无需显式列出多个组中的主机?

Zei*_*tor 5

使用库存插件建立最新@larsk 答案的输入constructed。原答案如下


如果您对集群组/子组保持相同的命名约定,则可以使用构建的插件进行更多的干燥,从而无需在组中引入额外的变量。

请注意,在库存目录中使用文件名约定也允许库存源的自然加载顺序,而无需修改ansible.cfg

给定以下最小inventories/cluster/cluster.yml静态库存源:

---
all:
  children:
    cluster_one:
      children:
        cluster_one_controller:
          hosts:
            host1:
            host2:
            host3:
        cluster_one_compute:
          hosts:
            host4:
            host5:
            host6:
    cluster_two:
      children:
        cluster_two_controller:
          hosts:
            host11:
            host12:
            host13:
Run Code Online (Sandbox Code Playgroud)

以及inventories/cluster/cluster_constructed.yml基于现有组名检测对应的动态库存源:

---
plugin: constructed
strict: false
groups:
  controller: group_names | select('match', '^.*_controller$') | length > 0
  compute: group_names | select('match', '^.*_compute$') | length > 0
Run Code Online (Sandbox Code Playgroud)

我们使用复合库存目录得到了预期的结果

$ ansible-inventory -i inventories/cluster --list
{
    "_meta": {
        "hostvars": {}
    },
    "all": {
        "children": [
            "cluster_one",
            "cluster_two",
            "compute",
            "controller",
            "ungrouped"
        ]
    },
    "cluster_one": {
        "children": [
            "cluster_one_compute",
            "cluster_one_controller"
        ]
    },
    "cluster_one_compute": {
        "hosts": [
            "host4",
            "host5",
            "host6"
        ]
    },
    "cluster_one_controller": {
        "hosts": [
            "host1",
            "host2",
            "host3"
        ]
    },
    "cluster_two": {
        "children": [
            "cluster_two_controller"
        ]
    },
    "cluster_two_controller": {
        "hosts": [
            "host11",
            "host12",
            "host13"
        ]
    },
    "compute": {
        "hosts": [
            "host4",
            "host5",
            "host6"
        ]
    },
    "controller": {
        "hosts": [
            "host1",
            "host11",
            "host12",
            "host13",
            "host2",
            "host3"
        ]
    }
}
Run Code Online (Sandbox Code Playgroud)

原答案


我对这让你感到难过@larks 深感抱歉。不幸的是,正如您刚刚经历的那样:

  • 该组的内容不取决于您定义它的位置,并且最终将合并所有主机/子定义。
  • 任何地方定义为子级的组将包含其他地方定义的所有主机。

我能想到的唯一一个最接近您的初始要求并尽可能尊重 DRY 原则的静态 yaml 库存定义是:

$ ansible-inventory -i inventories/cluster --list
{
    "_meta": {
        "hostvars": {}
    },
    "all": {
        "children": [
            "cluster_one",
            "cluster_two",
            "compute",
            "controller",
            "ungrouped"
        ]
    },
    "cluster_one": {
        "children": [
            "cluster_one_compute",
            "cluster_one_controller"
        ]
    },
    "cluster_one_compute": {
        "hosts": [
            "host4",
            "host5",
            "host6"
        ]
    },
    "cluster_one_controller": {
        "hosts": [
            "host1",
            "host2",
            "host3"
        ]
    },
    "cluster_two": {
        "children": [
            "cluster_two_controller"
        ]
    },
    "cluster_two_controller": {
        "hosts": [
            "host11",
            "host12",
            "host13"
        ]
    },
    "compute": {
        "hosts": [
            "host4",
            "host5",
            "host6"
        ]
    },
    "controller": {
        "hosts": [
            "host1",
            "host11",
            "host12",
            "host13",
            "host2",
            "host3"
        ]
    }
}
Run Code Online (Sandbox Code Playgroud)

这将允许您选择以下任何模式(非详尽列表):

  • 一个完整的集群,例如cluster_one
  • 集群的所有控制器,例如cluster_two_controllercluster_two:&controller
  • 跨集群的所有计算节点,例如compute
  • ...

希望这能帮助你照亮你的一天(或夜晚......)