接手一套跑了五六年的IT资产台账最让人头疼的不是数据少而是同一台服务器在三个表格里叫三个名字监控系统里叫app-prod-01工单系统里写的是10.20.1.11到了机房巡检表上又变成了“三号柜第二层那台戴尔”。维易CMDB这类配置管理数据库要解决的正是这种“谁都有一份账、谁都不敢信”的局面。配置管理数据库不是把Excel换个地方存它要做的是把服务器、网络设备、应用、数据库、业务系统之间的关系梳理成一张可查询、可追溯、可联动的图。这篇内容面向正在推进企业级IT配置管理建设的运维负责人、SRE、平台工程师也会照顾刚接触CMDB概念的新同学。我会围绕维易CMDB这套平台的落地过程把数据模型怎么设计、采集怎么做、数据怎么治理、周边系统怎么打通、出了问题怎么排查按我们团队实际干过的顺序拆开讲能直接抄的部分我会把配置和脚本贴出来。1. 先想清楚企业级CMDB到底在建设什么1.1 CMDB解决的从来不是“记录”问题很多人对CMDB的第一印象是“高级版资产表”这个理解会直接把项目带偏。资产表回答的是“我有什么”CMDB回答的是“它是什么、在哪里、归谁管、依赖谁、坏了会影响谁”。这四个问题里前三个还能靠人工维护第四个必须靠关系模型和自动化采集支撑。我见过不少团队上线CMDB的方式是拉一张大表把所有服务器、交换机、数据库一次性导进去然后宣布“CMDB建成了”。结果三个月后数据全面腐化新采购的机器没人录下线的机器没人删IP变更了没人改。原因不复杂他们把CMDB当成了一个静态台账而不是一个跟着IT环境持续呼吸的系统。维易CMDB在这件事上的定位比较清晰它把配置项CI拆成“类型 属性 关系”三部分类型可以按企业实际情况扩展属性支持必填校验和枚举约束关系支持可视化查看和API查询。这套模型本身不复杂难的是怎么用它把企业内部那套乱七八糟的命名习惯和职责边界统一起来。1.2 三种建设路径选错了后面全是返工企业级CMDB的落地路径大致有三种我做过对比也踩过其中的坑建设路径典型做法优点风险全量一次性建设花三个月梳理全部CI类型和关系一次性导入理论上最完整周期长业务方等不及模型容易过度设计场景驱动建设从监控告警、变更工单两个高频场景切入先建核心CI见效快数据有真实消费方需要控制范围避免场景蔓延最小可用建设只建服务器和网络设备两类CI先跑通采集上手最快后续扩展时容易推翻前期模型我们最终选的是场景驱动。理由很实在CMDB的数据如果没有消费方就一定会腐化。监控系统需要知道告警对应的CI责任人是谁变更工单需要知道这次变更影响哪些下游系统这两个场景对数据的准确性要求最高也最能倒逼各个团队把数据维护起来。维易CMDB的API和 webhook 能力刚好能撑住这种“边用边建”的节奏先把服务器、网络设备、应用系统三类CI建起来关系先做“部署于”和“依赖”两种跑两个月再扩。注意不要一上来就追求CI类型全覆盖。CI类型越多属性字段越多采集和校验的工作量呈指数上升。先把高频消费场景喂饱比画一张完美的大图更重要。1.3 快速构建的三个前提条件“快速”这个词在CMDB项目里是有前提的。我们复盘下来能在一个半月内把核心CI跑起来靠的是三件事提前到位第一是唯一标识源。每类CI必须有一个稳定的唯一键服务器用序列号网络设备用管理IP加设备型号应用系统用内部应用编码。这个键不能靠人工临时编必须来自采购系统、云平台或者设备本身。第二是责任人映射。每个CI必须绑定到具体的团队甚至具体的人维易CMDB里对应的是“归属团队”和“负责人”两个字段。没有责任人的CI数据错了没人认领巡检报告发出去也是石沉大海。第三是采集通道。至少有一条自动采集通道能覆盖60%以上的核心资产否则全靠手工录入项目上线即巅峰后面就是漫长的补录地狱。我们当时用SSH加SNMP覆盖了物理机和网络设备云上资源走云平台API同步剩下不到两成的手工补录。2. 数据模型设计CI分类、属性与关系的落地方法2.1 先定CI分类树再谈属性字段CI分类树是CMDB的骨架。我们按四层来切物理层、虚拟层、应用层、业务层。这个分层方式不是教科书规定而是根据我们自己的消费场景倒推出来的——监控告警需要定位到物理机和虚机变更工单需要定位到应用和业务模块中间必须有一层把两边串起来。层级典型CI类型说明物理层机房、机柜、服务器、交换机、路由器、防火墙、存储有明确物理位置和资产编号虚拟层集群、宿主机、虚拟机、容器节点、负载均衡实例依附于物理资源生命周期短应用层应用系统、服务、中间件、数据库实例、消息队列运维变更的主要对象业务层业务线、业务模块、对外服务面向业务方用于影响面分析这张表看起来简单实际设计时最容易吵架的是“应用系统”和“服务”的边界。我的建议是应用系统按业务归属划分一个应用系统可以包含多个服务服务按进程或部署单元划分和Kubernetes里的Deployment或者传统部署里的一个war包对应。边界定清楚以后后面做关系映射会顺很多。维易CMDB支持CI类型自定义创建类型时可以指定父类型天然形成树形结构。我们建的时候把“服务器”挂在“物理层”下把“虚拟机”挂在“虚拟层”下查询时按层级过滤非常方便。2.2 属性字段设计够用、可校验、别贪多属性字段设计有个很现实的取舍字段太少消费方拿不到需要的信息字段太多采集和录入成本压不住。我们给每类CI定了一套“必填 选填 系统自动生成”的三段式字段策略。以服务器为例字段名类型是否必填来源说明hostname字符串是采集主机名全局唯一serial_number字符串是采集序列号作为主匹配键ip_addressIP是采集管理IP多网卡时取管理网段os_version字符串是采集操作系统版本cpu_cores整数是采集逻辑核数memory_gb整数是采集内存容量env枚举是导入/补录生产、预发、测试、开发owner_team字符串是导入/补录归属团队owner字符串是导入/补录具体负责人idc字符串是导入/补录机房编码status枚举是系统在线、离线、维修、待回收created_at时间是系统创建时间有几个细节值得展开说。env字段一定要用枚举而不是自由文本否则你会看到“生产”“prod”“PROD”“正式”四种写法混在一起后面做影响面分析时筛选条件都写不对。owner字段不要填部门名要填具体的人维易CMDB里可以关联用户账号这样告警通知和巡检任务才能直接派到人。字段命名我们统一用下划线小写风格和API返回保持一致避免前端展示一套、接口返回一套、导出Excel又一套。这个规范最好在建模阶段就写进文档后面新加字段照着来。2.3 关系模型CMDB的价值一半在关系上只存CI不存关系CMDB就是一个带校验的资产表。关系模型才是它区别于普通台账的地方。我们第一版只定义了四种关系部署于虚拟机部署在宿主机上应用部署在服务器或容器上依赖于应用依赖数据库、缓存、消息队列连接于网络设备之间的物理或逻辑连接属于CI归属于某个业务系统或业务线这四种关系覆盖了我们80%的查询需求。比如线上告警进来先通过“部署于”找到宿主机和机柜位置再通过“依赖于”找到同机房的其他关联组件最后通过“属于”找到业务负责人整条链路在维易CMDB的关系视图里能直接点开看。关系设计有两个坑要提前避开。第一个是环形依赖A依赖B、B依赖C、C又依赖A做影响面分析时会陷入死循环。我们的做法是在关系创建时做一次简单校验检测是否形成环形成环的关系需要人工确认后才能保存。第二个是关系冗余同一对CI之间不要同时存在“依赖于”和“连接于”两条语义重叠的关系否则查询结果会重复统计口径也会乱。2.4 模型评审与冻结别让模型天天改数据模型最怕边建边改。我们的做法是建模阶段拉上运维、开发、网络、安全四个团队做一次评审评审通过后冻结两周。冻结期内只允许加选填字段不允许改类型、改关系定义、删字段。两周后根据实际采集结果再做一次小调整之后进入月度评审节奏。这个流程听起来官僚实际救了很多时间。之前有个项目没有冻结机制模型一天改三版采集脚本跟着改导入模板跟着改最后谁也不知道哪个字段是准的。维易CMDB的模型变更会记录操作日志我们就把这个日志当成评审依据每次变更前先看最近改了什么、影响了哪些CI。3. 采集与录入自动发现、批量导入、手工补录的组合拳3.1 自动采集通道怎么配才稳自动采集是CMDB数据新鲜度的生命线。我们按资产类型配了三条通道物理服务器走SSH网络设备走SNMP云上资源走云平台API同步。维易CMDB内置了发现任务配置也可以用它的开放接口自己写采集器我们选择的是平台内置任务加自定义脚本补充的方式。一个典型的SSH发现任务配置大概长这样discovery_task: name: prod-linux-scan protocol: ssh targets: - 10.20.0.0/24 - 10.20.1.0/24 credential_ref: cred-linux-prod interval: 24h timeout_seconds: 15 collect_fields: - hostname - serial_number - os_version - cpu_cores - memory_gb - disk_total_gb match_key: serial_number on_conflict: update exclude_patterns: - *-test-* - *-temp-*几个参数值得说明。match_key用序列号而不是IP是因为IP会变、序列号不会变用序列号做匹配能避免同一台机器换IP后被识别成新CI。on_conflict设为update表示匹配到已有CI时更新属性而不是新建这是增量采集的关键。exclude_patterns用来排除测试机和临时机否则扫描一遍网段会灌进来一堆不需要纳管的设备。采集频率我们按资产重要程度分了三档核心生产服务器每天一次普通服务器每周两次网络设备每小时一次。云资源因为弹性伸缩频繁走API每15分钟同步一次。频率不是越高越好扫描任务本身会占用网络和主机资源太频繁还会触发安全告警。提示采集账号权限要给最小集。SSH采集只需要读取主机名、序列号、系统信息的权限不要用root账号跑采集任务。SNMP用只读团体字不要用读写团体字。3.2 批量导入模板设计和数据清洗是关键自动采集覆盖不到的CI比如应用系统、业务模块、部分第三方托管设备需要走批量导入。维易CMDB提供了Excel导入模板但直接用平台模板往往不够我们会在导入前加一道清洗。清洗脚本用Python写核心做四件事字段标准化、去重、必填校验、格式转换。import pandas as pd import re df pd.read_excel(cmdb_import_raw.xlsx, sheet_nameserver) def normalize_ip(value): if pd.isna(value): return None value str(value).strip() match re.match(r^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}), value) return match.group(1) if match else None def normalize_env(value): mapping { 生产: prod, prod: prod, PROD: prod, 正式: prod, 预发: staging, staging: staging, 测试: test, test: test, 开发: dev, dev: dev } return mapping.get(str(value).strip(), None) df[ip_address] df[ip_address].apply(normalize_ip) df[env] df[env].apply(normalize_env) required_cols [hostname, serial_number, ip_address, env, owner_team] missing df[df[required_cols].isna().any(axis1)] if not missing.empty: missing.to_excel(cmdb_import_rejected.xlsx, indexFalse) df df.drop(missing.index) df df.drop_duplicates(subset[serial_number], keeplast) df.to_excel(cmdb_import_clean.xlsx, indexFalse)这个脚本看起来简单但实际救过我们好几次。有一次业务方发来的表里env列混了七种写法直接导入会生成七个环境分类报表全乱。还有一次ip_address列里带了端口号和备注导入后IP字段校验全部失败。清洗脚本跑一遍问题数据单独落一个文件退回给业务方导入成功率从六成提到九成以上。导入模板我们做了两版一版给业务方填字段少、带下拉选项、带填写说明一版给运维内部用字段全、允许留空、导入后走补录流程。两版模板分开维护避免业务方看到一堆看不懂的字段直接放弃填写。3.3 手工补录的边界要卡死手工补录是CMDB数据质量的最后一道口子也是最容易失控的地方。我们的原则是能自动采集的字段一律不开放手工编辑手工只能补录采集不到的管理属性比如负责人、归属团队、业务系统编码、机房位置。维易CMDB支持字段级权限控制我们把采集字段设为只读管理字段设为可编辑但需要审批。补录提交后进入待审核队列由CMDB管理员确认后生效。这个审批流程一开始被吐槽麻烦但跑了一个月以后重复CI和错误归属明显减少。补录还有一条规矩不允许新建CI类型之外的临时字段。有些团队图省事在备注字段里塞“这台机器是给某某项目用的”后面想按项目筛选根本筛不出来。需要按项目维度管理就正经加一个“所属项目”字段走模型变更流程。3.4 增量策略与冲突处理采集和导入都会遇到同一个问题同一条CI被多个来源更新以谁为准我们的策略是按字段设优先级字段优先级来源冲突处理serial_number采集采集值覆盖手工值ip_address采集采集值覆盖但变化时触发告警os_version采集采集值覆盖owner_team手工手工值优先采集不改env手工手工值优先status系统 手工下线操作以手工为准这个优先级表要写成文档发给所有数据消费方否则监控团队按采集值做告警路由业务团队按手工值做成本分摊两边对不上又要扯皮。4. 数据治理让CMDB的数据敢被消费4.1 唯一性校验与重复CI合并CMDB跑起来三个月后最常见的数据问题不是字段缺失而是重复CI。同一台机器因为重装系统换了序列号、因为多网卡被采集了两次、因为导入模板里多了一行最后在库里变成两三条记录。我们的做法是每周跑一次重复检测检测逻辑按CI类型区分SELECT ci_type, match_value, COUNT(*) AS cnt FROM ( SELECT server AS ci_type, serial_number AS match_value FROM ci_instance WHERE ci_type server UNION ALL SELECT server_ip, ip_address FROM ci_instance WHERE ci_type server ) t GROUP BY ci_type, match_value HAVING COUNT(*) 1;检测出重复后不能直接删要先做合并。合并规则是保留最早创建的那条作为主记录把其他记录的属性和关系迁移过来然后标记为已合并而不是物理删除。维易CMDB的关系表支持批量迁移我们写了一个小脚本调用它的API完成这件事迁移完在备注里记录合并来源方便后续追溯。注意物理删除CI之前一定要检查关系表。直接删CI会留下悬空关系查询时报错或者返回脏数据。正确的顺序是先删关系、再删CI或者用平台提供的级联删除功能。4.2 完整性、准确性、及时性三个指标怎么算数据治理不能靠感觉要有指标。我们盯三个数完整率按必填字段计算公式是非空必填字段数 / 总必填字段数按CI类型分别统计。低于95%的类型进入整改名单。准确率靠抽样核对每月随机抽50条CI和实际环境比对字段一致才算准确。准确率低于90%说明采集或导入环节有问题。及时率看变更后数据更新延迟比如服务器下线后多久状态变成“离线”新机器上线后多久进入CMDB。我们的目标是核心资产24小时内更新实际跑下来平均在6小时左右。这三个指标每周出一张报表按团队维度拆开发到各团队负责人。报表不点名批评只列数据和趋势连续两周不达标的团队由CMDB管理员单独沟通。这套机制比发红头文件管用。4.3 变更联动让CMDB跟着流程自动走CMDB数据腐化的根源是“变更发生了CMDB不知道”。解决这个问题只能靠流程联动。我们把维易CMDB和变更工单系统做了对接工单里选择变更CI工单关闭时自动回写CI状态和变更时间新建CI的工单审批通过后自动在CMDB创建记录下线工单通过后自动把CI状态置为“待回收”。对接方式用的是webhook加API回调。工单系统在状态变更时推一条消息到维易CMDB的接收端点CMDB根据消息里的CI标识和操作类型执行对应动作。消息格式大概是这样{ event: change_closed, ci_type: server, ci_key: SN-8F3A21, action: update_status, payload: { status: online, last_change_at: 2025-01-12T10:30:0008:00, change_ticket: CHG-20250112-0031 } }这条链路打通以后变更导致的CMDB滞后问题减少了七成以上。剩下三成主要是工单里没选CI或者选了错的CI这类问题靠工单提交时的必填校验和CI搜索优化来解决。4.4 定期巡检与责任到人再好的自动化也替代不了定期巡检。我们设了三层巡检每日自动巡检跑脚本检查新增CI的必填字段、关系完整性、重复记录结果发到运维群每周人工抽检每个团队抽5条CI核对现场重点看机房位置和负责人每月全量报表按CI类型出完整率、准确率、及时率抄送各团队负责人巡检发现的问题要落到具体的人不能只发群消息。维易CMDB里每条CI都有负责人字段巡检脚本直接把问题清单按负责人分组生成待办任务推给对应的人。这个动作看起来小但它是数据质量能维持住的关键——大家知道数据错了会找到自己头上录入时就会认真一点。5. 与周边系统集成从资产台账变成运维中枢5.1 监控系统对接告警能落到CI上监控系统和CMDB对接的价值在于告警关联。监控告警里通常只有IP或者主机名运维人员收到告警后还要去查这是哪台机器、归谁管、影响了哪个业务。CMDB如果能提供这层映射告警处理效率会明显提升。我们的做法是在监控系统里维护一份动态标签标签数据从维易CMDB的API定时拉取。拉取内容包括 hostname、owner_team、owner、env、business_system。告警触发时按 hostname 匹配标签告警消息里直接带上负责人和业务系统信息。curl -s https://cmdb.internal/api/v1/ci/search?ci_typeserverenvprodpage_size500 \ -H Authorization: Bearer ${CMDB_TOKEN} \ -o /opt/monitor/cmdb_labels.json这个接口我们每30分钟调一次拉全量生产服务器。数据量大的时候用分页按page参数翻页避免单次请求超时。拉下来的JSON经过一个转换脚本变成监控系统认识的标签格式推送到标签管理接口。5.2 工单与变更流程对接前面提到变更工单回写CMDB这里补充反向的联动工单创建时从CMDB拉取CI信息自动填充影响范围。比如提交一个服务器重启工单选择CI后系统自动带出这台服务器上部署的应用、这些应用依赖的数据库、以及对应的业务负责人审批人一看就知道影响面有多大。这个功能依赖CMDB的关系查询能力。维易CMDB提供了关系遍历接口给定一个CI ID可以按关系类型和层级深度查询关联CI。我们默认查两层第一层是直接依赖第二层是依赖的依赖。再深就容易查出无关组件影响工单可读性。5.3 自动化平台对接动态inventory自动化平台需要知道“现在有哪些机器、按什么分组”。传统做法是维护一份静态主机清单机器一多就维护不动。我们把维易CMDB做成了自动化平台的动态inventory源。以Ansible为例写一个动态inventory脚本从CMDB拉取服务器列表并按owner_team和env分组#!/usr/bin/env python3 import json import requests CMDB_API https://cmdb.internal/api/v1/ci/search TOKEN your-token-here resp requests.get( CMDB_API, params{ci_type: server, status: online, page_size: 1000}, headers{Authorization: fBearer {TOKEN}}, timeout10, ) resp.raise_for_status() inventory {_meta: {hostvars: {}}, all: {hosts: []}} for item in resp.json().get(data, []): host item[attributes][hostname] inventory[all][hosts].append(host) inventory[_meta][hostvars][host] { ansible_host: item[attributes][ip_address], owner_team: item[attributes][owner_team], env: item[attributes][env], } team item[attributes][owner_team] inventory.setdefault(team, {hosts: []})[hosts].append(host) print(json.dumps(inventory, ensure_asciiFalse))这个脚本挂到Ansible的inventory目录下加执行权限就能直接用。好处是机器上下线只需要改CMDB自动化平台自动跟着变不用两边维护。5.4 权限与审计谁能看、谁能改要有数CMDB里存的是企业IT环境的全貌权限控制不能马虎。我们按角色分了三层权限只读角色可以查询CI和关系不能看到敏感字段如管理IP、账号信息编辑角色可以修改自己团队的CI修改记录进审计日志管理员角色可以修改模型、合并CI、删除记录操作全部留痕维易CMDB支持字段级权限和CI级权限组合我们按“团队 CI类型”做授权比如网络团队只能编辑网络设备类CI应用团队只能编辑自己名下的应用系统。审计日志保留180天每月抽查一次高危操作重点看批量删除和模型变更。6. 常见问题排查实录与避坑清单6.1 采集类问题速查采集是问题最集中的环节我把我们遇到过的情况整理成一张表现象可能原因排查动作处理方式扫描任务显示成功但无数据目标网段不可达或防火墙拦截从采集节点telnet目标22端口开通采集节点到目标网段的访问策略部分机器采集失败SSH凭据错误或权限不足手动SSH登录验证更换凭据确认采集账号有读取权限网络设备采集不到SNMP团体字错误或版本不匹配用snmpwalk命令测试核对团体字和SNMP版本云资源同步缺失API密钥权限不足或地域未配置查看同步日志中的错误码补充只读权限确认地域列表采集到重复CI匹配键选择不当检查match_key配置改用序列号或云资源ID作为匹配键采集频率过高触发告警扫描间隔太短查看安全设备日志调整采集频率错峰执行这张表我们贴在运维值班文档里新人遇到采集问题先查表八成能自己解决。6.2 数据类问题与处理思路数据类问题比采集问题更隐蔽往往是用的时候才发现。典型的有这么几种关系断链。CI被删除或合并后关系表里还留着指向它的记录查询时报“关联CI不存在”。处理方式是定期跑关系完整性检查把悬空关系清理掉。维易CMDB的关系查询接口对不存在的CI会返回空不会直接报错但报表统计会少算所以还是要主动清理。属性值漂移。同一类CI的同一个字段出现多种格式比如内存有的写64有的写64GB有的写65536。这类问题靠导入前清洗和字段类型约束解决数值型字段就不要允许带单位。状态不同步。机器已经下线了CMDB里还是“在线”。这类问题只能靠变更流程联动和定期对账解决。我们每月做一次CMDB和监控系统的在线状态对账差异超过5%就启动专项排查。负责人离职未更新。这个听起来是小事但告警派不出去的时候就是大事。我们的做法是把负责人字段和内部账号系统关联账号停用后自动触发CMDB负责人变更提醒。6.3 上线初期最容易踩的五个坑第一个坑是模型过度设计。一开始就想把所有CI类型、所有关系、所有属性都定义清楚结果模型评审开了两个月一行数据没进库。正确做法是先建最小模型跑起来再迭代。第二个坑是把CMDB当成一个部门的事。CMDB的数据来源跨多个团队只靠运维一个团队推数据永远不全。上线前要把各团队的数据责任人定下来写进项目章程。第三个坑是没有消费方就上线。数据没人用就没人维护。上线前至少打通一个消费场景监控或者工单都行让数据转起来。第四个坑是忽视历史数据清洗。老台账里的数据质量往往很差直接导入等于把垃圾搬进新库。导入前必须做清洗和去重宁可少导入一些也不要导入脏数据。第五个坑是权限放得太开。所有人都能改最后谁改的都不知道。上线第一天就要把角色和权限分好审计日志开起来。6.4 我个人在实际操作中的几点体会CMDB这个项目技术难度其实不高难的是组织和流程。维易CMDB这套平台提供的模型、采集、关系、API能力已经够用了真正决定成败的是有没有人对数据负责、有没有场景在消费数据、有没有机制让数据持续更新。我在实际推进中感受最深的一点是先让数据有用再让数据变全。很多团队反过来做先追求全量覆盖结果数据躺在库里没人看三个月后全部过期。我们是从监控告警关联这个点切进去的只覆盖了生产环境的服务器和网络设备但这两类数据每天被告警系统调用几百次错了马上有人反馈数据质量反而维持得很好。另一个体会是采集能解决的不要靠人。手工录入的字段越多数据腐化越快。我们在模型设计阶段就明确了一条线能被自动采集的字段一律不开放手工编辑手工只负责管理属性。这条线执行得越坚决后面的治理成本越低。最后分享一个小技巧CMDB的巡检报告不要只发给负责人抄送一份给各团队的主管。数据质量这件事有上级关注和没有上级关注推进速度完全不一样。当然前提是报告本身要客观只列数据和趋势不做主观评价否则容易变成互相甩锅的工具。