)
独家实操腾讯云助手实现测试资源生命周期治理三生产白名单与误删防护实战——修复 AI 脚本误匹配生产资源缺陷系列导航第一篇被遗忘的测试资源、资源登记与到期标记体系、自动回收脚本实现第二篇延期申请与审批流程——让人有反悔机会的回收机制第三篇本篇生产白名单与误删防护实战——修复 AI 脚本误匹配生产资源的缺陷一、差点删掉生产库的那次演练回收脚本上线前的第一次演练我们准备了一个影子环境5 台测试 CVM 1 台伪装成测试机的生产配置镜像名称故意不规范模拟真实世界的脏数据。让腾讯云助手生成的回收脚本跑 dry-run输出计划如下[dry-run] 拟回收 6 台 1. cvm-test-teamA-01 到期 3 天前 envtest ✓ 2. cvm-test-teamB-04 到期 5 天前 envtest ✓ 3. ... 6. prod-db-proxy-bak 「到期 1 天前」env缺失第 6 台。一台生产环境的数据库代理备份机。事后排查它踩中的是一连串合理的逻辑缺陷这台机器env标签缺失历史遗留谁都没发现脚本的到期判断逻辑是expire-at now而这台机器根本没有biz:expire-at标签——AI 生成的代码里tags.get(biz:expire-at, 0)的默认值是字符串 “0”字符串0与当前时间比较Python 里int(0) now恒成立 →“缺标签被解读为1970 年到期”再叠加它名称里有个bakAI 的资源描述里写它是备份类资源长期无活跃进入了回收候选。一个默认值 一个脏标签差点合谋删掉生产机器。这个案例完美诠释了本系列反复出现的主题自动化回收的最大风险不是脚本删错选中的资源而是把不该选的资源选了进来。本篇讲三层白名单 缺陷修复确保选错人这件事在结构上不可能发生。二、修复一标签缺失 fail-fast禁止任何默认值第一处修复是哲学层面的和前面多租户系列的原则完全一致隔离/安全关键信息缺失时必须快速失败禁止回落默认值。# 修复前AI 初版——缺标签被静默解释为1970 年到期expireint(tags.get(biz:expire-at,0))# 修复后 —— 缺关键标签直接跳过回收 高优告警绝不猜defget_expiry(tags:dict):rawtags.get(biz:expire-at)ifrawisNone:raiseTagMissingError(biz:expire-at)try:expireint(raw)except(TypeError,ValueError):raiseTagInvalidError(fbiz:expire-at{raw!r})returnexpiredefrecycle_candidate(ins):try:returnget_expiry(ins.tags)now()exceptTagErrorase:alert(f[SKIP]{ins.id}标签异常({e})已跳过回收请人工处理,priorityhigh)returnFalse原则归纳信息不足和明确到期是两种完全不同的状态前者跳过告警后者才进回收流程。宁可漏回收浪费点钱不可错回收删掉生产。这就是回收场景的 default-deny。三、修复二三层白名单正反都要堵只有跳过异常还不够——那台代理机的标签齐全的话照样可能混进候选。所以回收执行前必须过三层白名单任何一层命中即拦截PROD_WHITELIST{# 第 1 层环境层 —— 只有显式 envtest 才可回收白名单语义防默认是测试env:{test,dev},# 第 2 层身份层 —— 生产资源 ID / 名称 / IP 硬清单黑名单语义最后防线ids:{ins-proddb-01,ins-proddb-02,ins-prod-db-proxy-bak},names:[prod-*,*-prod-*,prod_*],ips:[10.1.0.0/16],# 第 3 层属性层 —— 生产特征字段数据库、带宽包、备案域名绑定等attrs:{is_prod_domain_bound:True,bandwidth_package:True},}defpass_whitelist(ins)-tuple[bool,str]:# 层 1env 必须显式为 test/dev缺失/其他值一律拒绝ifins.tags.get(env)notinPROD_WHITELIST[env]:returnFalse,fenv{ins.tags.get(env)!r}not in test/dev# 层 2身份硬清单ifins.idinPROD_WHITELIST[ids]:returnFalse,fhit whitelist id:{ins.id}ifany(fnmatch.fnmatch(ins.name,p)forpinPROD_WHITELIST[names]):returnFalse,fhit whitelist name pattern:{ins.name}ifip_in_cidrs(ins.ip,PROD_WHITELIST[ips]):returnFalse,fhit whitelist ip:{ins.ip}# 层 3生产属性特征forattr,expectedinPROD_WHITELIST[attrs].items():ifgetattr(ins,attr,None)expected:returnFalse,fhit prod attribute:{attr}returnTrue,ok三层的设计逻辑值得展开层 1 是白名单语义可回收的环境要显式声明test/devenv 缺失 不可回收。如果反过来写黑名单“env ! prod 就回收”任何标签 typopord、PROD都会直接命中回收——那台代理机就是因为这个逻辑差点阵亡层 2 是显式硬清单关键生产资源逐台登记模式匹配兜住命名规律的prod-*。注意它不是第一道防线而是最后一道——万一标签全错名称和 IP 还能救命层 3 是语义特征有些生产资源名字干净、标签也对被误打的 envtest但属性露馅——绑了生产域名、挂了带宽包。属性层是 AI 建议补的我们让它扮演攻击者给一台生产资源伪装成测试资源混进回收清单它给出的伪装方案改标签、改名字都被前两层挡住后提出了绑定生产域名这条它自己也绕不开的特征。四、修复三执行前的双重人审 双因子确认白名单之外回收的执行动作本身还有两道流程闸门批量上限单次回收执行超过 20 台必须拆批——大量回收意味着要么是大清理该有人盯着要么是逻辑出错了双因子确认terminate/release_attachments级别动作执行前需要平台值班人 资源所属团队 TL 双方在审批卡片上确认。注意这里审批的是执行清单本身含全部资源明细不是抽象的批准回收——人必须看到具体删什么。配合第一篇的三重闸门环境/白名单/保护期完整防线变成候选生成标签校验缺失 fail-fast禁止默认值 ↓ 三层白名单env 显式声明 → 身份硬清单 → 生产属性特征 ↓ 保护期校验停机缓冲期内禁止 terminate ↓ 执行闸门批量上限 双因子确认人看明细清单 ↓ 执行后回收结果回报 全量审计日志五、演练体系白名单不是配完就完事我们把这整套防线做成了每周自动演练在影子环境里随机混入伪装生产资源改标签、改名字、绑生产属性三种伪装各一批跑完整回收流水线断言全部伪装资源被拦截defweekly_drill():shadowbuild_shadow_env(decoys[fake_prod(drop_env_tagTrue),# 去 env 标签fake_prod(fake_envtest),# 伪装 envfake_prod(fake_envtest,clean_nameTrue),# 标签名双伪装fake_prod(fake_envtest,prod_domainTrue),# 三重伪装靠属性层拦截])planrecycle_pipeline(shadow,dry_runFalse)assertall(d.idinplan.blockedfordinshadow.decoys),生产伪装资源未被全部拦截!assertlen(plan.recycled)len(shadow.expired_test),正常回收不应误伤四次演练抓过两个回归 bug一次是白名单改版后names模式匹配的大小写问题PROD-*没被prod-*匹配挡住fnmatch 需要显式 casefold一次是新同学加快速回收接口时绕过了层 3 校验。防线会被日常迭代悄悄打穿演练是唯一能持续验证它还活着的方式。六、系列总结三篇合起来测试资源生命周期治理的完整闭环登记创建即打 TTL 标签无标签不创建存量走待认领第一篇回收三级递进通知→停机→释放停机缓冲拦截 43% 误回收第一篇延期自动核验 递减配额 审批分层还在用必须过数据这一关第二篇防误删标签缺失 fail-fast、三层白名单env 白名单语义 身份硬清单 生产属性、批量上限、双因子确认、每周伪装演练本篇。其中最想传递的一条经验自动化回收系统的安全设计重心不在怎么删得准而在怎么保证删不到不该删的——前者是效率问题后者是敢不敢开自动化的前提。AI 生成的脚本在效率维度表现优秀但缺标签默认 1970 年到期这类默认值缺陷恰恰是它最稳定复现的盲区每一次安全关键路径都必须人工审到默认值这一层。系列完结。测试资源治理季度收益资源池缩 41%、月省约 4.2 万、零误删。做 FinOps 和资源治理的同学评论区聊聊你们敢不敢在生产开自动回收。