从NETCONF到OpenConfig:手把手带你用Docker复现官方gRPC通信Demo
从NETCONF到OpenConfig手把手带你用Docker复现官方gRPC通信Demo在当今网络自动化领域传统CLI和SNMP的局限性日益凸显。想象一下当你需要管理跨厂商设备时每次都要学习不同命令行语法或是面对SNMP复杂的MIB库束手无策——这种体验就像每次出国都要重新学习当地语言。而NETCONF协议的出现就像为网络世界带来了通用翻译器但各厂商的方言差异仍然让自动化运维举步维艰。这正是OpenConfig诞生的意义所在。本文将带你用最直观的方式感受OpenConfig技术栈的核心组件。不需要复杂的理论铺垫我们将直接动手搭建一个完整的gRPC通信Demo。通过Docker容器你将在15分钟内看到Protocol Buffers如何定义数据结构gRPC如何实现高效通信最终让client端成功获取server端的网络遥测数据。这个实验就像乐高积木虽然简单但包含了现代网络自动化最关键的技术模块。1. 实验环境准备在开始前请确保你的开发机满足以下基础要求64位操作系统Windows/Mac/Linux均可已安装Docker 20.10版本至少4GB可用内存10GB可用磁盘空间关键组件版本说明组件版本备注Docker20.10需支持network create命令Python3.7gRPC工具链依赖Protocol Buffers3.12语法版本需匹配提示如果遇到权限问题建议将当前用户加入docker用户组避免频繁使用sudo安装验证命令docker --version docker run hello-world当看到Hello from Docker!信息时说明环境已就绪。2. 构建容器化实验环境我们将创建两个Docker容器分别模拟gRPC的客户端和服务端。这种隔离环境能避免污染本地系统也方便随时重置实验。2.1 创建专用网络首先为实验创建独立的Docker网络docker network create --subnet172.20.0.0/24 ocnet这个子网将专门用于我们的gRPC通信实验。2.2 启动服务端容器在新的终端窗口中运行docker run -it --net ocnet -h grpc_server --ip 172.20.0.2 openconfig/grpc_server:v1 /bin/bash这个命令做了以下几件事-it以交互模式启动容器--net ocnet接入我们创建的专用网络-h grpc_server设置容器主机名--ip 172.20.0.2固定IP便于客户端连接2.3 启动客户端容器另开一个终端窗口运行docker run -it --net ocnet -h grpc_client --ip 172.20.0.3 openconfig/grpc_client:v1 /bin/bash现在两个容器已经就绪可以通过ping命令测试连通性# 在客户端容器中执行 ping 172.20.0.2看到正常的响应即表示网络配置正确。3. Protocol Buffers实战Protocol Buffers是gRPC的接口定义语言(IDL)它像一份双方约定的数据合同定义了通信的格式和规则。3.1 定义.proto文件在客户端容器中创建counters.proto文件syntax proto3; package cclab; service int_counter { rpc GetCounter(RxpacketRequest) returns (RxpacketReply) {}; } message RxpacketRequest { string interface 1; } message RxpacketReply { uint64 rxpackets 1; string message 2; }这个文件定义了一个RPC服务int_counter请求消息RxpacketRequest包含网络接口名响应消息RxpacketReply包含数据包计数和状态信息3.2 编译生成Python代码使用protobuf编译器生成客户端和服务端代码python -m grpc_tools.protoc -I./ --python_out. --grpc_python_out. ./counters.proto成功执行后会生成两个关键文件counters_pb2.py消息序列化/反序列化代码counters_pb2_grpc.pygRPC服务端和客户端存根4. 实现gRPC通信现在我们来编写实际的业务逻辑代码让客户端能获取服务端的网络接口统计信息。4.1 服务端实现在服务端容器中创建counters_grpc_server.pyfrom concurrent import futures import time import os import grpc import counters_pb2 import counters_pb2_grpc class int_counter(counters_pb2_grpc.int_counterServicer): def GetCounter(self, request, context): input os.popen(ifconfig request.interface) rxcounter int(.join([x.split()[2] for x in input if RX packet in x])) return counters_pb2.RxpacketReply( message Rx packets for %s: %i %(request.interface, rxcounter)) def serve(): server grpc.server(futures.ThreadPoolExecutor(max_workers10)) counters_pb2_grpc.add_int_counterServicer_to_server(int_counter(), server) server.add_insecure_port([::]:50051) server.start() print(gRPC server listening on port 50051) try: while True: time.sleep(99999) except KeyboardInterrupt: server.stop(0) if __name__ __main__: serve()这段代码的核心功能实现GetCounter方法处理客户端请求执行ifconfig命令获取指定接口的统计信息解析输出并提取RX packets计数通过gRPC返回结构化数据4.2 客户端实现在客户端容器中创建counters_grpc_client.pyfrom __future__ import print_function import grpc import counters_pb2 import counters_pb2_grpc def GetRxPackets(server_int): channel grpc.insecure_channel(172.20.0.2:50051) stub counters_pb2_grpc.int_counterStub(channel) response stub.GetCounter(counters_pb2.RxpacketRequest(interfaceserver_int)) return response if __name__ __main__: response GetRxPackets(eth0) print(response)客户端代码的工作流程创建到服务端的通道获取服务存根(stub)构造请求并调用远程方法打印响应结果5. 运行与验证现在让我们启动整个系统观察gRPC的实际运行效果。5.1 启动服务端在服务端容器中执行python counters_grpc_server.py你会看到输出gRPC server listening on port 50051表示服务已就绪正在监听50051端口。5.2 发起客户端请求在客户端容器中执行python counters_grpc_client.py成功时你将看到类似输出message: Rx packets for eth0: 42 rxpackets: 42这个数字是你的eth0接口实际接收的数据包数量每次运行可能会不同。5.3 调试技巧如果遇到问题可以尝试以下方法检查服务端是否正常运行netstat -tulnp | grep 50051验证网络连通性telnet 172.20.0.2 50051查看服务端日志是否有错误输出6. 深入理解技术栈通过这个简单的Demo我们已经实践了OpenConfig技术栈的几个核心组件gRPC的优势基于HTTP/2支持双向流默认使用Protocol Buffers高效紧凑跨语言支持自动生成客户端代码Protocol Buffers的特点二进制编码比JSON/XML更高效强类型接口定义向后兼容的版本控制在实际生产环境中OpenConfig通常会结合gNMI(gRPC Network Management Interface)使用它定义了标准的RPC方法集包括Capabilities获取设备支持的能力Get读取配置和状态数据Set修改配置Subscribe订阅遥测数据流这个Demo虽然简单但已经包含了现代网络自动化最关键的技术要素。当你理解了这些基础组件如何协同工作再学习更复杂的YANG模型和gNMI规范就会容易得多。