我们希望听到您的意见!帮助我们深入了解 Ansible 生态系统现状。
参加 2024 年 Ansible 项目调查

Playbook 创建者入门 Ansible.utils 集合

第 2 部分:使用 ansible.utils 集合进行操作状态评估的用例

ansible.utils中,有各种插件可用于网络设备的操作状态评估。我在这个两部分博客系列的第一部分概述了ansible.utils集合。如果您还没有回顾第一部分,我建议您这样做,因为我将在第二部分博客中在此信息的基础上进行构建。我们将看到ansible.utils集合如何在操作状态评估中作为用例示例发挥作用。

一般来说,状态评估工作流程包含以下步骤

  • 检索(真相来源)

    • 从远程主机收集当前操作状态。
    • 将其转换为规范化的结构化数据。结构化数据可以是 json、yaml 格式或任何其他格式。
    • 存储在清单变量中。
  • 验证

    • 以基于标准的格式定义所需的状态标准,例如,在 json 模式格式中定义。
    • 在运行时检索操作状态。
    • 根据预定义的标准验证当前状态数据,以识别是否存在任何偏差。
  • 修复

    • 实施必要的配置更改以纠正漂移。
    • 将更改报告为审计跟踪。

ansible.utils 集合如何在此工作流程中提供帮助?

ansible.utils集合使检索和解析数据变得更容易,以便随后可以从结构化格式中进一步评估。

使用 Ansible.utils.cli_parse 以结构化格式检索操作状态

此模块作为ansible.utils集合提供。它具有各种解析器,有助于解析 CLI 输出或文本输出。它可以与多个远程主机(如网络、Linux 或 windows.it)一起使用。它支持多个解析引擎,并且是可扩展的,这意味着您可以创建自己的解析引擎。它是一个运行命令、解析和设置事实的单一任务。

在 utils 集合可用之前,我们需要编写三个不同的任务来运行命令、解析命令的输出并设置事实。但是,由于cli_parse,我们只有一个任务将返回来自“show 命令”输出的结构化数据。

让我们看看ansible.utils.cli_parse任务的示例

  tasks:

  - name:  Run a command and parse results
    ansible.utils.cli_parse:
        command: show interfaces
        parser:
            name: ansible.utils.xxxx
            set_fact: interfaces

在此任务中,我们需要提供一个将在设备上执行的命令。解析器(它是cli_parse的子插件),plugin.set_fact将转换后的结构设置为 interfaces 键。然后,我们可以在我们的 playbook 中引用 interfaces 键。

上述任务将执行以下操作

  • 在设备上运行命令
  • 使用“xxxx”引擎解析
  • 使用默认模板文件夹
  • 将解析后的数据设置为事实
  • 将命令输出作为 stdout 返回

目前ansible.utils.cli_parse插件具有以下解析器

  • ansible.utils.textfsm:用于解析半格式化文本的 Python 模块
  • ansible.utils.ttp:基于模板的解析,低正则表达式使用,类似 jinja 的 DSL
  • ansible.netcommon.native:内部 jinja、正则表达式、yaml,无需额外的第三方库
  • ansible.netcommon.ntc_templates:作为 python 库打包的预定义 textfsm 模板
  • ansible.netcommon.pyats:Cisco 测试自动化和验证解决方案(11 个操作系统/2500 个解析器)
  • ansible.utils.from_xml:使用 xmltodict 将 XML 转换为 json

所有通用解析器都是ansible.utils集合的一部分,所有网络相关解析器都是ansible.netcommon集合的一部分。

使用 ansible.utils.validate 验证结构化数据并报告错误

Ansible.utils.validate模块是作为ansible.utils集合一部分提供的新模块,适用于所有平台。它具有可扩展的引擎支持,目前与 jsonschema 验证引擎一起使用,该引擎在底层使用 jsonschema python 库。它是一个单一任务,读取结构化数据并根据任务中提供的模型对其进行验证。如果数据根据模式有效或无效,此任务将报告成功或错误。

让我们看看ansible.utils.validate任务的示例

tasks:

- name:  Validate structured data
   ansible.utils.validate:
       data: "{{ input_data }}"
       criteria:
       - "{{ lookup('file', './criteria.json') | from_json }}"
       engine: ansible.utils.xxxx

在此任务中,我们需要提供应该是结构化数据的数据。标准是一系列标准。由于我们目前使用的是 jsonschema,因此我们以 json 格式提供标准。引擎是顶级验证插件的子插件。这里它是ansible.utils.jsonschema。同样,您可以编写自己的引擎,因为它具有可扩展性。

上述任务将执行以下操作

  • 读取输入 JSON 数据和数据标准(模式模式)
  • 使用“xxxx”引擎验证
  • 如果数据不符合模式标准,则返回错误列表

目前ansible.utils.validate插件支持以下验证引擎

  • ansible.utils.jsonschema:Python 模块,用于根据模式验证 json 数据。

现在让我们使用来自ansible.utils的上述插件来了解如何在实际场景中使用它们。在此示例中,我们将看到如何使用ansible.utils获取 BGP 操作状态数据,根据预定义的 json 模式对其进行验证,以及在检测到配置漂移时修复它。

对于这种情况,假设我们有三个正在运行 cisco ios xe 的 CSRv 路由器。它们彼此之间都是 BGP 邻居,并各自通告三个网络。

utils blog 2 image one

让我们检查与 BGP 相关的运行配置和操作状态数据。

utils blog 2 image two

让我们检查 CSRv1 节点。让我们执行命令show running-config | section bgp。如您所见,它配置了两个邻居,其中两个邻居具有相同的远程 AS,因此它们是 IBGP 邻居。这些邻居处于活动状态,并且在它们上启用了软重新配置入站。此节点还通告三个网络。

现在让我们执行命令show bgp summary

utils blog 2 image three

上面的屏幕截图告诉我们与其他两个节点建立的邻居关系以及当前节点从其他两个节点接收的 3 个前缀。

现在让我们使用路由表条目对其进行验证。让我们执行命令show ip route bgp

utils blog 2 image four

上面的屏幕截图显示了节点 1 的路由表条目。如您所见,此节点知道六条路由,下一跳是通告它们的相应 BGP 邻居。

同样,我们也配置了 CSRv2 和 CSRv3。

现在让我们检查我们在此示例中使用的 playbook,并详细说明步骤。

如果您想了解详细信息,请查看此代码

Playbook 分为两个部分

  • 收集事实并将它们存储在 yaml 文件中作为真相来源 (SOT)
  • 根据 SOT 验证结构化数据,并在检测到漂移时进行纠正

收集事实并将其存储在 yaml 文件中以供 SOT 使用

让我们检查facts.yaml的内容。

utils blog 2 image five

在第一个任务中,我们从目标设备收集 bgp_global 和 bgp_address_family 事实。在第二个任务中,我们将它们存储在 hostvars 目录下的平面文件中。这些文件将充当目标设备上 BGP 配置的 SOT(真相来源)。

让我们使用ansible-navigator run playbooks/facts.yaml命令运行上述 playbook。有关详细信息,请参阅ansible-navigator文档。

执行 playbook 后,这些数据是什么样子的?让我们检查playbooks/host_vars/csrv-1.yaml

utils blog 2 image six

根据 SOT 验证结构化数据,并在检测到漂移时进行纠正

在此步骤中,我们将检查我们拓扑中所有节点的 BGP 操作状态数据,然后确定它们是否按预期运行或是否存在任何配置漂移。

现在让我们看看playbooks/verify.yaml playbook,它将验证并纠正存在的漂移。

utils blog 2 image seven

在第一个任务中,我们使用了ansible.utils.cli_parse插件在目标设备上执行show ip route bgp命令,然后将此命令的输出传递给pyats 解析器

然后,pyats 解析器将输出转换为存储在 result 变量中的结构化数据。

在下一个任务中,我们将 result 变量中的值以及预定义的模式传递给ansible.utils.validate插件。然后,该插件使用 jsonschema 引擎将数据与模式或标准进行比较。每个节点都有一个模式文件,定义了它们从其他两个邻居接收的前缀范围。

正如我们从拓扑和 CLI 中看到的那样,这些节点应该从每个邻居节点接收六条路由(总共三条)。现在,这些前缀在模式中以模式的形式表示,以及其他属性,如 source_protocol、route_preferences、metric 和 active 状态。

模式还将 additional properties 设置为 false,并将属性的最小值和最大值定义为六。这确保了根据模式进行验证将始终告诉我们设备是否正在接收它们应该接收的精确路由集。

以下是节点 CSRv1 的模式文件示例。

utils-blog-eight

让我们进一步检查verify.yaml的任务

如果第二个任务中的模式验证失败,则 playbook 将进入 rescue 部分。在这里,我们使用 BGP 资源模块来强制执行我们之前保存在目标设备上的 yaml 文件中的 SOT。最终结果将是修复导致操作状态验证失败的任何配置漂移。

如果我们使用ansible-navigator run playbooks/verify.yaml命令执行 verify.yaml playbook,由于我们没有对任何目标设备进行更改,因此我们看到它们按预期工作并且模式验证通过。有关详细信息,请参阅ansible-navigator文档。

utils-blog-nine

让我们在所有设备上手动引入错误更改。然后,我们将再次运行相同的 playbook 并查看它的行为。让我们删除路由以进行错误更改它们正在通告。

utils-blog-ten

现在我们已经对所有路由器进行了更改。让我们再次使用ansible-navigator run playbooks/verify.yaml运行 playbook。

这次模式验证失败。执行了修复任务,并在所有三个节点上添加了缺少前缀的事实。让我们详细了解一下。

utils-blog-eleven

第一个任务,像往常一样,获取 show 命令的输出并将其转换为结构化数据。

第二个任务失败,因为模式验证失败并出现多个错误。数据与模式中定义的约束不匹配。这会导致修复任务一个接一个地执行。

修复任务完成后,配置 BGP 任务没有显示任何更改,因为我们没有对 BGP 全局属性进行任何更改。

第二个任务是 BGP 地址族检测漂移并重新配置缺少的前缀的地方。

正如我们在所有目标设备发送的命令中看到的,剧本将事实添加到已删除的路由中。

如果我们再次运行此剧本,它将是幂等的,并且不会报告任何更改,从而表明一切按预期工作。

在生产环境中,此剧本可以根据外部事件触发,也可以作为 Red Hat Ansible Automation Platform 的自动化控制器中的定期作业安排,以确保符合预期的运行状态。

要点与后续步骤

如上所示,ansible.utils 集合:

  • 使运行状态评估更容易,补充了 Ansible Automation Platform 的配置管理功能。
  • 充当收集整个清单的运行状态的单一入口点。
  • 提供了一种标准化的方法来定义和验证运行标准作为结构化数据模型。
  • 在自动化控制器中添加了运行状态评估步骤作为工作流模板,该模板可以触发其他事件,例如运行用于自动修复的剧本或向外部工具报告等。