CMDB核心是确保数据可信、变更可溯、接入可控:资产唯一标识须用source_type+source_id联合索引,多云特有属性存JSON字段,变更日志需含完整快照与diff字符串,禁用软删除并按月分区。

Go 实现 CMDB 不是堆功能,而是围绕「数据可信、变更可溯、接入可控」三个硬约束来组织代码。用 gin 或 beego 写个 CRUD 界面不难,但真正卡住上线的,永远是资产唯一标识怎么定、多云数据怎么对齐、变更日志怎么存才不丢不重。
怎么定义资产唯一标识(不是 hostname 或 IP)
CMDB 里最常踩的坑是把 hostname 或 ip 当主键:云主机重启换 IP、物理机重装系统改 hostname,老记录就断连了。实际生产中必须引入业务层唯一 ID。
- 推荐组合:
source_type(如"aliyun"、"vmware"、"physical") +source_id(云平台返回的实例 ID,如"i-bp1a2b3c4d5e6f7g8h9")作为联合唯一索引 - 避免用
uuid.New()自动生成——它和真实资产无绑定,下线后无法追溯历史 - 如果对接 Prometheus 或 Zabbix,可用其
instance标签值(格式如"10.1.2.3:9100"),但需加前缀标注来源,防止不同监控源冲突
多云资产入库时如何避免字段爆炸
阿里云有 InstanceChargeType,腾讯云叫 InstanceChargeType 但值不同,AWS 又叫 InstanceLifecycle。硬建几十个字段会把结构撑爆,也难查。
- 核心表只存通用字段:
name、ip_inner、ip_outer、os、status、source_type、source_id、created_at - 云平台特有属性统一进
jsonb(PostgreSQL)或text字段(MySQL 用JSON类型),例如存为cloud_metadata,内容是{"region":"cn-hangzhou","zone":"cn-hangzhou-b"} - 查询时用 GORM 的
Where("cloud_metadata->>'region' = ?", "cn-hangzhou"),别全量解析 JSON
变更日志必须带 diff 且不可删
很多实现只记「谁在什么时间改了哪台机器」,但审计时被问「到底改了什么」就哑火。日志字段设计错,后面补成本极高。
立即学习“go语言免费学习笔记(深入)”;
- 日志表至少含:
asset_source_id、op_type("create"/"update"/"delete")、before_data(JSON)、after_data(JSON)、diff(字符串,如"replicas: 2 → 4")、operator、created_at -
before_data和after_data必须是完整快照,不是 PATCH;diff 字段用于快速筛选,不能替代快照 - 日志表禁用软删除,也不做定期清理——等审计出事再恢复就晚了;用分区表按月切分更稳妥
对接 Kubernetes Deployment 时别直接调 client-go 写死
你写的 DeploymentInstanceGet 函数看着干净,但线上一跑就出问题:kubeconfig 权限不足、context 超时没设、namespace 不存在没兜底、clientset 复用不当导致 fd 耗尽。
- 每个请求应新建
context.WithTimeout(context.Background(), 10*time.Second),别用context.TODO() - kubeconfig 文件路径必须从配置中心或环境变量注入,禁止硬编码在
web.go里;多集群场景下,用source_id查映射表获取对应 config - clientset 建议封装成单例 + 连接池管理,参考
github.com/yunixiangfeng/gocmdb的utils/kubeclient.go初始化逻辑 - 更新 Deployment 前先
Get再Update,别用Patch——Patch 容易覆盖别人同时改的字段
CMDB 的复杂点不在接口多,而在每一行数据背后都连着运维动作、权限边界和审计红线。字段命名、日志粒度、ID 生成方式这些看似边缘的决定,半年后都会变成数据库迁移或合规检查时的拦路虎。


















