CMDB(Configuration Management Database)的数据范围、架构与底层存储设计研究
概览
系统研究 CMDB 的数据范围、配置项、关系建模、当前快照、历史变更事件、数据来源、数据质量、分层架构,以及面向读多写多云原生环境的 PostgreSQL 核心事实源、事件流、缓存、搜索索引与图关系投影设计。
摘要
CMDB(Configuration Management Database)用于记录配置项(Configuration Item, CI)、服务、资产及其关系。官方文档将 CMDB 描述为资产、服务及其关系的逻辑表示,并将组件详情以 CI 的形式保存。NIST SP 800-53 CM-8 对系统组件清单提出了准确反映系统、包含全部组件、避免重复计数、具备必要粒度、包含问责信息并定期更新等控制要求。基于这些定义,CMDB 不仅是资产台账,也应包含应用、服务、实例、网络、软件、人员责任关系、依赖关系、当前状态、历史变更和数据来源等信息。对于现代云原生环境,应用列表和人员关系属于高频读取数据,而实例、Pod、虚拟机、IP、可用区状态等属于高频变更数据。因此,CMDB 的底层设计应采用“核心主库 + 事件流 + 缓存 + 搜索索引 + 图关系投影”的组合架构。其中,核心主库适合选择 PostgreSQL 或具备同等事务、约束、索引、分区和复制能力的关系型数据库;缓存、搜索引擎和图数据库不宜作为唯一事实源,而应作为查询加速层或关系分析投影层。
关键词
CMDB;配置项;配置管理;PostgreSQL;事件驱动架构;读写分离;关系建模;云原生
1 引言
CMDB 的核心目标是保存信息系统中配置项及其关系,使组织能够识别系统组成、理解服务依赖、追踪配置变化,并为变更管理、故障影响分析、安全审计和容量管理提供数据基础。ServiceNow 官方文档将 CMDB 描述为对资产、服务和关系的逻辑表示,组件详情以 CI 形式存储;其 CMDB Schema Model 则将 CMDB 表述为一组相互连接的数据表,用于保存资产、业务服务和配置等信息1。NIST SP 800-53 CM-8 将系统组件清单作为配置管理控制项,要求清单准确反映系统、包含系统组件、避免重复计数,并以满足跟踪和报告需要的粒度进行维护3。
因此,CMDB 的设计不能只关注“有哪些机器”或“有哪些应用”,而应覆盖“对象、属性、关系、状态、来源、时间和责任人”。在微服务、Kubernetes、多环境、多可用区和弹性伸缩场景下,CMDB 同时面对高频读取和高频写入:应用列表、应用负责人、服务归属、权限校验等数据被大量系统读取;实例、Pod、节点、IP、版本、可用区部署状态等数据持续变化。CMDB 架构设计必须把数据稳定性、查询模式和变更频率作为建模依据。
2 CMDB 中包含与存储的信息
CMDB 的基本存储对象是配置项 CI。CI 可以表示一个应用、服务、数据库、虚拟机、容器、Pod、节点、网络设备、软件包、证书、域名、负载均衡、部署环境、可用区资源,也可以表示服务之间、应用与人员之间、应用与实例之间的关系。按照官方文档和配置管理控制要求,CMDB 应至少包含以下几类信息。
2.1 配置项身份信息
每个 CI 应具备唯一标识,用于避免重复计数和错误合并。该标识可以由内部 ci_id 与外部来源标识共同构成。例如,云主机可以保存云厂商实例 ID、账号、区域、可用区;Kubernetes 对象可以保存集群、命名空间、资源类型、名称、UID;应用可以保存应用 ID、应用编码、服务名和所属组织。NIST CM-8 对系统组件清单提出“不重复计数”和“唯一识别”的要求3,因此 CMDB 不应仅依赖名称作为唯一键。
2.2 配置项分类与属性信息
CI 应包含类别、名称、状态、生命周期、环境、区域、可用区、版本、标签、创建时间、更新时间、来源系统等字段。不同类型 CI 的属性不同:应用类 CI 需要保存应用名称、语言栈、仓库、负责人、运行环境、所属团队;实例类 CI 需要保存实例 ID、IP、端口、镜像版本、运行状态、所在节点、所在可用区;软件类 CI 需要保存名称、版本、许可证和安装路径。AWS Systems Manager Inventory 官方文档列出的可采集元数据包括应用、AWS 组件、文件、网络配置、Windows 更新、实例详情、服务、标签、注册表、角色和自定义清单等信息4,这些类型可以作为 CMDB 属性边界的参考。
2.3 关系信息
CMDB 的价值不仅来自单个 CI 的属性,也来自 CI 之间的关系。关系信息包括应用与服务、服务与实例、应用与数据库、应用与消息队列、应用与人员、应用与团队、实例与节点、节点与可用区、服务与上游/下游调用方等。关系表应包含源 CI、目标 CI、关系类型、来源、置信度、有效时间、失效时间和变更事件 ID。对于应用列表和人员关系表这类高频读取数据,应将其作为一等数据模型,而不是仅存储在非结构化 JSON 中。
2.4 当前状态、历史变更与审计信息
CMDB 既要保存当前状态,也要保存历史变更。当前状态用于快速查询,例如某应用在生产环境的实例数量、版本、可用区分布和负责人;历史变更用于审计、回溯和故障定位,例如某实例何时上线、何时下线、何时从一个可用区迁移到另一个可用区。AWS Config 官方文档说明其可以记录 EC2 或本地实例的软件清单变化并查看历史变化4。因此,CMDB 应同时设计“当前快照表”和“变更事件表”,而不是只保留最后一次状态。
2.5 数据来源与数据质量信息
同一 CI 可能来自云 API、Kubernetes API、Agent、CI/CD、服务注册中心、监控系统、HR 系统或 IAM 系统。CMDB 应保存数据来源、采集时间、最后观测时间、同步批次、原始外部 ID、数据可信级别和冲突处理结果。ServiceNow CMDB 官方文档中包含 CMDB Health、Identification and Reconciliation 等能力,用于监测健康问题、识别和调和数据完整性问题1。因此,身份识别、去重、冲突合并和质量检查应作为 CMDB 的基础能力。
3 CMDB 的总体架构设计
CMDB 架构应采用分层设计,将数据采集、事件接入、标准化、调和、核心存储、查询加速和对外服务拆开。该设计可以降低高频变更数据对核心查询链路的影响,并使不同查询场景使用不同的数据视图。
3.1 数据源层
数据源层负责从不同系统获取配置数据。典型来源包括云厂商资源 API、Kubernetes API、Agent 清单采集、CI/CD 发布系统、服务注册中心、监控系统、日志系统、HR/IAM 系统、工单系统和代码仓库。Kubernetes 官方文档将对象定义为表示集群状态的持久实体,并区分期望状态 spec 与当前状态 status5。因此,云原生 CMDB 在采集 Kubernetes 对象时,应同时保存对象身份、期望配置、当前状态和资源版本。
3.2 事件接入层
实例、Pod、节点、IP、部署版本和可用区状态属于高频变化数据。对这类数据,不宜直接由采集器同步写入核心业务表,而应先进入事件流。Apache Kafka 官方文档将事件流定义为从事件源实时捕获数据、持久存储事件流、实时或回溯处理并路由到目标系统的机制6。CMDB 可以将实例变更、部署变更、人员关系变更、服务关系变更和资源删除事件统一写入事件流,并以 CI 唯一标识作为事件 key,使同一 CI 的事件在分区内保持顺序。
3.3 标准化与调和层
不同来源的字段、命名和标识规则不同。标准化层负责将外部数据转换为统一 CI 模型;调和层负责根据唯一标识、来源优先级、时间戳和规则合并同一对象。该层需要处理以下问题:同一实例被云 API 和 Agent 同时上报;同一应用在 CI/CD 和服务注册中心存在不同名称;同一人员在 HR 和 IAM 中存在不同账号;同一关系来自调用链、配置文件和人工维护三种来源。调和结果应写入核心主库,并保留原始事件和来源信息。
3.4 核心数据层
核心数据层保存 CMDB 的事实数据。建议至少包含以下表:
| 表名 | 作用 |
|---|---|
ci_core | 保存 CI 的统一身份、类型、名称、状态、生命周期、来源和时间字段 |
ci_attribute | 保存不同 CI 类型的扩展属性,适合低频变化属性 |
ci_relation | 保存 CI 之间的关系,包括依赖、归属、运行于、负责、调用等 |
ci_relation_type | 保存关系类型定义及方向约束 |
app_person_relation | 保存应用与负责人、研发、运维、安全、业务责任人的关系 |
app_instance_snapshot | 保存应用实例当前状态,例如环境、区域、可用区、IP、版本、状态 |
ci_change_event | 保存配置项变更事件,用于审计和回溯 |
ci_baseline | 保存基线、批准配置和偏差信息 |
ci_source_record | 保存外部来源系统的原始 ID、同步时间和原始摘要 |
该模型将稳定数据、关系数据、当前快照和历史事件分开,能够支撑不同的读写模式。
3.5 查询加速层
CMDB 查询不应全部落到核心主库。应用列表、应用负责人、服务归属和应用拓扑属于高频读取数据,应建立缓存、物化视图和只读副本。Redis 官方文档将 Redis 描述为内存数据存储,可作为缓存以减少数据库负载并提升读取速度9。PostgreSQL 物化视图可以保存查询结果并直接返回,适合周期性刷新或事件触发刷新7。OpenSearch 官方文档将其定义为分布式搜索和分析引擎,适合保存 JSON 文档并执行搜索和分析[10]。因此,CMDB 可以使用 Redis 承载热点键值查询,使用 PostgreSQL 物化视图承载结构化报表查询,使用 OpenSearch 承载全文搜索和复杂筛选。
3.6 图关系投影层
服务依赖、影响分析、调用链拓扑和多跳关系查询可以投影到图数据库。Amazon Neptune 官方文档说明图数据库适用于高度连接的数据集,可以查询大量关系并获得毫秒级响应8。因此,图数据库适合作为 CMDB 关系分析层,但不应替代核心主库。原因是 CMDB 的事实源需要主键、外键、唯一约束、事务一致性、审计事件和生命周期状态,而图数据库更适合关系遍历和影响分析。
3.7 API 服务层
API 服务层应按查询类型提供接口:配置项查询 API、应用查询 API、实例快照 API、关系查询 API、拓扑查询 API、变更历史 API、审计 API 和数据质量 API。对读取频率高的应用列表和人员关系,应优先读取缓存或物化视图;对强一致写入和审计查询,应读取核心主库;对全文搜索,应读取搜索索引;对多跳依赖分析,应读取图关系投影。
4 CMDB 底层数据库选择
CMDB 的核心主库应选择 PostgreSQL,或选择具备同等事务、约束、索引、分区、复制和 JSON 扩展能力的企业级关系型数据库。该结论基于 CMDB 数据模型的客观特征:CI 需要唯一标识,关系需要引用完整性,变更需要事务一致性,查询需要组合索引,历史事件需要分区,扩展属性需要半结构化字段。
PostgreSQL 官方文档说明,其多版本并发控制 MVCC 能够使读写互不阻塞,读取不会阻塞写入,写入也不会阻塞读取7。这与 CMDB 的读多写多场景相匹配。PostgreSQL 同时提供主键、唯一约束和外键,用于维护实体唯一性和引用完整性7。对于不同 CI 类型的差异化属性,PostgreSQL 的 jsonb 支持二进制分解存储和索引,适合保存扩展属性7。对于高频写入的变更事件表和实例状态表,PostgreSQL 分区可以将大表拆成多个物理分区,提升特定场景下的维护和查询效率7。对于读扩展和下游同步,PostgreSQL 逻辑复制可以持续发送数据变更7。
不过,PostgreSQL 不应单独承担所有查询负载。CMDB 可以采用以下数据库分工:
| 层次 | 数据库/组件 | 主要用途 |
|---|---|---|
| 核心事实源 | PostgreSQL | CI、关系、人员关系、实例快照、变更事件、约束、事务 |
| 热点缓存 | Redis | 应用列表、应用负责人、应用基础信息、权限校验所需关系 |
| 搜索分析 | OpenSearch | 应用搜索、实例搜索、标签筛选、模糊查询、审计检索 |
| 图关系投影 | Neptune 或其他图数据库 | 多跳依赖、影响分析、服务拓扑、调用链关系 |
| 事件流 | Kafka | 高频变更接入、异步投影、缓存失效、CDC 分发 |
因此,底层数据库不应被理解为单一组件。准确表述应为:CMDB 的核心事实源选择 PostgreSQL;Redis、OpenSearch、图数据库和 Kafka 分别承担缓存、搜索、关系分析和事件流职责。
5 面向读多写多场景的设计要点
5.1 稳定数据与高频变更数据分离
应用、团队、人员、服务定义、应用负责人等属于相对稳定数据;实例、Pod、IP、节点、部署版本、运行状态、可用区分布属于高频变更数据。两类数据的表结构、索引、缓存策略和写入链路不应相同。稳定数据适合放在规范化主表和关系表中,高频变更数据适合采用“事件表 + 当前快照表”的双表模型。
5.2 应用列表与人员关系采用缓存和物化视图
应用列表和人员关系是高频读取数据,所有应用、发布系统、权限系统、网关系统、监控系统和告警系统都可能读取。该类数据应形成独立读模型,例如 app_read_model、app_owner_read_model、app_team_read_model。读模型可以由 PostgreSQL 物化视图或普通宽表承载,并同步到 Redis。缓存 key 可按版本或时间戳设计,例如 cmdb:app:list:{version}、cmdb:app:{app_id}:owners。当应用或人员关系发生变更时,通过事件流或 CDC 触发缓存失效和读模型更新。
5.3 实例信息采用事件表与快照表
实例变更频率高,尤其是在多环境、多可用区、弹性伸缩和 Kubernetes 场景中。实例数据应分为两部分:app_instance_snapshot 保存当前状态,ci_change_event 保存历史事件。每次实例上线、下线、重启、迁移、IP 变化、版本变化、可用区变化,都应生成事件;事件消费者根据事件更新当前快照。该设计可以同时满足快速读取当前状态和追溯历史变更两个目标。
5.4 高频写入表使用分区与幂等键
ci_change_event 和实例快照相关表应使用时间、环境、区域或可用区进行分区。事件表应包含 event_id、ci_id、source、event_type、event_time、sequence、payload_hash 等字段。幂等键可以由来源系统、外部资源 ID、事件类型和资源版本组成,避免重复消费导致状态错误。Kubernetes API watch 机制基于 resourceVersion 观察资源变化,客户端还需要处理资源版本过旧导致的重新同步场景5。该机制说明 CMDB 在采集云原生对象时必须保存版本号或序列号。
5.5 避免把高频字段塞入单个大 JSON
PostgreSQL 的 jsonb 适合保存不同 CI 类型的扩展属性,但不适合把高频变化字段全部塞入一个大 JSON 字段。PostgreSQL 官方文档说明,更新 JSON 数据时会取得行级锁,因此频繁变化字段应拆分为结构化列或独立快照表7。例如,实例状态、IP、可用区、版本、心跳时间应放在 app_instance_snapshot 的结构化列中;低频扩展属性可以放在 jsonb 中。
5.6 关系表必须记录有效期和来源
应用与人员、应用与实例、服务与服务之间的关系会变化。关系表不应只保存当前关系,还应保存 valid_from、valid_to、source、observed_at、confidence 和 change_event_id。这样可以支持历史追溯、责任归属和故障时间点还原。例如,当一个应用在某天更换负责人后,历史告警仍应能够关联到当时的负责人关系。
5.7 数据质量控制应前置到写入链路
CMDB 写入链路应执行身份识别、必填字段校验、唯一性校验、关系合法性校验、来源优先级处理和冲突记录。NIST CM-8 要求清单准确反映系统并包含必要粒度的信息3。ServiceNow CMDB Health 和 Identification and Reconciliation 也将健康检查、识别和调和作为 CMDB 能力1。因此,数据质量控制不应只依赖离线巡检,而应在采集、入库和投影阶段持续执行。
5.8 对外读取应按一致性要求分层
不同读取场景对一致性的要求不同。权限判断、发布审批、应用归属等场景需要较高一致性,应读取主库或强一致读模型;应用列表展示、搜索、拓扑浏览可以读取缓存或搜索索引;故障影响分析可以读取图关系投影;审计和变更回溯应读取事件表。通过一致性分级,可以避免所有请求都压到核心主库。
6 结论
CMDB 应保存配置项、属性、关系、当前状态、历史变更、责任人、来源和质量信息。其架构应采用数据采集、事件接入、标准化调和、核心事实源、查询加速、图关系投影和 API 服务的分层设计。对于底层数据库,PostgreSQL 适合作为核心事实源,因为其事务、约束、MVCC、JSONB、分区、复制和物化视图能力与 CMDB 的数据特征相匹配。Redis、OpenSearch、图数据库和 Kafka 应作为缓存、搜索、关系分析和事件流组件,而不是替代核心事实源。
在读多写多场景下,CMDB 的关键设计原则是:稳定主数据与高频变更数据分离;应用列表和人员关系建立读模型与缓存;实例变化采用事件表和当前快照表;高频事件表使用分区和幂等键;关系表保存有效期和来源;数据质量控制前置到写入链路。该设计能够同时支持应用级高频读取、实例级高频变更、跨环境跨可用区查询、历史审计和服务影响分析。
参考文献
1 ServiceNow 官方文档说明,CMDB 用于构建资产、服务和关系的逻辑表示,组件详情以 CI 形式存储,并包含 CMDB Health、Identification and Reconciliation 等能力。(ServiceNow)
2 ServiceNow CMDB Schema Model 官方文档说明,CMDB Schema Model 是一组相互连接的数据表,包含资产、业务服务、配置、计算机、网络设备、软件合同和许可证等信息。(ServiceNow)
3 NIST SP 800-53 Rev.5 的 CM-8 控制项要求系统组件清单准确反映系统、包含全部组件、避免重复计数、具备满足跟踪和报告需要的粒度,并包含问责信息、自动维护、未授权组件检测和集中仓库等增强要求。
4 AWS Systems Manager Inventory 官方文档列出可采集的应用、组件、文件、网络配置、实例详情、服务、标签、注册表、角色和自定义清单等元数据;AWS Config 官方文档说明可记录软件清单变化并查看历史变化。(AWS 文档)
5 Kubernetes 官方文档说明 Kubernetes 对象是表示集群状态的持久实体,包含 spec 与 status;API watch 机制基于 resourceVersion 观察后续变化,并要求客户端处理版本过旧的情况。(Kubernetes)
6 Apache Kafka 官方文档将事件流描述为实时捕获、持久存储、处理并路由事件流;Topic 可分区,同一 key 的事件会进入同一分区,从而支持有序处理。(kafka.apache.org)
7 PostgreSQL 官方文档说明 MVCC 使读写互不阻塞;约束、主键和外键用于维护数据有效性和引用完整性;jsonb 支持索引;分区可将大表拆成物理子表;逻辑复制可持续发送数据变更;物化视图可保存查询结果。(PostgreSQL)
8 Amazon Neptune 官方文档说明,图数据库适用于高度连接的数据集,并支持对大量关系进行低延迟查询。(AWS 文档)
9 Redis 官方文档说明,Redis 是内存数据存储,可作为缓存减少数据库负载并提升读取速度。(Redis)
[10] OpenSearch 官方文档说明,OpenSearch 是分布式搜索和分析引擎,文档以 JSON 形式存储,索引用于查询数据。(docs.opensearch.org)

参与讨论
评论会同步到 stellhub/stell-web 仓库的 GitHub Discussions。