4. 网络设备交互协议与库
在网络自动化工程师的面试中,协议与库的对比几乎是必考项。面试官真正想确认的不是你能否背出缩写,而是你能否在具体场景中做出合理选择,并说清背后的原因。本节围绕两条主线展开:一是设备交互协议(SSH、NETCONF、RESTCONF、gNMI、SNMP、Telnet)的定位与取舍;二是 Python 自动化库(Netmiko、Nornir、NAPALM、Scrapli)的适用边界与组合方式。
一、协议层:先分清"配置通道"与"监控通道"
六种协议可以按两个维度快速定位:是否面向配置、是否结构化。Telnet 与 SSH 属于交互式命令行通道,返回的是非结构化文本;SNMP 主要面向监控与状态采集,配置能力弱且厂商实现差异大;NETCONF、RESTCONF、gNMI 属于模型驱动(Model-Driven)的结构化通道,返回 XML、JSON 或 Protobuf,可直接被程序解析。
面试中常被追问的细节是:NETCONF 基于 SSH 传输(默认 830 端口),用 XML 编码,通过 <get-config>、<edit-config> 等操作配合 YANG 模型工作;RESTCONF 把同样的数据模型映射到 HTTP 方法上,用 GET/PUT/PATCH/DELETE 操作资源路径;gNMI 则基于 gRPC + HTTP/2,支持流式订阅(Subscribe),在遥测场景中优势明显。SNMP 的 GET/GETNEXT/GETBULK 适合周期性轮询,Trap 用于事件上报,但 MIB 覆盖度因厂商而异。
一个典型的选型判断可以这样表达:如果设备支持且需要高频、细粒度的状态采集,优先 gNMI 的 Subscribe 而非 SNMP 轮询;如果需要标准化配置下发且设备支持 YANG,优先 NETCONF/RESTCONF;如果面对老旧设备只开放 CLI,则退回 SSH + 文本解析,Telnet 仅在无 SSH 的极端遗留场景使用,且必须说明其明文传输的安全风险。
二、库层:从单机脚本到批量编排
Netmiko 建立在 Paramiko 之上,核心价值是把"连接设备、进入配置模式、发送命令、读取回显"这套 CLI 交互封装成稳定接口。它适合单设备或少量设备的脚本化操作,例如批量备份配置、下发 ACL。它的短板是并发能力有限、返回仍是文本,需要自己写正则或 TextFSM 解析。
Scrapli 同样面向 CLI,但更强调性能和异步支持,提供同步与 asyncio 两套 API,连接建立和命令执行速度通常优于 Netmiko,适合对执行效率敏感的场景。面试中可以这样对比:Netmiko 生态成熟、文档丰富、上手快;Scrapli 更轻量、更快、原生支持异步,但社区规模相对小。
NAPALM 的定位是"多厂商统一抽象"。它把 get_config、load_merge_candidate、commit_config 等操作抽象成统一方法,屏蔽了不同厂商 CLI 的差异,适合需要跨厂商统一配置管理的场景。但它的抽象层也带来限制:并非所有厂商特性都被覆盖,遇到抽象层未支持的命令时需要回退到原生方式。
Nornir 不是连接库,而是编排框架。它本身不负责与设备通信,而是通过 inventory 管理设备清单、通过 task 组织任务、通过 runner 控制并发,底层可挂接 Netmiko、Scrapli、NAPALM 等插件。它解决的是"几百台设备如何高效、可维护地批量执行"的问题。
三、组合实践:一个可复现的批量采集示例
下面用 Nornir + Netmiko 组合,演示批量采集设备版本信息并判断结果。示例中的 IP、账号均为假设值,仅用于说明结构。
# inventory/hosts.yaml(示例数据)
r1:
hostname: 192.0.2.11
platform: ios
username: auto
password: "Example@123"
r2:
hostname: 192.0.2.12
platform: ios
username: auto
password: "Example@123"
# tasks.py
from nornir import InitNornir
from nornir_netmiko.tasks import netmiko_send_command
from nornir_utils.plugins.functions import print_result
def get_version(task):
return task.run(
task=netmiko_send_command,
command_string="show version",
use_textfsm=True, # 尝试结构化解析
)
nr = InitNornir(config_file="config.yaml")
result = nr.run(task=get_version)
print_result(result)
# 判断依据:逐台检查 result 是否 failed
for host, r in result.items():
if r.failed:
print(f"{host} 采集失败: {r.exception}")
else:
print(f"{host} 采集成功,返回条目数: {len(r.result)}")
执行后需要观察三点:一是每台设备的 failed 标志,用于区分连接失败与命令失败;二是 use_textfsm=True 时返回是否为字典列表,若为原始字符串说明该平台缺少对应 TextFSM 模板,需要自行补充;三是整体耗时,若设备数量大而耗时线性增长,说明并发度不足,应调整 Nornir 的 num_workers 参数。
四、面试答题要点与常见追问
回答协议对比时,建议按"结构化程度—传输方式—典型用途—局限"四步展开,而不是罗列名词。回答库对比时,先说明它解决的是连接问题还是编排问题,再给出组合建议。常见追问包括:NETCONF 与 RESTCONF 如何选?可以答:设备同时支持时,若团队更熟悉 HTTP 生态、需要与 Web 系统集成,选 RESTCONF;若需要更完整的 NETCONF 操作集和事务能力,选 NETCONF。gNMI 与 SNMP 如何选?答:需要秒级遥测和流式订阅选 gNMI,只需分钟级轮询且设备 MIB 完善可用 SNMP。
下表可作为面试前的快速对照,字段只保留选型真正需要的维度。
| 协议/库 | 结构化 | 主要用途 | 关键局限 |
|---|---|---|---|
| Telnet | 否 | 遗留设备 CLI | 明文传输,不安全 |
| SSH | 否 | 通用 CLI 交互 | 返回文本需解析 |
| SNMP | 半结构化 | 监控轮询、Trap | MIB 差异大,配置弱 |
| NETCONF | 是(XML) | 标准化配置下发 | 依赖 YANG 模型覆盖 |
| RESTCONF | 是(JSON/XML) | HTTP 风格配置 | 操作集少于 NETCONF |
| gNMI | 是(Protobuf) | 遥测、流式订阅 | 设备支持度参差 |
| Netmiko | 否 | 单机/少量 CLI 脚本 | 并发弱,需自行解析 |
| Scrapli | 否 | 高性能 CLI、异步 | 生态相对小 |
| NAPALM | 是 | 多厂商统一配置抽象 | 特性覆盖有限 |
| Nornir | — | 批量编排框架 | 需搭配连接插件 |
最后提醒一个高频失分点:不要声称某个协议或库"最好"。面试官更看重你能否说出"在什么约束下选它"。把设备能力、团队技能、数据消费方式这三个约束讲清楚,选型结论自然成立。