4. 真实数据源#
新服务需要在本周末上线。变更内容很简单:一个新 VLAN、一个新子网、更新防火墙规则,以及边缘路由器上的一个新 BGP community。网络工程师清楚地知道该做什么。然而接下来是跨越五个系统、历时四天的协调工作:IPAM 工具用于预留子网,CMDB 用于注册服务,防火墙管理平台用于推送新策略,路由器配置系统用于 BGP community,监控平台用于添加新阈值。每个系统都有自己的界面、自己的数据模型、自己的审批流程。由于没有共享参考,工程师不得不手动携带上下文:将数值从一个系统复制到下一个系统,希望中间步骤不会出现偏差。
六个月后,服务下线。VLAN 被移除,子网被释放,但防火墙规则留了下来。没人记得它与那个服务关联。BGP community 还残留在两台边缘路由器上。监控阈值持续触发低优先级告警,NOC 学会了直接忽略。随着时间推移,网络积累了一层层孤立的配置:那些从未被完整追踪、从未被完整回滚、从未与共享意图记录相关联的变更残骸。
这就是在没有真实数据源的情况下运营网络的真实面貌。不是单一的灾难性故障,而是不一致性的缓慢累积:每次变更都需要更新多个孤立系统,却没有任何机制追踪哪些内容是相互关联的。
每个自动化系统都从一个问题开始:我究竟要做什么? 当你部署防火墙规则、添加 IP 地址或配置 VLAN 时,你是基于某种意图表达来操作的。这个表达就是你的真实数据源(Source of Truth):对于应该部署什么的单一、可靠版本。
我将"真实数据源"(Source of Truth)和"意图"(Intent)互换使用,它们是完全相同的概念。
没有可靠的真实数据源,网络运营就会沦为部落知识的混乱。工程师对已部署内容各执一词。电子表格与实际运行状态相矛盾。两个不同的自动化系统对同一设备做出冲突的变更。当故障发生时,你只能进行考古挖掘:“为什么这样配置?谁批准的?何时变更的?”
本章探讨如何构建一个真实数据源:无论管理几十台还是几十万台设备,它都能为所有需要数据的对象(人、自动化、其他系统)提供服务,保持数据准确可信,并处理从多个来源汇聚数据的复杂性。我们将介绍六个构建模块:建模、消费、执行、版本控制、聚合和设计驱动,它们共同为网络自动化奠定坚实基础。我还会涉及将现有网络接入该系统的实际问题,并展示现有的解决方案。
4.1. 基础概念#
真实数据源做三件事:定义你如何表达需求,意图存放在哪里,以及如何随时间保持其可信度。没有它,其他构建模块就成了没有共享参考的孤立工具;有了它,它们才能协同工作。
4.1.1. 目标#
你的真实数据源需要做六件事:
捕获一切所需内容。存储网络的完整图景:配置、资产、拓扑、服务、IP 地址、电路、设备规格、密钥、维护窗口、合规信息以及所有权归属。不仅包含今天正在运行的内容,还包括已规划的和正在退役的。当所有这些数据集中在一处而非散落在电子表格和人脑中时,你的自动化系统才真正具备做出明智决策所需的上下文。
让运营人员以业务术语思考,而非设备语法。员工应在业务层面工作(“新增一个分支机构"或"建立 MPLS 服务”),而非 Command Line Interface (CLI) 层面。在幕后,系统负责推导出实际的设备专属配置。这让人们专注于想要实现的目标,而不是底层细节。
让人员和机器轻松访问数据。系统需要 Application Programming Interface (API)(Representational State Transfer (REST)、GraphQL),以便自动化获取和修改数据;需要 Web UI 和 Command Line Interface (CLI),以便人员浏览和编辑;所有人都需要完善的访问控制,确保只能看到应该看到的内容。系统可以同时运行数百个自动化工作流、数十名员工编辑数据、外部系统同步数据,一切保持一致且高效。
保持数据清洁可信。验证一切:检查数据类型是否正确、关系是否合理、VLAN 是否在有效范围内、IP 地址是否重复。追踪谁在何时做了什么变更。在重大变更生效前允许人员审批。出错时可以回滚。你的自动化需要信任数据的准确性,因为错误数据会导致错误的网络状态和中断。
让人员并行工作而不相互干扰。多个团队应能同时提出变更。变更被分组为原子包:要么全部生效,要么全部失败,不存在中间状态。变更可以在暂存区测试后再上线。对于大型迁移,可以分支操作,完成后再合并回来。你始终知道当前使用的是哪个意图,以及哪些是待提议的。
从其他系统引入数据。你可能已经有用于硬件的资产管理系统、用于地址的 IP 系统、用于连接的电路提供商、用于服务的 CMDB。不要重复建设,而是同步引入。明确规定哪个系统拥有哪类数据,保持双向同步。这样你就能获得统一视图,而无需重新发明轮子。
4.1.2. 支柱#
这六个支柱不是独立功能,而是构成一个分层架构。建模定义可以表达什么。设计驱动将表达转化为技术制品。消费使这些制品对所有需要它们的系统可用。执行确保数据在写入时保持可信。版本控制随时间保留意图记录,支持回滚和审计。聚合通过从已拥有数据的系统引入权威数据,防止 SoT 成为又一个孤立数据孤岛。
缺少其中任何一个,其余的都会退化。没有执行,消费就提供了错误数据。没有版本控制,故障发生时就无法推断何时发生了什么变更。没有聚合,运营人员就要在多个系统中维护重复数据,SoT 就会失去可信度。第 4.2 节将深入讨论每一个方面。
在详述六个功能之前,先来厘清真实数据源的职责范围。
4.1.3. 职责范围#
在深入实现细节之前,重要的是先了解真实数据源负责什么,不负责什么。
职责范围内:
真实数据源管理所有意图数据:对网络应呈现什么样子的完整定义。这包括生产配置、暂存环境、开发分支和测试场景。所有描述"你想要什么"的内容都存放在这里。
职责范围外:
真实数据源不做几件看似相关的事情:
可观测性数据:真实数据源不存储指标、日志或运行时状态。但它确实定义了用于比较的预期值,例如告警的阈值或基线性能数字。实际的可观测性数据存放在别处(第 6 章介绍)。
网络交互:真实数据源不与设备通信,也不推送配置。它提供必要的制品(设备配置、验证规则、部署清单),但不执行它们。那是执行器的工作(第 5 章)。
编排逻辑:真实数据源不定义部署变更的步骤序列或工作流。它定义预期的最终状态。如何到达那里(哪些设备先行、哪些验证步骤、回滚流程)属于编排器的职责(第 7 章)。
把真实数据源想象成网络自动化策略的北极星,是对"网络应该是什么样子"这个问题的单一权威答案。你的自动化系统中的其他一切(执行、监控、编排)都参考这个真相来完成自己的工作。当现实偏离意图时,真实数据源告诉你现实应该变成什么样。
4.2. 功能详述#
现在来讨论实现这一切的六个功能。
每个功能都对应一个目标和支柱:
- 建模:定义存储什么数据以及数据之间的关系。设备模型、接口、VLAN、电路、服务,随需求变化而演进。
- 设计驱动:通过模板和逻辑将高级意图转化为实际设备配置。
- 消费:人员和系统实际获取和使用数据的方式。Application Programming Interface (API)、Web UI、Command Line Interface (CLI)。所有人按角色获得相应访问控制。
- 执行:防止错误数据混入。验证、唯一性检查、引用完整性。清晰的错误消息。
- 版本控制:保留完整历史。谁在何时变更了什么,以及为什么。需要时回滚。
- 聚合:从其他系统(CMDB、IPAM 等)引入数据并保持同步。
graph LR
%% --- Subgraphs ---
subgraph 目标
direction TB
A1[捕获一切所需内容]
A2[让运营人员以业务术语思考]
A3[让人员和机器轻松访问数据]
A4[保持数据清洁可信]
A5[让人员并行工作而不干扰]
A6[从其他系统引入数据]
end
subgraph 支柱
direction TB
B1[灵活数据建模框架]
B2[设计与模板]
B3[API 与接口]
B4[数据验证]
B5[变更历史]
B6[数据聚合]
end
subgraph 功能
direction TB
C1[建模]
C2[设计驱动]
C3[消费]
C4[执行]
C5[版本控制]
C6[聚合]
end
A1 --> B1 --> C1
A2 --> B2 --> C2
A3 --> B3 --> C3
A4 --> B4 --> C4
A5 --> B5 --> C5
A6 --> B6 --> C6
classDef row1 fill:#eef7ff,stroke:#4a90e2,stroke-width:1px;
classDef row2 fill:#ddeeff,stroke:#4a90e2,stroke-width:1px;
classDef row3 fill:#cce5ff,stroke:#4a90e2,stroke-width:1px;
classDef row4 fill:#b3d8ff,stroke:#4a90e2,stroke-width:1px;
classDef row5 fill:#99ccff,stroke:#4a90e2,stroke-width:1px;
classDef row6 fill:#80bfff,stroke:#4a90e2,stroke-width:1px;
class A1,B1,C1 row1;
class A2,B2,C2 row2;
class A3,B3,C3 row3;
class A4,B4,C4 row4;
class A5,B5,C5 row5;
class A6,B6,C6 row6;
意图模块的架构视角如下:
graph TB
subgraph T1[外部层]
A[消费]
end
subgraph T2[数据层]
B[设计驱动]
D[建模]
end
subgraph T3[引擎层]
C[聚合]
E[执行]
F[版本控制]
end
A <--> B
A <--> D
B <--> D
D <--> C
D <--> E
D <--> F
4.2.1. 建模#
你的数据模型至关重要:它决定了你能表达什么,以及工作起来有多顺畅。正如乔治·博克斯所说:“所有模型都是错的,但有些是有用的。“没有适合所有人的完美模型。以我的经验,数据建模更像是艺术而非科学。但某些模式在成功项目中反复出现。
4.2.1.1. 基础原则#
数据的组织方式很重要。 它决定了你能表达什么,以及系统验证和使用数据的效率。不同格式有不同的权衡。YAML 可读性强但验证有限。JavaScript Object Notation (JSON) 通用性好但对人而言较冗长。Yet Another Next Generation (YANG) 增加了验证但学习曲线陡峭。根据实际需求选择。
| 格式 | 用途 | 优势 | 权衡 |
|---|---|---|---|
| YAML | 配置、人工编辑 | 可读性强、简洁 | 模式验证有限 |
| JavaScript Object Notation (JSON) | Application Programming Interface (API)、文档存储 | 工具生态完善 | 对人而言较冗长 |
| XML | 基于标准的交换 | XSLT 处理、模式支持 | 语法重 |
| Protocol Buffers | 性能、序列化 | 紧凑、版本化 | 二进制,需代码生成 |
| YANG | 网络设备建模 | 行业标准(RFC 6020),层次约束 | 学习曲线陡峭 |
数据存在于不同层次。 同一网络部件可以用多种方式描述,服务于不同目的:
- 服务层:业务友好(“为分支机构 X 建立 MPLS L3VPN”)
- 技术层:技术规格(“BGP AS 65001,路由目标 65001:100,策略…")
- 设备层:实际配置(“interface xe-0/0/0; unit 100;…")
好的模型连接这些层次。你可以从业务层开始,自动生成设备配置。但并非总需要三个层次,这取决于你在构建什么。
4.2.1.2. 数据持久化与规模#
数据存储方式的选择对一致性、性能和演进具有深远影响,当网络从数百个扩展到数十万个管理对象时,这些影响变得至关重要。
关系型数据库(如 MySQL、PostgreSQL):这是大多数团队的稳妥选择,我这是褒义。它们强制 schema 一致性,提供 ACID 事务,而且团队里的每个工程师都已经懂 SQL。它们非常擅长表示规范化层次结构(包含接口的 VLAN),防止数据异常。缺点是:大规模下 schema 变更代价高昂,跨数百万行的深层联结性能下降。但这是个好问题,意味着你真的部署了什么。
文档数据库(如 MongoDB、CouchDB):如果需要 schema 灵活性和水平扩展性,这是不错的选择。文档天然建模嵌套结构(设备及其所有配置和元数据作为一个整体)。但这里有个陷阱:你现在负责跨文档的一致性,复杂查询很快变得昂贵。除非有特定原因选择文档型,否则坚持使用关系型。
图数据库(如 Neo4j):当关系比对象更重要时,这些数据库确实更好:“这个接口连接到哪些 VLAN?哪些设备在这两个位置之间路由?” 它们能高效遍历任意深度的关系。但除非你在不断地进行复杂拓扑查询,否则你是在选择一个小众方案。你的运维团队不了解它,工具成熟度较低,简单更新的写入性能也落后。图数据库解决真实问题,但先确认你真的有那些问题。
flowchart TD
Q1{主要需求?}
Q1 -->|深度遍历复杂关系| Q2{频繁拓扑查询?}
Q1 -->|Schema 频繁演进| DB_D[文档存储]
Q1 -->|结构化查询、引用完整性| DB_R[关系型数据库]
Q2 -->|是| DB_G[图数据库]
Q2 -->|偶尔| DB_R
style DB_R fill:#ccffcc,stroke:#28a745
style DB_G fill:#cce5ff,stroke:#4a90e2
style DB_D fill:#ffffcc,stroke:#ffc107
从不同角度了解更多关于数据持久化的内容,请参见可观测性章节。
数据库选型是该领域产品的关键差异化因素之一。例如,NetBox 和 Nautobot 使用关系型数据库,而 Infrahub 使用图数据库,详见第 4.2.8 节。
持久化也可以使用基于文件的存储,采用 YAML 或 JavaScript Object Notation (JSON)(或 CSV)等数据模型,通常在 Git 系统中进行版本控制追踪。
大多数生产级真实数据源系统使用多语言持久化:关系型数据库用于权威意图和关系,文档存储或 Git 用于灵活性和缓存,图能力用于拓扑分析。
模型粒度应该多细? 这对性能很重要。如果将每台设备上的每个接口建模为单独的对象,中型网络最终会有 50,000 多个对象,查询变慢,更新变痛苦。
实际做法:对常见模式使用模板。声明"接口 1-40 使用这个标准模板”,只追踪例外情况。这样只需 2 个对象而不是 40 个,查询保持快速,渲染仍然有效。
在第 11 章中,我们将进一步探讨这类决策如何影响性能。
4.2.1.3. 网络数据域#
全面的真实数据源实现通常对以下相互关联的域建模:
- 清单与资产:物理和逻辑设备、硬件规格、序列号、采购日期、合同条款、生命周期阶段
- 数据中心基础设施:位置(地理和层次)、建筑、楼层、机房、机架、配电、线缆路由
- IP 地址管理(IPAM):地址池、子网、分配、DNS 解析、DHCP 范围、利用率追踪
- 虚拟化与云:VPC、子网、安全组、计算实例、存储、容器编排关系
- 连接:物理电路(MPLS、Ethernet)、虚拟隧道、对等关系、带宽分配、QoS 策略
- 路由:BGP community、自治系统、路由策略、前缀列表、L3VPN 服务的路由目标
- 服务:逻辑服务定义(L3VPN、L2VPN、防火墙穿越)、服务到设备映射、SLA
- 安全与合规:访问控制列表、防火墙规则、安全区域、合规标签、审计要求
- 管理:SNMP 详情、gNMI 订阅、NTP 源、syslog 目标、TACACS+/RADIUS 集成
这些域相互依赖:路由引用连接,服务跨越清单和 IPAM,安全策略同时适用于设备和服务。设计良好的 SoT 明确建模这些关系,而不是将每个域视为孤立的表。
graph TD
INV[清单与资产]
DC[数据中心基础设施]
IPAM[IP 地址管理]
VIRT[虚拟化与云]
CONN[连接]
ROUTE[路由]
SVC[服务]
SEC[安全与合规]
MGMT[管理]
DC --> INV
INV --> IPAM
INV --> MGMT
CONN --> INV
VIRT --> IPAM
ROUTE --> CONN
SVC --> INV
SVC --> ROUTE
SVC --> IPAM
SEC --> INV
SEC --> SVC
classDef foundation fill:#ddeeff,stroke:#4a90e2,stroke-width:2px
classDef overlay fill:#e8f5e9,stroke:#28a745
classDef policy fill:#fff3cd,stroke:#ffc107
class INV,IPAM,CONN foundation
class ROUTE,VIRT,DC,MGMT overlay
class SVC,SEC policy
除了网络特定域,还需要许多其他数据类型。例如,用于存储凭证的密钥后端。更广泛地说,全面的数据管理属于全球 IT 基础设施管理系统的范畴。
我想分享一个许多团队在争论使用网络专属数据源(如 NetBox)还是通用数据源(如 ServiceNow)时的常见问题。根据我的经验,尽管可以实现类似效果,但 ServiceNow 是公司范围内的系统,使其演进更加困难(也更慢),从而拖慢了网络团队利用它进行完整网络表示的速度。
数据分类与通用属性
在各网络域中,某些分类模式反复出现。设计良好的模型包含这些基础属性以保持一致的数据处理:
- 角色:该对象服务于什么目的?(核心、汇聚、接入;主用、备用)
- 状态:是活跃、已规划、退役中还是已退役?
- 类型:是什么类型的对象?(VLAN、设备、电路、服务)
- 所有权:哪个团队或业务单元管理这个?
- 位置:该资源在地理或组织上位于何处?
4.2.1.4. 模型设计模式:可扩展性、多态性与迁移#
有些解决方案基于创建者对网络应有样子的假设内置了模型。如果你的网络符合那个假设,这很棒;如果不符合,就不那么美好了。其他解决方案让你从零开始构建:灵活性很好,但需要自律。通常,最好的方法是混合型:对常见情况(80% 的通用场景)使用内置模型,同时确保可以针对特定需求进行扩展。
从专制到定制的谱系
这里存在一个谱系,值得了解你处于哪个位置:
高度专制的模型(如开箱即用的 NetBox):
- 优点:部署快,决策少,内置最佳实践
- 缺点:如果网络不符合模型,会很痛苦;更改模型困难
完全定制的模型(从零开始构建,如 Infrahub):
- 优点:完全适配特定需求,无多余字段
- 缺点:需要时间设计,大量试错,没有他人可以借鉴(但有参考资料)
尽管 Infrahub 允许构建完全定制的模型,但它也提供了现成的专制模型供快速上手。
实际应该从哪里开始?我告诉所有人:从 NetBox、Nautobot 或 Infrahub 等有专制模型的工具开始。句号。不管你认为自己的网络有多特殊。那些"我们要构建自己完美模型"的团队还在建模,而用现成工具的团队早在很多个月前就交付了有效的模型。
你不是 Google(也许是?)。在很多情况下,你不是在构建超大规模云。用现有的东西,在遇到真实限制(而非想象中的限制)时再扩展,交付能用的东西。
显然,如果你预见到有非常特殊的网络用例,可以考虑哪个工具能更好地支持它,但不要从第一天起就完全重新发明轮子。
唯一重要的决定是:能否在不重写的情况下扩展?如果添加一个自定义字段来追踪"成本中心"需要重建整个 schema,请逃离。如果可以在 20 分钟内将其添加为自定义属性,你就找到了合适的工具。
你需要 80% 的标准化和 20% 的灵活性(处理你的特定现实)。任何声称"无限灵活"的东西都需要无限时间来配置。
多态性:一个模型,多种变体
并非所有接口都生而平等。物理光口和隧道接口共享一些属性,但本质上是不同的东西。你可以为每种类型创建完全独立的模型,但这很快会变得混乱,并限制可用性。
更好的方法:定义一个涵盖共同点的基础模型,然后为不同细节创建专门变体。
# 所有接口共享这些基础属性
interfaces:
- name: "eth0"
type: "physical"
status: "up"
mtu: 1500
ipv4_address: "192.0.2.1/24"
# 物理光口有额外属性
- name: "eth0"
type: "physical_optical"
status: "up"
mtu: 1500
ipv4_address: "192.0.2.1/24"
optics_module: "100GBASE-LR4"
tx_power_dbm: -2.5
rx_power_dbm: -8.3
laser_temperature: 48.2
# 隧道接口的底层完全不同
- name: "tun-vpn-dallas"
type: "tunnel_gre"
status: "up"
mtu: 1476
ipv4_address: "10.0.0.1/30"
tunnel_source: "203.0.113.1"
tunnel_destination: "198.51.100.5"
tunnel_encap: "GRE"
tunnel_key: 100这样,你的脚本可以查询"该设备上的所有接口”,而不需要知道在与光口还是隧道交互。但当需要光口特定细节时(获取 TX 功率读数),可以访问那些专门字段。将来添加新接口类型?没问题,只需添加另一个变体。
模型会变:为此做好规划
网络存在数十年,你的模型不会一成不变。你会添加新字段,改变事物之间的关系,弃用不再有用的东西。但你不能一键切换就破坏一切基于旧 schema 运行的内容。
挑战在于,当模型变更时,大量下游内容可能会出问题:验证器需要新规则,API 返回内容改变,数据库查询假设某些列存在,你的模板需要不同的字段路径,报告是针对旧结构编写的。所有这些都需要适应,或者至少不能灾难性地崩溃。以下是如何在不炸掉一切的情况下处理变更:
在删除前标记为弃用。如果一个字段要消失,提前 2-3 个版本告知所有人,给他们迁移的宽限期。
在过渡期间支持字段别名。老代码请求
device_name?在底层路由到hostname。你的 API 仍然有效,人们有时间更新自动化。创建迁移辅助工具。当你重组数据(如将接口从扁平列表移到设备下的嵌套结构),提供脚本来完成繁重工作。
用依赖你数据的一切进行测试。在推出 schema 变更之前:API 是否仍以旧方式返回数据(通过别名)?模板是否仍能渲染?SQL 查询是否仍然有效?与外部系统的集成是否仍能解析收到的内容?
预期生产环境中同时存在多个版本一段时间。大型组织经常同时有三个不同 schema 版本的设备:
150 台设备使用 schema 1.9(旧版) 300 台设备使用 schema 2.0(当前) 50 台设备使用 schema 2.1(beta 测试)
你的系统需要同时处理这三种情况而不出问题。这种复杂性是值得的:网络太重要了,不能因粗心的 schema 变更而受损。
4.2.1.5. 配置模板#
模板将抽象意图(“我需要一个 VLAN”)转化为实际的 Command Line Interface (CLI) 命令。核心规则是:模板包含逻辑,不包含数据。模板说"使用数据模型中的 VLAN ID,在这里输出”。实际的 VLAN ID 来自数据,不来自模板。这使数据可移植且可测试。Jinja2 很流行,因为它可读性好,与 Python 和 Ansible 集成,适用于真实网络。但它不是唯一选项,有很多有效的替代方案。
例如,给定接口的数据结构:
interfaces:
- name: Ethernet1
description: Uplink to core
enabled: true
- name: Ethernet2
description: Server port
enabled: false以及这个 CLI 配置的 Jinja2 模板:
# Interfaces
{% for iface in interfaces %}
interface {{ iface.name }}
description {{ iface.description }}
{% if iface.enabled %}
no shutdown
{% else %}
shutdown
{% endif %}
{% endfor %}它会生成以下 CLI 输出:
# Interfaces
interface Ethernet1
description Uplink to core
no shutdown
interface Ethernet2
description Server port
shutdown注意数据和配置制品之间清晰的关注点分离。
Jinja 的一个有趣替代方案是 CUE 声明式配置语言,它统一了多种数据功能:
- 原始数据,类似 YAML
- 数据验证/schema,类似 JSON Schema(更多内容见执行部分)
- 动态数据生成,类似 Jinja
CUE 将配置视为带有强制不变量的类型化、可组合数据,而非松散结构化的文本(如 Jinja)。
4.2.2. 设计驱动#
当你有 50 台设备和 30 个 VLAN 时,可以逐一管理:手动创建每个 VLAN、配置每个接口、分配每个 IP。虽然繁琐但可管理。
当你有 5,000 台设备和数百个服务时,手动管理是不可能的。新增一个分支机构意味着为每个位置手动指定 100 多个配置项。设计驱动构建模块解决了这个问题:运营人员用高级语言描述需求(“新增一个分支机构”),系统将其扩展为完整的技术规格。
4.2.2.1. 从业务意图到技术数据#
示例场景 — “在达拉斯新增分支机构”:
业务意图(高层):
{
"type": "branch_office",
"location": "dallas-tx",
"site_code": "DAL-01",
"circuit_count": 2,
"employee_count": 50,
"applications": ["erp", "voip", "video"]
}设计处理过程
flowchart LR
A[业务意图]
B[应用模板]
C[分配资源]
D[解析逻辑]
E[渲染细节]
F[执行器所需对象]
A --> B --> C --> D --> E --> F
style A fill:#fff3cd,stroke:#ffc107
style B fill:#ffe6cc,stroke:#fd7e14
style C fill:#d4edda,stroke:#28a745
style D fill:#cce5ff,stroke:#4a90e2
style E fill:#e2d9f3,stroke:#6f42c1
style F fill:#d1ecf1,stroke:#17a2b8
| 阶段 | 任务 |
|---|---|
| 1. 应用模板 | 创建站点对象;从委托池(区域 IPAM)分配子网;创建数据、语音、访客 VLAN;定义安全区域和防火墙规则 |
| 2. 分配资源 | 站点的下一个可用子网 /22:10.15.0.0/22;下一个可用 VLAN 范围:2010-2014;下一个可用 BGP community:65001:2010 |
| 3. 解析逻辑 | 站点员工数 < 100?是 → 小型办公室模板;需要冗余电路?是 → 创建 2 个 BGP 邻居;应用包含 [erp, voip]?是 → 添加防火墙策略 |
| 4. 渲染细节 | PE 设备配置(BGP 建立、路由目标、语音 QoS);CE 设备配置(LAN 接口、VLAN、NTP);防火墙策略(允许 ERP 流量、优先语音);办公服务的 DNS 条目;监控设置(SNMP、syslog、告警) |
| 5. 输出 | 50 多个准备部署的配置对象 |
这将低投入的高级意图转化为全面的技术细节。
4.2.2.2. 设计模式与可复用构建块#
有效的设计系统依赖于模式库。
网络设计模式库
| 模式 | 组件 |
|---|---|
| 小型分支机构 | 单台边缘路由器(通过备份实现弹性);2-3 个 VLAN(数据、语音、访客);单条 MPLS VPN 带 BGP 备用对等;语音 QoS(EF、AF 类);防火墙规则:仅允许 ERP 和 VoIP |
| 中型区域枢纽 | 冗余边缘路由器(主备模式);10-15 个 VLAN(按部门 + 访客 + OOB);多条 MPLS VPN(部分按应用定制);复杂 QoS(6 个类别);高级防火墙策略(应用层) |
| 数据中心边缘 | 四重冗余 Clos 拓扑;100 多个 VLAN(按客户自动生成);BGP unnumbered、多路径;自动 VLAN 分配 |
每个模式都编码了经过验证的架构决策。偏离需要明确批准,但部署它们应被视为正常操作。
4.2.2.3. 使设计可重现#
这里有个问题:你在周一设计一个站点并分配 VLAN 100。周二设计另一个站点并分配 VLAN 101。但如果你六个月后重新运行周一的设计进行验证,系统可能分配 VLAN 102,因为 VLAN 100 已被使用。
这不可重现。解决方案:每次发出设计请求时,记录哪个设计获得了哪些资源。如果相同请求再次出现,返回相同的 VLAN。这需要永久追踪请求到资源的映射,并始终以相同顺序分配。
- 确定性分配顺序:始终以相同顺序迭代候选项
- 原子分配:资源预留是原子的,不可能部分分配
这就是为什么许多设计系统使用内容寻址存储(设计的哈希值)来确保一致性。
4.2.2.4. 渲染与构建的区别#
设计系统分离两个阶段:
| 阶段 | 输入 | 输出 | 副作用 | 回答的问题 | 用例 |
|---|---|---|---|---|---|
| 渲染 | 高层设计 | 技术规格 | 无——不分配资源,不推送变更 | “会创建什么?““有错误吗?““能看到提议的数据扩展吗?” | 审批前审查;验证测试;估算变更范围 |
| 构建 | 渲染的规格 | 真实变更(IP 提交、VLAN 创建、配置推送、审计跟踪) | Atomic Operation、Idempotency、可监控、可回滚 | “实际部署了什么?““何时发生的?““可以回滚吗?” | 生产部署;资源预留;触发执行工作流 |
支持无构建的渲染使能:
- 提交前的安全验证
- 无风险的假设分析
- 团队评审和审批工作流
- 先在测试环境中暂存
4.2.2.5. 设计版本控制与演进#
网络设计随时间演进。新模式出现,工具改进。2020 年的设计可能需要针对 2025 年进行更新。
设计版本控制的挑战:
- 设计版本 1(2020):分支机构模板:单台路由器,2 个 VLAN
- 设计版本 2(2023):分支机构模板:双路由器(冗余),4 个 VLAN,安全性增强
使用版本 1 部署的分支机构会怎样?
- 继续运行旧版本?(安全债务)
- 强制升级所有分支?(变更风险)
- 逐步迁移?(运营复杂性)
解决方案:
设计即代码,带版本控制
designs/
├─ branch_office_v1.yaml (已于 2023-01-01 弃用)
├─ branch_office_v2.yaml (当前)
└─ branch_office_v2_beta.yaml (测试中)
Sites:
- site: DAL-01
design: branch_office_v2 (引用特定版本)
design_parameters: {...}这允许:
- 精确知道哪个设计版本生成了每个站点
- 逐步迁移(逐站点更新)
- 如果 v2 有问题可以回滚到 v1
- 在推广前在暂存环境中测试 v3
雪花场景处理
大多数站点使用 design_v2 模板,但 DAL-01 站点有特殊要求:
- 额外机架空间(旧建筑特殊情况)
- 非常规 IP 寻址(遗留分配)
- 自定义防火墙规则(历史业务需求)
解决方案:
- 以 design_v2 为基础部署
- 应用站点专属覆盖
- 单独追踪覆盖内容(记录雪花)
这防止了:
- 将例外设计进模板(污染设计)
- 手动配置例外(随时间产生漂移)
- 失去例外存在原因的上下文
4.2.3. 消费#
锁在数据库里的数据毫无价值。消费层是人员和系统实际获取数据的方式。使其简单,你就获得了支持;使其困难,人们就会绕过它。
4.2.3.1. API 设计与安全#
不同的 API 风格服务于不同的消费模式。以下是当前最流行的一些选择:
API 风格对比
| 接口 | 请求模式 | 用例 | 优势 | 权衡 |
|---|---|---|---|---|
| Representational State Transfer (REST) | 资源 URL 上的 Hypertext Transfer Protocol (HTTP) 动词(GET、POST、PATCH、DELETE) | 通用 CRUD | 简单、广泛理解、无状态 | 可能需要多次请求;Versioning 挑战 |
| GraphQL | 单一端点,客户端指定精确所需字段 | 复杂的多资源查询 | 灵活、客户端驱动、减少过度获取 | 服务器实现更复杂,N+1 查询风险 |
| gRPC | 基于 Protobuf 的 HTTP/2 RPC | 高性能、低延迟 | 双向流、二进制效率、比 REST 快 10-100 倍 | 学习曲线,浏览器支持有限 |
| Webhooks | 服务器将变更推送到已注册端点 | 响应式自动化、实时同步 | 异步、解耦、无轮询开销 | 不可靠投递、重试复杂性、安全挑战 |
有效的消费策略通常组合多种接口:
- REST 用于人类友好的简单操作
- GraphQL 用于带授权过滤的复杂多域查询
- gRPC/流式传输用于高容量自动化
- Webhooks 用于响应式下游系统
关于 MCP(模型上下文协议)的说明 除了传统 API 风格外,模型上下文协议(MCP)等新兴交互模型使 AI 智能体能够以结构化、工具导向的方式与系统交互。与定义传输和请求语义的 REST 或 gRPC 不同,MCP 专注于安全的能力发现、上下文数据检索和智能体驱动工作流的受控操作执行。这种模式在 AI 辅助操作和可观测性用例中尤为相关,自动化推理系统需要对遥测、配置和修复工具进行结构化访问。虽然仍在演进中,MCP 代表着从以资源为中心的 API 向以智能体为导向的交互模型的转变。
一个关键规则:在 API 层进行身份验证和授权,而不是在下游。这防止安全漏洞并使审计正常运作。
更多关于安全影响的内容见第 12 章。
4.2.3.2. API 操作:版本控制、性能与缓存#
一旦 API 被设计和保护,关于演进和性能的运营关切就变得至关重要。
API 版本控制与演进
网络是长寿命基础设施;自动化系统必须在不破坏运营工作流的情况下演进。
URL 版本控制:
/api/v1/devices和/api/v2/devices维护独立实现- 优点:明确、可调试,客户端选择何时升级
- 缺点:需要维护多个实现(这实际上是好事:迫使你规划迁移)
请求头版本控制:相同端点,版本在
Accept: application/vnd.company+json; version=2中- 优点:单一端点,URL 更简洁
- 缺点:在日志中不可见,难以调试,客户端经常搞错
无论哪种方式,提前 6-12 个月通过弃用头部宣布破坏性变更:
Deprecation: true
Sunset: Mon, 01 Jan 2026 00:00:00 GMT
Link: <https://docs/migration>; rel="deprecation"我推荐使用 URL 版本控制:/api/v1/devices 和 /api/v2/devices。是的,请求头版本控制在文档中看起来更简洁。但当凌晨 3 点出了问题,你在 grep 日志时,你想立刻看到 /v1/ 与 /v2/,而不是为了弄清是哪个 API 版本引发问题而去挖请求头。你未来值班的自己会感谢你。
性能与缓存
逐条消费数据对某些用例效果良好,但随着规模增长,最终会遇到性能限制。
批量操作允许在单个 API 调用中更新数千个对象。这对规模来说必不可少,但引入了权衡:
单对象 API:
POST /api/devices/device优点:验证每个变更,每个对象清晰的错误消息 代价:10,000 台设备更新 = 10,000 个 API 请求 + 往返 = 几分钟批量 API:
POST /api/devices/bulk-update优点:10,000 条更新单次往返,可并行化后端处理 代价:验证缩水(跳过昂贵检查),更难报告每个对象的错误
其他改善数据消费的替代方案包括通过以下方式限制范围:
分页和过滤防止客户端意外将数百万对象加载到内存中或超时:
GET /api/devices?location=datacenter-1&status=active&limit=100&offset=0基于游标的分页比基于偏移的分页在处理大型数据集时更有优势,因为它对分布式系统更高效,即使在请求之间修改数据也能保持一致。
缓存策略显著提高性能:
- 服务器端缓存:Redis 缓存"位置 X 中的所有设备”,在该位置任何设备变更时失效
- 客户端缓存:HTTP ETag 让客户端在不重新获取的情况下验证缓存数据
- 验证层绕过:对只读查询,跳过验证检查
速率限制保护后端免受过载:
- 每用户每秒 10 个请求
- 每 API 密钥每分钟 1,000 个请求
- 背压信号(HTTP 429)告知客户端放慢速度
4.2.3.3. 上下文感知数据建模#
不同人员需要不同内容。网络工程师想搜索和查找数据、编辑特定字段并获得验证反馈、查看关系。自动化工作流需要 API、事务和 Webhooks。运营团队想要以任务为中心的视图和审计跟踪。业务部门想要没有技术细节的报告。外部系统需要双向同步数据。
注意,消费模块的用户界面属于展示层。我们将在第 8 章中详细介绍。
数据必须适应每个消费者的上下文。例如,并非所有设备细节都需要对每个角色开放。上下文感知定制使数据消费更高效、更有效。
网络工程师需要接口和路由细节;财务部门需要成本和保修信息;安全部门需要合规区域。与其向每个人返回所有 500 个字段,不如给每个消费者只他们需要的内容。可以通过 API 查询参数(?view=network_engineer)或 GraphQL 让他们请求特定字段来实现。
挑战:一个数据模型无法满足所有消费者
考虑 SoT 中包含数百个属性的单台设备对象:
- 硬件细节(型号、序列号、固件版本)
- 网络配置(IP 地址、VLAN、路由协议)
- 运营元数据(位置、成本中心、保修到期)
- 服务关系(哪些客户使用这台设备)
- 安全上下文(合规区域、访问策略)
不同消费者需要对这些数据截然不同的视图:
示例:设备 “router-core-01” 在不同上下文中
| 消费者 | 上下文 | 数据表示 | 关键属性 |
|---|---|---|---|
| 网络工程师 | 连接故障排查 | 以网络为中心的视图 | 接口、IP 地址、BGP 对等、路由、VLAN、上行链路状态 |
| 财务团队 | 成本分配 | 以业务为中心的视图 | 成本中心、折旧计划、保修状态、购买日期、厂商 |
| 安全团队 | 合规审计 | 以安全为中心的视图 | 合规区域、访问策略、最后安全扫描、补丁级别、未修复漏洞 |
| 自动化工作流 | 配置部署 | 以执行为中心的视图 | 管理 IP、凭证引用、设备平台、配置模板名称 |
| 服务目录 | 客户影响分析 | 以服务为中心的视图 | 服务的客户、承载的服务、SLA 层级、冗余组 |
实现模式
基于视图的转换:API 查询指定所需上下文,服务器相应转换数据模型
GET /api/devices/router-core-01?view=network-engineer → 返回: {interfaces: [...], bgp_peers: [...], vlans: [...]} GET /api/devices/router-core-01?view=finance → 返回: {cost_center: "...", warranty_expiry: "...", purchase_cost: ...}GraphQL 字段选择:消费者明确请求所需字段
query NetworkEngineerView { device(name: "router-core-01") { interfaces { name, ip_address, status } bgp_neighbors { peer_ip, state } } } query FinanceView { device(name: "router-core-01") { cost_center purchase_date warranty_expiration } }投影层:后端为特定访问模式计算派生视图
- 网络拓扑图:设备作为节点,连接作为边(用于拓扑可视化)
- 服务依赖树:服务 → 设备 → 组件的层次视图(用于影响分析)
- 合规矩阵:按区域分组的设备与策略遵从状态(用于审计)
领域专用语言(DSL):针对用户心智模型的专用查询语言
- 网络工程师:“显示数据中心 1 中 BGP 会话中断的所有设备”
- 财务:“计算 2025 年 Q3 购买设备的月折旧”
- 安全:“列出 PCI 区域中存在严重 CVE 的设备”
上下文感知建模的优势
| 优势 | 影响 | 示例 |
|---|---|---|
| 减少认知负担 | 用户只看到与任务相关的数据 | 财务团队从不看 VLAN 配置;网络工程师不看采购订单 |
| 性能优化 | API 返回最少数据,减少带宽和处理 | 移动应用请求设备摘要(5 个字段)vs. 完整设备对象(200 多个字段) |
| 通过最小化过度暴露提升安全 | 敏感字段根据消费者角色过滤 | 凭证、安全区域对未授权消费者隐藏 |
| API 稳定性 | 如果视图保持稳定,后端 schema 变更不会破坏消费者 | 添加新设备字段不影响现有网络工程师视图的消费者 |
| 多语言支持 | 字段名称、枚举值、描述根据消费者语言环境翻译 | 加泰罗尼亚语运营人员看到 “Ubicació” 而非 “Location” |
但你必须考虑挑战和其他注意事项:
- 视图维护开销:每个新视图都需要定义、测试、文档
- 跨视图一致性:通过多个视图暴露的相同数据必须保持一致
- 性能复杂性:计算动态视图增加延迟;需要缓存策略
- 可发现性:消费者必须知道存在哪些视图以及何时使用它们
上下文感知建模是数据结构优化(如何高效存储数据)和消费优化(消费者如何自然访问数据)之间的桥梁。它认识到真实数据源服务于众多主体,每个主体对"真相"对其工作意味着什么都有自己的视角。
4.2.3.4. AI 辅助接口#
在消费层应用 AI 降低了处理大型复杂数据模型的认知开销。三种模式在现代 SoT 实现中越来越常见:
上下文建议:当你输入设备名称时,系统建议你之前在该位置编辑过的匹配设备。创建服务时,根据服务类型和历史模式建议合理的技术参数。这减少了输入错误而不增加验证摩擦。
写入时的异常警告:在批量更新之前,如果操作与历史模式相比不寻常,接口会标记。通常涉及 10 台设备的批量 VLAN 重新分配如果即将涉及 400 台,就会触发确认步骤。系统不阻止操作,只是提出问题。
自然语言查询:LLM 支持的接口允许运营人员使用普通语言查询 SoT:“B 楼中哪些设备没有监控标签?“接口将其转换为结构化 API 查询并以人类可读形式返回结果。这对临时调查很有价值,但不是结构化自动化接口的替代品。
三种模式依赖同样的基础:访问历史操作数据和 AI 可以推理的良好建模 schema。第 4.2.4.4 节涵盖类似技术如何应用于写入路径上的数据质量验证。
4.2.4. 执行#
坏数据会毁掉自动化。错误的意图导致破损的网络、安全漏洞和困惑的运营团队。执行是你的守护者:它阻止明显错误的数据进入,并清晰地解释原因。
4.2.4.1. Schema 与约束执行#
| 验证类型 | 目的 | 示例规则 | 示例错误 |
|---|---|---|---|
| Schema 验证 | 强制数据类型和格式 | VLAN id:1-4094 的整数;VLAN 名称:字符串,最长 32 字符;VLAN 站点:站点引用数组;VLAN 状态:enum(active, planned, deprecated) | { "id": 5000, "name": "CUSTOMER-VLAN" } → 错误:VLAN ID 5000 超过最大值 4094 |
| 唯一性约束 | 防止重复条目 | VLAN 100:每站点唯一;IP 192.0.2.1:在 IPAM 中全局唯一;主机名 “pe-01”:每区域唯一 | 尝试在同一区域创建第二个 “pe-01” → 错误:主机名已存在 |
| 引用完整性 | 确保关系保持有效 | 电路引用:site_a、site_b(必须存在于站点中),vendor(必须存在于厂商中) | 删除被电路引用的 site_a → 选项:拒绝删除、级联删除或孤立标记为"站点未知” |
| 范围验证 | 强制数字和模式约束 | BGP AS:1-4294967295;IPv4:正则 ^(\d{1,3}\.){3}\d{1,3}$;接口速率:{1G, 10G, 25G, 40G, 100G} | 接口速率 “5G” → 错误:无效速率,必须是 {1G, 10G, 25G, 40G, 100G} 之一 |
| 业务规则验证 | 强制组织策略 | 如果 VLAN 状态=‘active’ → 必须有 ≥1 个站点;如果设备类型=‘firewall’ → 必须有 security_zone;如果服务类型=‘L3VPN’ → route_distinguisher 每客户必须唯一 | 没有站点的活跃 VLAN → 错误:活跃 VLAN 必须分配到至少一个站点 |
实现 schema 验证有多种方式,从通用编程语言到更具体的解决方案:
- JSON Schema:描述约束的 JSON 文档,用于与实际数据比较。
- CUE:提供带约束和验证的类型化、经验证的数据生成。
- YANG:内置约束执行的网络专用建模语言。
例如,使用 JSON Schema,可以验证 JSON(或 YAML)数据:
- JSON 数据
{
"hostname": "sw-core-01",
"mgmt_ip": "192.0.2.10",
"role": "core",
"interfaces": [
{
"name": "Ethernet1",
"enabled": true,
"vlan": 100
},
{
"name": "Ethernet2",
"enabled": false,
"vlan": 200
}
]
}- JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["hostname", "mgmt_ip", "role", "interfaces"],
"additionalProperties": false,
"properties": {
"hostname": {
"type": "string",
"pattern": "^[a-z0-9-]+$"
},
"mgmt_ip": {
"type": "string",
"format": "ipv4"
},
"role": {
"type": "string",
"enum": ["core", "distribution", "access"]
},
"interfaces": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["name", "enabled", "vlan"],
"additionalProperties": false,
"properties": {
"name": {
"type": "string",
"pattern": "^Ethernet[0-9]+$"
},
"enabled": {
"type": "boolean"
},
"vlan": {
"type": "integer",
"minimum": 1,
"maximum": 4094
}
}
}
}
}
}4.2.4.2. 硬性执行与软性执行#
拒绝坏数据。硬停止。我见过太多"软验证"系统变成垃圾堆,因为"就这一次"成了标准操作。如果某件事重要到值得验证,它就重要到值得强制执行。
但是,像往常一样,也有例外:
策略指引(非规则):“你使用 /22 子网,而我们通常使用 /24"是警告,不是错误。警告用户、记录日志,但如果他们覆盖,让他们继续。
昂贵的跨对象检查:如果验证需要几秒以上,接受变更并异步验证。但仍然强制执行结果:标记违规、通知用户并要求修复。
褐地网络发现:当你导入现有配置时,会发现到处都是违规。标记它们,但不要阻止导入。重点是发现实际存在的内容,即使它违反了你的理想模型。
其他所有情况?拒绝。你的自动化依赖可信数据。坏数据意味着中断。
4.2.4.3. 验证成本与性能权衡#
验证不是免费的。验证成本的层次结构影响设计决策:
graph LR
SPEED["⚡ 速度"]
V1["< 1ms<br/>类型验证"]
V2["~10ms<br/>唯一性"]
V3["5-50ms<br/>正则表达式"]
V4["50-200ms<br/>引用<br/>完整性"]
V5["100-500ms<br/>规则引擎"]
V6["1-5 秒<br/>外部 API"]
V7["数小时+<br/>一致性"]
THOROUGH["全面性 🎯"]
SPEED --> V1
V1 --> V2
V2 --> V3
V3 --> V4
V4 --> V5
V5 --> V6
V6 --> V7
V7 --> THOROUGH
style SPEED fill:none,stroke:none,font-size:14px,font-weight:bold
style THOROUGH fill:none,stroke:none,font-size:14px,font-weight:bold
style V1 fill:#d4edda,stroke:#28a745,stroke-width:2px
style V2 fill:#d7ecf1,stroke:#17a2b8,stroke-width:2px
style V3 fill:#dfe8f1,stroke:#17a2b8,stroke-width:2px
style V4 fill:#fff3cd,stroke:#ffc107,stroke-width:2px
style V5 fill:#ffe8cd,stroke:#ffc107,stroke-width:2px
style V6 fill:#f8d7da,stroke:#dc3545,stroke-width:2px
style V7 fill:#f5c2c7,stroke:#dc3545,stroke-width:2px实际系统选择一个性能目标,仅对同步写入路径验证到该级别:
- 快速路径(< 10ms):类型、正则表达式、本地索引检查
- 标准路径(< 100ms):唯一性、引用完整性
- 慢速路径(< 5秒):规则引擎、复杂业务逻辑
- 异步路径(数小时后):后台验证、一致性检查
4.2.4.4. AI 增强数据质量#
机器学习在不降低吞吐量的情况下提高数据质量。这些 AI 驱动的验证技术与第 4.2.3.4 节中面向用户的 AI 功能相辅相成,共同创建一个全面的智能数据层。
异常检测
将历史模式与新请求匹配,推断不一致性:
- 历史模式:配置新分支时,运营人员在 1000-1999 范围内创建 VLAN,分配到 site_a,配置静态路由
- 新请求:创建 VLAN 2500,分配到 site_c,启用 OSPF
- 告警:“这个 VLAN 创建模式不寻常。你确定吗?(98% 置信度认为应该在 1000-1999 范围内)”
- 机器学习技术:历史变更向量的聚类和异常检测
自动纠错建议
自动建议朝最可能有效的解决方案纠正:
- 输入:IP 地址 “192.0.2.1/33”(无效前缀长度 > 32)
- 系统:“你是指 /24 吗?(根据该站点类似子网推断)”
- 机器学习技术:同一位置内子网分配的模式匹配
向量嵌入确保一致性
使用嵌入检测与对等配置的显著偏差:
- 存储每个设备配置的嵌入
- 提交新设备配置
- 将嵌入与同角色类似设备比较
- 如果差异显著:“该设备与同角色对等设备不同:类似设备的 NTP 服务器为 X、Y、Z,syslog 到服务器 Z”
- 机器学习技术:设备配置嵌入的余弦相似度
机器学习实现注意事项
| 方面 | 建议 | 理由 |
|---|---|---|
| 置信度阈值 | 只显示置信度 > 90% 的建议 | 防止假阳性导致的告警疲劳 |
| 训练数据 | 使用 6-12 个月的已验证变更 | 平衡近期性与统计显著性 |
| 模型更新 | 每周或检测到漂移时重新训练 | 适应不断演进的网络模式 |
| 可解释性 | 始终显示 AI 标记问题的原因 | 建立运营人员对建议的信任 |
| 人工覆盖 | 允许运营人员标记假阳性 | 通过反馈循环改进模型 |
注意"置信度"分数的使用。这是使用 AI 时的重要概念,它提供了对建议可靠程度的更多上下文。始终将 AI 建议与触发它们的底层模式解释配对。
4.2.4.5. 执行成本:系统设计影响#
高保真验证影响架构:
| 方法 | 优势 | 劣势 | 最适用于 |
|---|---|---|---|
| 同步验证(写入前验证) | 用户立即获得反馈;数据一致性有保证 | API 响应慢(验证延迟);阻塞高吞吐量自动化 | 关键数据完整性操作;交互式用户工作流 |
| 异步验证(先接受,后验证) | API 响应快;高吞吐量 | 存在数据一致性窗口;错误报告复杂(“写入成功但 5 分钟后验证失败”) | 批量操作;高容量自动化 |
| 混合方法 | 同步快速类型/格式验证;异步昂贵的跨对象验证;检查验证状态的 API 端点 | 实现更复杂;需要状态追踪 | 大多数生产系统;平衡性能与正确性 |
4.2.5. 版本控制#
你的网络意图在不断变化。设备被添加,配置被更新,服务被迁移,策略被调整。版本控制让你了解某个时刻的真实状态,它是如何变成那样的,以及在需要时如何回到安全状态。
4.2.5.1. 版本控制与不可变审计跟踪#
所有变更必须被不可变地记录,形成完整的历史。这可以采取不同形式,例如:
变更日志
Change Event: timestamp: 2025-02-07T14:32:15Z user: engineer@company.com action: UPDATE resource_type: vlan resource_id: vlan-100 changes: description: "Customer VLAN" → "Production Customer VLAN" assigned_sites: [site-a, site-b] → [site-a, site-b, site-c] reason: "Adding new office location" request_id: req-12345Git 提交
commit 0c0ad51152f9b3be307802badb15eca8d121c576 (HEAD -> new-site, origin/new-site) Author: Engineer <engineer@company.com> Date: Sat Feb 7 09:43:59 2026 +0100 Adding a new site: BCN01 diff --git a/sites.yaml b/site.yaml index ae18c87..dabf6c5 100644 --- a/sites.yaml +++ b/sites.yaml @@ -219,51 +219,1279 @@ sites: + BCN01:
这个不可变日志回答了关键问题:
- X 日期时网络意图是什么?(时间旅行)
- 谁做了这个变更,为什么?(责任追溯)
- 哪个部署配置对应这个意图?(可追溯性)
- Y 版本和 Z 版本之间发生了什么变化?(差异/对比)
不可变性是关键:任何人,包括管理员,都不能编辑历史记录。这防止了掩盖行为,确保审计跟踪保持可信。
版本控制还与保留策略相关,需要在合规与实用性之间取得平衡,例如:
- 保留所有变更 7 年(监管要求)
- 2 年后精简中间版本(如果 VLAN 100 变更了 10 次,只保留起始和结束状态)
- 1 年后归档到冷存储(降低成本)
与数据变更事件相关,事件溯源模式(将所有变更存储为事件以完整重建数据)功能强大,但在网络基础设施管理中不太常见。这是因为网络意图高度有状态,当前数据比导致它的变更序列更重要。此外,网络变更通常涉及外部状态(设备配置、外部系统中的 IP 分配),无法仅从事件中完整重建。但事件溯源在特定用例中很有价值,如审计合规或取证分析。
4.2.5.2. 版本控制模式:分支、合并与回滚#
现代真实数据源系统大量借鉴软件版本控制模式。这些能力支持安全的并行工作、实验性变更以及快速从错误中恢复。
分支支持并行工作流
任何有多位工程师或 AI 智能体并行工作的组织都需要一种不相互阻塞的工作方式。当一个参与者(人或 AI)正在配置新数据时,不能阻塞整个真实数据源。
借鉴软件开发,分支机制支持并行工作流。每个团队可以在并行数据轨道上工作,准备好后再与"主"轨道合并。这次合并是解决可能引入的任何不一致性的机会。
示例工作流:
main 分支(生产意图)
│
├─── feature/add-dallas-office(工程师 A)
│ • 创建站点 DAL-01
│ • 分配 VLAN 2100-2110
│ • 定义 5 台新设备
│
└─── feature/upgrade-ntp-servers(工程师 B)
• 修改所有设备的 NTP 配置
• 更新 3,000 条设备记录当两个分支都合并回 main 时:
- 无冲突:修改了不同对象 → 自动合并
- 检测到冲突:两者都修改了 device-core-01 的 NTP → 需要手动解决
- 验证:合并结果必须在提交前通过所有执行规则
在传统数据库中实现这种分支机制本身就是一个重要问题。例如,依赖关系型数据库的 NetBox 和 Nautobot 采用了不同方法:NetBox 使用数据库副本进行分支,Nautobot 利用 Dolt(一个内置 Git 式 Versioning 的 SQL 数据库)。Infrahub 从一开始就以 Git 式分支为核心设计,使用内置原生分支能力的图数据库实现。
Rollback 与恢复
错误是会发生的。数据 Rollback 必须快速可靠。注意这是意图数据本身的 Rollback,不是直接对网络配置的回滚。
回滚数据需要执行组件来强制配置变更(如果网络基础设施支持,可以回滚网络配置,但最终网络和意图都必须同步以维持稳定状态)。
为支持数据 Rollback,有两种主要方法:
| 方法 | 工作原理 | 存储开销 | 恢复速度 | 复杂性 |
|---|---|---|---|---|
| 快照 | 定期完整复制整个数据集 | 高(每次快照全量复制) | 快(直接恢复) | 实现复杂性低 |
| 事件溯源 | 将所有变更记录为事件,回放以重建状态 | 低(只存储增量) | 慢(必须回放事件) | 实现复杂性高 |
| 混合 | 每 N 小时快照 + 快照间的事件日志 | 中等 | 快到快照,然后回放事件 | 中等复杂性 |
Rollback 可以通过两种方式触发:
- 手动:运营人员发现问题,启动 Rollback
- 自动化:
- 部署后可观测性检测到错误率升高
- 部署后验证失败(“500 台设备在变更后无法访问”)
- 超过业务影响阈值(“客户 SLA 违规 > 10 次”)
分支(无冲突的并行工作)和 Rollback(快速从错误中恢复)的结合提供了大规模网络自动化所需的时间灵活性。
4.2.5.3. 原子事务与一致性保证#
事务保证确保多个相关变更必须一起成功或一起失败时的数据一致性:
- 原子性:要么全部成功,要么全部回滚
- 一致性:前后都满足数据约束
- 隔离性:并发事务不相互干扰
- 持久性:一旦提交,即使系统崩溃也能持续
实现这一点需要仔细设计:
- 数据库事务(如果所有数据在单个 DB 中)
- 分布式事务(如果数据跨系统)
- Saga 模式(如果没有原生分布式事务支持)
在第 11 章中,我们将进一步介绍这些要求如何影响可靠系统。
4.2.5.4. 变更审批工作流#
一旦数据变更被提议,它们可能需要人工审批工作流才能生效。数据通常在被认为最终确认之前流经几个阶段,类似于持续集成管道。
graph LR
A["📝 运营人员提议变更<br/>新增 50 台分支设备"] --> C["📦 暂存<br/>暂无网络影响<br/>预览、测试、预演"]
C --> D["✓ 自动检查验证<br/>Schema 与约束?"]
C --> E["✓ 仿真<br/>路由/MPLS 影响?"]
C --> F["✓ 合规<br/>安全策略?"]
D --> G{所有检查<br/>通过?}
E --> G
F --> G
G -->|通过| H["👥 人工审查<br/>变更控制"]
G -->|失败| I["❌ 拒绝<br/>通知提议者"]
H --> J{已批准?}
J -->|是| K["✅ 已批准<br/>准备部署"]
J -->|否| I示例数据变更工作流可能如下所示:
运营人员提议变更:“新增 50 台分支设备”
变更进入暂存状态:(暂无网络影响,可以预览、测试、预演)
自动检查运行(持续集成):
- 验证:是否通过 schema 和约束?
- 仿真:是否破坏路由、MPLS 等?
- 合规:是否违反安全策略?
- 报告:✓ 全部通过
人工审查:
- 变更控制委员会收到通知
- 审查差异、理由、影响范围
- 批准或请求变更
批准决定,变更进入已批准状态。
部署触发:一旦批准,触发工作流组件最终将相关变更部署到网络(自动化执行工作流的常见触发器)
然而,并非所有变更都需要人工审批,这正是大多数组织出错的地方。变更控制委员会是自动化的终结地。我不是说跳过审批,我是说将审批自动化(即大规模变更审批)。
如果你的 CAB 每周开会审批添加 VLAN,你已经输了。构建护栏自动批准 95% 的变更,将人工审查留给真正有风险的内容。例如,配置 AWS VPC 时,运营人员不等人工批准网络变更:他们在定义好的边界内遵循经过验证的模板。
规则是:符合明确护栏的变更自动推进;只有护栏逻辑本身需要人工审查和批准。定义最低护栏覆盖率和最大影响容忍度,然后让系统工作。
否则,你的"自动化"只是一种更漂亮的等待开会方式。
4.2.6. 聚合#
你的网络数据不存在于真空中。HR 系统追踪谁在哪里工作。资产管理知道设备详情和保修日期。IPAM 系统拥有 IP 地址分配。电路提供商有连接信息。服务团队有 SLA 详情。
不要再构建另一个数据孤岛。你的组织已经有太多了。如果你的真实数据源无法从 ServiceNow、Infoblox 和 CMDB 拉取数据,你只是在构建带 API 的电子表格 2.0。没人会维护它。你将花时间乞求人们"请更新 SoT”,而他们无视你,继续使用现有工具。
聚合不是可选的:从现有系统引入数据,保持双向同步,呈现统一视图。真实数据源应该是联邦层,而不是替代数据库。
4.2.6.1. 你不是从零开始#
你几乎肯定有数据散落在多个系统中。每个系统在其域中是权威的:HR 拥有组织,资产系统拥有硬件详情,IPAM 拥有 IP 分配。真实数据源不替代这些系统;它将它们的数据汇聚到一个一致的接口中,使客户端不必查询五个不同的系统。
组织上下文:
- HR 系统:部门、团队、角色、职责矩阵
基础设施:
- 资产管理:硬件详情、序列号、采购、保修
- 云平台:VPC、子网、安全组、实例详情
- 电路提供商(外部):连接状态、利用率、故障
- IPAM 系统:IP 分配、DHCP 范围、DNS 条目
- 配置管理:模板、基线
服务:
- 服务目录:服务定义、SLA、客户
- 计费系统:分摊、容量规划
每个系统在其域内是权威的(将域理解为数据类型,或清晰界定的数据类型子集)。真实数据源不替代它们;它将它们的数据编排成一个连贯的整体,通过一致的接口访问,消除了复杂客户端应用需要关联多个来源数据的需求。
4.2.6.2. 联邦系统中的冲突解决#
当数据来自多个来源时,冲突会产生:
- 集中式 IPAM 系统显示:192.0.2.0/24 分配给客户 X
- CMDB 显示:192.0.2.0/24 分配给客户 Y
谁是正确的?这取决于通过治理进行的权限指定。
例如,资源域所有权策略可能规定:
集中式 IPAM,以下内容的真实数据源:
- IP 地址分配
- 子网大小
- DHCP 范围
CMDB,以下内容的真实数据源:
- VLAN 到子网映射
- 接口 IP 分配
- 网络接口运营状态
冲突解决策略包括:
来源权限(最常见):治理决策指定一个系统为权威(如资产系统对设备凭证具有权威性)
基于时间戳:使用最后修改时间戳;最新变更获胜。风险:不区分纠正性变更与错误
逻辑解决:评估上下文:
- SoT 值当前在设备上使用(当前状态,已验证有效)
- 资产系统值声称是 Desired State(应有状态)
- 选项 1:信任当前(有效的)
- 选项 2:信任应有(治理模型)
- 选项 3:检测:设备上的配置与任何一个值都不匹配,进一步调查
手动升级:当置信度中等时(值不同但不矛盾),升级到人工审查
4.2.6.3. 聚合架构#
数据聚合有两种基本方法:
| 方法 | 架构 | 工作原理 | 同步模式 | 优势 | 劣势 |
|---|---|---|---|---|---|
| 集中式聚合(拉取模型) | 中央 SoT 从外部系统获取 | 聚合器轮询/订阅来源;转换为统一 schema;检测冲突;丰富本地数据;提供统一视图 | 双向(SoT ↔ IPAM);单向(SoT ← HR) | 集中控制;积极验证/丰富;单一消费者查询点 | 到来源的网络延迟;依赖外部可用性;只能最终一致;规模挑战 |
| 分布式联邦(推送模型) | 每个系统维护自己的数据,SoT 协调 | 事件驱动(消息总线);变更实时通知 Webhooks;参考数据缓存层;缓慢变化数据的定期刷新 | 事件驱动;基于 Webhook;缓存参考数据 | 域所有者负责数据质量;无重复;无瓶颈扩展;强大的每域一致性 | 消费者需查询多个系统;跨系统连接代价高;复杂消息协调 |
4.2.6.4. 同步机制#
跨系统保持数据一致是聚合的核心挑战。架构选择决定使用哪种同步方法:
| 机制 | 工作原理 | 示例流程 | 优势 | 劣势 | 典型延迟 |
|---|---|---|---|---|---|
| 定期同步(基于计划) | 数据按计划拉取 | 每 6 小时:SoT 从 IPAM 读取;与本地缓存对比;应用变更到视图;发布 SoT 变更 | 简单;可预测;低开销 | 数小时的不一致窗口;批量冲突 | 分钟到小时 |
| 事件驱动(消息总线) | 实时响应变更 | IPAM 更改子网 → 发布 “Subnet:Changed” 到总线 → SoT 消费消息 → 更新本地缓存 | 实时;响应式 | 复杂编排;难以调试 | 秒级 |
| 流/Webhooks(直接推送) | 来源推送到已注册 Webhook | SoT 注册 Webhook → IPAM 分配 10.0.2.5/32 → HTTP POST 到 Webhook → SoT 验证、更新 | 直接通信;无需消息总线 | 需要 Webhook 支持;网络可靠性问题 | 亚秒到秒级 |
没有真正的实时同步系统。数据将最终一致,但这可能需要一些时间,每个用例都需要评估。
4.2.6.5. 数据治理与权限框架#
有效的联邦需要清晰的治理,每个数据域有明确的定义。例如:
| 域 | 权威来源 | 同步方向 | 频率 | 冲突解决 |
|---|---|---|---|---|
| 设备清单 | 资产管理系统 | 资产 → SoT(SoT 只读) | 每日 | 资产始终胜出 |
| 网络拓扑 | 中央 SoT | SoT(报告系统) | 实时 | N/A(SoT 是来源) |
| IP 分配 | IPAM 系统 | 双向 | 入站每小时,出站实时 | 空闲池 IPAM 胜出,静态分配 SoT 胜出 |
对于每个数据元素,权限元数据应追踪:
- 来源系统:它来自哪里?
- 最后同步时间:何时验证的?
- 更新方法:轮询、推送还是 Webhook?
- 权限级别:这个数据有多可信?
有了这些元数据,系统就能对数据处理做出明智的治理决策。
当与多个实体协作时,要做好应对故障的准备。外部系统不可避免地会失败。当联邦来源不可用时(如 IPAM 宕机 30 分钟),有几种策略可选(各有利弊):
- 阻止操作:“没有 IPAM 无法分配 IP 地址”
- 使用缓存数据并标记为过时:“使用 2 小时前的 IPAM 缓存数据;可能不一致”
- 优雅降级:“仍然可以配置设备,跳过 IP 分配,并在 IPAM 恢复时排队处理”
4.2.7. 褐地接入#
上述六个功能描述了 SoT 在填充和可信后如何运作。两个运营现实决定了它是否能到达这一步并保持在那里:如何从现有网络填充它,以及如何随时间保持其准确性。两者都不能整洁地映射到单一功能,但都是实践中任何六个功能正常运作的前提条件。
在现有网络中部署真实数据源时,你面临一个棘手的问题:如何在不只是将所有遗留杂乱内容永久化为真相的情况下填充它?
错误的方法:轮询你的设备并假设"正在运行的 = 应该有的”。你会将所有变通方法、黑客手段和技术债务直接加载到真实数据源中。
正确的方法:将当前网络状态作为起点,而非真相。对其快照,加载进来,然后有意识地重新设计以使其干净。一旦你获得了真正想要的设计,停止从网络同步。真实数据源成为主导;网络跟随它的引领。
实际操作如下:
引导:对当前网络做快照(设备、IP、VLAN、电路)并将其作为起始数据加载到真实数据源中。
重新设计:在数周和数月内,让人们审查这些数据并决定预期状态实际上应该是什么。你可能想要整合冗余 VLAN、清理遗留内容、标准化命名,并为未来部署编写设计模板。
翻转方向:一旦你获得了想要的设计,停止从网络向真实数据源同步。现在真实数据源是主导。执行(第 5 章)向外将变更推送到网络。
检测漂移:可观测性(第 6 章)监视与真实数据源所说应有状态不同的设备。当漂移发生时,运营人员决定:修复设备还是修复真实数据源?
这种方法需要初期投入,但避免了将已部署状态视为永久真相的陷阱。你的 SoT 向干净的设计意图演进,即使网络需要时间完全对齐。显然,你可以继续以预演模式使用它来双重检查网络是否已漂移。
4.2.8. 数据生命周期与协调#
数据会过时。一台交换机被停用但未从 SoT 中移除。一个 IP 地址在事故中被手动重新分配。一个 VLAN 在故障排查时被承包商添加到了额外的中继端口。三个月后,没人记得,SoT 记录的是网络几周前就已停止的状态。
执行(第 4.2.4 节)在写入时验证数据,但这还不够。一条创建时准确的记录可能仅仅因为周围世界发生了变化而变得不准确。没有持续的协调过程,SoT 会逐渐失去可信度:团队停止信任它,开始维护自己的电子表格,建立在它之上的自动化开始悄悄地产生错误结果。
协调模式
协调意味着定期比较实际网络状态与 SoT,并对每个差异进行分类:
- 配置漂移:设备与其 SoT 意图不同。SoT 是正确的;网络已漂移。触发执行模块进行修复。
- 未记录的变更:对网络做了有意的变更但未记录在 SoT 中。网络是正确的;SoT 已过时。提醒运营人员更新意图。
- 孤立记录:SoT 有一个对象(设备、前缀、VLAN),但它在网络中已不存在。排队进行清理审查。
每类需要不同的响应。自动化可以处理漂移修复(在定义的护栏内)。未记录的变更需要人工判断:这是应该正式化的紧急修复,还是应该回滚的未授权变更?孤立记录需要不自动删除但将候选项浮出水面供审查的清理工作流。
需要注意的数据衰减模式
在实践中,SoT 过时最常见的来源是:
- 已停用设备未被移除:SoT 有一个设备记录带管理 IP,但设备已被物理移除。以该 IP 为目标的自动化将失败,或者更糟,到达一个以不同角色重新部署的设备。
- 手动重新分配的 IP:SoT 中列为属于设备 A 的 IP 现在被设备 B 使用,在事故中分配的。SoT 和 IPAM 可能内部都一致,但相对于实际网络都是错误的。
- VLAN 范围蔓延:VLAN 被部署到定义的一组交换机,但在故障排查时被添加到了额外的中继端口。SoT 意图不再匹配实际成员资格。
协调频率
不是所有数据以相同速率老化。设备清单变化缓慢;运营状态不断变化。实际做法是按数据类型分层协调节奏:设备清单每日协调,IP 分配每小时协调,VLAN 成员资格在每次变更事件后以及每日批量扫描时协调。
褐地接入(第 4.2.7 节)是一次性迁移。协调是保持 SoT 在上线后可信的运营过程。跳过协调的团队会发现,在几个月内对 SoT 的信任就会侵蚀,建立在它之上的自动化开始悄悄地产生错误结果。
SoT 作为活跃依赖
将 SoT 用作参考(自动化在工作流开始时读取它)与用作活跃依赖(自动化在工作流每个步骤读取它,信任数据是当前的)之间存在结构性差异。两种模式都有效,但第二种创造了第一种没有的运营要求。
当执行器或编排器在工作流开始时从 SoT 读取设备清单,然后跨 200 台设备展开时,它是在基于快照工作。如果在运行中一台设备被停用,或者在快照读取和执行步骤之间 IP 地址被重新分配,自动化就会基于过时数据行动。对于短期工作流,这通常可以接受。对于长期工作流(运行数小时的固件升级,跨越维护窗口的配置运行),过时窗口是显著的。
缓解措施是将 SoT 可用性视为依赖项,而非假设:
- 编排器应在开始展开步骤之前验证 SoT 读取成功并返回了当前记录(通过检查最后同步时间戳或使用 SoT 的健康端点)。
- 对于长期工作流,考虑在每个主要工作流阶段重新读取 SoT,而不是只在开始时读取一次。
- 如果 SoT 不可用,工作流应以明确的错误干净地失败,而不是以未知年龄的缓存快照继续。
这也意味着 SoT 本身必须为可用性而设计。作为所有自动化写入权威来源但没有高可用配置的 SoT 是整个自动化平台的单点故障。第 4.2.9 节介绍具体解决方案;第 11 章讨论整个平台的可用性设计。
4.2.9. 解决方案全景#
市面上有很多真实数据源产品。有些是开源的,有些是商业的。有些是通用的,有些专门针对 IP 管理等特定域。以下是 2026 年初的快照:该领域在不断变化,在选择之前请务必查看当前能力和发展势头。
4.2.9.1. 开源解决方案#
| 解决方案 | 覆盖的数据域 | 关键技术特征 |
|---|---|---|
| NetBox | IPAM、DCIM、电路、设备、虚拟化、清单 | 广泛的插件生态(150 多个插件);成熟(10 多年)拥有庞大社区;版本间频繁的破坏性变更 |
| Nautobot | IPAM、DCIM、电路、设备、清单、可扩展应用 | NetBox 的分支,增强了可扩展性;自动化工作流的作业框架;Git 数据源集成;稳定 API 和专业支持 |
| Infrahub | 网络拓扑、设备、IPAM、Schema、关系 | 用于复杂关系建模的图数据库;Git 式分支内置于核心架构;Schema 驱动,动态数据模型;用于变更审查的提议状态工作流 |
4.2.9.2. 商业解决方案#
| 解决方案 | 覆盖的数据域 | 关键技术特征 |
|---|---|---|
| ServiceNow CMDB | 配置项、服务、资产、变更 | 企业 ITSM 集成;ITIL 对齐工作流;多厂商联邦能力;AI/ML 驱动的洞见和建议 |
| Device42 | 数据中心资产、依赖关系、应用映射、IPAM | 全面的自动发现以快速接入;应用依赖映射;跨多平台的无代理发现 |
上述所有开源解决方案也都提供商业版本。
4.2.9.3. 专用平台#
| 解决方案 | 覆盖的数据域 | 关键技术特征 |
|---|---|---|
| Infoblox | DNS、DHCP、IPAM(DDI) | 企业级 DDI 权威;DNS 安全和威胁情报;多站点复制 |
| SolarWinds IPAM | IP 地址管理、DHCP、DNS | 与 SolarWinds 监控生态系统原生集成;自动化 IP 冲突检测;Active Directory 集成 |
| phpIPAM | IP 地址管理、子网、VLAN | 轻量级且经济实惠;简单部署(LAMP 栈);无 DCIM 复杂性的直接 IPAM |
4.2.9.4. 选型考量#
评估真实数据源解决方案时,考虑以下对齐因素:
- 规模要求:设备数量(数百台 vs. 数十万台)、变更速率、查询量
- 数据模型需求:关系结构(NetBox、Nautobot)vs. 图关系(Infrahub)vs. 灵活文档存储
- 集成生态:必须联邦数据的现有工具(监控、ITSM、云平台)
- 团队专业知识:Python/Django 熟悉度、对低代码平台的偏好、对 Git 工作流的适应性
- 运营模型:自托管 vs. SaaS、变更审批流程、RBAC 要求
- 演进路径:褐地迁移路径、Schema 可扩展性、API 稳定性
4.3. 实施示例#
4.3.1. 用例:为园区网络构建 SoT#
我们回到第 3 章介绍的园区网络。大约 800 台来自 Cisco、Arista 和 HPE 的接入和汇聚交换机分布在多栋建筑中,运营团队处理着稳定的服务请求流:新 VLAN、IP 子网分配、路由策略更新和访问控制变更。在所有这些能够可靠自动化之前,数据必须在一个一致、权威的地方。
今天园区使用三个独立系统,每个系统各拥有一部分图景:
- Infoblox:权威 IPAM,管理整个园区子网的 IP 地址分配、前缀分配和 DNS
- ServiceNow:资产清单和 CMDB,追踪交换机位置、硬件型号、建筑分配和维护历史
- 园区交换机:实际运行配置,分布在 800 台设备上,没有单一的已部署内容的整合视图
挑战:当应用团队提交新 VLAN 服务段请求时,网络工程师必须手动交叉引用 Infoblox 查找可用子网、ServiceNow 查知目标建筑中哪些交换机,以及通过设备 Secure Shell (SSH) 会话检查当前 VLAN 分配。Configuration Drift 不断积累,因为对每台交换机预期状态没有单一的共识。添加新厂商设计模板需要在多处更新文档,无法保证一致性。
解决方案:部署 Nautobot 作为联邦网络真实数据源,与 Infoblox 和 ServiceNow 集成,从园区交换机拉取当前状态,并添加 Infoblox 和 ServiceNow 都无法提供的网络专属数据模型:VLAN 定义、每厂商配置模板、接入和汇聚层的设计模式,以及将业务请求与执行器运行单个 Playbook 之前必须存在的技术对象相连接的服务请求数据模型。
这个示例是说明性的,不是规定性的。有许多有效的 SoT 产品和架构可以解决这个场景。重点是演示六个构建模块:建模、消费、执行、版本控制、聚合和设计驱动如何在真实场景中协同工作。你的组织的 SoT 可能会根据现有工具、团队专业知识和约束而有所不同。
4.3.2. 解决方案架构#
graph TB
IPAM["Infoblox<br/>权威 IPAM<br/>IP 范围、DNS"]
CMDB["ServiceNow<br/>权威 CMDB<br/>资产、位置、元数据"]
DEVICES["🖧 园区交换机<br/>Cisco、Arista、HPE<br/>~800 台设备"]
SLURPIT["Slurpit<br/>褐地发现<br/>配置提取"]
subgraph NAUTO ["🔗 Nautobot(聚合中心)"]
direction TB
AGG["聚合层<br/>权限规则<br/>冲突解决"]
SOT["整合 SoT 和数据扩展<br/>设备、IP、站点<br/>关系"]
API["消费 API<br/>REST、GraphQL<br/>Webhooks"]
end
EXEC["🚀 执行系统<br/>配置生成<br/>设备部署"]
OBS["👁️ 可观测性<br/>状态验证<br/>漂移检测"]
UI["🖥️ 展示层<br/>Web UI、CLI<br/>仪表板"]
IPAM -->|Webhooks/轮询<br/>IP 数据| AGG
CMDB -->|Webhooks/轮询<br/>资产数据| AGG
DEVICES -->|SSH/NETCONF<br/>设备状态| SLURPIT
SLURPIT -->|转换数据<br/>初始引导| AGG
AGG --> SOT
SOT --> API
API -->|意图查询| EXEC
API -->|配置模板| EXEC
API -->|数据访问| UI
OBS -->|状态漂移| API
API -->|清单| OBS
EXEC -.->|部署配置| DEVICES
OBS -.->|监控状态| DEVICES核心洞见:Nautobot 不是在替换 Infoblox 或 ServiceNow。它在聚合它们的数据、解决冲突,并作为下游系统(执行、可观测性、展示层)消费的单一 API 服务。这种关注点分离允许每个系统都是最佳选择。
六个组件如何协同工作#
建模:每个数据源都有自己的数据模型,存在一些重叠,允许通过标识符连接数据。职责是分布式的,每个数据源专注于不同数据。结构必须允许在所有信息整合之前存在部分数据(例如,在 IP 分配之前设备可以存在于 Nautobot 中)。
消费:Nautobot 提供 REST API 和 GraphQL 接口,供其他设备以一致的方式查询数据,作为集中点而非必须与所有数据源集成。
执行:Nautobot 强制执行一致性的全局验证。如果 IPAM 显示 10.1.1.5 分配给 device-dal-01,但这个前缀分配给了设备不属于的另一个区域,必须标记。它还防止孤立数据:如果设备不存在于 ServiceNow 中,则无法从 Infoblox 分配 IP(引用完整性)。此外,软验证会警告:“设备在 ServiceNow 中最后更新是 30 天前;可能已过时”(不阻塞),具有清理数据的能力。
版本控制:所有变更作为变更日志记录追踪。当对象变更且 IPAM 自动重新分配 IP 时,Nautobot 记录"IPAM Webhook:IP 10.1.1.5 于 2024-02-08T14:32:00Z 分配给 device-dal-02 的 interface eth1.1”,这允许追溯设备为何拥有其当前 IP 的历史。但回滚能力有限,因为没有回到过去某个时刻的机制(注:Nautobot VCS 应用支持更复杂的功能,但为简化起见此处不涵盖)。
聚合:这是该解决方案的关键方面,因为有多个数据源需要互联。Nautobot 优先使用 Infoblox 的 IP 数据(它是权威 IPAM)。对于资产元数据(保修、成本中心),ServiceNow 是权威的,Nautobot 用它来解决差异。同步策略可能如下:
- ServiceNow → Nautobot:每 4 小时定期同步(可以容忍资产元数据的轻微延迟)
- Infoblox → Nautobot:IP 变更的实时 Webhooks(IPAM 变更紧急,不能等待轮询)
- 网络设备 → Nautobot:使用 Nautobot 接入应用将网络数据接入 Nautobot 数据模型(最终一致性可接受) 此外,如果出现故障,Nautobot 可以提供一些弹性机制,例如:
- 如果 Infoblox 宕机 2 小时,Nautobot 继续使用缓存的 IP 数据,标记为"过时”
- 运营人员看到警告:“IP 数据来自 2 小时前;IPAM 当前不可用;新分配延迟”
- Infoblox 恢复后,待处理分配被原子地处理
设计驱动:使用 Nautobot Design Builder App,Nautobot 为满足新 VLAN 服务请求提供高级接口。运营人员提供高级意图:{ "vlan_name": "app-payments", "subnet_size": "/24", "location": "building-b", "vendors": ["arista", "cisco"] }。然后,设计模板扩展这个:在 Nautobot 中创建 VLAN 对象,向 Infoblox 请求 building-b IP 范围中的可用 /24 前缀并自动分配,自动生成每厂商配置模板(汇聚交换机的 Arista EOS 语法,接入交换机的 Cisco IOS-XE 语法),查询 ServiceNow 以确定 800 台园区交换机中哪些物理位于 building-b,最终得到执行器在运行单个 Playbook 之前所需的所有技术对象。
4.3.3. 实施流程#
初始数据加载
- Infoblox 导入:Nautobot 连接到 Infoblox API → 拉取所有 IP 范围、预留、DNS 记录
- ServiceNow 导入:Nautobot 连接到 ServiceNow CMDB → 拉取所有 IT 资产、位置、关系
- 使用 Slurpit 进行褐地网络发现:Slurpit.io 连接到现有网络设备提取当前配置状态:
- 设备清单(型号、序列号、软件版本)
- 接口配置和运营状态
- IP 寻址和 VLAN 分配
- 路由协议配置
- 将设备配置转换为 Nautobot 兼容的数据模型
- 差异检测和解决:Nautobot 审计流程关联来自三个来源的数据(Infoblox、ServiceNow、Slurpit):
- 冲突示例:设备接口显示 10.1.1.5/24,但 Infoblox 显示此 IP 分配给不同设备
- 解决工作流:Nautobot 标记 47 个冲突供人工审查
- 网络工程师评估每个:「信任设备状态」或「信任 IPAM;设备需要纠正」
- 应用治理规则:「接入端口信任设备,基础设施 IP 信任 IPAM」
- 批量解决:类似冲突以一致策略解决
- 统一 schema 填充:Nautobot 合并三个来源:
devices[*].{ name, location_id, ipv4_address, serial_number, cost_center }使用经验证、无冲突的数据
实时运营
- 新 VLAN 服务请求:应用团队在 ServiceNow 中提交请求。Nautobot 捕获 Webhook,创建 VLAN 和前缀对象,向 Infoblox 查询 building-b 地址范围中下一个可用的 /24,自动分配,并用请求者、审批者和时间戳标记记录。执行模块现在可以从 Nautobot 查询在所有目标交换机上部署该服务所需的每个数据点。
- 新园区交换机接入:运营人员在 ServiceNow 中创建资产条目。Nautobot 捕获 Webhook,创建带有位置、厂商和角色元数据的设备对象,向 Infoblox 查询站点管理范围中的管理 IP 并分配,根据设备角色和厂商分配适当的设计模板。交换机在任何人触碰 CLI 之前就已注册到 SoT 并可用于未来部署。
- Infoblox 维护窗口:IPAM 离线 2 小时。Nautobot 显示缓存数据"IP 数据有效截至 14:30 UTC;刷新待处理”。运营人员仍然可以查询设备清单和 VLAN 定义,但新 IP 分配被延迟。Infoblox 恢复后,待处理分配排队并原子地处理。
处理不一致性和定期漂移检测
初始接入后,Nautobot 持续监控所有三个数据源的偏差:
持续同步:除了变更发生时触发的事件驱动更新,定期同步每 4-6 小时运行:
- Infoblox 同步:IP 变更的 Webhook 驱动 + 定期协调
- ServiceNow 同步:资产元数据更新的定期轮询
- Slurpit 发现:捕获实际网络状态的定期设备轮询
Nautobot 审计和关联:Nautobot 的审计流程比较来自所有来源的数据以检测不一致性:
- 数据源冲突:设备接口 IP 与 Infoblox 分配不同
- Configuration Drift:设备状态与 Nautobot 意图不同(NTP 服务器变更,VLAN 添加到中继)
- 过时元数据:ServiceNow 资产最后更新是 90 天前(潜在过时)
偏差分类和修复:
- 类型 1 - Configuration Drift:设备与 Nautobot 意图不同 → 触发执行纠正设备
- 示例:设备上的 NTP 服务器变更 → 执行重新生成配置并推送纠正
- 类型 2 - 意图过时:有意变更尚未反映在 Nautobot 中 → 提醒运营人员更新 SoT
- 示例:运营人员在事故中手动添加 VLAN → 更新 Nautobot 以反映当前意图
- 类型 3 - 外部权限不匹配:权威来源之间的冲突(Infoblox vs. 设备现实)
- 示例:IP 分配不匹配 → 需要基于治理规则的人工决策
- 类型 1 - Configuration Drift:设备与 Nautobot 意图不同 → 触发执行纠正设备
自动 vs. 手动修复:
- 自动修复:预批准变更(NTP、DNS、syslog 服务器)通过执行自动纠正
- 手动审批:关键变更(BGP 配置、路由协议、安全策略)在纠正前需要人工审查
- 升级:无法解决的冲突或重复漂移模式升级到网络团队
审计跟踪:所有检测到的偏差、解决方案和修复操作记录用于合规和故障排查
4.3.4. 方法权衡#
此方法的优势#
| 优势 | 描述 | 收益 |
|---|---|---|
| 整合而不替换 | Infoblox 和 ServiceNow 继续作为权威来源 | Nautobot 协调而不是替换现有投资 |
| 大多数用例的多来源真相 | 5-30 秒同步延迟对大多数操作可接受 | 设备配置(4 小时同步)、IP 分配(30 秒延迟)、配置生成(夜间)都运行良好 |
| 尊重域专业知识 | 每个团队拥有其域 | Infoblox 团队:IP 策略;ServiceNow 团队:资产生命周期;网络团队:设计/部署 |
| 丰富数据模型 | 跨系统建模关系 | 支持跨域查询:“高安全位置中保修到期的设备?” |
| 运营弹性 | 中断期间缓存数据可用 | Infoblox 宕机 → 缓存 IP 数据;ServiceNow 宕机 → 最后已知元数据 |
| 审计与合规 | 所有变更以完整血缘追踪 | 监管查询:“谁批准了从 10.1.1.5 到 10.1.2.5 的 IP 变更,何时,为何?” |
局限性与约束#
| 局限性 | 影响 | 缓解策略 |
|---|---|---|
| 同步延迟 | 5-30 秒(Webhooks)到 4 小时(轮询)延迟 | 对于关键分配,绕过 Nautobot 直接调用 Infoblox;异步同步 |
| 冲突复杂性 | 重叠属性需要明确的解决逻辑 | 使用权限矩阵使冲突明确(如 ServiceNow 拥有 MAC 地址) |
| 运营开销 | 每个 Webhook/API/同步作业都是潜在的故障点 | 监控集成健康状况(Webhook 失败、超时、延迟);为每种故障模式维护运行手册 |
| 数据质量依赖 | 垃圾进,垃圾出 | 软验证(警告非阻塞);可疑数据的异常检测 |
| 过时数据窗口 | 中断期间,运营人员使用数小时前的缓存数据 | 记录可接受的过时窗口;培训运营人员"延迟 > 2 小时使用缓存"的标准 |
| 集成维护 | API 版本升级需要 Nautobot 更新 | 使用抽象层(集成适配器);季度集成测试 |
还有其他方式和解决方案可能更适合你的用例。根据你的需求做出自己的决定,始终需要权衡。
4.4. 总结#
开篇故事中孤立的防火墙规则不是配置错误。没有人没能完成工作。规则留了下来,是因为没有系统将 VLAN 与服务、防火墙策略连接起来。当 VLAN 被移除时,这种连接不存在,所以规则没有任何机制触发其清理。真实数据源就是使这些连接显式化的系统。
六个功能构建了这个系统。建模定义网络应该是什么样子,以及在什么抽象层次。设计驱动将业务请求(“新增达拉斯分支”)转化为执行器在接触设备之前所需的 50 多个技术对象。消费使意图对人员、自动化工作流和其他系统一致可用。执行确保进入 SoT 的数据在能够在下游产生错误网络状态之前是有效的。版本控制以作者、原因和时间戳记录每次变更,使 SoT 可审计且可恢复。聚合将 SoT 与已拥有部分数据的权威系统连接:IPAM 用于地址,CMDB 用于资产,电路提供商用于连接。
园区实施示例展示了六者协同工作:Nautobot 作为联邦中心,Infoblox 和 ServiceNow 作为各自域的权威来源,设计模板将 VLAN 服务请求转化为自动化部署所需的一切。结果不仅仅是网络状态的数据库,而是每个其他构建模块查询以了解网络应该是什么的单一参考。
第 5 章将把这个意图转化为行动:执行模块从 SoT 读取并将变更推送到网络,具有 SoT 的版本控制功能所提供的一致性保证和回滚行为。
💬 Found something to improve? Send feedback for this chapter