从传统 CLI 到自动化:网管协议( SNMP / NETCONF / RESTCONF)与 YANG

注:本文为 "网管协议" 相关文章合辑


网管协议 - SNMP,NETCONF,RESTCONF

posted @ 2021-02-22 21:13 来份锅包肉

传统 CLI 配置网络设备存在的挑战,网管协议出现的背景

随着 5G 的兴起,SDN、NFV 等概念被频繁提及。要更好地理解这些概念,网络协议是必不可少的一环。

以 SDN 为例,其全称为 Software Defined Networking(软件定义网络)。传统网络采用分布式架构,控制平面和转发平面均位于同一台设备上,在运维及灵活性方面存在诸多挑战。

SDN 的出现将控制平面和转发平面解耦,并将所有设备统一管理,使网络具备了可编程能力。从面向服务的角度出发,可根据业务需求实时动态地调整设备的配置或状态,从而大幅降低了管理难度。

那么,NETCONF、RESTCONF 等协议又起到了怎样的作用呢?

这需要从 SDN 架构说起,SDN 主要包含三个角色:SDN 应用、SDN 控制器以及网络设备。

SDN 应用通常通过 HTTP 方式调用 SDN 控制器暴露的接口,而 SDN 控制器则通过 NETCONF、RESTCONF 等类似协议与设备进行交互,实现业务的下发。

由此可见,NETCONF 等类似协议起到了与设备直接交互的作用。

此外,DEVOPS 概念的流行也强调从传统人工 CLI 配置向自动化的网络配置过渡,NETCONF 等类似协议使得这些自动化操作成为可能,例如目前的 ANSIBLE、Python 的各种类库等。

以下是网管协议的实际用例,其涵盖的范围已经非常广泛:

下面从传统 CLI 面临的挑战开始,详细了解这些发挥着重要作用的协议。

传统命令操作带来的主要挑战

采用传统 CLI 配置方式主要存在以下挑战:

在兼容性方面,网络工程师肯定深有体会。

以配置静态路由为例,Cisco 设备的命令如下:

c 复制代码
Router(config)#ip route 0.0.0.0 0.0.0.0 10.10.10.1 

而对于华为和华三设备来说:

c 复制代码
Router(config)#ip route-static 0.0.0.0 0.0.0.0 10.10.10.1 

有时不仅不同厂商之间的命令不同,甚至同一厂商不同型号之间的命令也不相同。

例如,思科针对不同场景区分了不同的网络软件系统:

  • 针对企业的 IOS
  • 针对运营商的 IOS-XR
  • 针对数据中心的 NX-OS
  • 以及面向下一代的 IOS-XE,将数据层面和控制解耦,底层支持 Linux

在出错率方面,人工配置远不如机器配置准确且迅速。

当前的网络在规模和需求上与以往大不相同,例如在实时性方面,运营商需要根据业务需求动态调整策略,如 EVPN、L3VPN、L2TP,传统 CLI 手工配置根本无法满足,也无法做到维护管理。而目前的常用解决方案是利用一些现成的 SDN Controller 进行实时调整,如 Cisco 的 NSO。

在数据采集方面,传统人工定时登录设备查看系统日志、分析情况的方式已无法适用,其在故障响应上也存在先天不足,如收集效率低、数据利用率低或延迟高等问题。

从商业成本角度考虑,人工维护方案也是一笔较高的支出。

对于工程师而言,需要不断学习不同厂商的配置命令,学习成本很高,但意义不大。

通常来说,网络工程师在开始一个项目前,会进行以下四个部分的操作:

  1. 了解用户需求
  2. 针对用户需求,确定相应的具体方案
  3. 根据用户方案,查找并学习对应设备的配置命令
  4. 最后申请割接窗口,准备回滚方案并实施

其中第三步是一个比较耗时但意义不大的过程,因为在集中学习不同厂商的设备命令,但从业务角度考虑,明明解决的都是同一个问题。

在发现 CLI 管理设备的方式出现瓶颈后,并非立即过渡到当前流行的网络自动化配置方式,而是先推出了一个名为 Simple Network Management Protocol(SNMP)的应用层协议,甚至在当前的一些现网中,依然被使用。

SNMP

SNMP 的出现主要旨在解决以下两个问题:

  1. 设备信息的采集
  2. 使用 GUI 替代 CLI 的方式进行设备配置下发

但由于其读多写少的特点,目前被广泛用于设备信息的监控和采集。

SNMP 目前共有三个版本:

  • SNMP V1,第一个版本。在管理设备时,采用明文方式,有 read-onlyread-writetrap 三种与设备通信的方式。
  • SNMP V2,主要改进了性能、安全性和设备交流的方式。
  • SNMP V3,主要优化了安全性,增加了一些更强的认证流程。

SNMP 原理

SNMP 整体架构类似于 Client/Server,其主要工作组件有三个:

  • SNMP Manager:主要用于管理网络中的多个设备,对其进行读写操作,类似于 Server。
  • SNMP Agent:运行在网络设备上,通常需要手动开启。作为 SNMP 代理,在收到 SNMP Manager 发出的请求后,对请求内容进行解析,然后对设备进行配置,并将配置结果作为 Response 回复给 Manager。
  • SNMP MIB:MIB(Management Information Base)全称为信息管理库。可以将其理解为用于交互的一种数据模型,也就是交互的规则。MIB 同样存在于网络设备中,定义和描述了如何管理设备上的资源,Manager 和 Agent 之间的交流信息即为 MIB 的内容。

可以看到,一个 Manager 可以管理网络中的多个设备,而每台设备上运行着 SNMP Agent 用于与 Manager 信息交互,交流内容需要符合 MIB 的规范。

看到这里,可能对 MIB 这个概念还比较模糊。下面从设计角度来分析为什么要有 MIB 这个东西。

这里想要实现的是通过 Manager 去管理网络上的 Agent(其实就是管理设备)。那么如何管理呢?例如,Manager 想要获取 Agent1 的 GigabitEthernet0/0/0/1 的 IP 地址。

这时就需要在 Agent1 上先约定好一个内容,比如当 Agent 接收到 1.1 这个字符串时,就会将接口的信息返回给 Manager。

之后如果 Manager 发送 1.1 就能获取到接口的信息,但发送其他内容,Agent 是无法识别并工作的。MIB 本质上就是确定了如 1.1 这样的一组规则,去规范信息交互的访问方式。

实际上,在 MIB 中还以层级的方式存在着许多这样的对象,将网络设备的资源抽象成形如 1.1 的对象。通过这些对象,Manager 和 Agent 就可以实现很好的交流。

真正的 MIB 类似于下图,而这里形如 1.3.6.1.1.1.2 这样连接起来的字符串称为 ASN,其实就是对应了设备上的各种资源,Manager 和 Agent 也通过它们进行交流。

![img](https://img-blog.csdnimg.cn/img_convert/81dc27ab236f1aef29cbfed

5ed05608e.jpeg =900x)

SNMP 操作

SNMP Manager 和 SNMP Agent 间的交互主要有以下三种类型:

  • SNMP Get
  • SNMP Set
  • SNMP Notifications

SNMP Get:主要用于检索设备的信息,Get 又分为以下三种类型:

  • GET:从 SNMP Agent 获取固定的对象。
  • GETNEXT:检索当前对象的后一个对象。由于 MIB 本身具有层级的树形结构,因此存在后继对象。
  • GETBULK:获取一组固定的对象。

SNMP Set:主要用于修改 MIB 中的对象,进而修改设备的配置。

SNMP Notifications:是 SNMP 的主要特性之一。之前的 GET 和 SET 属于拉的操作,而 SNMP Notifications 则相反,类似于推的操作,可以由 Agent 发起,将一些信息 push 到 SNMP Manager 上,类似于 Web Socket。主要用于通知如认证失败、重启、断开连接等事件。

Notifications 主要有两种形式:Traps 和 Informs。两者之间的主要区别在于可靠性。Agent 在产生 Informs 给 Manager 后,如果发送失败,会重新发送。Manager 收到后,需要回复确认给 Agent。

而 Traps 则不同,无论消息发送是否成功,Manager 都不需要回复。

SNMP 缺点

虽然 SNMP 的出现一定程度上解决了网络设备的管理问题,但面对现代大规模网络时,依然存在诸多挑战:

  1. 性能不足,在下发和读取配置时,采用依次读取的方式,效率较低。
  2. 下发能力不足,支持写 MIB 的对象相对于读较少。
  3. 不支持事务机制,在配置下发失败时,无法回滚。
  4. 拓展性差,提供给外部的接口较少。
  5. 模型兼容性差,MIB 库混乱,无法适配所有厂商,导致定义各种私有 MIB 库。

针对这些问题,2006 年由 IETF 领导并开发出了一个新的协议 - NETCONF(网络管理协议)。与 SNMP 不同,NETCONF 基于 RPC 的方式,天生就能很好地支持事务回滚等操作,从而更好地处理复杂网络的各种需求。

NETCONF

NETCONF 协议提供了一种更简单的方式来管理("查询、配置、修改、删除")设备,类似于数据库操作中的 DML。同时开放了 API 接口,当想要对设备进行操作时,直接通过调用 API 即可。

对于支持 NETCONF 的设备来说,至少能开启一个或多个 session。并且在每个 session 中应用的配置更改,都可以被全局的 session 监听到。这使得一个或多个 Manager(Client)操作同一个设备(Agent)成为可能。

与 SNMP 相比,NETCONF 具有以下优势:

  1. 基于 RPC,增加了事务支持。
  2. 优化查询功能,增加了过滤查询方式。
  3. 拓展性强,在其协议内部分为 4 层,各层之间相互独立。
  4. 更好地将配置和状态数据解耦,并区分状态数据(candidate、running、startup)。
  5. 易于使用,结合提供的 API,实现可编程性的网络操作。
  6. 安全性更好,在传输层可选用 SSH、TLS 协议等。

NETCONF 采用 C/S 架构,通过 RPC 在 Client 和 Server 间交流。Client 可以是 Python 脚本或应用,Server 一般指的是网络设备。在具体实现上有三个组件:

  1. NETCONF Agent:运行在网络设备上,用于接收和处理 RPC 请求。还可主动将一些告警事件通知客户端。
  2. NETCONF 客户端:利用 NETCONF 协议对网络设备进行管理以及接收 Agent 发出的告警通知。
  3. Datastore:在 NETCONF 中,区分了多个不同类型的 Datastore,这些 Datastore 保存着不同状态下的设备信息。

关于 Datastore,可以将其理解为一个可以获取和存储信息的概念。在具体实现上,可以是文件、数据库、内存等。

在 NETCONF 中常用到三类 Datastore:

  • Startup Configuration Datastore:保存了设备启动时加载的配置信息。
  • Candidate Configuration Datastore:保存了想要运行的配置信息,修改该数据库时,并不会影响设备的真实配置。
  • Running Configuration Datastore:保存了当前设备上正在生效的配置,修改时会影响真实的设备。

此外,提到 Datastore 就必须提到一种数据模型语言 - YANG。Datastore 中就是以 YANG 的形式来约束配置的数据。

YANG 的出现结合 NETCONF 和 RESTCONF 等协议,为自动化、可编程化的网络提供了强大的支持。YANG 的本质和 SNMP 中 MIB ASN 一样,作用都是以一种方式来约束数据。关于 YANG 后续会单独写一篇文章介绍。

NETCONF 协议架构

NETCONF 分为 4 层,各层之间相互独立。

  1. 内容层

    这一层包含了以 XML 或 JSON 格式的配置数据,也就是对设备进行管理的具体内容(由 XSD 或 YANG 约束生成)。

  2. 操作层

    定义了 Client 和 Server 交互时的一系列操作方法,用于获取或修改配置数据。

  3. 消息层

    为编码数据时提供了一种 RPC 和通知的机制:

    scss 复制代码
    * RPC invocations(<rpc> messages)  
    * RPC results(<rpc-reply> messages)
    * event notifications(<notification> messages)
  4. 传输层

    NETCONF 使用 SSH 或 TLS 协议,保证数据在 Client 和 Server 传输的安全性。

NETCONF 交互

对于 Manager 和 Agent 来说,Session 建立会经历以下过程:

  1. Manager 请求 NETCONF 中 SSH 子系统建立连接。
  2. Agent 回复 Hello 消息,包含其本身支持的特性和能力。
  3. Manager 告知 Agent 自己所支持的特性和能力。
  4. Manager 开始发送 RPC 操作请求。
  5. Agent 回复 RPC 请求操作结果。

具体来看 NETCONF 中消息的报文结构,以修改接口配置为例:

Manager 请求变更接口配置:

xml 复制代码
<rpc message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
    <edit-config>
        <target>
            <running/>
        </target>
        <config>
            <top xmlns="http://example.com/schema/1.2/config ">
                <interface>
                    <name>Ethernet0/0</name>
                    <mtu>1500</mtu>
                </interface>
            </top>
        </config>
    </edit-config>
</rpc>

Agent 回复结果:

xml 复制代码
<rpc-reply message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
    <ok/>
</rpc-reply>

可以看到,NETCONF 使用 XML 作为数据传输的格式。

第一行的 <rpc> 标签表明该请求是 RPC 请求,message-id 属性由 client/manager 确定。Agent 在回复结果时,会带上 message-id,用于表示该操作的结果。

urn:ietf: 属性表示 XML 中的命令空间,base:1.0 表示当前 NETCONF 的版本。

第二行 <edit-config> 指定执行 RPC 操作的内容为修改配置。

之后 <config> 中包裹的内容就是想要下发的配置内容,修改 mtu 为 1500。

但这里还有一个疑问,在提到 NETCONF 时,总提到一种叫 YANG 的语言,那么它们之间的关系是什么?

在组装修改设备配置 Payload 时,这里也没有用到 YANG?

其实,YANG 早已用到了。为什么 <interface> 中可以包含 <name><mtu> 属性,而不是把 mtu 放在和 <interface> 同级?

原因就在于上面的格式,都是按照 YANG 的约束而来。

在设备中,存在着许多的 YANG Module,这些 Module 都是由 YANG 语言编写的文件。当 Agent 接收到 RPC 请求时,会通过 YANG Module 来校验发来的数据,格式是否合法。

简单来说,可以把 YANG 理解成一份约束文件,里面规定着传来参数的格式,是数组、对象还是其他格式。

至于说为什么 YANG 文件能约束 XML 的文件格式,原因在于 YANG 和 XML 之间是可以相互转换的,甚至 YANG 还可以转换成 JSON。在之后的 RESTCONF 中会提到这一点。

到目前为止,对 NETCONF 已经有了一个大体认识:

NETCONF 的出现是为了弥补像 SNMP 这些协议的不足,更好地满足现在网络的需要,在易用性、拓展性等方面都做出了进一步优化,从而更方便、高效地管理网络。

究其本质,NETCONF 是由多个协议组装而成。数据的产生及校验通过 YANG,数据的格式是 XML,接口的调用通过 RPC,数据的传输通过 SSH。

NETCONF 操作

Server 端 :打开设备 NETCONF

mipsasm 复制代码
# 打开 netconf 
netconf-yang

# 查看 netconf 进程
show platform software yang-management

Client 端 :测试设备 NETCONF

css 复制代码
ssh admin@IP -p 830 -s netconf

关于 NETCONF 具体实现编程化操作,可以参见 YANG

RESTCONF

在谈起 RESTCONF 前,想必刚接触这个概念的人都会有这样一个疑问:RESTCONF 和 REST 到底有没有关系?

在回答这个问题前,先来回忆一下什么是 REST,以及 REST 出现的背景。

REST - Representational State Transfer,全称为表现层状态转化,是建立在 HTTP 基础上,对其进行规范的一种架构风格要求。

注意,REST 是一种设计的风格,而不是标准。

其认为,网络中的实体都是以资源的方式存在,但资源存在着多种表现形式,取决于使用者的需要。例如一个用户的信息,可以用 XML、JSON、甚至是 txt 等多种方式表现出来。将不同的网络资源转换成不同的表现形式,就是其表现层的体现。

而状态转移来说,由于 HTTP 本身是无状态的协议,所以资源的状态全都保存在服务端。当对服务端的资源进行操作时,必然存在数据状态的改变。

但由于状态的改变基于表现层,所以称为表现层状态转移。

在具体实现上,URI 定义了访问资源的具体路径,而 HTTP 中 Header 的 Content-TypeAccept 决定了表现层的形式。

HTTP 中的 CURD 动作(Create,Put,Get,Delete,patch 等)去改变服务端的资源状态。

例如查询书店具有的图书:

bash 复制代码
GET http://www.store.com/products  

通过 REST 的方式,更合理地实现 WEB 服务之间的交互。

这时再看 RESTCONF,就很好理解了。RESTCONF 是通过 REST 来实现对网络设备管理的协议。其本质和 NETCONF 很像,使用 YANG 进行数据的定义和约束,使用 HTTP 进行交互,使用 NETCONF 中 Datastore 的概念,进行信息的储存。

RESTCONF 架构

图中很好地表示了 RESTCONF 协议的组成,很形象地指出 RESTCONF = NETCONF / YANG + HTTP(s)。

如果拿之前的 NETCONF 协议架构作为对比,RESTCONF 就是将:

  • 内容层,同样由 YANG 约束生成。
  • RPC 消息层和操作层,换成了 HTTP 的操作层。
  • 将 SSH 构成
    的传输层,换成了 HTTP(s)的传输方式。

RESTCONF VS NETCONF 交互

图中很好地对比了 RESTCONF 和 NETCONF 的交互过程,都是采用了 C/S 架构,在具体组件上:

NETCONF RESTCONF
客户端 NETCONF client HTTP Client
配置格式由谁约定 YANG module / XSD YANG module
发送内容格式 XML XML/JSON
交互方式 RPC HTTP
传输协议 SSH HTTP(s)
服务端 NETCONF server HTTP server

对于操作来说,将 RPC 操作换成了 HTTP 操作:

RESTCONF 操作

Server 端 :打开设备 RESTCONF

mipsasm 复制代码
# 打开 RESTCONF 
restconf-yang

# 查看 RESTCONF 进程
show platform software yang-management

Client 端

由于已经采用了 REST 风格,可以利用 POSTMAN 等 HTTP 客户端进行测试。

关于 RESTCONF 具体实现编程化操作和其 URL 的使用是非常重要的一部分,但由于其依赖 YANG 这个概念,后续会单独提到,可以参见 YANG 的相关介绍。

总结

这篇文章耗时很久,查阅了大量资料,完成后如释重负。

当然,对网管协议也有了进一步的理解。

下面做一个简单的总结:

传统 CLI 配置方式已经无法满足当代网络可编程化的需要,而且在兼容性、易用性、正确率等方面存在着诸多问题,进而网管协议应运而生。

SNMP 作为推出的第一代协议,在一定程度上解决了设备管理的问题。但由于其读多写少的特点,以及在兼容性、效率和缺乏事务性方面的不足,在现网中,一般用其作为设备配置采集或监控的工具。

为了更好地满足网络的需要,第二代协议 NETCONF 出现。由于 NETCONF 天生 RPC 支持事务的特点,再加上 YANG 解决了多厂商命令兼容性的问题,现被广泛使用在各种网管平台、SDN 控制器中。

随后 HTTP REST 风格的普及,IETF 又推出了 RESTCONF 协议,将 NETCONF 和 HTTP 整合在一起,以更为流行的方式,实现对设备的管理。


数据模型与网络自动化

posted @ 2021-03-04 16:24 来份锅包肉

传统人工 CLI 配置网络的模式,已经不再适用于当代的网络,面临着兼容性、容错率低、效率低下等问题。

在这样的大背景下,各种网管协议应运而生。但这时就产生一个问题,以怎样的格式和内容去传递配置?

YANG 就是为了解决该问题而出现的。在解释 YANG 前,我们先来回忆一下,传统 CLI 是如何下发配置的?

常常是由网络工程师通过 console、Telnet、SSH 等方式登录上设备,然后直接对设备进行配置,这时自然不用考虑怎样传参的问题,只要懂得设备的命令,直接上去敲就可以。

而 CLI 这样的配置,是一种无结构化的数据。

diff 复制代码
!
interface Bundle-Ether2
!
interface Bundle-Ether780
 description evpn-vpws-test
!
interface MgmtEth0/RSP0/CPU0/0
 vrf mgmt
 ipv4 address 10.124.3.85 255.255.255.0
!
interface MgmtEth0/RSP0/CPU0/1
 shutdown
!
interface TenGigE0/0/1/0
 shutdown
!
interface TenGigE0/0/1/1
 shutdown
!
interface TenGigE0/0/2/0
 shutdown

这样无结构的数据对我们人来说是非常友好的,容易理解和阅读。

但由于换成了 NETCONF 这样的网管协议管理设备,这样的数据发挥不出任何优势,甚至无法被机器识别。因为使用 NETCONF 的目的就是为了使用自动化、可编程化的方案代替人工,从而满足当下网络的各种业务场景。

此时配置结构化的数据就成了必然。

于是各个厂商开始对配置进行结构化的约定,在 NETCONF 中,配置使用 XML 表示,进行参数的下发。

例如对接口的 MTU 进行更改:

xml 复制代码
<rpc message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
    <edit-config>
        <target>
            <running/>
        </target>
        <config>
            <top xmlns="http://example.com/schema/1.2/config ">
                <interface>
                    <name>Ethernet0/0</name>
                    <mtu>1500</mtu>
                </interface>
            </top>
        </config>
    </edit-config>
</rpc>

但此时又有一个问题,就是下发数据的格式和参数是由谁指定呢?例如这里 interface 命名的定义、类型的定义、层级的定义是如何确定的呢?

我怎么知道在下发接口配置时,就下发这样的配置内容呢?

答案在于各个厂商定义了一套约束标准,也可以理解成配置的模板。这些模板对数据进行约束,判断是否是合法的数据。这也就是数据模型的由来。

以 NETCONF 为例,NETCONF 采用 C/S 架构,Client 端在生成配置内容时会参考定义好的数据模型。Server 在接收时,同样会用这些数据模型进行校验。

具体来说,例如针对下发 JSON 格式的配置,通过 JSON Scheme 定义的 JSD 对数据进行约束。

如左图是具体的数据,右图中是对左侧数据具体进行约束的数据模型。例如这里限定了 productName 的类型是字符串,当前对象共有三个属性等。当传入其他不符合 scheme 的数据时,会进行报错。

如果对 JSON-Scheme 感兴趣,可以去官网仔细了解。

对于思科设备来说,这种由 JSON-Scheme 定义的文件叫 JSD,用于约束传入的数据类型。需要注意的是,不同厂商定义的 JSD 内容和格式是不一样的,甚至同一厂商定义的不同类型的 JSD 也不一样。

针对下发的 XML 格式的配置也采用相同的方法,各个厂商通过 XML Scheme 定义 XSD 对数据进行约束。

左面是 xml 格式的数据,右边是 XSD 文件对其进行约束,规定了属性的类型。同样不同厂商编写的 XSD 约束也是不一样的。

虽然通过编写 XSD 和 JSD 的方式解决了如何约束配置数据的问题,但由于不同厂商编写的数据模型没有统一的规范,导致各种各样的 JSD/XSD 出现,学习成本也很高。而且造成很严重的兼容性问题。例如 Cisco 的 JSD 或者 XSD 一定和 HUAWEI 不一样。甚至 Cisco 本身每个团队开发出的 JSD/XSD 的内容也不一样。

为了解决这个问题,由 IETF 主导,开发出了 YANG - Yet Another Next Generation,被现在各个协议广泛使用。

YANG

YANG 的定义

YANG 是一种数据模型语言,用于在 NETCONF 等网络协议中,将想要操作的配置或状态数据进行模型化,用层次化的表现形式,对数据进行表述。对于 YANG 模型来说,每个都有唯一标识命名空间 URI,用于区分。

简单来说,通过 YANG,对下发配置进行约束,如下的公式很好地描述了 YANG:

data(下发的数据)+ YANG = 下发给设备的配置

上图很好地表示了 YANG 起到的作用,YANG 本身并不是数据,而更像是一种配置模板,起到约束数据的作用。

那么 YANG Model 一般是由谁定义的呢?

YANG Model 的定义,主要有两个角色:

  • 标准化的 YANG Model,由 IETF、OpenConfig 等机构进行规划定义。这类的 YANG 主要是考虑到多尝试的兼容性问题,而推出的统一的 YANG Module。所有厂商都需要支持。
  • 各个厂商实现自定义私有的 YANG。这类 YANG Model 主要是为了厂商实现某些私有或特有功能。例如 Cisco 中有许多私有的协议,如 EIGRP、BGP 的某些功能只有思科设备上有。

YANG 的结构

YANG Module 以层次化树形结构被组织起来,每个模块可以引入外部其他的模块,包含其子模块的数据。

简单来说,就是可以将模块作为参数,引入其他的模块进行使用。

YANG 定义了很多的内置类型,并提供了自定义类型的机制,类似于 C 中的 typedef

在 YANG 中定义了四种类型,用于将数据模型化:

Leaf Nodes:

一个节点用于表示数字或字符串等简单的数据。但只能表示一个值,不能拥有子节点。

YANG 表示:

go 复制代码
leaf host-name {
    type string;
    description "Hostname for this system";
}

XML 表示:

xml 复制代码
<host-name>my.example.com</host-name>

JSON 表示:

json 复制代码
{
    "host-name": "my.example.com"
}
Leaf-List Nodes:

表示由 leaf node 构成的列表。

YANG 表示:

go 复制代码
leaf-list domain-search {
    type string;
    description "List of domain names to search";
}

XML 表示:

xml 复制代码
<domain-search>high.example.com</domain-search>
<domain-search>low.example.com</domain-search>
<domain-search>everywhere.example.com</domain-search>

JSON 表示:

json 复制代码
[
    {"domain-search": "high.example.com"},
    {"domain-search": "low.example.com"},
    {"domain-search": "everywhere.example.com"}
]
Container Nodes:

类似于编程语言中的 MAP 形式,将多个 node 组装到一起。一个 container node 可以包含多个任意类型的 node 节点,如 leafs、lists、leaf-lists,及本身 container 的类型。

YANG 表示:

fsharp 复制代码
container system {
    container login {
        leaf message {
            type string;
            description
                "Message given at start of login session";
        }
    }
}

XML 表示:

xml 复制代码
<system>
    <login>
        <message>Good morning</message>
    </login>
</system>

JSON 表示:

json 复制代码
{"system":{"login": {"message": "Good morning"}}}
List Nodes:

由一个或多个 key leaf 和多个任意类型的子节点组成,类型包括 leafs、lists、containers 等。

其中 key leaf 用于表示当前 list 的唯一性。

YANG 表示:

typescript 复制代码
list user {
    key "name";
    leaf name {
        type string;
    }
    leaf full-name {
        type string;
    }
    leaf class {
        type string;
    }
}

这里的 name 作为唯一的标识符。

XML 表示:

xml 复制代码
<user>
    <name>glocks</name>
    <full-name>Goldie Locks</full-name>
    <class>intruder</class>
</user>
<user>
    <name>snowey</name>
    <full-name>Snow White</full-name>
    <class>free-loader</class>
</user>
<user>
    <name>rzell</name>
    <full-name>Rapun Zell</full-name>
    <class>tower</class>
</user>

List Nodes 和 Leaf-List Nodes 的区别在于,Leaf-List Nodes 仅能包含类型是 Leaf Nodes 的节点,而 List Nodes 可以包含任意类型。

YANG 的其他特性

对于 YANG 来说,本身支持很多特性:

  • 配置状态数据,对于定义那些不能配置的配置信息。
  • 内置大量的基础类型,如 binary、bits、boolean 等。
  • 派生类型,自定义去定义如 binary 等类型。
  • 可重用组,引用通过 grouping 陈述定义的组,用于解耦和封装。
  • 支持 choices,类似于枚举。
  • 使用 augment 对 model 进行约束。
  • 提供 RPC 调用。
  • 提供通知定义。

更多功能,可以参考 YANG - RFC 文档

PYANG - 更好的浏览 YANG Model

在了解 YANG 语言提供的强大功能后,一般在项目中,会使用由 Python 开发的 Pyang 工具来浏览 YANG 模型。

简单提一下安装方法,目前 Pyang 支持 Python2 和 Python3。

可以通过 docker 打包 Python 镜像后,作为运行环境:

perl 复制代码
[root@localhost pyang-env]# ls
Dockerfile  requirements.txt  yang_modules

[root@localhost pyang-env]# cat Dockerfile
FROM python:3.8.5

ENV MY_PROXY_URL="http://xxx:80"
ENV HTTP_PROXY=$MY_PROXY_URL \
    HTTPS_PROXY=$MY_PROXY_URL \
    FTP_PROXY=$MY_PROXY_URL \
    http_proxy=$MY_PROXY_URL \
    https_proxy=$MY_PROXY_URL \
    ftp_proxy=$MY_PROXY_URL

WORKDIR /src

COPY ./requirements.txt /

RUN pip install --no-cache-dir  pyang

ENV MY_PROXY_URL=
ENV HTTP_PROXY=$MY_PROXY_URL \
    HTTPS_PROXY=$MY_PROXY_URL \
    FTP_PROXY=$MY_PROXY_URL \
    http_proxy=$MY_PROXY_URL \
    https_proxy=$MY_PROXY_URL \
    ftp_proxy=$MY_PROXY_URL

使用 docker run -v /home/xx/pyang-env/yang_modules:/src -it --name pyang-env pyang-image /bin/bash 启动运行环境。

接着去 YANG 的 Github

中,下载由 IETF 或各个厂商开发后的 YANG Module。这里以 IOS-XE 版本为 633 的 YANG Module 为例。

可以看到有很多类似的 YANG 文件:

这时就可以通过 Pyang 工具,来浏览内容:

sql 复制代码
root@a8af90280cf1:/src/633# pyang -f tree ietf-interfaces.yang
module: ietf-interfaces
  +--rw interfaces
  |  +--rw interface* [name]
  |     +--rw name                        string
  |     +--rw description?                string
  |     +--rw type                        identityref
  |     +--rw enabled?                    boolean
  |     +--rw link-up-down-trap-enable?   enumeration {if-mib}?
  +--ro interfaces-state
     +--ro interface* [name]
        +--ro name               string
        +--ro type               identityref
        +--ro admin-status       enumeration {if-mib}?
        +--ro oper-status        enumeration
        +--ro last-change?       yang:date-and-time
        +--ro if-index           int32 {if-mib}?
        +--ro phys-address?      yang:phys-address
        +--ro higher-layer-if*   interface-state-ref
        +--ro lower-layer-if*    interface-state-ref
        +--ro speed?             yang:gauge64
        +--ro statistics
           +--ro discontinuity-time    yang:date-and-time
           +--ro in-octets?            yang:counter64
           +--ro in-unicast-pkts?      yang:counter64
           +--ro in-broadcast-pkts?    yang:counter64
           +--ro in-multicast-pkts?    yang:counter64
           +--ro in-discards?          yang:counter32
           +--ro in-errors?            yang:counter32
           +--ro in-unknown-protos?    yang:counter32
           +--ro out-octets?           yang:counter64
           +--ro out-unicast-pkts?     yang:counter64
           +--ro out-broadcast-pkts?   yang:counter64
           +--ro out-multicast-pkts?   yang:counter64
           +--ro out-discards?         yang:counter32
           +--ro out-errors?           yang:counter32

还可以转换成 js 浏览:

mipsasm 复制代码
pyang -f jstree ietf-interfaces.yang >> ietf-interfaces.html

更多命令可以查看帮助文档。

这时,对于网络工程师来说,可以将其从学习各厂商不同的配置命令转化到学习 Yang Module 中,更加聚焦功能,而不用再花费时间去学习相同的功能不同的命令。

YANG-Suite 介绍

YANG-Explorer 是一个用于浏览 YANG Model 的 WEB 服务,并提供生成 NETCONF RPC payload 等实用的功能。但由于其使用 Flash 编写,而在 2020 年 12 月后,Flash 已经被禁用,导致该工具无法使用。有兴趣的同学,可以安装老版本带 flash 的浏览器测试学习。

安装可以采用 docker:

bash 复制代码
docker pull robertcsapo/yang-explorer

docker run -it --rm -p 8088:8088 robertcsapo/yang-explorer

最新 CISCO 开源了一个产品为 YANG-Suite,基于 YANG-Explorer 拓展了许多功能,并可以使用 docker-compose 启动,兼容性更好,预计未来会主流接受。

例如下面使用其生成 NETCONF RPC Payload:

![Screenshot showing the selected YangModel, various parameters such as the selected value, mode, datastore, and RPC window with the RPC textbox displaying the RPC](https://img-blog.csdnimg.cn/img_convert/ab99a40582e4f3ceadaf7af5889a26f8.png) ### YANG 与 NETCONF YANG 在早期是专为 NETCONF 而开发的一种语言,后来才被普及到各个协议中。关于 NETCONF 的介绍,可以参考相关资料。 下面主要涉及具体的操作,使用的设备是 ASR9000(IOS-XR 6.3.3)版本。 由于 NETCONF 本身采用 C/S 架构,需要在设备端打开: ```undefined netconf agent ssh ``` 在客户端方面,可以使用 `ssh` 进行测试: NETCONF 会首先使用 Hello 建立链接,报告所拥有的能力。 ````xml [root@localhost ~]# ssh cisco@ip -p 830 -s netconf Password: urn:ietf:params:netconf:base:1.1 urn:ietf:params:netconf:capability:candidate:1.0 urn:ietf:params:netconf:capability:rollback-on-error:1.0 urn:ietf:params:netconf:capability:validate:1.1 urn:ietf:params:netconf:capability:confirmed-commit:1.1 urn:ietf:params:netconf:capability:notification:1.0 urn:ietf:params:netconf:capability:interleave:1.0 urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring?module=ietf-netconf-monitoring&revision=2010-10-04&deviations=cisco-xr-ietf-netconf-monitoring-deviations http://cisco.com/ns/yang/cisco-xr-ietf-netconf-monitoring-deviations?module=cisco-xr-ietf-netconf-monitoring-deviations& ;revision=2016-02-16 http://cisco.com/ns/yang/Cisco-IOS-XR-Ethernet-SPAN-cfg?module=Cisco-IOS-XR-Ethernet-SPAN-cfg& ;revision=2015-11-09 http://cisco.com/ns/yang/Cisco-IOS-XR-Ethernet-SPAN-datatypes?module=Cisco-IOS-XR-Ethernet-SPAN-datatypes& ;revision=2015-11-09 http://cisco.com/ns/yang/Cisco-IOS-XR 每个 capability 都可包含四部分内容: - Model URI - Module Name - Revision Date - Protocol Features - Deviations - 修改自哪个 Module ```xml urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring?module=ietf-netconf-monitoring&revision=2010-10-04&deviations=cisco-xr-ietf-netconf-monitoring-deviations ```` * Model URI = urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring * Module Name = module=ietf-netconf-monitoring * Revision = 2010-10-04 * Protocol Features = NULL * Deviations = cisco-xr-ietf-netconf-monitoring-deviations 使用 `ncclient` 操作 NETCONF 设备,使用参见 [ncclient-github](https://github.com/ncclient/ncclient)。 获取 running 配置: ```python from ncclient import manager host = "10.1.1.22" username = "cisco" password = "cisco" device_params = {"name": "iosxr"} with manager.connect(host=host, port=830, username=username, hostkey_verify=False, password=password) as m: c = m.get_config(source='running').data_xml with open("%s.xml" % host, 'w') as f: f.write(c) ``` 上面演示了 NETCONF 中 `get-config` 操作,其余配置或过滤的功能,可参考文档。 需要注意一点的是,在配置时,payload 的生成一般通过上面介绍的 YANG-Suite 工具。 ### YANG 与 RESTCONF RESTCONF 和 NETCONF 很像,简单来说,就是将 HTTP 融入了 NETCONF 中,采用 REST 风格替代 SSH 和 RPC 的交互方式。 下面主要集中在具体操作。 先来看下 RESTCONF URL 的内容: ```xml https://

///[YANGMODULE:]CONTAINER/[?] ``` * ADDRESS:表示 RESTCONF 代理的 IP * ROOT:表示 restconf 请求的入口点 * DATASTORE:被查询的数据库 * \[YANGMODULE:\]CONTAINER - 使用基础的模块名称 * : 在 Container 内的独立 node * ?:返回结果的过滤参数 这里以 NSO - 思科的产品为例,直接操作设备也同理,比如 IOS-XE 的设备。 首先查询是否具有 RESTCONF 功能: ```bash http://xx:8080/.well-known/host-meta ``` * Response 包含具有 RESTCONF 内容: ```xml ``` * 里面的内容表示 ROOT 的内容,作为 RESTCONF 的入口点。 查看 NETCONF 支持的能力: ```bash http://xx:8080/restconf/data/netconf-state/ ``` 查看 RESTCONF 支持的能力: ```bash http://xx:8080/restconf/data/restconf-state/ ``` > NOTE: > > 需要在 Headers 中,指定发送和接收数据的格式: > > Content-type: > > * application/yang-data+json > * application/yang-data+xml > > Accept: > > * application/yang-data+json > * application/yang-data+xml 查询 NSO 纳管的设备 - GET Method: ```bash http://10.124.207.154:8080/restconf/data/tailf-ncs:devices/device=ASR9K/name/ ``` 修改接口描述 - Patch Method: ```bash http://10.124.207.154:8080/restconf/data/tailf-ncs:devices/device=ASR9K/config/tailf-ned-cisco-ios-xr:interface/TenGigE/ { "tailf-ned-cisco-ios-xr:TenGigE": { "id": "0/0/1/0", "description": "restconf-test" } } ``` ### 总结 YANG 的本质是一种对数据进行结构化描述的语言,本身不是数据,而是起到约束数据的作用。 至于为什么需要 YANG,原因在于传统 CLI 的方式,已不再适合当代网络的要求。而且结构化、统一的数据更容易被机器所处理。 现在 YANG 被广泛使用,特别是其可编程化的特点,像让自动化、动态编排服务,甚至网络自我调节与优化都成为了可能。 下图很好地描述了 YANG 所发挥的作用,在设备上通过 YANG 的定义,提供如 RESTCONF、NETCONF 的接口,让其通过 HTTP 或 RPC 管理设备。在控制器中,根据定义的 YANG Module 来开发各种客户端,去调用设备。 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/468a3fc733134aba82351508e164326e.png) *** ** * ** *** ## yang 模型理解 wellbeing • 16-11-10 ### 前言 继之前分享的几篇文章之后,本文将阐述作者对 YANG 模型的理解。关于如何搭建环境以及编写应用程序等内容,请参阅前几篇文章。 ### 一、Yang 的来源 2003 年,IETF 成立了 NETCONF 工作组,提出了一种基于 XML 的网络配置管理协议,即 NETCONF(Network Configuration Protocol)。由于该协议配置功能强大,同时兼顾监控与故障管理、安全验证及访问控制,因此获得了业界的广泛认可,并被广泛用于网络配置。 NETCONF 协议分为传输层、RPC 层、操作层和内容层。其中,内容层是唯一未标准化的层。因此,一种新的建模语言 YANG 应运而生,其目标是对 NETCONF 数据模型和操作进行建模,覆盖 NETCONF 协议的操作层和内容层。 ### 二、Yang 的基本元素 #### module module 是 YANG 的基本单元,是编写 YANG 文件的基本框架,包含以下几种类型的语句: 1. 头语句(yang - version / namespace / prefix) 2. 连接语句(import / include) 3. 元信息(organization / contact) 4. revision 语句 5. 定义语句(container / leaf / leaf - list / grouping 等) YANG 模块的布局如下: ```yang module { // header information yang - version statement; namespace statement; prefix statement; // linkage statements import statements; include statements; // meta information organization statement; contact statement; description statement; reference statement; // revision history revision statements; // module definitions other statements; } ``` 例如: ![SDN - YANG - fig - 2](https://i-blog.csdnimg.cn/img_convert/e2e4f8e307b25acbb7ee88e65cdb6146.png) #### submodule submodule 是部分模块定义,用于为模块提供支持。submodule 文件的内容布局如下: ```yang submodule { yang - version statement; // module identification belongs - to statement; // linkage statements import statements; include statements; // meta information organization statement; contact statement; description statement; reference statement; // revision history revision statements; // module definitions other statements; } ``` submodule 示例: ![SDN - YANG - fig - 3](https://i-blog.csdnimg.cn/img_convert/bdb59484b9d36d326ade20e6e8a6f472.png) **注意:** submodule 必须通过 `belongs - to` 语句使用。submodule 只能由 `belongs - to` 指定的 module 或该 module 的其他 submodule 进行 include,其他 module(包括 submodule)均不能 include。同时,子模块不能 import 其父模块。 #### namespace module 中必须定义所有节点所属的特定 XML 命名空间,该命名空间由一个 URI 指定。例如: ![SDN - YANG - fig - 4](https://i-blog.csdnimg.cn/img_convert/26ec2913a0626053ae43995908ee4efe.png) #### Import revision import 或 include 语句包含一个 `revision - date` 子句,所有引入的 YANG 定义均来自要导入或引入的指定 revision 模块。通过引入特定的模块修订,我们可以独立发布演变中的模块。YANG 提供了指定的规则,用于发布演变中的模块并保持向后兼容性。例如: ![SDN - YANG - fig - 5](https://i-blog.csdnimg.cn/img_convert/5efdcbd4eb6705a198eaaafdbb15fe53.png) #### YANG 的数据类型 **基本数据类型** YANG 的基本数据类型如下表所示: | 类别 | 类型 | 限制 | |:--------------|:-----------------------------|:-------------------------| | Integral | Integral {u,}int{8,16,32,64} | range | | Decimals | decimal64 | range, fraction - digits | | String | string | length, pattern | | Enumeration | enumeration | enum | | Bool and Bits | boolean, bits | | | Binary | binary | length | | References | leafref | path | | References | identityref | base | | References | instance - identifier | | | Other | union | | | Other | empty | | 更详细的描述请参阅 RFC6020 协议。例如: ![SDN - YANG - fig - 6](https://i-blog.csdnimg.cn/img_convert/aa04799619fb91f1cfe454e549190653.png) #### 派生类型 YANG 使用 `typedef` 语句定义派生类型。例如,定义一个派生类型 `percent`,其限制类型为内置类型 `uint8`: ```yang typedef percent { type uint8 { range "0 .. 100"; } } ``` 再如,定义一个 `ip - address` 类型,它包含两个派生类型的联合: ```yang typedef ip - address { type union { type ipv4 - address; type ipv6 - address; } } ``` ### 三、YANG 数据节点 #### leaf `leaf` 定义的节点只有一个值,是一个叶子节点,只能有一个实例。例如: ![SDN - YANG - fig - 7](https://i-blog.csdnimg.cn/img_convert/69364faf1e9d85ecb8774b7e59a0d64e.png) #### leaf - list `leaf - list` 定义一组相同类型的叶节点,类似于数组。与 `leaf` 的区别在于,`leaf` 只有一个实例,而 `leaf - list` 可以有多个实例。例如: ![SDN - YANG - fig - 8](https://i-blog.csdnimg.cn/img_convert/046a05f046f1be13033c2d3cb3376f71.png) #### container `container` 主要定义一个 schema 树的内部节点,它本身没有任何值和意义,只是作为一系列子节点的父节点存在,且只有一个实例。例如: ![SDN - YANG - fig - 9](https://i-blog.csdnimg.cn/img_convert/13fb51280bd663837b07a1789d583f64.png) #### list `list` 描述了一组节点的集合,类似于数据库表,表的每一行用 `key` 来标识其主键,可以有多个实例。例如: ![SDN - YANG - fig - 10](https://i-blog.csdnimg.cn/img_convert/5d0d2a0f4ae19eee28a6ea4715a51899.png) #### grouping 一个 `grouping` 定义了一个可重复使用的节点集合,使用时通过 `use` 语句,并可通过 `refine` 语句进行改进。例如: ![SDN - YANG - fig - 11](https://i-blog.csdnimg.cn/img_convert/6e45b4d393a220fcf88584681e821423.png) 使用 `grouping` 时,通过 `use` 语句,它会将 `grouping` 定义的节点复制到当前的 schema 树(如果有 `refine`,则进行更新)。 #### choice 一个 `choice` 节点定义了一个可供选择的项的集合,每一个选择项都会在某种情况下存在。一个 `choice` 由多个分支组成,通过 `case` 子语句定义。例如: ![SDN - YANG - fig - 12](https://i-blog.csdnimg.cn/img_convert/f810eb0f24c25ea3177cb113ff0ce698.png) #### anyxml `anyxml` 表示任何未知的数据定义。例如: ![SDN - YANG - fig - 13](https://i-blog.csdnimg.cn/img_convert/b12571cd77e33c412a5b14a567a0b3b4.png) #### augment YANG 提供 `augment` 语句,用于扩展一个模块层次,将节点添加到一个已存在的模块或子模块中。目标节点可以是一个 container、list、choice、case、rpc、input、output、notification 等。 `augment` 可以是条件的,使用 `when` 语句,当特定条件满足时,新节点才会出现。例如: !\[SDN - YANG - fig - 14\](https://img1.sdnlab .com/wp-content-uploads/2016/11/SDN-YANG-fig-14.png =900x) #### notification `notification` 语句用于定义 Notification 内容,其内容数据的定义与 YANG 数据定义相同。以下示例使用上文定义的 connection。 ![SDN - YANG - fig - 15](https://i-blog.csdnimg.cn/img_convert/4cfa3f24c93f803b31c00bdfdd97dfdf.png) #### rpc `rpc` 语句用于定义 NETCONF 协议的 RPCs,input 和 output 使用 YANG 数据定义语句。以下示例建模了一个激活软件图片的 RPC: ![SDN - YANG - fig - 16](https://i-blog.csdnimg.cn/img_convert/8cd8311d6a228a515d00884e6fa8c81f.png) > 作者简介:鸿哥,硕士研究生,国内某通信设备公司软件研发工程师,主要从事云计算、SDN 技术开发。 *** ** * ** *** ## via: * 一文读懂网管协议 - SNMP,NETCONF,RESTCONF - 来份锅包肉 - 博客园 * 参考 [SNMP 介绍](https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/snmp/configuration/xe-16/snmp-xe-16-book/nm-snmp-cfg-snmp-support.html#GUID-633FA74F-DA24-419F-B0AC-3CD0D3FD8384) ... [NETCONF - wiki](https://en.wikipedia.org/wiki/NETCONF) [RFC6241 - NETCONF](https://tools.ietf.org/html/rfc6241) [NETCONF datestore](https://tools.ietf.org/id/draft-ietf-netmod-revised-datastores-08.html) [通过 NETCONF 实现网络自动化](https://medium.com/@k.okasha/network-automation-and-the-rise-of-netconf-e96cc33fe28) ... [REST 介绍](http://www.ruanyifeng.com/blog/2011/09/restful.html) [RESTCONF - RFC8040](https://tools.ietf.org/html/rfc8040) [基于Model驱动的自动化网络](https://www.ciscolive.com/c/dam/r/ciscolive/emea/docs/2018/pdf/LTRCRT-2700.pdf) [RESTCONF 介绍](https://www.ciscolive.com/c/dam/r/ciscolive/apjc/docs/2016/pdf/DEVNET-1081.pdf) [CISCO 可编程化网络](https://www.cisco.com/c/en/us/td/docs/switches/lan/catalyst4500/XE3-9-0E/15-25E/configuration/guide/xe-390-configuration/prgrmblty.html) ... [SDN 和 NFV 的关系](https://time.geekbang.org/column/article/210059) * 数据模型与网络自动化 - 来份锅包肉 - 博客园 * 参考 [RFC6020 - YANG](https://datatracker.ietf.org/doc/rfc6020/) [RFC6020 - YANG1.1](https://datatracker.ietf.org/doc/rfc7950/) [YANG-Study](http://www.yang-central.org/twiki/bin/view/Main/WebHome) [YANG Models](https://github.com/YangModels/yang/tree/master/standard/ietf) [yang-explorer](https://github.com/CiscoDevNet/yang-explorer) [RESTCONF-URL](https://blog.wimwauters.com/networkprogrammability/2020-04-02_restconf_introduction_part1/) * yang模型理解 \| SDNLAB