- 后端
- 企业应用
- 运维
【免费下载链接】bk-cmdb
蓝鲸智云配置平台(BlueKing CMDB)
导读
本文围绕蓝鲸智云配置平台(BlueKing CMDB,即 bk-cmdb)的模型(Model)体系,系统梳理 docs/db/model.md 中定义的 7 张核心元数据表:cc_ObjDes(模型定义)、cc_ObjClassification(模型分组)、cc_ObjAttDes(模型属性)、cc_PropertyGroup(属性分组)、cc_AsstDes(关联类型)、cc_ObjAsst(模型关联)、cc_ModelQuoteRelation(模型引用关系)。这些表是 CMDB 自定义模型建模能力的存储根基——从"新建一个业务模型"到"为模型挂属性、分组、关联、引用",底层写入的就是这 7 张集合。读完本文,你将掌握每张表的字段语义、表间关系、自增 ID 生成机制,以及 coreservice 中对应的数据操作代码位置,可据此进行二次开发与数据排障。
说明:CMDB 底层使用 MongoDB 存储,上述"表"实际为 MongoDB 中的 Collection(集合),"字段"为文档(Document)中的键。原文档位于 docs/db/README.md,其中明确指出:"MongoDB 是一个面向文档的数据库,因此它没有传统的表结构,而是使用集合(Collection)和文档(Document)来组织数据,本目录下文档中涉及的表结构和字段解释仅供参考,请以实际环境中的结构为准。" 因此本文所有字段类型(如 ObjectId、NumberLong、ISODate、Boolean)均为文档层面的逻辑类型约定。
一、模型相关表的整体分工与数据流
CMDB 的模型(Model)又称"对象模型",是描述一类配置资源的元数据结构。在模型相关表体系中,7 张集合各司其职,共同支撑"模型定义 → 分组归类 → 属性建模 → 属性分组 → 关联建模 → 关联类型 → 引用建模"的完整链路:
| 集合(Collection) | 作用 | 对应源码常量 | 核心 CRUD 源码位置 |
|---|---|---|---|
cc_ObjDes | 存放模型信息(模型定义) | common.BKTableNameObjDes | model_crud.go |
cc_ObjClassification | 存放模型分组信息 | common.BKTableNameObjClassification | classification_crud.go |
cc_ObjAttDes | 存放模型属性字段信息 | common.BKTableNameObjAttDes | attribute_curd.go |
cc_PropertyGroup | 模型属性字段分组信息表 | common.BKTableNamePropertyGroup | model_attribute_group_crud.go |
cc_AsstDes | 存放模型间的关联类型 | common.BKTableNameAsstDes | kind_crud.go |
cc_ObjAsst | 存放模型关联信息 | common.BKTableNameObjAsst | model_crud.go |
cc_ModelQuoteRelation | 存放模型与引用类型关联关系信息 | common.BKTableNameModelQuoteRelation | model_crud.go、attribute.go |
这些表名常量统一定义在 src/common/tablenames.go,并被AllTables列表登记(见 src/common/tablenames.go)。其中:
cc_ObjDes、cc_ObjClassification、cc_ObjAttDes、cc_PropertyGroup属于模型元数据,由 coreservice 的model模块管理;cc_AsstDes、cc_ObjAsst属于关联元数据,由 coreservice 的association模块管理;cc_ModelQuoteRelation是模型引用(表格型字段引用另一模型)的桥接表,由model模块在使用/删除表格型属性时读写。
模型相关表与实例相关表(如cc_ObjectBase、cc_InstAsst,见 instance.md)的关系是:模型表描述"有什么类型的东西、长什么样",实例表描述"具体有哪些东西、值是什么"。以主机(bk_obj_id = host)为例,cc_ObjDes中登记主机模型,cc_ObjAttDes中登记bk_host_innerip等属性定义,而主机实例数据则落在cc_HostBase中(见 src/common/tablenames.go 的BKTableNameBaseHost)。
二、cc_ObjDes:模型定义表
2.1 作用
模型表,存放模型信息。每条文档对应一个模型,包括模型唯一标识bk_obj_id(如host、set、module以及业务自定义模型)、模型名称bk_obj_name、所属分组bk_classification_id等。
2.2 表结构(继承自原文档并补充说明)
| 字段 | 类型 | 描述 |
|---|---|---|
_id | ObjectId | 数据唯一 ID |
position | String | 模型坐标,用于模型关系拓扑图中 |
modifier | String | 修改者 |
id | NumberLong | 自增 ID |
bk_obj_id | String | 模型唯一标识 |
bk_obj_name | String | 模型名称 |
description | String | 描述信息 |
bk_classification_id | String | 模型所属分组 |
bk_obj_icon | String | 模型 Logo |
bk_ishidden | Boolean | 是否是隐藏模型(如进程、服务模型等),隐藏模型在前端不展示 |
ispre | Boolean | 是否为系统预置 |
bk_ispaused | Boolean | 是否停用 |
creator | String | 创建者 |
obj_sort_number | NumberLong | 模型排序序号 |
bk_supplier_account | String | 开发商 ID |
create_time | ISODate | 创建时间 |
last_time | ISODate | 最后更新时间 |
2.3 源码对照
Go 侧对应的结构体为metadata.Object,定义在 src/common/metadata/object.go,字段与表一一对应(通过bson标签绑定 MongoDB 键名)。写入侧的关键逻辑在 model_crud.go:
id, err = mongodb.Client().NextSequence(kit.Ctx, common.BKTableNameObjDes) // 自增 id model.ObjSortNumber = sortNum // 排序号 model.ID = int64(id) model.OwnerID = kit.SupplierAccount // 开发商 ID可见id由 MongoDB 序列生成器NextSequence产出,bk_supplier_account直接取自请求上下文kit.SupplierAccount,create_time/last_time由服务端time.Now()写入。此外,模型保存成功后还会为模型实例生成独立的 ID 规则记录(GetIDRule,见 model_crud.go)。
关于字段校验,从源码可以推断:
bk_obj_id是模型的核心业务键,几乎所有查询都以其为过滤条件;bk_ishidden = true的模型(如进程、服务模型)在前端不展示(见 src/common/metadata/object.go 注释 "front-end don't display the object if IsHidden is true");ispre = true表示系统预置模型(如biz、host、set、module、plat、process等内置模型),此类模型禁止删除、禁止新增属性(notAddAttrModel,见 attribute_curd.go)。
三、cc_ObjClassification:模型分组表
3.1 作用
存放模型分组(分类)信息。每个模型都必须归属一个分组,分组用bk_classification_id唯一标识。
3.2 表结构
| 字段 | 类型 | 描述 |
|---|---|---|
_id | ObjectId | 数据唯一 ID |
bk_classification_id | String | 分组唯一标识 |
bk_classification_name | String | 分组名 |
bk_classification_type | String | 分组类型 |
bk_classification_icon | String | 分组 Logo |
id | NumberLong | 自增 ID |
bk_supplier_account | String | 开发商 ID |
3.3 源码对照
metadata.Classification定义在 src/common/metadata/classification.go。系统预置了 5 个内置分组(见 src/common/metadata/classification.go):
| 分组 ID | 分组名 | 典型用途 |
|---|---|---|
bk_host_manage | 主机管理 | 主机、云区域等主机相关模型 |
bk_biz_topo | 业务拓扑 | 业务、集群、模块等主线模型 |
bk_organization | 组织架构 | 组织相关模型 |
bk_network | 网络 | 网络设备等模型 |
bk_uncategorized | 未分类 | 默认兜底分组 |
写入侧逻辑在 classification_crud.go:同样通过NextSequence(cc_ObjClassification)生成自增id,并将bk_supplier_account设为请求上下文中的开发商 ID。注意其update方法会显式Remove(metadata.ClassFieldClassificationID),即分组唯一标识创建后不可修改(见 classification_crud.go)。
四、cc_ObjAttDes:模型属性字段表
4.1 作用
存放模型属性字段信息。这是模型体系中信息量最大的一张表,一个模型的全部字段(内置字段 + 自定义字段)都以文档形式存于此表。
4.2 表结构
| 字段 | 类型 | 描述 |
|---|---|---|
_id | ObjectId | 数据唯一 ID |
bk_isapi | Boolean | 是否为 API 参数 |
creator | String | 创建人 |
bk_property_name | String | 属性字段名称 |
placeholder | String | 提示信息 |
editable | Boolean | 在实例中是否可编辑 |
bk_issystem | Boolean | 是否仅为系统内部使用 |
option | — | 用户自定义内容,存储的内容及数据格式由字段类型决定 |
id | NumberLong | 自增 ID |
bk_obj_id | String | 模型 ID |
bk_property_id | String | 属性字段 ID |
bk_property_group | String | 属性字段分组 |
unit | String | 单位 |
isrequired | Boolean | 是否必填 |
isreadonly | Boolean | 是否只读 |
bk_property_index | NumberLong | 属性字段排序号 |
ispre | Boolean | 是否为系统预置 |
bk_property_type | String | 属性字段类型 |
bk_biz_id | NumberLong | 业务 ID,不为 0 则代表是业务自定义属性 |
bk_template_id | NumberLong | 字段模板 ID |
default | — | 字段默认值,存储的内容及数据格式由字段类型决定 |
description | String | 描述信息 |
ismultiple | Boolean | 是否可多选 |
isonly | Boolean | 是否唯一 |
bk_supplier_account | String | 开发商 ID |
create_time | ISODate | 创建时间 |
last_time | ISODate | 最后更新时间 |
4.3 关键字段:bk_property_type 支持的类型
bk_property_type决定了option、default的存储格式与校验规则。CMDB 支持的字段类型常量定义在 src/common/definitions.go:
| 类型值 | 含义 | option 内容说明 |
|---|---|---|
singlechar | 单行短文本 | 可存正则表达式,默认最大长度 256(FieldTypeSingleLenChar) |
longchar | 长文本 | 可存正则表达式,默认最大长度 2000(FieldTypeLongLenChar) |
int | 整数 | {min, max}区间(IntOption),未配置时默认[MinInt64, MaxInt64] |
float | 浮点数 | {min, max}区间(FloatOption) |
enum | 枚举单选 | [{id, name, type, is_default}](EnumVal) |
enummulti | 枚举多选 | 同枚举,配合ismultiple使用 |
enumquote | 枚举引用(引用其他模型实例) | 引用模型的相关配置 |
date | 日期 | — |
time | 时间 | — |
timezone | 时区 | — |
bool | 布尔 | — |
objuser | 用户 | 可多人,默认最大长度 2000(FieldTypeUserLenChar) |
list | 列表 | [elem1, elem2, ...]字符串数组 |
table | 表格(内部类型) | 表格型字段,驱动模型引用 |
innertable | 内部表格(模型引用场景) | 模型引用场景专用 |
organization | 组织 | — |
id_rule | ID 规则字段 | — |
所有合法类型汇总在FieldTypes列表(src/common/definitions.go)。字段值的运行时校验在 src/common/metadata/attribute.go 的Attribute.Validate中按类型分发,例如:
int/float类型会解析option中的min/max并校验取值范围(ParseIntOption见 attribute.go,ParseFloatOption见 attribute.go);enum类型会把option解析为[]EnumVal并校验取值必须在枚举列表中(ParseEnumOption见 attribute.go,EnumVal结构见 attribute.go,枚举元素要求id、name非空且type == "text");singlechar/longchar类型若option为正则表达式字符串,则用正则校验字段值(见 attribute.go)。
4.4 源码对照
metadata.Attribute结构体定义在 src/common/metadata/attribute.go,是cc_ObjAttDes的 Go 映射。写入侧在 attribute_curd.go:通过NextSequence(cc_ObjAttDes)生成自增id,通过GetAttrLastIndex自动计算排序号bk_property_index。
值得注意的业务约束(见 attribute_curd.go):
notAddAttrModel = {plat, process}:云区域(plat)与进程(process)模型不允许新增属性;RequiredFieldUnchangeableModels = {biz, host, set, module, plat, process}:这些内置模型的属性必填标记isrequired不允许修改;bk_biz_id != 0表示该属性是业务自定义属性(即该业务下专属);bk_template_id非 0 表示该属性来自字段模板(见 field_template.md)。
五、cc_PropertyGroup:模型属性分组表
5.1 作用
模型属性字段分组信息表。用于把同一模型的多个属性组织成"基础信息""资源"等分组,对应前端属性表单的折叠分区。
5.2 表结构
| 字段 | 类型 | 描述 |
|---|---|---|
_id | ObjectId | 数据唯一 ID |
bk_biz_id | NumberLong | 业务 ID |
id | NumberLong | 自增 ID |
bk_obj_id | String | 分组所属模型 ID |
ispre | Boolean | 是否为系统预置 |
bk_group_id | String | 分组唯一标识 |
bk_group_name | String | 分组名称 |
bk_group_index | NumberLong | 分组索引 |
bk_isdefault | Boolean | 是否是默认分组 |
is_collapse | Boolean | 是否折叠 |
bk_supplier_account | String | 开发商 ID |
create_time | ISODate | 创建时间 |
last_time | ISODate | 最后更新时间 |
5.3 源码对照
metadata.Group定义在 src/common/metadata/group.go,其中bk_isdefault(默认分组)与is_collapse(是否折叠)是本表独有字段。写入侧在 model_attribute_group_crud.go,同样走NextSequence(cc_PropertyGroup)生成id。
分组与属性通过cc_ObjAttDes.bk_property_group关联:属性的bk_property_group字段值即分组 ID(cc_PropertyGroup.bk_group_id),迁移属性到其他分组时只需更新该字段(对应接口参数见 group.go 的PropertyGroupObjectAtt,更新bk_property_group与bk_property_index)。
六、cc_AsstDes:关联类型表
6.1 作用
存放模型间的关联类型。关联类型(Association Kind)是"关联关系的种类",如"属于""依赖""组成",被cc_ObjAsst引用。
6.2 表结构
| 字段 | 类型 | 描述 |
|---|---|---|
_id | ObjectId | 数据唯一 ID |
id | NumberLong | 自增 ID |
src_des | String | 源模型到关联目标模型的描述 |
dest_des | String | 目标模型到源模型的描述 |
direction | String | 方向:源指向目标、无方向、双向 |
ispre | String | 是否为系统预置 |
bk_asst_name | String | 关联类型名称 |
bk_asst_id | NumberLong | 关联类型唯一标识 |
bk_supplier_account | String | 开发商 ID |
6.3 源码对照
metadata.AssociationKind定义在 src/common/metadata/association.go。direction字段的取值常量在 association.go:
NoneDirection AssociationDirection = "none" // 无方向 DestinationToSource AssociationDirection = "src_to_dest" SourceToDestination AssociationDirection = "dest_to_src" Bidirectional AssociationDirection = "bidirectional" // 双向bk_asst_id的合法性校验在 kind_crud.go:要求长度不超过AttributeIDMaxLength,且匹配严格标识正则^[a-zA-Z]\w*$(FieldTypeStrictCharRegexp,见 src/common/definitions.go)。写入侧同样使用NextSequence(cc_AsstDes)(见 kind_crud.go)。系统内置的关联类型中有一个特殊值mainline(主线关联),用于支撑业务拓扑主线,用户侧禁止创建或操作该类型(见 src/common/metadata/object.go)。
七、cc_ObjAsst:模型关联表
7.1 作用
存放模型关联信息,即"哪个模型通过哪种关联类型与哪个模型关联"的具体定义。模型拓扑(包括主线拓扑)正是通过本表构建的。
7.2 表结构
| 字段 | 类型 | 描述 |
|---|---|---|
_id | ObjectId | 数据唯一 ID |
bk_asst_obj_id | String | 关联模型名称(目标模型) |
id | NumberLong | 自增 ID |
bk_obj_id | String | 模型名称(源模型) |
bk_asst_id | String | 关联类型 |
bk_obj_asst_id | String | 关联标识 |
bk_obj_asst_name | String | 关联名称 |
ispre | Boolean | 是否为系统预置 |
mapping | String | 源-目标约束,有n:n、1:n、1:1三种 |
on_delete | String | 是否可删除(删除关联时的级联行为) |
bk_supplier_account | String | 开发商 ID |
7.3 源码对照
metadata.Association定义在 src/common/metadata/association.go。其中:
bk_obj_asst_id的生成规则在源码注释中有明确规定:"$ObjectID"_"$AsstID"_"$AsstObjID"(见 association.go),例如主机与业务之间形如biz_run_host的组合标识,它是实例关联表cc_InstAsst中bk_obj_asst_id的外键语义来源;mapping取值常量:1:1(一对一)、1:n(一对多)、n:n(多对多),定义在 association.go;on_delete取值常量:none(删除关联时不做级联)、delete_src(级联删除源实例)、delete_dest(级联删除目标实例),见 association.go;ispre = true表示该关联是 CMDB 自身使用的主线/预置关联,仅on_delete、关联类型、别名可更新(CanUpdate方法见 association.go)。
写入侧在 model_crud.go,通过NextSequence(cc_ObjAsst)生成自增id后Insert。模型主线的构建原理见 src/source_controller/coreservice/core/mainline/README.md:"主线模型及关联关系可直接通过模型关联关系表cc_ObjAsst拿到,最终的拓扑模型可以用一个链表表示",即业务 → 集群(set)→ 模块(module)→ 主机(host)这样的主线层级就存储在本表中。
八、cc_ModelQuoteRelation:模型引用关系表
8.1 作用
存放模型与引用类型关联关系信息。用于支撑"表格型字段引用另一模型"(模型引用/内嵌表格)的能力。
8.2 表结构
| 字段 | 类型 | 描述 |
|---|---|---|
_id | ObjectId | 数据唯一 ID |
dest_model | String | 引用模型(派生模型) |
src_model | String | 源模型 |
bk_property_id | String | 模型属性 ID |
type | String | 模型属性类型 |
bk_supplier_account | String | 开发商 ID |
8.3 源码对照
metadata.ModelQuoteRelation定义在 src/common/metadata/model_quote.go,注释给出了典型示例:"例如主机上的磁盘表格字段,DestModel为bk_host_disk,SrcModel为host,PropertyID为disk,Type为table。"
派生的被引用模型 ID 通过 GenerateModelQuoteObjID 生成:"bk_" + srcModel + "#" + propertyID,例如主机磁盘模型的bk_obj_id为bk_host#disk。反向解析(由dest_model反查src_model)由 GetModelQuoteSrcObjID 完成。
引用关系表的典型使用场景(删除表格型属性时):
- 在 model_crud.go 中,先根据
src_model+bk_property_id构造派生模型 ID,删除派生的实例表(DropTable),再删除cc_ObjAttDes中的属性记录,最后删除cc_ModelQuoteRelation中的引用关系,并清理cc_PropertyGroup与cc_ObjDes中派生模型的残留; - 在 attribute.go 中,更新表格属性前会先查
cc_ModelQuoteRelation拿到DestModel,再决定是否对派生实例表执行删列(dropColumns)。
九、贯穿各表的公共机制
9.1 自增 ID(cc_idgenerator)
7 张表文档中标注为"自增 ID"的id字段,均由 MongoDB 序列生成器统一分配。NextSequence底层依赖cc_idgenerator集合(BKTableNameIDgenerator,见 src/common/tablenames.go),每个目标表作为一个序列键,按序递增。对应调用点:
cc_ObjDes:model_crud.gocc_ObjClassification:classification_crud.gocc_ObjAttDes:attribute_curd.gocc_PropertyGroup:model_attribute_group_crud.gocc_AsstDes:kind_crud.gocc_ObjAsst:model_crud.go
9.2 开发商隔离(bk_supplier_account)
几乎每张模型相关表都带bk_supplier_account字段,用于按开发商(供应商账户)做数据隔离。写入侧统一由kit.SupplierAccount赋值(如 model_crud.go),查询侧通过util.SetQueryOwner自动追加开发商过滤条件(如 classification_crud.go)。在单租户部署中该值通常为0(对应分表命名中的pub,见 src/common/tablenames.go)。
9.3 时间与审计字段
create_time、last_time以及creator、modifier由服务端统一写入:创建时若CreateTime/LastTime为空则填充time.Now(),并记录当前操作用户(见 model_crud.go)。
9.4 数据同步与运维脚本
模型相关表也是 CMDB 数据同步(datasynchronize)与升级脚本的重点对象:
- datasynchronize/model.go 展示了
cc_ObjClassification、cc_ObjAttDes、cc_PropertyGroup、cc_ObjDes四张表的同步适配逻辑; - 运维脚本 fix_inner_model.js、fix_module_missed_fields.js 以及 admin_server/upgrader 目录下的历史升级脚本,都直接操作这些集合进行数据修复。
十、常见问题排查与二次开发指引
- 模型查询不出来:检查
cc_ObjDes中bk_supplier_account是否与请求开发商一致、bk_ispaused是否为true(停用模型)、bk_ishidden是否导致前端不展示(src/common/metadata/object.go)。 - 属性值校验失败:对照
cc_ObjAttDes中该属性的bk_property_type与option内容,确认值与类型匹配,例如int类型检查option.min/max区间、enum类型检查取值是否在option的EnumVal列表中、singlechar检查是否匹配option中的正则。 - 关联建不出来:确认
cc_AsstDes中已存在关联类型(bk_asst_id满足^[a-zA-Z]\w*$),且cc_ObjAsst的bk_obj_asst_id遵循源模型ID_关联类型ID_目标模型ID的组合规则;主线(mainline)关联类型禁止用户操作。 - 表格型字段(模型引用)异常:核对
cc_ModelQuoteRelation中src_model/bk_property_id与派生模型dest_model(形如bk_源模型#属性ID)是否一致,派生模型的实例数据存放在GetInstTableName计算出的分表(见 src/common/tablenames.go)。 - 业务自定义属性:
cc_ObjAttDes.bk_biz_id != 0的属性仅作用于该业务,跨业务查询时需注意过滤。
二次开发时可重点阅读以下源码,掌握模型相关表的完整读写链路:
- 模型元数据 CRUD:src/source_controller/coreservice/core/model(含 model_test.go、attribute_test.go、classification_test.go、model_attribute_group_test.go 等测试用例);
- 关联元数据 CRUD:src/source_controller/coreservice/core/association;
- 字段类型与校验:src/common/metadata/attribute.go、src/common/definitions.go。
结语
cc_ObjDes、cc_ObjClassification、cc_ObjAttDes、cc_PropertyGroup、cc_AsstDes、cc_ObjAsst、cc_ModelQuoteRelation这 7 张模型相关表构成了蓝鲸 CMDB 自定义建模的元数据底座:模型定义与分组回答"有哪些模型",属性与属性分组回答"模型长什么样",关联类型与模型关联回答"模型之间什么关系",模型引用关系回答"表格字段如何内嵌另一模型"。理解这些集合的字段语义与 coreservice 的读写逻辑,是进行模型管理二次开发、排查建模异常和读懂升级脚本的前提。本文所有表结构均继承自 docs/db/model.md,字段语义的深化说明均有对应源码佐证,实际部署环境中的数据结构请以 docs/db/README.md 的说明为准,以实际 MongoDB 集合内容为准。
- 后端
- 企业应用
- 运维
【免费下载链接】bk-cmdb
蓝鲸智云配置平台(BlueKing CMDB)
相关推荐
蓝鲸 CMDB 实例相关表深度解析:cc_ObjectBase 与 cc_InstAsst 分表结构与字段说明
蓝鲸 CMDB 实例相关表深度解析:cc_ObjectBase 与 cc_InstAsst 分表结构与字段说明 导读 本文聚焦于蓝鲸智云配置平台(bk cmdb
后端企业应用运维蓝鲸 CMDB 业务资源数据表深度解析:cc_ServiceCategory、cc_ServiceInstance、cc_Process 与关联表实战指南
蓝鲸 CMDB 业务资源数据表深度解析:cc_ServiceCategory、cc_ServiceInstance、cc_Process 与关联表实战指南 导读
后端企业应用运维Standard Open Arm 100仿生设计:模仿人类手臂的运动学优化
Standard Open Arm 100仿生设计:模仿人类手臂的运动学优化 你是否曾为传统机械臂的僵硬动作感到困扰?是否希望机器人能像人类手臂一样自然灵活地完
后端企业应用运维
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考