镜像不干净,容器跑得再稳也白搭:我在生产环境踩过的镜像安全那些坑
大家好,我是 Echo_Wish。
这些年在运维和云原生一线混,容器、K8s、CI/CD 基本是天天见。说句掏心窝子的:
现在很多“安全事故”,不是被黑客多牛逼,而是我们自己把后门打包进了镜像。
今天就聊一个特别容易被忽视、但又特别致命的话题:
容器镜像安全:构建时静态分析 + 运行时防护(cosign + runtime)
不讲安全术语轰炸,也不搞 PPT 风格,就按“咱平时干活”的视角,把这套东西讲明白。
一、先泼盆冷水:镜像一旦进仓库,基本就是“带毒传播”
很多团队的镜像流程是这样的:
写 Dockerfile → build → push → deploy
看着很丝滑,但我问你几个问题:
- 这个镜像里有没有高危漏洞?
- 这个镜像是不是被人偷偷替换过?
- 这个容器运行后干了什么,你知道吗?
如果你的答案是:
“呃……没出过事,应该没问题吧?”
那我只能说一句老运维名言:
没出事 ≠ 没问题,只是还没轮到你。
二、镜像安全不是一个点,而是一条链
我个人把容器镜像安全拆成两句话:
构建时,别把脏东西打进去
运行时,别让它乱来
今天重点就放在这两个阶段:
1️⃣ 构建时:静态分析 + 镜像签名(cosign)
2️⃣ 运行时:容器行为防护(runtime)
三、构建时静态分析:别等上线了才查漏洞
1️⃣ 静态分析到底在查什么?
说白了就是三件事:
- 基础镜像漏洞(glibc、openssl 那些老熟人)
- Dockerfile 不规范(root 运行、ADD 滥用)
- 应用依赖漏洞(Log4j 这种)
示例:在 CI 里加一道“安检”
trivy image myapp:1.0.0
输出如果是这样:
CRITICAL: glibc CVE-2023-XXXX
HIGH: openssl CVE-2024-YYYY
我的建议很简单:
CI 直接 fail,别心软。
你现在不拦,后面出事就是运维背锅。
2️⃣ 我的真实感受
很多人嫌静态扫描“慢”“烦”“经常误报”。
但你换个角度想:
你愿不愿意为了省 2 分钟构建时间,去换一次凌晨三点的电话?
我反正不愿意。
四、cosign:给镜像上个“身份证”
这是我近两年最推荐的一个工具。
1️⃣ 镜像最大的问题是什么?
不是漏洞,而是:
你根本不知道现在跑的,是不是你当初 build 的那个镜像。
2️⃣ cosign 是干嘛的?
一句话解释:
给镜像做签名,部署时只认“亲笔签名”的镜像。
示例:给镜像签名
cosign sign myrepo/myapp:1.0.0
验证签名
cosign verify myrepo/myapp:1.0.0
只要镜像被篡改过,校验直接失败。
3️⃣ 配合 K8s 使用(非常关键)
apiVersion: policy.sigstore.dev/v1beta1
kind: ClusterImagePolicy
spec:
images:
- glob: "myrepo/*"
authorities:
- key:
secretRef:
name: cosign-public-key
这意味着一句话:
没签名的镜像,连 Pod 都起不来。
五、运行时防护:镜像再干净,也怕“变坏”
这是很多团队最容易忽略的一环。
现实是:
镜像上线后,才是真正危险的开始。
1️⃣ 运行时主要防什么?
- 容器里突然执行
bash - 访问不该访问的文件
- 连不该连的 IP
- 提权、挖矿、反弹 shell
2️⃣ 一个典型的“事故现场”
我见过真实案例:
- 镜像本身没问题
- 但应用被打了 RCE
- 攻击者在容器里直接
curl | sh
如果你没有 runtime 防护——
你连发生过什么都不知道。
六、Runtime 防护怎么做才不“折磨人”?
我个人不太喜欢“规则写到手抽筋”的方案。
推荐思路:行为基线
容器平时只干这几件事,其他一律算异常。
示例:限制容器执行 shell
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
再配合 runtime 工具(Falco / Tetragon 等):
- rule: Unexpected Shell
condition: proc.name in (bash, sh)
output: "Shell spawned in container"
效果就一句话:
不该发生的行为,一发生就报警。
七、把三件事串起来,才叫“闭环”
我自己在项目里的推荐组合是:
CI:
Dockerfile 检查
↓
镜像漏洞扫描
↓
cosign 签名
CD:
K8s 校验签名
↓
Runtime 行为防护
不是为了“安全评级”,
而是为了一个目标:
让问题尽量死在上线之前。
八、我自己的几点真实感悟
说点不太好听的:
- 安全不是工具问题,是态度问题
- 镜像安全不是“安全团队的事”,而是运维底线
很多事故复盘到最后,结论都很像:
“如果当初多加一步,其实是能拦住的。”
那一步,往往就是:
- 一个扫描
- 一个签名
- 一个 runtime 规则
九、写在最后
如果你现在只能做一件事,我的建议是:
先上 cosign。
它是投入产出比最高的一步。
如果你能再往前走一步:
构建时静态分析 + 运行时防护,一起上。