摘自:https://blog.csdn.net/weixin_30453651/article/details/112237507
最近让我写一篇NETCONF在网络运维中实际应用的读者越来越多,趁着最近回沙特后能把KAUST堆满仓库的3850, 9200, 9300等IOS-XE真机设备拿出来做实验,趁这个机会我就写写NETCONF,YANG和ncclient,分为上、下两篇,上篇讲NETCONF和YANG,下篇讲ncclient,包含理论和实战。以后有时间也会讲讲REST和RESTCONF。
NETCONF的前世今生
2002年6月,互联网架构委员会(Internet Architeture Board,简称IAB)举办了一个主题为Network Management的workshop,邀请了一大帮研发界业内名气响当当的巨佬(大多来自IETF)共同商议讨论彼时普遍使用的网络管理协议,找出它们各自的优势和缺点,并列出一个优秀的网络管理协议必须具备的特征,准备为开发下一代网络管理协议(NextGen Network Management Protocol)做准备。2003年5月,IETF发布了RFC 3535(Overview of the 2002 IAB Network Management Workshop),正式提出了下一代网络管理协议应该具备的七大特征:
在这个背景下,IETF于2006年12月率先发布了RFC 4741, 也就是NETCONF这个基于XML,用来替代CLI、SNMP的网络配置和管理协议。在随后几年加加改改进行一番修订后,IETF又于2011年6月以RFC 6241作为终稿将其再次发布。
虽然NETCONF年龄不算小,但是倒退10年前你要是问一个网络工程师什么是NETCONF(更别提YANG了),大概率你会看到对方一脸懵逼的把你看着,因为当时主流的思科IOS设备根本就不支持NETCONF,当时的思科对NETCONF并不感冒,而是自己闭门造车分别在2007年和2012年搞出了WSMA(Web Service Management Agent)和onePK这两个API。那些年跟随思科的步伐一路从CCNA,CCNP,CCIE摸爬滚打起来的网工压根就没听说过还有这么一个书上不会教,考试不会考,工作中也基本用不到的非常小众的技术。十年河东十年河西,这些年随着SDN和网络运维自动化技术的强势崛起,NETCONF终于在诞生10多年后在传统计算机网络这个行业里有了一定的曝光率,跟着RESTCONF和gRPC这俩哥们一起站在时代的风口上飞了起来。
NETCONF理论部分
关于NETCONF的理论部分网上有很多资料,最权威的肯定还是RFC 6241,这里做一下总结:
1. NETCONF的协议框架分为四层:由低到高分别为安全传输(Secure Transport),消息(Messages),操作(Operations)和内容(Content):
- 安全传输层最常见、最常用的是SSH,这也是NETCONF和同为最近几年炒的火热的REST(基于WEB)最大的区别
- 消息层基于Remote Procedure Call(远程调用)这个协议,其作用是提供一个简易的不依赖于传输层,生成RPC和通知消息框架的通信协议。在后面的NETCONF实验中你会多次看到这两个东西。
- 操作层定义了一组用来配置、复制、删除设备命令以及获取设备信息的基本操作,基本操作包括get, get-config, edit-config, copy-config, delete-config, lock, unlock, close-session, kill-session,这些基本操作都是在XML语言下被调用,比如等等,后面实验部分会讲到。
- 内容层由管理数据内容的数据模型定义,该数据模型也就是我们后面会讲到的YANG。
2. NETCONF的编码格式基于XML,基于XML来做网络管理主要是看中了XML强大的数据表示能力(对初学者来说XML其实并不怎么友好,不如JSON, YAML那么易读和容易上手,这是我个人的观点)。
3. NETCONF网络架构由客户端和服务器组成,客户端就是我们的主机,服务器就是被操控的交换机或者路由器,NETCONF默认使用端口830,可以更改。
4. NETCONF协议中还有一个重要的概念叫做数据集(Datastores),数据集的作用是用来存储一份配置数据的备份,确保设备能从开机时的初始状态进入到它能正常运行时的工作状态(说白了就是改了配置后需要write memroy,不然重启设备后配置会丢失)。数据集分为Running(类似于思科的running config), Start-up(类似于思科的startup config)和Candidate(思科IOS-XR会用到)三种,其中只有Running这个datastore是强制使用的。
讲完NETCONF的理论部分,下面再来看看YANG。
什么是数据模型?
在讲YANG之前,我们首先需要知道什么是数据模型。
数据模型的作用是用来描述一组具有统一标准的数据,并用明确的参数和模型来将数据的呈现标准化、规范化。举个例子,不同厂商之间对一些行业术语的规范及具体参数存在较大差异,比如用来区分路由协议优先级,在思科这边被称作管理距离(Administrative Distance)的东西到了Juniper那边被改叫做Route Preference,并且它们分配给各个路由协议的AD和RP值也不一样,比如RIP在思科的AD为120,在Juniper的RP为100, 又比如OSPF在思科的AD为110,而在Juniper这边OSPF还被分为OSPF Interal(RP值为10),OSPF External(RP值为150)。虽然不同厂商之间对某些技术标准存在这样那样的差异,但是对于绝大部分技术它们还是遵守统一标准的,比如VLAN。
用来描述VLAN的数据无外乎如下几点:
1. VLAN ID (1-4096的整数,rw类型)
2. VLAN Name (用字符串代表的VLAN名称,rw类型)
3. VLAN State (用枚举表示的down/up或shutdown/no shutdown表示的VLAN状态,ro类型)
可以看到类似于这种明确定义了数据内容及其数据类型和范围,以及rw、ro类型的一套模型,就被叫做数据模型。
YANG
YANG是一种“以网络为中心的数据模型语言”(Network-centric data modeling language),由IETF于2010年10月(也就是NETCONF终稿发布之前的一年)在RFC 6020中被提出,其诞生之初的目的很明确, 是专门为NETCONF量身打造的建模语言,不过现在也被REST和其他协议所采用。
YANG模型(Model)
YANG的模型分为标准(Open或者Standard)和私有(Native)两种类型,其中标准类型中比较著名的有IETF, IEEE, OpenConfig等国际知名组织制定的模型(IETF制定的YANG模型最常见)。除标准YANG模型之外,各家厂商又根据自家产品的不同设计了私有的YANG模型,比如思科、Juniper、华为、Fujitsu、诺基亚等都有自家的YANG模型。
其中思科的YANG模型又分为Cisco Common和Cisco Platform Specific,其中前者为思科所有OS(IOS-XE, IOS-XR, NX-OS)通用的YANG模型,后者为一些OS上独占的YANG模型。
YANG模块(Module)
模块(Module)是YANG定义的基本单位,一个模块可以用来定义一个单一的数据类型,也可以增加一个现有的数据模型和其他节点:
下面是一个叫做ietf-interfaces,由IETF制定,用来描述设备端口参数的YANG模块:
在Github下载YANG模块
在Github(https://github.com/YangModels/yang)上存放着大部分标准(standard)和私有(vendor)的YANG模型,截止2020年9月,标准模型中包含IETF,IEEE,ETSI等国际知名组织和协会制定的YANG模块,私有模型中包含思科,Juniper,华为,诺基亚,富士通在内的厂商自己制定的YANG模块。
我们可以通过git clone来下载上述所有标准和私有的YANG模型及其对应的模块:
git clone https://github.com/YangModels/yang.git
下载完毕后,当前目录下多出来了一个名叫yang的子目录,其中yang/standard/ietf/RFC下包含了全部由IETF制定的YANG模块,其中也包含我们上面举例的ietf-interfaces模块(不在截图里)。
用cat ietf-interfaces.yang查看该模块的内容:
你也许会问,怎么和上面我们举例的ietf-interfaces模块内容不一样?这是因为上面的例子中我们是以树形格式(Tree View Format)展开ietf-interfaces模块,而这里用cat查看的是该模块的源代码。我们可以用pyang这个Python模块来以树形格式的形式查看一个YANG模块的具体结构。
Pyang
Pyang是Python专为YANG开发的一个开源模块,主要有三个功能:1. 用来验证YANG模块代码的准确性,2. 将YANG模块转换成其他格式(比如我们前面讲到的树形格式), 3. 从YANG模块中生成代码。这里我们主要讲下如何使用Pyang来将刚才的ietf-interfaces.yang这个模块转化为树形格式。
首先通过pip下载安装pyang:
然后回到yang/standard/ietf/RFC下,使用命令pyang -f tree ietf-interfaces.yang即能将ietf-interfaces这个YANG模块转换成树形模式查看。
实验环节
讲完理论后来做实验。实验环境很简单,就是一台CENTOS 7主机和一台思科3850的交换机直连。
实验拓扑
主机操作系统:CentOS 7
交换机型号:WS-C3850-48P-S
交换机OS版本:IOS-XE 16.09.05 (Fuji)
主机IP: 172.16.224.27
交换机IP: 172.16.224.28
实验设计的端口为交换机的GigabitEthernet1/0/33,其初始配置如下:
开始实验前先提几点使用NETCONF的重点:
- IOS-XE版本必须为16.3以上。
- Netconf默认使用TCP端口830, 可以更改。
- Netconf的传输协议基于SSH,在交换机上必须开启SSH, 并且用户特权级别必须为15。
- 如果交换机配置了AAA+TACACS(比如说思科的ISE),必须保证配置了“aaa authorization exec default local”,然后使用交换机本地创建的用户名(非ISE上的用户名),否则在主机端会出现“Permission denied, please try again.”,在交换机端会出现“%DMI-5-AUTHENTICATION_FAILED:”的错误:
实验步骤:
- 首先在交换机上开启NETCONF,方法很简单,在全局模式下输入netconf-yang和netconfg ssh(可选,前面理论部分已经讲了,NETCONF默认使用的是SSH作为安全传输层协议,所以netconf ssh这条命令默认就是开启的,不需要特意配置)即可。其余的交换机初始配置,比如开启SSH和创建特权级别为15的用户请读者自行完成,这里就不讲了。
SW(config)#netconf-yang SW(config)#netconf ssh (默认是开启的)
2. 回到主机,通过SSH访问交换机的830端口:
3. 连接成功后,交换机会回复一个hello包,以及一长串capabilities,也就是该交换机支持的yang model:既有思科的,也有IETF的,由于回显内容过多,下图只截取部分以作演示:
4. 随后我们复制粘贴下列XML代码向交换机回复一个hello包(交换机不会做出任何回应),之后主机和交换机之间的netconf session即建立成功。
<?xml version="1.0" encoding="UTF-8"?>urn:ietf:params:netconf:base:1.0]]>]]>
这里简单讲下XML语言的格式和内容,XML指令以<?xml version="1.0" encoding="UTF-8"?>开头,其中:
- :表示一条XML指令的开始。
- xml:表示此文件是XML文件。
- version:NETCONF协议版本号。
- encoding:字符集编码格式,当前仅支持UTF-8编码。
- ?>:表示一条XML指令的结束。
里:
- hello表示主机(NETCONF客户端)向交换机(NETCONF服务器)回复的hello包。
- xmlns是XML Namespace(XML命名空间)的缩写,在XML里面,元素名称(你可以把它理解为Python中的变量名)是由开发者自己定义的,当将两个不同的文档合并成一个文档,如果两个文档里面使用相同的元素名时,就会发生命名冲突。比如说你和我分别开发了一个XML文档,我用name作为元素名称来描述一个人名,而你也用name作为元素名称来描述一个地名,虽然我俩描述的东西不一样,但是你我定义的元素名称(name)是一样的,当我俩的文档被合并成一个文档时,就会造成冲突,而XML命名空间的作用就是避免XML内元素的冲突。
- urn:ietf:params:xml:ns:netconf:base:1.0, 在RFC 4741中规定了所有涉及NETCONF协议的元素必须以urn:ietf:params:xml:ns:netconf:base:1.0作为XML命名空间。
- 代表能力集,代表具体的能力,是NETCONF客户端和服务器互相向对方说明自己具备什么能力的作用,这里的urn:ietf:params:netconf:base:1.0表示客户端告诉服务器:我具备使用IETF制定的NETCONF协议的能力。
- 和Python不一样,XML并没有严格要求缩进,但是为了美观和可读性,一般我们用两个空格或者四个空格做缩进。
- 注意代码最尾部的]]>]]>,它是NETCONF客户端和NETCONF服务器用来表示消息请求或回复终止的部分(用来告知对方“我话说完了,轮到你了”),并不是XML语言本身的一部分,后面会说明为什么它很重要。
5. 发送下列XML代码向交换机查询Gi1/0/33端口的配置:
<?xml version="1.0" encoding="UTF-8"??>1/0/33]]>]]>
随即交换机会回复一个rpc-reply包(下图红框中的部分),后面的内容即我们请求的Gi1/0/33端口的配置信息,包括该端口下的description和IP地址(为空)。
6. 如果你觉得交换机回复的rpc-reply不易读,可以将它复制粘贴到Code Beautify(https://codebeautify.org/xmlviewer),用Code Beautify下面XML Viewer提供的Tree View或者Beautify / Format让交换机的rpc-reply内容更易读。
注意复制RPC-REPLY内容时不要把末尾的]]>]]>给一并复制了(前面讲了它们不是XML语言的一部分),不然Code Beautify会报错:
7. 接下来我们用下面这段XML代码来查询交换机的running configuration。请自行尝试这里就不放截图了:
这里我故意没做缩进,就是为了告诉你XML没有严格要求代码缩进。
<?xml version="1.0"?>]]>]]>
8. 用下面这段XML代码来为端口Gi1/0/33添加一个description,内容为test XML,表示该description是我们通过NETCONF配置的:
<?xml version="1.0"? encoding="UTF-8"??>1/0/33test XML]]>]]>
这里我们使用到了这个前文NETCONF理论部分讲到的基本操作,通常下面会接一个,表示需要修改配置的目标,表示数据集,这里我们要更改的是startup这个数据集(也可以使用running/),后面的表示这里我们使用了前面讲到了的思科私有(Native)YANG模型。
回到交换机上验证Gi1/0/33的配置:
9. 最后我们用下面这段XML代码给Gi1/0/33配置一个10.1.1.2 /24这个IP地址
<?xml version="1.0"? encoding="UTF-8"??>1/0/33 10.1.1.2 255.255.255.0]]>]]>
之后回到交换机上验证Gi1/0/33的配置:
关于NETCONF和YANG的理论和实战就讲到这里,可以看到NETCONF这种通过复制粘贴XML代码的操作方式对传统工程师来说很不适应,虽然不太好用,但NETCONF确实是SDN时代网工们必须掌握的技能之一。下篇我将继续讲解ncclient这个Python专为NETCONF客户端开发的第三方模块,看看NETCONF结合Python会不会省事一些。