Kubernetes 镜像构建与安全:从 BuildKit 到供应链信任

系统讲解 Kubernetes 镜像工程化:Docker/BuildKit 高效构建、多阶段构建与镜像瘦身、镜像层与缓存、漏洞扫描(Trivy/Grype)、SBOM 生成、镜像签名(cosign/SLSA)、私有仓库与拉取策略、镜像生命周期,以及软件供应链安全(SLSA/供应链信任)的完整落地。

镜像既是应用的分发载体,也是攻击面与信任边界。镜像小了、安全了、可验证了,部署才谈得上可靠;镜像里藏着漏洞、悬空的基础镜像、无签名来源,等于把后门和风险一起交付。本指南从构建到扫描再到签名与供应链信任,建立一条「构建得快、镜像得小、来源可验、内容可信」的镜像产线。


目录


1. 高效构建:BuildKit 与缓存的艺术

1.1 为什么默认启用 BuildKit

传统 docker build 用的是旧引擎,难以并行、缓存脆弱。BuildKit 提供并发执行、挂载缓存、远程缓存等能力:

DOCKER_BUILDKIT=1 docker build -t app:latest .
# 或 Docker 23+ 默认启用
docker buildx build --platform linux/amd64,linux/arm64 -t app:latest .

1.2 缓存关键:让"稀疏变化的层"放前面

缓存命中靠不变量。把很少变化的依赖层放前面、频繁变化的源代码层放后面:

# 差:整层拷贝源码,任何改动都炸缓存
COPY . /src
RUN npm install        # 源码一变,依赖全部重装

# 好:依赖层独立,只有 package.json 变化才重装
COPY package.json package-lock.json /app/
RUN npm ci
COPY . /app

1.3 BuildKit 缓存挂载(经典鸡生蛋)

npm ci 本身要网络,用 RUN --mount=type=cache 缓存下载:

RUN --mount=type=cache,target=/root/.npm \
    npm ci --ignore-scripts

一句话:构建 = 用最小不变量分组 + Cache mount + 多架构并发——缓存命中是最便宜的优化。


2. 多阶段构建与镜像瘦身

2.1 多阶段:构建工具不进运行镜像

编译后的应用只需要运行产物,不需要依赖和编译器。多阶段把"构建环境"与"运行镜像"分离:

# ---------- 阶段 1:构建 ----------
FROM golang:1.22 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /app/server .

# ---------- 阶段 2:运行(极简) ----------
FROM gcr.io/distroless/static:nonroot
COPY --from=builder /app/server /server
USER nonroot
ENTRYPOINT ["/server"]

2.2 显著瘦身手段

手段效果
多阶段构建甩掉编译器/依赖
用 distroless / alpine去掉 shell、包管理器
合并 RUN、清理 apt 缓存减层数、减体积
选合适的基础镜像用官方 slim 版
RUN apt-get update \
 && apt-get install -y --no-install-recommends curl \
 && rm -rf /var/lib/apt/lists/*     # 关键:清理缓存

2.3 安全与体积的平衡

alpine(musl)有时与某些 CGO 库不兼容;distroless 无 shell 不便排障。推荐:常规服务用较省体积的发行版或 distroless,需要调试失败保留 slim。

一句话:多阶段 + distroless = 只交付运行所需——又小又安全,构建依赖不泄漏到生产镜像里。


3. 镜像漏洞扫描与安全基线

3.1 扫描工具

工具特点
Trivy全面、快、OSS,可做 CI 门禁
GrypeAnchore 开源,Syft 配套
ClairRed Hat 的仓库级扫描
Snyk商业,含运行时与依赖

3.2 在 CI 里做门禁

把扫描做成阻断性步骤,严重影响高危漏洞就不让推送:

# GitHub Actions 示例
- name: 扫描镜像
  uses: aquasecurity/trivy-action@master
  with:
    image-ref: ghcr.io/me/app:latest
    severity: CRITICAL,HIGH
    format: table
    exit-code: '1'   # 高危存在即失败

3.3 信任与基线

  • 不追求"零漏洞"(基础系统总有低危项),而是设可控基线(阻止高/危急);
  • 对基础镜像与应用依赖分仓扫描;
  • 建立已知可接受风险清单,注明原因与时间。

一句话:扫描 = CI 门禁(高危阻断)+ 基线化(可接受风险清单)——让镜像在进仓库前就"体检"。


4. SBOM:镜像的物料清单

4.1 什么是 SBOM

SBOM(Software Bill of Materials,软件物料清单) 列出镜像内所有组件、版本、许可证与来源。它让"这个镜像里到底有什么"可审计,是供应链可见性的基础。

4.2 生成 SBOM

# 用 Syft 生成
syft ghcr.io/me/app:latest -o cyclonedx-json > app-sbom.json

# 或 Trivy
trivy image --format cyclonedx --output app-sbom.json ghcr.io/me/app:latest

4.3 SBOM 的用途

用途说明
漏洞追踪组件级排查漏洞影响范围
合规审计许可证与成分审查
供应链信任与签名一起构成"原料可追溯"
平台治理作为镜像资产的一部分存档

一句话:SBOM = 镜像的户口本——没有它,“里面有什么"是不可审计的;让漏洞排查从"猜"变成"查”。


5. 镜像签名:cosign 与供应链信任

5.1 为什么要签名

镜像从构建方到集群要经过仓库、传输、拉取多个环节。若无人验证,攻击者可在任一环节替换镜像。签名 保证镜像的签发者与完整性可被校验。

5.2 使用 cosign 签名

# 生成密钥
cosign generate-key-pair

# 签名
cosign sign --key cosign.key ghcr.io/me/app:latest

# 校验
cosign verify --key cosign.pub ghcr.io/me/app:latest
# Verification true / 失败会有明确错误

5.3 SLSA 与可复现供应链

SLSA(Supply-chain Levels for Software Artifacts)定义从"完整"到"规范"的信任等级。将构建输入、签名、SBOM 关联,形成可验证、可复现的供应链:

源码 → 信任构建(记录构建元数据)→ 生成 SBOM → cosign 签名(+SBOM 一起)→ 推送仓库 → 部署时校验

一句话:签名 = 给镜像盖章,让平台知道"这是可信签发者发布的";加上 SBOM,供应链从"来源不明"变成"逐层可验"。


6. 私有仓库与拉取策略

6.1 使用容器仓库策略

  • 用 私有仓库 + 访问控制(registry + IAM/凭证);
  • 开启 内容信任(Notary/DCT)或 加固访问;
  • 用 镜像拉取镜像(imagePullPolicy)控制缓存策略:
spec:
  containers:
    - name: app
      image: registry.example.com/team/app:1.2.3
      imagePullPolicy: IfNotPresent   # 或 Always,避免用旧缓存

6.2 仓库级扫描与策略

在云厂商或制品库侧开启扫描 + 策略(如阻断高危镜像出仓),作为 CI 的补充防线。

一句话:仓库 = 鉴权 + 扫描 + 拉取策略——把好第一道,不让带毒镜像散发出。


7. 镜像准入:在集群侧强制签名

7.1 为什么需要准入策略

CI 扫描 + 签名做了,但部署时谁保证用的是签名镜像?若有人绕过 CI 直接创建 Pod,可能用脏镜像。ImagePolicyWebhook(或 Gatekeeper/President)在集群侧强制校验。

7.2 用准入策略做防线

  • 用 Open Policy Agent / Gatekeeper 规则:只允许签名 cosign verify 通过的镜像;
  • 设 imagePullPolicy 强制 Always/fixed-tag,禁止 latest 在非 dev 命名空间;
  • 对关键命名空间 禁止允许源不明的镜像。

一句话:构建门禁 + 仓库扫描 + 集群准入 三层防线,让"脏镜像"到不了运行时。


8. 最佳实践与常见坑

8.1 常见坑

坑现象对策
用 docker build 忘构建缓存构建慢用 BuildKit + 缓存 mount
不瘦身镜像过大多阶段 + distroless
从来不扫描带漏洞上线CI 加门禁
无 SBOM漏洞影响面难查生成 SBOM 存档
无签名镜像可能被替换cosign 签名 + 校验
用 latest无法复现固定不可变 tag

8.2 端到端流水线

源码提交 → 信任构建(记录元数据)
   → SBOM 生成(Syft/Trivy)
   → 漏洞扫描(高危阻断)
   → cosign 签名(镜像 + SBOM)
   → 推私有仓(仓库扫描)
   → 部署时集群准入校验签名
   → 运行镜像可追溯

构建快、镜像小、扫描全、签名真、准入严——一条面向生产可解释、可审计的镜像产线。

总结:镜像治理 = 高效构建(快)+ 多阶段瘦身(小)+ 漏洞扫描(安全)+ SBOM(可见)+ 签名(可信)+ 准入(强制)。让镜像是可信的交付包袱,而不是攻击面。镜像之所以可信,是因为每一个环节都被验证和记录。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「云原生」更多文章

  1. Kubernetes 备份容灾与数据保护:Velero、etcd 与恢复演练实战
  2. Kubernetes 渐进式交付:Argo Rollouts、金丝雀/蓝绿与流量治理实战
  3. Kubernetes 集群排障与诊断:从 Pod 症状到节点/集群根因的实战手册