本文篇幅较长,主要涉及以下内容:
介绍传统 CLI 配置网络设备存在的挑战,网管协议出现的背景
SNMP 原理,交互过程,以及 trade-off
NETCONF 架构,交互过程
RESTCONF 架构,和 NETCONF 的对比
随着 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 设备命令如下:
Router(config)#ip route 0.0.0.0 0.0.0.0 10.10.10.1
而对于华为和华三设备来说:
Router(config)#p 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.
在数据采集方面,传统人工定时登上设备材料系统日志,分析情况,这更加无法适用。在故障响应上,数据采集,分析都存在先天的不足。比如收集效率低,数据的利用率延迟或不高。
最后从商业成本的考虑,人工的维护方案也是较高的一笔输出。
而且对于工程师而言,需要不断学习不同厂商的配置命令,学习成本很高,但意义不大。
通常来说,网络工程师在开始一个项目前,会进行如下四个部分:
- 了解用户的需求
- 针对用户的需求,确定相应的具体方案。
- 根据用户的方案,查找并学习对应设备的配置命令
- 最后申请割接窗口,准备回滚方案并实施。
在这里的第三步,其实就是一个比较耗时,但没多少意义的过程。因为在集中学习不同厂商的设备命令,但从业务考虑明明解决的都是同一个问题。
在发现 CLI 管理设备的方式出现瓶颈后,并不是马上过度到现在流行的网络自动化配置方式,而是先推出了一个叫 Simple Network Management Protocol
- SNMP 的应用层协议,甚至在当前的一些现网中,依然被使用。
SNMP
SNMP 的出现,主要想解决两个问题:
- 设备信息的采集
- 使用 GUI 替代 CLI 的方式进行设备配置下发
但由于其读多写少的特点,现被广泛用于设备信息的监控和采集。
SNMP 目前共有三个版本:
- SNMP V1,第一个版本。在管理设备上,采用明文的方式,有
read-only
,read-write
,trap
三种和设备通信的方式。 - 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 用于和 Manger信息交互,交流的内容需要符合 MIB 的规范。
看到这,可能对 MIB 这个概念还是有些模糊。这样,我们先不从最后的结果来分析这个组件的作用,而是从设计的角度,来说一下推导下为什么要有 MIB 这个东西?
这里想要实现的是通过 Manager 去管理网络上的 Agent(其实就是管理设备)。那么如何管理呢,比如 Manager 想要获取 Agent1 的 GigabitEthernet0/0/0/1 的 IP 地址。
这时就需要在 Agent1 上先约定好一个内容,比如当 Agent 接收到 1.1
这个字符串时,就会将接口的信息返回给 Manager.
之后如果 Manager 发送 1.1
就能获取到接口的信息了,但发送别的内容,Agent 是无法识别并工作的。MIB 本质就是这样,确定了如 1.1
这样的一组规则,去规范信息交互的访问方式。
其实,这里的 1.1
就是 MIB 中的一个对象,在 MIB 中还以层级的方式存在着许多这样的对象,将网络的设备的资源抽象成形如 1.1
对象。通过这些对象,Manger 和 Agent 就可以实现很好的交流了。
真正的 MIB 类似与下图,而这里形如 1.3.6.1.1.1.2
这样连接起来的字符串称为 ASN,其实就是对应了设备上的各种资源,Manager 和 Agent 也通过它们进行交流。
SNMP 操作
SNMP Manger 和 SNMP Agent 间的交互主要有三种类型:
- SNMP Get
- SNMP SET
- SNMP Notifications
SNMP Get:主要是检索设备的信息,Get 一种有三种类型:
- GET - 从 SNMP agent 获取固定的对象。
- GETNEXT - 检索当前对象的后一个对象,由于 MIB 本身层级的树形结构,存在后继。
- GETBULK - 获取一组固定的对象。
SNMP SET:主要是修改 MIB 中的对象,进而修改设备的配置。
SBMP Notifications:是 SNMP 的主要特性,之前的 GET 和 SET 是属于拉的操作,而 SNMP 正好相反,类似于推的操作,可以由 agent 发起,将一些信息 push 到 SNMP Manager 上。类似于 Web Socket. 主要用于通知如认证失败,重启,断开连接等事件。
Notifications 主要有两种形式:Traps 和 Informs. 两者间的不同主要在于可靠性,agent 在产生 Informs 给 Manager 后,如果发送失败,会重新发送。Manager 收到后,需要回复确认给 agent。
而 Traps 不同,无论消息发送是否成功,Manager 都不需要回复。
SNMP 缺点
虽然 SNMP 的出现,在一定程度上解决了网络设备的管理问题。但面对现代大规模的网络来说,依然有着很多挑战:
- 性能不足,在下发和读取配置时,采用依次读取,效率低。
- 下发不足,支持写 MIB 的对象相对于读较少。
- 不支持事务机制,在配置下发失败是,无法回滚。
- 拓展性差,提供给外部的接口较少。
- 模型兼容性差,MIB 库混乱,无法适配所有厂商,导致定义各种私有 MIB 库。
面对这些问题,06 年由 IETF 领导并开发出了一个新的协议 - NETCONF,网络管理协议。和 SNMP 不同,NETCONF 基于 RPC 的方式,天生就能很好的支持事务回滚等操作,从而更好地处理复杂网络的各种需求。
NETCONF
NETCONF 协议提供了一种更简单的方式来管理("查询,配置,修改,删除")设备,就像数据库操作中的 DML. 同时开放了 API 接口,当想要对设备进行操作时,直接通过调用 API 进行。
对于支持 NETCONF 的设备来说,至少能开启一个或多个 session。并且在每个 session 中应用的配置更改,都可以被全局的 session 监听到。这就让一个或多个 Manager(Client) 操作同一个设备(agent)成为了可能。
相比 SNMP 而言,有着如下的优势:
- 基于 RPC,增加了事务支持
- 优化查询功能,增加过滤查询方式
- 拓展性强,在其协议内部分为 4 层,各层之间相互独立
- 更好的将配置和状态数据解耦,并区分状态数据(candidate, running, startup)
- 易使用,结合提供的 API,实现可编程性的网络操作
- 安全性更好,在传输层可选用 SSH,TLS 协议等。
NETCONF 采用 C/S 的架构,通过 RPC 在 client 和 server 间交流。client 可以是 Python 脚本或应用。server 一般指的是网络设备,在具体实现上有三个组件:
NETCONF agent:运行在网络设备上,用于接收和处理 RPC 请求。还可主动将一些告警事件通知客户端。
NETCONF 客户端:利用 NETCONF 协议对网络设备进行管理以及接收 agent 发出的告警通知。
datastore:在 NETCONF 中,区分了多个不同类型的 datastore, 这些 datastore 保存着不同状态下的设备信息。
关于 datastore 可以将其理解成一个可以获取和存储信息的概念。在具体实现上,可以是文件,数据库,内存等等。
在 NETCONF 中常用到三类 datastore:
startup configuration datastore: 保存了设备启动时,加载的配置信息。
candidate configuration datastore: 保存了想要运行的配置信息,修改该数据库时,并不会影响设备的真实配置。
running configuration datastore: 保存了当前设备上正在生效的配置,修改时会影响真实的设备。
此外提到 datastore 就必须要提到一种数据模型语言 —— YANG,datestore 中就是以 YANG 的形式来约束配置的数据。
YANG 的出现结合上 NETCONF 和 RESTCONF 这样的协议,为自动化,可编程化的网络提供了强大的支持。YANG 的本质和之前 SNMP 中 MIB ASN 一样,作用都是以一种方式来约束数据,关于 YANG 之后会写一篇文章单独介绍。
NETCONF 协议架构
NETCONF 分为 4 层,各层之间项目独立。
- 内容层:
这一层包含了以 XML 或 JSON 格式的配置数据,也就是想对设备进行管理的具体内容。(由 XSD 或者 YANG 约束生成)
- 操作层:
定义了 Client 和 Server 交互时的一系列操作方法,用于获取或修改配置数据。
- 消息层:
为编码数据时,提供了一种 RPC 和通知的机制:
* RPC invocations(<rpc> messages)
* RPC results(<rpc-reply> messages)
* event notifications(<notification> messages)
- 传输层:
NETCONF 使用 SSH 或 TLS 协议,保证数据在 Client 和 Server 传输的安全性。
NETCONF 交互
对于 Manager 和 Agent 来说,Session 建立会经历如下的过程:
- Manager 请求 NETCONF 中 SSH 子系统建立连接。
- Agent 回复 Hello 消息,包含本身支持的特性和能力。
- Manager 告知 Agent 自己所支持的特性和能力。
- Manager 开始发送 RPC 操作请求。
- Agent 回复 RPC 请求操作结果。
具体看下 NETCONF 中消息的报文结构,以修改接口配置举例:
Manager 请求变更接口配置:
<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 回复结果:
<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
# 打开 netconf
netconf-yang
# 查看 netconf 进程
show platform software yang-management
Client 端:测试设备 NETCONF
ssh admin@IP -p 830 -s netconf
关于 NETCONF 具体实现编程化操作,可以参见 这篇。
RESTCONF
在谈起 RESTCONF 前,想必刚接触这个概念的人都会有这样一个疑问 RESTCONF 和 REST 到底有没有关系?
再回答这个问题前,先来回忆一下什么是 REST,以及 REST 出现的背景。
REST - Representational State Transfer,全称为表现层状态转化,是建立在 HTTP 基础上,对其进行规范的一种架构风格要求。
其认为,网络中的实体都是以资源的方式存在,但资源却存在着多种表现形式,取决于使用者的需要。比如一个用户的信息,可以用 XML, JSON, 甚至是 txt 等多种方式表现出来。将不同的网络资源转换成不同的表现形式,就是其表现层的体现。
而状态转移来说,由于 HTTP 本身是无状态的协议,所以资源的状态全都保存在服务端。当对服务端的资源进行操作时,必然存在数据状态的改变。
但由于状态的改变基于表现层,所以称为表现层状态转移。
在具体实现上,URI 定义了访问资源的具体路径,而 HTTP 中 Header 的 Content-Type
和 Accept
决定了了表现层的形式。
HTTP 中的 CURD 动作(Create,Put,Get,Delete,patch..)去改变服务端的资源状态。
比如查询书店具有的图书:
GET http://www.store.com/products
通过 REST 的方式,更合理的实现 WEB 服务之间的交互。
这时再看 RESTCONF,就很好理解了。RESTCONF 是通过 REST 来实现对网络设备管理的协议。其本质和 NETCONF 很像,使用 YANG 进行数据的定义和约束,使用 HTTP 进行交互。使用 NETCONF 中 datastore 的概念,进行信息的储存。
RESTCONF 架构
图中很好的表示了 RESTCONF 协议组成,很形象的指出 RESTCONF = NETCONF / YANG + HTTP(s).
如果拿之前的 作为对比,RESTCONF 就是将:
- 内容层,同样由 YANG 约束生成。
- RPC 消息层和操作层,换成了 HTTP 的操作层。
- 将 SSH 构成的传输层,换成了 HTTP(s)的传输方式。
RESTCONF VS NETCONF 交互
图中很好的对比了 RESTCONF 和 NETCONF 的交互过程,都是采用了 C/S 架构,在具体组件上:
对于操作来说,将 RPC 操作换成了 HTTP 操作:
RESTCONF 操作
Server 端:打开设备 RESTCONF
# 打开 RESTCONF
restconf-yang
# 查看 RESTCONF 进程
show platform software yang-management
Client 端:
由于已经采用了 REST 风格,可以利用 POSTMAN 等等 HTTP 客户端进行测试。
关于 RESTCONF 具体实现编程化操作和其 URL 的使用是非常重要的一部分,但由于其依赖 YANG 这个概念,这个后面会单独提到,可以参见 这篇。
总结
这篇文章,耗时很久,查阅了大量资料,完成后真的如释重负一般。
当然对网管协议也有了进一步的理解。
下面做一个简单的总结:
传统 CLI 配置方式,已经无法满足当代网络可编程化的需要,而且在兼容性,易用性,正确率存在着诸多问题,进而网管协议应运而生。
SNMP 作为推出的第一代协议,在一定程度上解决了设备管理的问题。但由于其读多写少的特点,以及在兼容性,效率,以及缺乏事务性的不足,在现网中,一般用其作为设备配置采集或监控的工具。
为了更好的满足网络的需要,第二代协议 NETCONF 出现,由于 NETCONF 天生 RPC 支持事务的特点,再加上 YANG 解决了多厂商命令兼容性的问题,现被广泛使用在各种网管平台,SDN 控制器中。
随后 HTTP REST 风格的普及,IETF 又推出了 RESTCONF 协议,将 NETCONF 和 HTTP 整合在一起,以更为流行的方式,实现对设备的管理。