Skip to content

Files

Latest commit

f87fb9e · Dec 29, 2021

History

History
841 lines (632 loc) · 34.2 KB

File metadata and controls

841 lines (632 loc) · 34.2 KB

六、使用 NAPALM 和 Ansible 管理多供应商网络

多厂商支持的网络自动化和可编程抽象层 ( NAPALM)顾名思义,是一个多厂商的 Python 库,旨在与不同厂商的设备进行交互,它提供了一种与所有这些设备进行交互的一致方法,与所使用的厂商设备无关。

在前几章中,我们已经看到了如何使用 Ansible 与不同的网络设备进行交互。但是,对于每个供应商的操作系统,我们必须使用不同的 Ansible 模块来支持特定的操作系统。此外,我们看到从每个供应商操作系统返回的数据完全不同。尽管为多供应商设备编写剧本仍然是可能的,但它需要使用多个不同的模块,我们需要处理这些设备返回的不同数据结构。这是 NAPALM 试图解决的主要问题。NAPALM 试图提供一个抽象和一致的应用编程接口来与多个供应商操作系统交互,而 NAPALM 从这些不同的供应商操作系统返回的数据是标准化和一致的。

NAPALM 按照这个节点支持的最常见的 API,以及社区广泛采用的 API,与各个设备进行交互。下图概述了 NAPALM 如何与最常见的网络设备交互,以及 NAPALM 中用于与这些设备上的应用编程接口交互的库:

由于 NAPALM 试图提供一种与网络设备交互的一致方法,因此它支持一组特定的供应商设备。NAPALM 还支持在这些设备上执行的最常见任务,例如设备配置、检索接口的操作状态、边界门协议 ( BGP )和链路层发现协议 ( LLDP )以及许多其他任务。有关支持的设备以及与这些设备交互时支持的方法的更多信息,请查看以下链接:https://napalm.readthedocs.io/en/latest/support/index.html

在本章中,我们将概述如何使用 NAPALM 和 Ansible 来自动化多供应商网络。我们将概述如何管理这些不同供应商操作系统的配置,以及如何从这些设备检索操作状态。我们将根据以下基本服务供应商网络的网络图示例进行说明:

下表概述了我们的示例拓扑中的设备及其各自的管理互联网协议 ( IPs ):

| 装置 | 角色 | 供应商 | 管理(MGMT)港 | MGMT IP | | mxp01 | 路由器 | Juniper vMX 14.1 | fxp0 | 172.20.1.2 | | mxp02 | 路由器 | Juniper vMX 14.1 | fxp0 | 172.20.1.3 | | mxpe01 | 对等路由器 | Juniper vMX 14.1 | fxp0 | 172.20.1.4 | | mxpe01 | 对等路由器 | Juniper vMX 17.1 | fxp0 | 172.20.1.5 | | xrpe03 | 对等路由器 | Cisco XRv 6.1.2 版 | Mgmt0/0/CPU0/0 | 172.20.1.6 |

本章涉及的主要配方如下表所示:

  • 安装 NAPALM 并与 Ansible 集成
  • 建立一个可靠的网络清单
  • 使用 ansible 连接和验证网络设备
  • 构建设备配置
  • 使用 NAPALM 在网络设备上部署配置
  • 用 NAPALM 收集设备事实
  • 使用 NAPALM 验证网络可达性
  • 用 NAPALM 验证和审计网络

技术要求

本章的代码文件可以在这里找到:https://github . com/packt publishing/Network-Automation-cook book/tree/master/ch6 _ NAPALM

本章将需要以下软件:

  • 运行 CentOS 7 的 Ansible 机器
  • Ansible 2.9
  • 运行 Junos OS 14.1R8 和 Junos OS 17.1R1 版本的 Juniper 虚拟 MX ( vMX )路由器
  • 运行 IOS XR 6.1.2 的思科 XRv 路由器

查看以下视频,了解《行动守则》: https://bit.ly/2Veox8j

安装 NAPALM 并与 Ansible 集成

在这个食谱中,我们概述了如何安装 NAPALM,并将其集成到 Ansible 中。该任务是强制性的,因为 NAPALM Ansible 模块不是 Ansible 默认附带的核心模块的一部分。因此,为了开始使用这些模块,我们需要安装 NAPALM 及其所有的 Ansible 模块。然后,我们需要通知 Ansible 在哪里找到它,并开始使用 NAPALM 团队为 Ansible 开发的特定模块。

准备好

机器上需要安装 Ansible 和 Python 3,还有python3-pip包,我们会用它来安装 NAPALM。

怎么做...

  1. 安装napalm-ansible Python 包,如下代码片段所示:
$ pip3 install napalm-ansible
  1. 运行napalm-ansible命令,如下代码块所示:
$ napalm-ansible
  1. 为了确保 Ansible 可以使用 NAPALM 模块,您必须将以下配置添加到 Ansible 配置文件中(ansible.cfg):
[defaults]
 library = /usr/local/lib/python3.6/site-packages/napalm_ansible/modules
 action_plugins = /usr/local/lib/python3.6/site-packages/napalm_ansible/plugins/action

更多关于 Ansible 配置文件的详细信息,请访问https://docs . ansi ble . com/ansi ble/latest/intro _ configuration . html

  1. 创建一个名为ch6_napalm的新文件夹,并创建ansible.cfg文件,更新如下代码块所示:
$ cat ansible.cfg
[defaults]
inventory=hosts
retry_files_enabled=False
gathering=explicit
host_key_checking=False
library = /usr/local/lib/python3.6/site-packages/napalm_ansible/modules
action_plugins = /usr/local/lib/python3.6/site-packages/napalm_ansible/plugins/action

它是如何工作的…

由于 NAPALM 包和相应的 NAPALM Ansible 模块不是默认情况下随 Ansible 一起运输和安装的核心模块的一部分,我们需要将其安装在系统上,以便开始使用 NAPALM Ansible 模块。NAPALM 团队已经发送了一个特定的 Python 包来安装 NAPALM 以及所有 Ansible 模块和所有依赖项,以便从 Ansible 内部开始使用 NAPALM。这个套餐是napalm-ansible。我们将使用pip3程序来安装这个包,因为我们使用的是 Python 3。

为了告诉 Ansible ansi ble 模块安装在哪里,我们需要将这些模块的路径输入 ansi ble。NAPALM 团队还提供了如何找到安装 NAPALM 模块的路径,以及如何通过napalm-ansible程序将其与 Ansible 集成的简单说明。我们执行napalm-ansible命令,该命令输出我们需要包含在ansible.cfg文件中的所需配置,以便 Ansible 可以找到我们将要使用的 NAPALM 模块。

我们用从napalm-ansible命令获得的输出更新ansible.cfg文件。然后,我们更新库和动作插件选项,告诉 Ansible 在搜索模块或动作插件时将这些文件夹包含在其路径中。在ansible.cfg文件中,我们包含了我们在前面章节中使用的常规配置。

建立一个可靠的网络清单

在本食谱中,我们将概述如何构建我们的 Ansible 库存,以描述本章中概述的示例服务供应商网络设置。为了告诉 Ansible 如何连接到被管理设备,建立 Ansible 清单是一个强制性步骤。对于 NAPALM,我们需要将网络中的不同节点分类到 NAPALM 支持的正确供应商类型中。

怎么做…

  1. 在新文件夹(ch6_napalm)中,我们创建一个hosts文件,内容如下:
$ cat hosts
[pe]
 mxpe01 ansible_host=172.20.1.3
 mxpe02 ansible_host=172.20.1.4
 xrpe03 ansible_host=172.20.1.5

[p]
 mxp01 ansible_host=172.20.1.2
 mxp02 ansible_host=172.20.1.6

[junos]
 mxpe01
 mxpe02
 mxp01
 mxp02

[iosxr]
 xrpe03
 [sp_core:children]
 pe
 p

它是如何工作的…

我们使用hosts文件构建了 Ansible 清单,并定义了多个组来划分我们的基础架构,如下所示:

  • 我们创建了PE组,它引用了拓扑中所有的多协议标签交换 ( MPLS ) 供应商边缘 ( PE )节点。
  • 我们创建了P组,它引用了拓扑中所有的 MPLS 供应商 ( P )节点。
  • 我们创建了junos组来引用拓扑中的所有 Juniper 设备。
  • 我们创建了iosxr组来引用所有运行 IOS-XR 的节点。

在使用 NAPALM 时,根据供应商或操作系统划分和定义组是最佳实践,因为我们使用这些组来指定 NAPALM 所需的参数,以识别远程管理节点的供应商,以及如何与该远程节点建立网络连接。在下一个配方中,我们将概述我们将如何使用这些组(junosiosxr),以及我们将包括哪些参数,以便 NAPALM 与远程管理的节点建立连接。

使用 ansible 连接和验证网络设备

在本食谱中,我们将概述如何使用 Ansible 连接到 Juniper 和 IOS-XR 节点,以便开始与设备交互。

准备好

为了遵循该配方,应根据之前的配方构建一个 Ansible 的库存文件。此外,必须配置 Ansible 控制机器和网络中所有设备之间的 IP 可达性。

怎么做…

  1. 在 Juniper 设备上,配置用户名和密码,如以下代码块所示:
system {
 login {
 user ansible {
 class super-user;
 authentication {
 encrypted-password "$1$mR940Z9C$ipX9sLKTRDeljQXvWFfJm1"; ## ansible123
 }
 }
 }
}
  1. 在思科 IOS-XR 设备上,配置用户名和密码,如以下代码块所示:
!
 username ansible
 group root-system
 password 7 14161C180506262E757A60 # ansible123
!
  1. 在 Juniper 设备上启用网络配置协议 ( 网络配置,如下所示:
system {
 services {
 netconf {
 ssh {
 port 830;
 }
 }
 }
}
  1. 在 IOS-XR 设备上,我们需要启用安全外壳 ( SSH )以及启用xml-agent,如下所示:
!
xml agent tty
iteration off
!
xml agent
!
ssh server v2
ssh server vrf default
  1. 在 Ansible 机器上,在ch6_napalm文件夹中创建group_vars目录,并创建junos.ymliosxr.yml文件,如下代码块所示:
$ cat group_vars/iosxr.yml
---
 ansible_network_os: junos
 ansible_connection: netconf

 $ cat group_vars/junos.yml
---
 ansible_network_os: iosxr
 ansible_connection: network_cli
  1. group_vars文件夹下,用以下登录详细信息创建all.yml文件:
$ cat group_vars/all.yml
ansible_user: ansible
 ansible_ssh_pass: ansible123

它是如何工作的…

NAPALM 为 NAPALM 支持的每一个供应商设备使用特定的运输 API。它使用这个应用编程接口来连接到设备,因此在我们的示例拓扑中,我们需要在 Juniper 设备上启用 NETCONF。对于思科 IOS-XR 设备,我们需要启用 SSH,以及在 IOS-XR 设备上启用 XML 代理。

必须在远程节点上配置 Ansible 控制机器上用于向设备进行身份验证的用户名/密码。我们在设备上执行所有这些步骤,以便为 NAPALM 与它们通信做好准备。

Using the legacy xml agent on the IOS-XR devices in production is not recommended and needs to be evaluated as per the Cisco documentation. For further details, refer to https://www.cisco.com/c/en/us/td/docs/routers/asr9000/software/asr9k_r5-3/sysman/command/reference/b-sysman-cr53xasr/b-sysman-cr53xasr_chapter_01010.html.

在 Ansible 机器上,我们为每个供应商设置ansible_connection参数(junipernetconfiosxrnetwork_cli,我们指定ansible_network_os参数来指定供应商操作系统。所有这些参数都是在junos.ymliosxr.yml中的group_vars层次结构下定义的,对应于我们在清单中定义的用于在供应商操作系统基础上对设备进行分组的组。最后,我们通过all.yml文件中的ansible_useransible_ssh_pass指定用户名和密码,因为我们使用同一个用户对 Juniper 和 Cisco 设备进行身份验证。

为了测试和验证这一点,我们可以使用 Ansible ping模块从 Ansible 控制机器与设备通信,如以下代码块所示:

$ ansible all -m ping
mxpe01 | SUCCESS => {
  "changed": false,
  "ping": "pong"
}
mxpe02 | SUCCESS => {
  "changed": false,
  "ping": "pong"
}
mxp02 | SUCCESS => {
  "changed": false,
  "ping": "pong"
}
mxp01 | SUCCESS => {
  "changed": false,
  "ping": "pong"
}
xrpe03 | SUCCESS => {
  "changed": false,
  "ping": "pong"
} 

构建设备配置

NAPALM 不提供声明性模块来配置被管理设备上的各种系统参数,比如接口的 BGP、服务质量 ( QoS )等等。但是,它提供了一个通用的应用编程接口来将基于文本的配置推送到所有设备,因此它要求设备的配置以文本格式呈现,以便推送所需的配置。在本食谱中,我们将为所有设备创建配置。这是我们将在下一个配方中使用 NAPALM 推送到设备上的配置。

准备好

作为该配方的先决条件,必须有一个 Ansible 的库存文件。

怎么做…

  1. 创建一个roles文件夹,在这个文件夹中,创建一个名为build_router_config的新角色,如下所示:
$ mkdir roles && mkdir roles/build_router_config
  1. 使用与我们在第 3 章中为 Juniper 设备开发的build_router_config角色完全相同的内容(Jinja2 模板和任务),使用 Ansible 在服务供应商中自动化 Juniper 设备,以生成设备的配置。目录布局应该如下面的代码块所示:
$ tree roles/build_router_config/

roles/build_router_config/
 ├── tasks
 │ ├── build_config_dir.yml
 │ ├── build_device_config.yml
 │ └── main.yml
 └── templates
 └── junos
 ├── bgp.j2
 ├── intf.j2
 ├── mgmt.j2
 ├── mpls.j2
 └── ospf.j2
  1. templates文件夹下创建一个名为iosxr的新文件夹,并用不同 IOS-XR 配置部分的 Jinja2 模板填充它,如以下代码块所示:
$ tree roles/build_router_config/templates/iosxr/
 roles/build_router_config/templates/iosxr/
 ├── bgp.j2
 ├── intf.j2
 ├── mgmt.j2
 ├── mpls.j2
 └── ospf.j2
  1. 用需要的数据更新group_vars/all.yml文件来描述我们的网络拓扑,如下面的代码块所示:
$ cat group_vars/all.yml
tmp_dir: ./tmp
config_dir: ./configs
p2p_ip:
< -- Output Omitted for brevity -->
  xrpe03:
    - {port: GigabitEthernet0/0/0/0, ip: 10.1.1.7 , peer: mxp01, pport: ge-0/0/2, peer_ip: 10.1.1.6}
    - {port: GigabitEthernet0/0/0/1, ip: 10.1.1.13 , peer: mxp02, pport: ge-0/0/2, peer_ip: 10.1.1.12}

lo_ip:
  mxp01: 10.100.1.254/32
  mxp02: 10.100.1.253/32
  mxpe01: 10.100.1.1/32
  mxpe02: 10.100.1.2/32
  xrpe03: 10.100.1.3/32
  1. host_vars目录中为每台主机创建一个特定的目录,并在每个目录中创建包含以下 BGP 对等内容的bgp.yml文件:
$ cat host_vars/xrpe03/bgp.yml
bgp_asn: 65400
bgp_peers:
  - local_as: 65400
    peer: 10.100.1.254
    remote_as: 65400
  1. 创建一个名为pb_napalm_net_build.yml的新剧本,利用build_router_config角色来生成设备配置,如以下代码块所示:
$ cat pb_napalm_net_build.yml
---
- name: " Generate and Deploy Configuration on All Devices"
 hosts: sp_core
 tasks:
 - name: Build Device Configuration
 import_role:
 name: build_router_config
 delegate_to: localhost
 tags: build

它是如何工作的…

在本食谱中,我们的主要目标是创建我们将在示例拓扑中的设备上部署的设备配置。我们使用的 Ansible 角色与我们在第 3 章中为 Juniper 设备生成配置时使用的角色相同,使用 Ansible 在服务供应商中自动化 Juniper 设备。对这个角色的唯一补充是,我们正在为 IOS XR 添加所需的 Jinja2 模板。

以下是对这些步骤的快速解释,作为快速回顾:

  • 通过 Ansible 变量对网络建模

我们描述了我们网络拓扑的不同方面,如对等 ( P2P )接口、环回接口、开放最短路径优先 ( OSPF )参数在group_vars/all.yml文件中的不同数据结构下。对于任何特定于主机的数据,我们使用host_vars目录来填充特定于特定节点的所有变量/参数,并且,在我们的例子中,我们对 BGP 数据使用这种方法来概述每个节点的bgp_peers变量。这为我们提供了填充 Jinja2 模板所需的所有数据,以便为示例网络中的每个设备生成最终配置。

  • 构建 Jinja2 模板

我们将所有的 Jinja2 模板放在我们角色内的templates文件夹中,并根据供应商操作系统对我们的 Jinja2 模板进行分段,每个模板都放在一个单独的文件夹中。接下来,我们为配置的每个部分创建一个 Jinja2 模板。以下代码片段概述了模板文件夹的目录结构:

templates/
 ├── iosxr
 │ ├── bgp.j2
 │ ├── intf.j2
 │ ├── mgmt.j2
 │ ├── mpls.j2
 │ └── ospf.j2
 └── junos
 ├── bgp.j2
 ├── intf.j2
 ├── ospf.j2
 ├── mgmt.j2
 └── mpls.j2

For a detailed explanation of the different Jinja2 templates used in this recipe and how they use the defined Ansible variables to generate the final configuration, please refer to Chapter 3 of this book, Automating Juniper Devices in the Service Providers Using Ansible, since we are using the exact same network topology and the same data structures for both JunOS and IOS-XR devices.

运行此行动手册将在configs文件夹中生成我们的 Ansible 清单中所有设备的配置,如以下代码块所示:

$ tree configs/
configs/
 ├── mxp01.cfg
 ├── mxp02.cfg
 ├── mxpe01.cfg
 ├── mxpe02.cfg
 └── xrpe03.cfg 

使用 NAPALM 在网络设备上部署配置

在本食谱中,我们将概述如何使用 Ansible 和 NAPALM 在不同的供应商设备上推送配置。NAPALM 为配置管理提供了一个单一的 Ansible 模块,这个模块允许我们使用单一的通用方法在 NAPALM 支持的任何供应商设备上推送任何配置,大大简化了 Ansible 行动手册。

准备好

为了遵循这个方法,您需要已经建立了一个 Ansible 清单,并且在 Ansible 控制器和网络设备之间建立了网络可达性。我们将推送到设备的配置是我们在之前的配方中生成的配置。

怎么做…

  1. 更新pb_napalm_net_build.yml剧本文件,添加如下代码块所示的任务:
$ cat pb_napalm_net_build.yml

---
- name: " Play 1: Deploy Config on All JunOS Devices"
  hosts: sp_core
  tasks:

< -- Output Omitted for brevity -->

    - name: "P1T5: Deploy Configuration"
      napalm_install_config:
        hostname: "{{ ansible_host }}"
        username: "{{ ansible_user }}"
        password: "{{ ansible_ssh_pass }}"
        dev_os: "{{ ansible_network_os }}"
        config_file: "{{config_dir}}/{{ inventory_hostname }}.cfg"
        commit_changes: "{{commit | default('no')}}"
        replace_config: yes
      tags: deploy, never

它是如何工作的…

如前所述,NAPALM 提供了一个单一的 Ansible 模块,将配置推送到网络设备。它要求配置出现在文本文件中。当它连接到网络设备时,会将配置推送到相应的设备。

由于我们使用的是可以跨 NAPALM 支持的所有供应商操作系统设备使用的单一配置模块,并且 NAPALM 使用不同的连接应用编程接口来管理设备,因此我们需要告诉模块设备的供应商操作系统。我们还需要提供其他参数,如用户名/密码,以登录并使用设备进行身份验证。

napalm_install_config模块需要以下强制参数才能正确登录被管理设备并将配置推送到该设备:

  • hostname:这是我们可以到达设备的 IP 地址。我们为该参数提供ansible_host的值。
  • username/password:这是连接设备的用户名和密码。我们需要提供ansible_useransible_ssh_pass属性。
  • dev_os:此参数提供了 NAPALM 需要的厂商 OS 名称,以便选择正确的 API 和正确的库与设备通信。对于该选项,我们提供ansible_network_os参数。
  • napalm_install_config模块使用以下参数管理远程设备上的配置:
    • config_file:提供包含需要推送到被管理设备的设备配置的配置文件的路径。
    • commit_changes:告知设备是否提交配置。NAPALM 为配置提交提供了一种一致的方法,即使是默认情况下不支持它的设备(例如思科 IOS 设备)。
    • replace_config:该参数控制设备上现有的配置和config_file参数中的配置如何合并。在我们的例子中,由于我们正在生成整个设备配置,并且所有配置部分都在 Ansible 下管理,因此我们用生成的配置替换整个配置。这将导致我们的配置文件中没有的设备上的任何配置被删除。

根据本食谱中概述的配置,当我们使用deploy标签运行剧本时,NAPALM 将连接到设备并推送配置。但是,它不会在远程设备上提交配置,因为我们已经将commit_changes的默认值指定为no。如果我们需要在远程设备上推送和提交配置,我们可以在运行剧本时将commit参数的值设置为yes,如以下代码片段所示:

$ ansible-playbook pb_napalm_net_build.yml --tags deploy --e commit=yes

还有更多…

napalm_install_config模块提供了额外的选项来控制如何管理远程设备上的配置,例如配置差异。通过这个选项,我们可以收集设备上运行的配置和我们将通过 NAPALM 推送的配置之间的差异。该选项可以按如下方式启用:

  • 创建一个名为config_diff的文件夹来存储 NAPALM 捕获的配置差异,如以下代码块所示:
$ cat group_vars/all.yml

< -- Output Omitted for brevity -->
config_diff_dir: ./config_diff

$ cat tasks/build_config_dir.yml

- name: "Create Config Diff Directory"
 file: path={{config_diff_dir}} state=directory
 run_once: yes
  • 更新pb_napalm_net_build.yml剧本,如下代码块所示:
$ cat pb_napalm_net_build.yml

---
- name: "Generate and Deploy Configuration on All Devices"
 hosts: sp_core
 tasks:

< -- Output Omitted for brevity -->

 - name: "Deploy Configuration"
 napalm_install_config:
 hostname: "{{ ansible_host }}"
 username: "{{ ansible_user }}"
 password: "{{ ansible_ssh_pass }}"
 dev_os: "{{ ansible_network_os }}"
 config_file: "{{config_dir}}/{{ inventory_hostname }}.cfg"
 diff_file: "{{ config_diff_dir}}/{{ inventory_hostname }}_diff.txt"
 commit_changes: "{{commit | default('no')}}"
 replace_config: yes
 tags: deploy, never

接下来,我们创建一个新文件夹来存放我们将为每个设备生成的所有配置差异文件,并将diff_file参数添加到napalm_install_config模块。这将收集每个设备的配置差异,并将其保存到每个设备的config_diff目录中。

当我们在设备上使用修改后的配置再次运行剧本时,我们可以看到为每个设备生成了config_diff文件,如以下代码块所示:

$ tree config_diff/
config_diff/
 ├── mxp01_diff.txt
 ├── mxpe01_diff.txt
 ├── mxpe02_diff.txt
 └── xrpe03_diff.txt

用 NAPALM 收集设备事实

在本食谱中,我们将概述如何使用 NAPALM 事实收集 Ansible 模块从网络设备收集运行状态。这可用于验证跨多供应商设备的网络状态,因为 NAPALM Ansible 的事实收集模块返回 NAPALM 支持的所有供应商操作系统的一致数据结构。

准备好

按照这个方法,假设 Ansible 库存已经到位,并且 Ansible 控制器和网络之间的网络可达性已经建立。最后,按照之前的方法配置网络。

怎么做…

  1. 创建名为pb_napalm_get_facts.yml的 Ansible 行动手册,内容如下:
$ cat cat pb_napalm_get_facts.yml

---
- name: " Collect Network Facts using NAPALM"
 hosts: sp_core
 tasks:
 - name: "P1T1: Collect NAPALM Facts"
 napalm_get_facts:
 hostname: "{{ ansible_host }}"
 username: "{{ ansible_user }}"
 password: "{{ ansible_ssh_pass }}"
 dev_os: "{{ ansible_network_os }}"
 filter:
 - bgp_neighbors
  1. 使用以下任务更新行动手册,以验证 NAPALM 事实模块返回的数据:
$ cat pb_napalm_get_facts.yml

< -- Output Omitted for brevity -->

- name: Validate All BGP Routers ID is correct
 assert:
 that: napalm_bgp_neighbors.global.router_id == lo_ip[inventory_hostname].split('/')[0]
 when: napalm_bgp_neighbors

- name: Validate Correct Number of BGP Peers
 assert:
 that: bgp_peers | length == napalm_bgp_neighbors.global.peers.keys() | length
 when: bgp_peers is defined

- name: Validate All BGP Sessions Are UP
 assert:
 that: napalm_bgp_neighbors.global.peers[item.peer].is_up == true
 loop: "{{ bgp_peers }}"
 when: bgp_peers is defined

它是如何工作的…

我们使用napalm_get_factsAnsible 模块从网络设备中检索操作状态。我们提供与napalm_install_config相同的参数(hostnameusername/passworddev_os,以便能够连接到设备并从这些设备收集所需的操作状态。

为了控制我们使用 NAPALM 检索哪些信息,我们使用filter参数并提供我们需要检索的所需信息。在本例中,我们将检索的数据限制在bgp_neighbors内。

napalm_get_facts模块返回从节点检索的数据作为 Ansible 事实。该数据可以从napalm_bgp_neighbors变量中检索,该变量存储从设备中检索的所有 NAPALM 整编事实。

以下片段概述了从朱诺操作系统设备中检索到的napalm_bgp_neighbors输出:

ok: [mxpe02] => {
  "napalm_bgp_neighbors": {
    "global": {
      "peers": {
        "10.100.1.254": {
          "address_family": {
            "ipv4": {
              "accepted_prefixes": 0,
              "received_prefixes": 0,
              "sent_prefixes": 0
            },
 < -- Output Omitted for brevity -->
          },
          "description": "",
          "is_enabled": true,
          "is_up": true,
          "local_as": 65400,
          "remote_as": 65400,
          "remote_id": "10.100.1.254",
          "uptime": 247307
        }
      },
      "router_id": "10.100.1.2"
    }
  }
}

以下片段概述了从 IOS-XR 设备检索到的napalm_bgp_neighbors输出:

ok: [xrpe03] => {
  "napalm_bgp_neighbors": {
    "global": {
      "peers": {
        "10.100.1.254": {
          "address_family": {

< -- Output Omitted for brevity -->
          },
          "description": "",
          "is_enabled": false,
          "is_up": true,
          "local_as": 65400,
          "remote_as": 65400,
          "remote_id": "10.100.1.254",
          "uptime": 247330
        }
      },
      "router_id": "10.100.1.3"
    }
  }
}

我们可以看到,不同网络厂商的 BGP 信息从 NAPALM 返回的数据在不同网络厂商之间是一致的。这简化了对这些数据的解析,并允许我们运行更简单的行动手册来验证网络状态。

我们使用 NAPALM 返回的数据来对照我们的网络设计来比较和验证网络的运行状态,我们使用 Ansible 变量(如bgp_peers)来定义网络设计。我们使用assert模块来验证多个 BGP 信息,例如:

  • BGP 对等体的正确数量
  • BGP 路由器标识
  • 所有 BGP 会话均可运行

我们在不同的assert模块中使用when语句,在这种情况下,我们的拓扑中有一台路由器不运行 BGP ( mxp02就是一个例子)。因此,我们跳过了对这些节点的检查。

另请参见…

napalm_get_fact模块可以根据支持的厂商设备和该厂商支持的事实级别,从网络设备中检索大量信息。例如,它支持检索几乎所有已知网络供应商的接口、IP 地址和 LLDP 对等体。

有关napalm_get_facts模块的完整文档,请查看以下网址:

有关 NAPALM 支持的完整事实/信息及其对供应商设备的支持矩阵,请参考以下网址: https://napalm.readthedocs.io/en/latest/support/

使用 NAPALM 验证网络可达性

在本食谱中,我们将概述如何利用 NAPALM 及其 Ansible 模块来验证整个网络的网络可达性。该验证执行从被管理设备到我们指定的目的地的 pings,以确保网络上的转发路径按预期工作。

准备好

按照这个方法,假设 Ansible 库存已经到位,并且 Ansible 控制器和网络之间的网络可达性已经建立。假设此配方中的网络是根据相关的先前配方配置的。

怎么做…

  1. 创建名为pb_napalm_ping.yml的新剧本,内容如下:
$ cat pb_napalm_ping.yml

---
- name: " Validation Traffic Forwarding with NAPALM"
 hosts: junos:&pe
 vars:
 rr: 10.100.1.254
 max_delay: 5 # This is 5 msec
 tasks:
 - name: "P1T1: Ping Remote Destination using NAPALM"
 napalm_ping:
 hostname: "{{ ansible_host }}"
 username: "{{ ansible_user }}"
 password: "{{ ansible_ssh_pass }}"
 dev_os: "{{ ansible_network_os }}"
 destination: "{{ rr }}"
 count: 2
 register: rr_ping
  1. 使用以下代码块中显示的验证任务更新行动手册:
$ cat pb_napalm_ping.yml

< -- Output Omitted for brevity -->
- name: Validate Packet Loss is Zero and No Delay
 assert:
 that:
 - rr_ping.ping_results.keys() | list | first == 'success'
 - rr_ping.ping_results['success'].packet_loss == 0
 - rr_ping.ping_results['success'].rtt_avg < max_delay

它是如何工作的…

NAPALM 提供了另一个 Ansible 模块napalm_ping,它连接到远程被管理设备,并执行从远程被管理设备到我们指定的目的地的 pings。使用本模块,我们能够验证被管理设备和指定目的地之间的转发路径。

这个napalm_ping模块目前不支持 Cisco IOS-XR 设备,这也是我们只选择 Junos OS 组中所有 PE 设备的原因。在我们的剧本中,我们使用junos:&pe模式来做到这一点。

在我们的示例中,我们创建了一个新的行动手册,并使用vars参数指定了我们想要 ping 的目的地,以及行动手册本身中 ping 数据包的最大延迟。然后,我们使用napalm_ping模块连接到拓扑中的 MPLS 对等设备(只有 Junos OS 设备),从所有这些对等节点向我们指定的目的地执行ping(在我们的例子中,这是我们的路由反射器 ( RR )路由器的环回)。我们将所有这些数据存储在一个名为rr_ping的变量中。

下面的代码片段显示了从napalm_ping返回的输出:

"ping_results": {
 "success": {
 "packet_loss": 0,
 "probes_sent": 2,
 "results": [
 {
 "ip_address": "10.100.1.254",
 "rtt": 2.808
 },
 {
 "ip_address": "10.100.1.254",
 "rtt": 1.91
 }
 ],
 "rtt_avg": 2.359,
 "rtt_max": 2.808,
 "rtt_min": 1.91,
 "rtt_stddev": 0.449
 }
}

最后,我们使用assert模块将 NAPALM 返回的结果与我们的要求进行验证和比较(ping 成功,无丢包,延迟小于max_delay)。

用 NAPALM 验证和审计网络

在本食谱中,我们将概述如何通过定义网络的预期状态并让 NAPALM 验证网络的实际/运行状态与我们的预期状态相匹配来验证网络的运行状态。这在网络基础设施的网络审计和合规性报告中非常有用。

准备好

按照这个方法,假设 Ansible 库存已经到位,并且 Ansible 控制器和网络之间的网络可达性已经建立。最后,按照前面概述的方法配置网络。

怎么做…

  1. 创建一个名为napalm_validate的新文件夹,并为每个设备创建一个 YAML 文件。我们将验证它的状态,如下面的代码块所示:
$ cat napalm_validate/mxpe01.yml

---
- get_interfaces_ip:
 ge-0/0/0.0:
 ipv4:
 10.1.1.3:
 prefix_length: 31
- get_bgp_neighbors:
 global:
 router_id: 10.100.1.1
  1. 创建新的pb_napalm_validation.yml行动手册,内容如下:
$ cat pb_napalm_validation.yml

---
- name: " Validating Network State via NAPALM"
 hosts: pe
 tasks:
 - name: "P1T1: Validation with NAPALM"
 napalm_validate:
 hostname: "{{ ansible_host }}"
 username: "{{ ansible_user }}"
 password: "{{ ansible_ssh_pass }}"
 dev_os: "{{ ansible_network_os }}"
 validation_file: "napalm_validate/{{ inventory_hostname}}.yml"
 ignore_errors: true
 register: net_validate
  1. 更新行动手册,创建一个文件夹来存储每个设备的合规报告,如以下代码块所示:
$ cat pb_napalm_validation.yml

< -- Output Omitted for brevity -->

- name: Create Compliance Report Folder
  file: path=compliance_folder state=directory

- name: Clean Last Compliance Report
  file: path=compliance_folder/{{inventory_hostname}}.txt state=absent

- name: Create Compliance Report
  copy:
    content: "{{ net_validate.compliance_report | to_nice_yaml }}"
    dest: "compliance_folder/{{ inventory_hostname }}.txt"

它是如何工作的…

NAPALM 为网络验证提供了另一个模块,即napalm_validate模块。该模块主要用于为网络基础设施执行审计和生成合规性报告。主要思想是声明网络的预期状态,并在 YAML 文档中定义它。这个 YAML 文件有一个特定的格式,遵循产生不同 NAPALM 事实的相同结构。在这个 YAML 文件中,我们指定了要从网络中检索的 NAPALM 事实,以及网络的预期输出。

我们将这些验证文件提供给napalm_validate模块,NAPALM 将连接到设备,检索这些验证文件中指定的事实,并将从网络检索的输出与这些验证文件中声明的网络状态进行比较。

接下来,NAPALM 生成一个compliance_report对象,该对象具有比较的结果以及网络是否符合这些验证文件。我们还设置了ignore_errors参数,以便在设备不符合的情况下继续本行动手册中的其他任务,因此我们可以在我们将生成的符合性报告中捕获此符合性问题。

最后,我们为每个节点将输出保存在一个单独的名为compliance_folder的文件夹中,复制compliance_report参数的内容,并使用to_nice_yaml过滤器对其进行格式化。

mxpe01设备生成的正确合规报告的代码如以下代码片段所示:

complies: true
get_bgp_neighbors:
 complies: true
 extra: []
 missing: []
 present:
 global:
 complies: true
 nested: true
get_interfaces_ip:
 complies: true
 extra: []
 missing: []
 present:
 ge-0/0/0.0:
 complies: true
 nested: true
skipped: []

另请参见…

有关验证部署和napalm_validate其他可用选项的更多信息,请查看以下网址: