第285篇:Telemetry 数据采集与模型驱动
关键词:YANG模型、OpenConfig、模型驱动、IETF YANG、数据建模、Telemetry采集、NETCONF
一、引言
第284篇介绍了Telemetry与gRPC的基础架构和部署方式。本节深入探讨Telemetry背后的核心基石——模型驱动(Model-Driven)理念,以及YANG数据模型如何在网络设备Telemetry采集中实现标准化和结构化。
模型驱动网络管理(MD-NMS)的核心思想是:用统一的YANG数据模型描述设备状态和配置,用NETCONF/RESTCONF管理配置,用gNMI/Telemetry采集状态,从而打破不同厂商设备的私有协议壁垒。
二、YANG 数据模型基础
2.1 YANG 模型结构
YANG(Yet Another Next Generation)是IETF定义的数据建模语言,用于描述网络设备的数据结构和操作语义。
一个典型的YANG接口模型片段:
module openconfig-interfaces {
yang-version 1.1;
namespace "http://openconfig.net/yang/interfaces";
prefix "if";
import ietf-inet-types { prefix "inet"; }
import openconfig-yang-types { prefix "oc-yang"; }
// 容器: 接口列表
container interfaces {
description "Top-level container for interfaces";
// 列表: 每个接口一个entry
list interface {
key "name";
description "List of interfaces";
leaf name {
type string;
description "Interface name, e.g., 100GE1/0/1";
}
container state {
description "Operational state data";
leaf oper-status {
type identityref {
base IF-STATE;
}
description "Operational status (UP/DOWN/UNKNOWN)";
}
leaf admin-status {
type enumeration {
enum UP { value 1; }
enum DOWN { value 2; }
enum TESTING { value 3; }
}
description "Administrative status";
}
container counters {
description "Interface counters";
leaf in-octets {
type oc-yang:zero-based-counter64;
description "Total bytes received";
}
leaf out-octets {
type oc-yang:zero-based-counter64;
description "Total bytes transmitted";
}
leaf in-pkts {
type oc-yang:zero-based-counter64;
description "Total packets received";
}
leaf out-pkts {
type oc-yang:zero-based-counter64;
description "Total packets transmitted";
}
leaf in-errors {
type oc-yang:zero-based-counter64;
description "Inbound error count";
}
leaf out-errors {
type oc-yang:zero-based-counter64;
description "Outbound error count";
}
}
leaf speed {
type oc-yang:bps;
description "Physical speed in bits per second";
}
}
container config {
description "Configuration data";
leaf description {
type string;
description "Interface description";
}
leaf enabled {
type boolean;
description "Enable/disable interface";
}
}
}
}
}
2.2 YANG 模型分类
| 模型类型 | 说明 | 示例 |
|---|---|---|
| IETF标准模型 | IETF官方维护 | ietf-interfaces, ietf-ip, ietf-routing |
| OpenConfig模型 | OpenConfig联盟维护 | openconfig-interfaces, openconfig-bgp |
| 厂商私有模型 | 设备厂商自定义 | huawei-ifm, cisco-ios-xe-interfaces |
| 扩展模型 | 基于标准模型的扩展 | 厂商增强字段 |
2.3 YANG 与 NETCONF 的关系

三、模型驱动 Telemetry 采集
3.1 采集路径与 YANG 映射
Telemetry的采集路径(Subscription Path)直接对应YANG模型的节点路径:
| Telemetry路径 | YANG节点 | 数据类型 | 说明 |
|---|---|---|---|
/interfaces/interface/state/counters/in-octets |
interfaces/interface/state/counters/in-octets |
uint64 | 接口入字节数 |
/interfaces/interface[name=100GE1/0/1]/state/oper-status |
interfaces/interface[name]/state/oper-status |
string | 接口状态 |
/bgp/neighbors/neighbor[state=ESTABLISHED]/state/uptime |
bgp/neighbors/neighbor/state/uptime |
int64 | BGP会话Uptime |
/system/cpu/state/cpu-usage |
system/cpu/state/cpu-usage |
uint8 | CPU使用率 |
3.2 结构化采集 vs 原始采集
| 采集方式 | 数据格式 | 优点 | 缺点 |
|---|---|---|---|
| 结构化采集 | GPB (编码为YANG路径+值) | 标准化、可跨设备对比 | 依赖设备YANG支持 |
| 原始采集 | 原始二进制/ASCII | 灵活性高 | 解析复杂、不可移植 |
| JSON编码 | JSON | 可读性好 | 体积大、解析开销大 |
3.3 Telemetry 数据流完整流程

3.4 华为 CE 设备支持的 YANG 模型
| YANG模型 | 说明 | 采集能力 |
|---|---|---|
| huawei-ifm | 接口管理 | 接口状态、计数器、光模块 |
| huawei-system | 系统管理 | CPU、内存、温度、风扇 |
| huawei-bgp | BGP管理 | BGP状态、Peer、路由 |
| huawei-isis | IS-IS管理 | IS-IS状态、邻居、LSDB |
| huawei-ospf | OSPF管理 | OSPF状态、邻居、LSA |
| huawei-vxlan | VXLAN管理 | VTEP、隧道、转发表 |
| huawei-aaa | AAA管理 | 用户会话、认证状态 |
四、模型驱动管理实战
4.1 NETCONF 配置下发示例
使用YANG模型通过NETCONF下发配置:
<!-- NETCONF Edit-Config 请求 -->
<rpc message-id="101"
xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<edit-config>
<target>
<running/>
</target>
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<!-- 使用 OpenConfig 接口模型 -->
<interfaces xmlns="http://openconfig.net/yang/interfaces">
<interface>
<name>100GE1/0/1</name>
<config>
<description>Uplink_to_Spine_01</description>
<enabled>true</enabled>
</config>
</interface>
</interfaces>
<!-- 配置BGP -->
<bgp xmlns="http://openconfig.net/yang/bgp">
<global>
<config>
<as>65001</as>
<router-id>10.255.1.1</router-id>
</config>
</global>
<neighbors>
<neighbor>
<neighbor-address>10.255.0.1</neighbor-address>
<config>
<peer-as>65001</peer-as>
<auth-password cipher>Admin@123</auth-password>
</config>
</neighbor>
</neighbors>
</bgp>
</config>
</edit-config>
</rpc>
4.2 NCClient(Python)NETCONF 操作
from ncclient import manager
import xml.etree.ElementTree as ET
# NETCONF连接CE交换机
with manager.connect(
host="10.255.1.1",
port=830,
username="admin",
password="Admin@123",
hostkey_verify=False,
device_params={"name": "huawei"}
) as m:
# 1. 获取接口配置 (get-config)
filters = [('subtree', '''
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
<interface>
<name>100GE1/0/1</name>
</interface>
</interfaces>
''')]
result = m.get_config(source="running", filter=filters)
print(ET.tostring(ET.fromstring(result.xml), encoding="unicode"))
# 2. 下发配置 (edit-config)
config = '''
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
<interface>
<name>100GE1/0/1</name>
<description>Updated by NETCONF</description>
<enabled>true</enabled>
</interface>
</interfaces>
'''
m.edit_config(target="running", config=config)
print("Configuration updated successfully")
# 3. 获取状态数据 (get)
state_result = m.get(filter=('subtree', '''
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
<interface>
<name>100GE1/0/1</name>
<oper-status/>
</interface>
</interfaces>
'''))
print(f"Interface state: {state_result.xml}")
4.3 基于 YANG 的 Telemetry 订阅脚本
from gnmi_cli import gNMI_Subscriber
import json
class TelemetrySubscriber:
"""基于YANG模型的Telemetry订阅器"""
# 定义YANG路径到监控指标的映射
YANG_PATHS = {
# 接口监控
"/interfaces/interface/state/counters/in-octets": "if_in_octets",
"/interfaces/interface/state/counters/out-octets": "if_out_octets",
"/interfaces/interface/state/counters/in-errors": "if_in_errors",
"/interfaces/interface/state/counters/out-errors": "if_out_errors",
"/interfaces/interface/state/oper-status": "if_oper_status",
# 系统监控
"/system/cpu/state/cpu-usage": "cpu_usage",
"/system/memory/state/memory-usage": "memory_usage",
"/system/state/temperature": "temperature",
# BGP监控
"/bgp/neighbors/neighbor/state/session-state": "bgp_session_state",
"/bgp/neighbors/neighbor/state/uptime": "bgp_uptime",
}
def __init__(self, device_ip, port=4073):
self.device_ip = device_ip
self.port = port
self.subscriber = None
def subscribe_all(self):
"""订阅所有预定义YANG路径"""
paths = list(self.YANG_PATHS.keys())
self.subscriber = gNMI_Subscriber(
target=f"{self.device_ip}:{self.port}",
paths=paths,
mode="sample",
interval=10000 # 10秒
)
self.subscriber.start(callback=self.on_update)
def on_update(self, update):
"""处理Telemetry更新"""
for path, value in update.items():
metric_name = self.YANG_PATHS.get(path, path)
# 计算接口带宽利用率(每秒)
if "octets" in metric_name:
# 需要与前一次采样值对比计算速率
rate = self._calculate_rate(metric_name, value)
print(f"[{metric_name}] rate={rate:.2f} B/s")
else:
print(f"[{metric_name}] value={value}")
if __name__ == "__main__":
subscriber = TelemetrySubscriber("10.255.1.1")
subscriber.subscribe_all()
4.4 YANG 模型与 Prometheus 集成
# gnmi_exporter.yml - gNMI到Prometheus的导出配置
collection:
- name: dc1_leaf_01
address: 10.255.1.1:4073
port: 9399 # Prometheus scrape端口
path:
- /interfaces/interface/state/counters/in-octets
- /interfaces/interface/state/counters/out-octets
- /system/cpu/state/cpu-usage
interval: 10s
encoding: json_ietf
metrics:
- name: interface_in_octets
path: /interfaces/interface/state/counters/in-octets
type: counter
labels:
- name # 接口名作为标签
description: "Total bytes received on interface"
rate: true # 自动计算速率
- name: interface_out_octets
path: /interfaces/interface/state/counters/out-octets
type: counter
labels:
- name
description: "Total bytes transmitted on interface"
rate: true
- name: system_cpu_usage
path: /system/cpu/state/cpu-usage
type: gauge
description: "CPU usage percentage"
五、模型驱动管理的优势与挑战
5.1 优势
| 维度 | 说明 |
|---|---|
| 标准化 | YANG模型提供统一的数据结构,跨厂商可互操作 |
| 可编程 | 数据结构化,便于程序化处理和分析 |
| 版本管理 | YANG模型本身支持versioning,兼容性好 |
| 自动化 | 模型驱动的配置和采集天然适合自动化编排 |
| 一致性 | 配置和状态使用同一模型,减少数据映射错误 |
5.2 挑战
| 挑战 | 说明 | 应对方案 |
|---|---|---|
| 模型差异 | 不同厂商YANG模型不一致 | 优先使用OpenConfig/IETF标准模型 |
| 设备支持 | 老旧设备不支持YANG/NETCONF | 通过适配器层转换CLI到YANG |
| 模型版本 | YANG模型频繁更新导致兼容性问�� | 使用最新的稳定版本,做好回归测试 |
| 性能 | 大模型解析开销 | 精确订阅所需路径,避免全量订阅 |
六、总结
| 能力 | 传统CLI | 模型驱动(YANG) |
|---|---|---|
| 数据格式 | 自由文本 | 结构化XML/JSON/GPB |
| 可编程性 | 低(需正则解析) | 高(直接API调用) |
| 标准化 | 无 | IETF/OpenConfig标准 |
| 配置管理 | 手动/脚本 | NETCONF/RESTCONF |
| 状态采集 | CLI抓取/SNMP | gNMI/Telemetry |
| 版本兼容 | 差 | YANG版本号管理 |
| 最佳实践 | 说明 |
|---|---|
| 优先标准模型 | 使用OpenConfig/IETF标准模型,避免厂商私有模型 |
| 精确订阅 | 只订阅需要的YANG路径,减少带宽和存储开销 |
| 模型版本控制 | 将YANG模型纳入版本管理,跟踪模型变更 |
| 模型验证 | 使用YANG编译器(如pyang)验证模型语法 |
| 渐进迁移 | 从标准接口/YANG模型逐步扩展到BGP/ISIS等复杂模型 |
思考
- YANG模型定义了数据的结构,但不同厂商对同一YANG模型(如openconfig-interfaces)的支持程度可能不同,如何检测设备的模型支持差异?
- 当YANG模型版本升级时(如从1.0到1.1),已有的Telemetry订阅和NETCONF配置是否需要修改?如何平滑迁移?
- OpenConfig模型和IETF YANG模型在某些领域存在重复定义(如接口模型),实际部署中如何选择?
下篇预告:第286篇:数据中心网络运维 AI 辅助分析