Ansible:如何使用多值数据列表作为清单并传递给目标主机

Ansible: How to use multi-value data list as inventory and pass to target host

我的主机清单的来源来自一个输出成对值的内部工具,例如,这里有六个观察值,我目前有 160 个观察值:

   servername1  processname1
   servername1  processname2
   servername1  processname3
   servername2  processname1
   servername3  processname1
   servername4  processname1

所以第 1 列是我的目标主机列表(我的清单)。 Column2 是唯一的 processname 值,专门分配给 servername 的值。通常会出现相同的服务器。有些服务器只有一个进程名,其他服务器可能有 2 到 N 个。这意味着我的目标主机可能会重复一个唯一的进程名列表。我想使用此输出对列表中的两个动态清单,并且我需要将每个观察值的两个值关联并分配给变量。我不是绝对需要使用动态库存,我只需要一个解决方案。我还需要通过命令传递给目标主机和 {{ processname# }} 中的值:或 shell: modules。 (这个是唯一的,没有与此需求相关的模块)

如果需要,我有办法过滤这些数据并以 JSON 格式或 YAML 输出,为每个主机制作一个单独的 YML 文件。虽然我更喜欢动态处理这些;预处理列表是可以接受的。

因为 ansible-playbook 需要一些已知的主机清单列表,所以在我开始播放时,我无法理解如何从我的动态输出中创建这个列表。

到目前为止我所做的:我尝试阅读并尝试将这些对设置为 /etc/ansible/hosts/host_vars/servername#.yml 文件中的内容。这非常难看,因为我必须将数据输出预处理为 YML 格式。但它没有给我一个主机列表以供在我的剧本中参考。因此,虽然看起来 hostvar 是合乎逻辑的选择,但我无法理解它。

我需要的:

- The suggested format of the data?  JSON? YAML? Other? (if I cannot read it in dynamically.
- Is putting this in host_vars correct?
- Last night I saw another answer using set_fact, would that help?

感谢您的任何见解。我现在已经使用 Ansible 3.5 周了!我使用静态和动态库存做得很好,但这让我很困惑,因为库存列表不明显,给出匹配对的格式。

注意:许多人建议使用 host_vars,但在我看来,这是为主机名、相关端口和代理值保留的。我可能是错的。

=========================================== ======================

更新:感谢您在正确方向上的帮助。 我已经更新了我们的清单脚本以在 JSON 中输出主机列表。 第一个新选项是输出 JSON 中的主机。 例子: {"my_host":["servername1","servername2",]}

将其称为动态库存脚本,效果很好!

ansible all -m ping 服务器名1 |成功=> { "changed":错误, "ping": "pong" } 服务器名2 |成功=> { "changed":错误, "ping": "pong" }

下一步:清单脚本的第二个新选项是添加一个新开关以输入主机名。这部分仍然让我感到困惑。这是输出: showInv --host=servername1

{"servername1":["processname1","processname2","processname3",]}

我遗漏的最后一部分是如何从我的剧本中调用带有特定“--host={{ my_host }} 的清单脚本。

看来我需要找到现有主机名的变量并将其作为开关选项传递回清单脚本“--host=”

您将需要开发一个动态清单脚本,它将第一列作为主机名,第二列作为该主机的变量。

请在link下面找到我写在php中的动态清单 https://github.com/walden-it/ansible-ij/blob/master/inventory.php

查看函数 get_vars() 和 get_hosts() 以了解如何填充数组。

如果您需要它,这里是该脚本正在查看的数据库的转储: https://github.com/walden-it/ansible-ij/blob/master/ansible.sql

然后你只需在 ansible 运行 中用 -i inventory 指定它,或者将它作为 inventory_file 添加到 ansible.cfg

你说你对动态库存没问题。自己做。

这里是the docs.

您需要制作一个脚本来做两件事:

  • 当使用 --list 执行时,处理您的文件并将此 JSON 打印到标准输出:

    { "myhosts": ["servername1", "servername2", "servername3"] }
    
  • 当使用 --host servername1 执行时,将此 JSON 打印到标准输出:

    { "myprocesses": ["processname1", "processname2"] }
    

因此,对于 --list,您应该提供唯一的主机列表。在我的示例中,他们属于 myhosts 组。

对于 --host <hostname>,您应该提供该主机 (<hostname>) 的主机变量列表字典。在我的示例中,有一个列表变量 myprocesses,其中包含该主机的所有进程。

然后调用 ansible-playbook -i my_inv_script myplaybook.yml.

示例剧本:

---
- hosts: myhosts
  tasks:
    - debug:
        msg: "Process name is {{ item }}"
      with_items: "{{ myprocesses }}"

此剧本将遍历动态清单中的所有主机,并打印每个主机的所有进程。

结束。在 Konstantin 的建议的帮助下,我现在有了一个工作游戏。不是很明显的是,Ansible 正在幕后做一些 "magic"。我必须修改我的清单脚本,它生成我的动态清单以接受“--list”开关选项和“--host hostname”选项。

完成此操作后,我可以 运行 带有 -i listInv 的剧本,Ansible 在内部将此脚本称为 listInv --list,它会生成我的动态清单。然后它循环到 with_items,并在内部将脚本调用为 listInv --host {{ items }} 并输出匹配的进程名称。

此外,我的脚本生成的 JSON 输出必须生成 "group"(第一个)字段 "myprocess"。最初,我将其设置为 "my_process",但失败了。删除下划线,修复了那个错误。

现在一切正常。这是一个很好的学习示例,但它仍然很神奇。

剧本如下所示:

- hosts: all
  gather_facts: no
  connection: local

  tasks:
    - debug:
        msg: "Process name is {{ item }}"
      with_items:  "{{ myprocess }}"