构建您的清单

在没有清单的情况下运行剧本需要多个命令行标志。此外,对单个设备运行剧本与手动进行相同更改相比,效率提升并不大。充分利用 Ansible 潜力的下一步是使用清单文件,将受管理的节点组织成组,并包含诸如 ansible_network_os 和 SSH 用户之类的信息。功能齐全的清单文件可以充当您网络的真相来源。使用清单文件,单个剧本可以使用单个命令维护数百个网络设备。本页将逐步向您展示如何构建清单文件。

基本清单

首先,按逻辑对您的清单进行分组。最佳做法是按用途 (应用程序、堆栈或微服务)、位置 (数据中心或区域) 和时间 (开发阶段) 对服务器和网络设备进行分组。

  • **用途**: db、web、leaf、spine

  • **位置**: east、west、floor_19、building_A

  • **时间**: dev、test、staging、prod

在您的组名中避免使用空格、连字符和前导数字 (使用 floor_19,而不是 19th_floor)。组名区分大小写。

这个小型示例数据中心说明了基本组结构。您可以使用 [metagroupname:children] 语法对组进行分组,并将组列为元组的成员。这里,组 network 包含所有叶子和所有脊柱;组 datacenter 包含所有网络设备以及所有 Web 服务器。

---

leafs:
  hosts:
    leaf01:
      ansible_host: 10.16.10.11
    leaf02:
      ansible_host: 10.16.10.12

spines:
  hosts:
    spine01:
      ansible_host: 10.16.10.13
    spine02:
      ansible_host: 10.16.10.14

network:
  children:
    leafs:
    spines:

webservers:
  hosts:
    webserver01:
      ansible_host: 10.16.10.15
    webserver02:
      ansible_host: 10.16.10.16

datacenter:
  children:
    network:
    webservers:

您也可以使用 INI 格式创建相同的清单。

[leafs]
leaf01
leaf02

[spines]
spine01
spine02

[network:children]
leafs
spines

[webservers]
webserver01
webserver02

[datacenter:children]
network
webservers

将变量添加到清单

接下来,您可以为清单中的许多变量设置值,这些变量在第一个 Ansible 命令中需要,这样您就可以在 ansible-playbook 命令中跳过它们。在本例中,清单包括每个网络设备的 IP、操作系统和 SSH 用户。如果您的网络设备只能通过 IP 访问,则必须将 IP 添加到清单文件。如果您使用主机名访问网络设备,则不需要 IP。

---

leafs:
  hosts:
    leaf01:
      ansible_host: 10.16.10.11
      ansible_network_os: vyos.vyos.vyos
      ansible_user: my_vyos_user
    leaf02:
      ansible_host: 10.16.10.12
      ansible_network_os: vyos.vyos.vyos
      ansible_user: my_vyos_user

spines:
  hosts:
    spine01:
      ansible_host: 10.16.10.13
      ansible_network_os: vyos.vyos.vyos
      ansible_user: my_vyos_user
    spine02:
      ansible_host: 10.16.10.14
      ansible_network_os: vyos.vyos.vyos
      ansible_user: my_vyos_user

network:
  children:
    leafs:
    spines:

webservers:
  hosts:
    webserver01:
      ansible_host: 10.16.10.15
      ansible_user: my_server_user
    webserver02:
      ansible_host: 10.16.10.16
      ansible_user: my_server_user

datacenter:
  children:
    network:
    webservers:

在清单中对变量进行分组

当组中的设备共享相同的变量值 (例如操作系统或 SSH 用户) 时,您可以将这些值合并到组变量中,以减少重复并简化维护。

---

leafs:
  hosts:
    leaf01:
      ansible_host: 10.16.10.11
    leaf02:
      ansible_host: 10.16.10.12
  vars:
    ansible_network_os: vyos.vyos.vyos
    ansible_user: my_vyos_user

spines:
  hosts:
    spine01:
      ansible_host: 10.16.10.13
    spine02:
      ansible_host: 10.16.10.14
  vars:
    ansible_network_os: vyos.vyos.vyos
    ansible_user: my_vyos_user

network:
  children:
    leafs:
    spines:

webservers:
  hosts:
    webserver01:
      ansible_host: 10.16.10.15
    webserver02:
      ansible_host: 10.16.10.16
  vars:
    ansible_user: my_server_user

datacenter:
  children:
    network:
    webservers:

变量语法

变量值的语法在清单、剧本和 group_vars 文件中有所不同,后者将在下面介绍。即使剧本和 group_vars 文件都使用 YAML 编写,您在每个文件中使用变量的方式也不同。

  • 在 ini 样式的清单文件中,您**必须**使用 key=value 语法来表示变量值:ansible_network_os=vyos.vyos.vyos

  • 在任何扩展名为 .yml.yaml 的文件中 (包括剧本和 group_vars 文件),您**必须**使用 YAML 语法:key: value

  • group_vars 文件中,请使用完整的 key 名称:ansible_network_os: vyos.vyos.vyos

  • 在剧本中,请使用简短形式的 key 名称,该名称会删除 ansible 前缀:network_os: vyos.vyos.vyos

按平台对清单进行分组

随着清单的增长,您可能希望按平台对设备进行分组。这使您可以轻松地为该平台上的所有设备指定特定于平台的变量。

---

leafs:
  hosts:
    leaf01:
      ansible_host: 10.16.10.11
    leaf02:
      ansible_host: 10.16.10.12

spines:
  hosts:
    spine01:
      ansible_host: 10.16.10.13
    spine02:
      ansible_host: 10.16.10.14

network:
  children:
    leafs:
    spines:
  vars:
    ansible_connection: ansible.netcommon.network_cli
    ansible_network_os: vyos.vyos.vyos
    ansible_user: my_vyos_user

webservers:
  hosts:
    webserver01:
      ansible_host: 10.16.10.15
    webserver02:
      ansible_host: 10.16.10.16
  vars:
    ansible_user: my_server_user

datacenter:
  children:
    network:
    webservers:

使用此设置,您只需要使用两个标志就可以运行 first_playbook.yml

ansible-playbook -i inventory.yml -k first_playbook.yml

使用 -k 标志,您会在提示符下提供 SSH 密码。或者,您可以使用 ansible-vault 将 SSH 和其他机密信息以及密码安全地存储在您的 group_vars 文件中。有关详细信息,请参阅 使用 ansible-vault 保护敏感变量

验证清单

您可以使用 ansible-inventory CLI 命令显示 Ansible 看到的清单。

$ ansible-inventory -i test.yml --list
  {
    "_meta": {
        "hostvars": {
            "leaf01": {
                "ansible_connection": "ansible.netcommon.network_cli",
                "ansible_host": "10.16.10.11",
                "ansible_network_os": "vyos.vyos.vyos",
                "ansible_user": "my_vyos_user"
            },
            "leaf02": {
                "ansible_connection": "ansible.netcommon.network_cli",
                "ansible_host": "10.16.10.12",
                "ansible_network_os": "vyos.vyos.vyos",
                "ansible_user": "my_vyos_user"
            },
            "spine01": {
                "ansible_connection": "ansible.netcommon.network_cli",
                "ansible_host": "10.16.10.13",
                "ansible_network_os": "vyos.vyos.vyos",
                "ansible_user": "my_vyos_user"
            },
            "spine02": {
                "ansible_connection": "ansible.netcommon.network_cli",
                "ansible_host": "10.16.10.14",
                "ansible_network_os": "vyos.vyos.vyos",
                "ansible_user": "my_vyos_user"
            },
            "webserver01": {
                "ansible_host": "10.16.10.15",
                "ansible_user": "my_server_user"
            },
            "webserver02": {
                "ansible_host": "10.16.10.16",
                "ansible_user": "my_server_user"
            }
        }
    },
    "all": {
        "children": [
            "datacenter",
            "ungrouped"
        ]
    },
    "datacenter": {
        "children": [
            "network",
            "webservers"
        ]
    },
    "leafs": {
        "hosts": [
            "leaf01",
            "leaf02"
        ]
    },
    "network": {
        "children": [
            "leafs",
            "spines"
        ]
    },
    "spines": {
        "hosts": [
            "spine01",
            "spine02"
        ]
    },
    "webservers": {
        "hosts": [
            "webserver01",
            "webserver02"
        ]
    }
  }

使用 ansible-vault 保护敏感变量

命令 ansible-vault 为文件和/或单个变量 (如密码) 提供加密。本教程将向您展示如何加密单个 SSH 密码。您可以使用以下命令来加密其他敏感信息,例如数据库密码、特权升级密码等。

首先,您必须为 ansible-vault 本身创建一个密码。它用作加密密钥,有了它,您可以在整个 Ansible 项目中加密数十个不同的密码。在运行剧本时,您可以使用单个密码 (ansible-vault 密码) 访问所有这些机密信息 (加密的值)。以下是一个简单的示例。

  1. 创建一个文件,并将您的 ansible-vault 密码写入其中

echo "my-ansible-vault-pw" > ~/my-ansible-vault-pw-file
  1. 创建 VyOS 网络设备的加密 SSH 密码,从刚刚创建的文件中提取 ansible-vault 密码

ansible-vault encrypt_string --vault-id my_user@~/my-ansible-vault-pw-file 'VyOS_SSH_password' --name 'ansible_password'

如果您更愿意键入 ansible-vault 密码,而不是将其存储在文件中,则可以请求提示

ansible-vault encrypt_string --vault-id my_user@prompt 'VyOS_SSH_password' --name 'ansible_password'

然后键入 my_user 的 vault 密码。

标志 --vault-id 允许为不同的用户或不同的访问级别使用不同的 vault 密码。输出包括来自 ansible-vault 命令的用户名 my_user,并使用 YAML 语法 key: value

ansible_password: !vault |
       $ANSIBLE_VAULT;1.2;AES256;my_user
       66386134653765386232383236303063623663343437643766386435663632343266393064373933
       3661666132363339303639353538316662616638356631650a316338316663666439383138353032
       63393934343937373637306162366265383461316334383132626462656463363630613832313562
       3837646266663835640a313164343535316666653031353763613037656362613535633538386539
       65656439626166666363323435613131643066353762333232326232323565376635
Encryption successful

这是一个使用 YAML 清单摘录的示例,因为 INI 格式不支持内联 vault

...

vyos: # this is a group in yaml inventory, but you can also do under a host
  vars:
    ansible_connection: ansible.netcommon.network_cli
    ansible_network_os: vyos.vyos.vyos
    ansible_user: my_vyos_user
    ansible_password:  !vault |
         $ANSIBLE_VAULT;1.2;AES256;my_user
         66386134653765386232383236303063623663343437643766386435663632343266393064373933
         3661666132363339303639353538316662616638356631650a316338316663666439383138353032
         63393934343937373637306162366265383461316334383132626462656463363630613832313562
         3837646266663835640a313164343535316666653031353763613037656362613535633538386539
         65656439626166666363323435613131643066353762333232326232323565376635

 ...

要使用内联 vault 变量和 INI 清单,您需要将其存储在 YAML 格式的“vars”文件中,它可以位于 host_vars/ 或 group_vars/ 中,以便自动获取或通过 vars_filesinclude_vars 从剧本中引用。

要使用此设置运行剧本,请删除 -k 标志,并添加您的 vault-id 标志

ansible-playbook -i inventory --vault-id my_user@~/my-ansible-vault-pw-file first_playbook.yml

或者使用提示而不是 vault 密码文件

ansible-playbook -i inventory --vault-id my_user@prompt first_playbook.yml

要查看原始值,您可以使用调试模块。请注意,如果您的 YAML 文件定义了 ansible_connection 变量(正如我们在示例中所使用的那样),它将在您执行以下命令时生效。为了防止这种情况,请在没有 ansible_connection 变量的情况下复制该文件。

$ cat vyos.yml | grep -v ansible_connection >> vyos_no_connection.yml

ansible localhost -m debug -a var="ansible_password" -e "@vyos_no_connection.yml" --ask-vault-pass
Vault password:

localhost | SUCCESS => {
    "ansible_password": "VyOS_SSH_password"
}

警告

Vault 内容只能使用用于加密它的密码解密。如果您想停止使用一个密码并迁移到一个新的密码,您可以使用 ansible-vault rekey myfile 更新和重新加密现有的 Vault 内容,然后提供旧密码和新密码。使用旧密码加密的 Vault 内容副本仍然可以使用旧密码解密。

有关构建清单文件的更多详细信息,请参见 清单简介;有关 ansible-vault 的更多详细信息,请参见 完整的 Ansible Vault 文档.

现在您已经了解了命令、剧本和清单的基础知识,是时候探索一些更复杂的 Ansible 网络示例了。