跳到主要内容

容器镜像安全:Trivy 扫描 + OPA/Kyverno 准入控制

容器镜像供应链面临的风险

  • 基础镜像漏洞:系统包、语言运行时未更新,留下 CVE。
  • 恶意软件/后门:镜像被篡改或下载来源不可信。
  • 缺乏签名:部署前无法验证镜像出处。
  • 准入缺失:集群允许任何镜像运行,即使未扫描或来自公开仓库。

构建安全镜像交付流程需要“扫描 -> 签名 -> 准入”的闭环。

使用 Trivy 进行漏洞与配置扫描

  1. 安装

    brew install trivy   # macOS
    # 或
    curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sudo sh -s -- -b /usr/local/bin
  2. 镜像扫描

    trivy image --severity HIGH,CRITICAL registry.example.com/app:1.0
    • --ignore-unfixed:忽略尚未有修复方案的漏洞。
    • --format json:便于在 CI/CD 中解析。
  3. 文件/配置扫描

    trivy config --severity HIGH,CRITICAL ./manifests
  4. CI/CD 集成(GitLab 示例):

    scan:image:
    stage: test
    image: aquasec/trivy:latest
    script:
    - trivy image --exit-code 1 --severity HIGH,CRITICAL $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    artifacts:
    reports:
    dependency_scanning: trivy-report.json

    通过 --exit-code 1 在检测到高危漏洞时阻断流水线。

镜像签名与验证(Cosign + Sigstore)

  1. 签名
    cosign generate-key-pair
    cosign sign --key cosign.key registry.example.com/app:1.0
  2. 验证
    cosign verify --key cosign.pub registry.example.com/app:1.0
  3. 无密钥(Keyless)模式:利用 Sigstore Fulcio + OIDC,对 CI 进行短期签名,避免私钥托管。

OPA Gatekeeper / Kyverno 建立准入控制

Kyverno 策略示例:要求签名、限制仓库

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-signed-images
spec:
validationFailureAction: enforce
background: true
rules:
- name: verify-signature
match:
resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "registry.example.com/*"
attestors:
- entries:
- keys:
publicKeys: |
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt...
-----END PUBLIC KEY-----
- name: restrict-registry
match:
resources:
kinds:
- Pod
validate:
message: "只允许使用公司私有镜像仓库"
pattern:
spec:
containers:
- image: "registry.example.com/*"

Gatekeeper 策略(约束未扫描镜像)

package k8srequiredlabels
violation[{
"msg": msg,
"details": {"container": c.name}
}] {
input.review.kind.kind == "Pod"
c := input.review.object.spec.containers[_]
not startswith(c.image, "registry.example.com/")
msg := sprintf("container %s 使用非授权镜像: %s", [c.name, c.image])
}

在 ConstraintTemplate 中引入扫描结果标签(如 security.trivy.io/status=pass)后可实现更细致控制。

交付流程示例(CI -> 签名 -> 准入)

  1. CI 阶段
    • 使用 Trivy 扫描源码依赖、镜像层。
    • 构建通过后使用 Cosign 签名,并将签名推送到 OCI registry。
  2. CD 阶段
    • 通过 GitOps(ArgoCD/Flux)同步 Deployment,并在 Manifest 中加入镜像 digest。
    • Kyverno/Gatekeeper 在 Admission 时验证镜像签名、仓库来源、扫描状态。
  3. 运行时监控
    • 借助 Falco、Sysdig Secure 等工具监控容器异常行为,实现持续防护。

常见问题与排查

  • 扫描耗时长:可使用 Trivy 的缓存或在生产环境部署 Trivy Server。
  • 误报:定期维护忽略列表 (.trivyignore),记录为何忽略,定期复查。
  • CI 无法访问私有仓库:提前配置 Docker registry 凭证或使用 Kaniko + Cosign 集成。
  • 策略导致上线受阻:先以 audit 模式运行 Kyverno/Gatekeeper,观察 1-2 周后再开启 enforce

总结

镜像安全需要 DevSecOps 贯穿整个生命周期:在构建阶段发现问题(Trivy)、在发布阶段确认来源(Cosign)、在运行阶段阻断未授权镜像(Kyverno/OPA)。完成闭环后,可以显著降低供应链攻击面,为集群提供可审计、可追溯的安全保障。