这条讲怎么用本地命令行工具扫 Google Cloud 项目里的僵尸资源——没挂的磁盘、没人用的静态 IP、停着还在计费的实例。工具叫 zombiescan,出处是 dev.to 的 Google Developer Experts 账号,原作者 xbill,9 月 22 日发的,源码 MIT,在 xbill9/zombiescan-gcp。
我压到今天才写,因为中间去干了一件事:把源码拉下来,看“只读”这俩字它到底靠什么撑住。
教程里打动我的是一句:所有扫描调用仅为 list 或 get,代码路径不会删除、修改或释放任何资源。很多人写工具 README 开头就是“安全只读”,读完正文你找不到任何能核对的地方。这篇不一样,它把只读保证拆成几处痕迹,你可以去查。
我先跑测试。装的命令:
uv venv
uv pip install -e .
pytest
测试离线跑,用的是录好的 API 响应。324 通过、4 个被取消选择,0.37 秒。这个细节我信,因为它把“测试时不碰真实项目”当底线来写。
324 passed, 4 deselected in 0.37s
跑完我顺带查了清理脚本。原作者写的是:「clean 命令默认只做预览,不修改任何资源;只有加上 --apply 才会把计划中的变更发送到 Google Cloud。」
这不是一句笼统的“不会删东西”。它把写操作挪到了单独的 apply 动作后面,和扫描是两个行为。我 grep 过源码里的 delete / remove 调用,扫资源那半边一个没有,写路径全在 cleanup 那个包里。
grep -rn "delete\|remove" zombiescan/core zombiescan/gke | head -20
我跑了测试、看了代码,愿意推这条的原因就一个:只读不是嘴上说说,读和写拆得够开。
但最让我在意的一条在文章末尾,很容易被划过去。作者说:仓库里经过审查的两个包有只读保证;从 PyPI 安装的第三方包会使用相同凭据,但不附带同等保证。
读到这句我手指停住了。同一个名字,pip install 来的和源码装的,保证等级不一样。我自己就是图省事 pip install 派,这会儿得逼着自己回头去装源码。一个工具标榜只读,结果只读是跟着安装渠道走的——这事本身够写出来提醒人。
这个提醒比工具本身的检查逻辑更值得点。
顺带说它扫的东西。75 个项目、20 项检查,全量扫完 79 秒,713 条发现,月浪费 $387.74。其中空 VPC 网络、没生命周期规则的版本化存储桶、没匹配流量的防火墙规则、没人用的子网这些零成本垃圾就占了 527 条。剩下真正烧钱的是未挂载磁盘 $153.53/月、闲置静态 IP $89.06/月、没用的自定义镜像 $75.25/月。成本从高到低排,每触发的检查至少占一行。
没节点的 GKE 集群一个月收 $73 管理费,这个数我读的时候看了两遍,有点反直觉。作者顺手列了几处 Google Cloud 和 AWS 习惯不一样的收费逻辑:闲置 Cloud NAT 网关按持有的地址收,每个地址一小时 $0.005;未绑定的预留静态 IP 比绑到运行中实例的更贵。这些属于扫之前不会去想的坑。
有个地方我一直没想清楚。作者说它跳过了一些会重复计数的东西:已停止实例上的磁盘会归到 stopped-instance 那一类,不会重复算到别处;源磁盘还存在的快照不报;免费的 Google 托管 KMS 密钥也不报。这些抑制误报的规则我第一眼觉得保守,再读又觉得确实该这样——一个清理脚本比扫描结果更容易搞出事故。有些项目里的僵尸资源不是你扫出来就该删,人工看完再动更稳妥。
它甚至有一条:没有清理器但有原因说明的检查,会以 unsupported 形式报告,测试也会拒绝那些既没清理器又没原因的检查。这种把克制写进代码的做法,我在很多号称一键清理的工具里没见过。
最后说回 75 项目扫描——我一个人没那份权限原样重跑。测试和 grep 源码算我这次的顺手验证,跑通了;扫描的 79 秒是把已有只读凭据喂进去之后的事,不是开箱即跑。它能分清 API 从未启用的项目和启用过又关掉的吗?评论区有人问,作者回得老实:工具目标是快速抓演示后遗留的资源,不是完整平台。
这篇值得点。不点链接也能带走的一句:判断一个声称只读的工具,别只看 README 上“只读”两个字,去看它把写操作拆在哪儿、默认干跑还是真干,还有,装之前确认一下你装的是哪个渠道的包——同一个名字,渠道不同,保证可能完全不同。