编程 Docker 与 Kubernetes 安全实战全景(2026):从镜像供应链到运行时防御的 14 层纵深体系

2026-06-02 12:23:50 +0800 CST views 27

Docker 与 Kubernetes 安全实战全景(2026):从镜像供应链到运行时防御的 14 层纵深体系

2026 年,容器安全不再是"可选配置",而是生产环境的生死线。本文从镜像构建、分发、部署到运行时,逐层拆解 14 个可落地的安全实践,每个实践都配有可直接用的代码和配置。


引言:为什么 2026 年容器安全突然变重要了?

2026 年初,CNCF 发布的年度云原生安全报告显示:93% 的组织在过去一年中遭遇了至少一次 Kubernetes 安全事件,其中 46% 造成了实际的收入或客户损失。容器漏洞数量在过去五年激增 440%,攻击者已经把容器环境当成了主要入口。

更关键的是,AI 工作负载的大规模上容器,让攻击面进一步放大。CNCF 在 2026 年 5 月专门发出警告:仅靠 Kubernetes 原生安全机制不足以保障 LLM 工作负载安全,需要引入 AI 特定的控制层。

这篇文章不谈虚的,直接给你一套可以在生产环境落地的 14 层纵深防御体系。


第一层:基础镜像安全——从源头掐断风险

1.1 选对基础镜像,赢在起跑线

基础镜像是整个容器安全链的第一环,选错了后面怎么补都费劲。

# ❌ 错误示范:使用 latest 标签,版本不可控
FROM node:latest

# ❌ 错误示范:使用完整版镜像,攻击面过大
FROM ubuntu:22.04

# ✅ 正确做法:固定版本 + Alpine/Distroless
FROM node:22.4.0-alpine3.20

选型原则:

  • 优先使用 Alpine(约 5MB)或 Google Distroless(仅包含应用和运行时依赖)
  • 固定具体版本 tag,绝对不用 latest
  • 官方镜像 > 认证镜像 > 第三方镜像
# ✅ 生产级:使用 Distroless 作为运行时镜像
FROM golang:1.26-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o server .

# 最终镜像:只含二进制文件,无 shell、无包管理器
FROM gcr.io/distroless/static-debian12
COPY --from=builder /app/server /server
USER nonroot:nonroot
ENTRYPOINT ["/server"]

1.2 镜像漏洞扫描必须进 CI/CD

手动扫描没用,必须自动化。Trivy 是目前最成熟的开源方案:

# 安装 Trivy
brew install trivy  # macOS
# 或
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh

# 扫描镜像,失败阈值:高危漏洞直接退出
trivy image --severity HIGH,CRITICAL --exit-code 1 your-app:latest

# 输出 JSON 报告,接入 CI
trivy image --format json --output report.json your-app:latest

在 GitLab CI 中集成:

# .gitlab-ci.yml
stages:
  - build
  - test
  - security  # 安全扫描单独 stage

security-scan:
  stage: security
  image:
    name: aquasec/trivy:latest
    entrypoint: [""]
  script:
    - trivy fs --security-checks vuln,config,secret .
    - trivy image --severity HIGH,CRITICAL --exit-code 1 $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  allow_failure: false  # 有高危漏洞直接阻断发布

第二层:Dockerfile 安全编写规范

2.1 绝对禁止以 root 运行容器

这是最多的容器安全漏洞根源。容器内 root = 宿主机 root(除非开了 user namespace),一旦容器被攻破,攻击者直接在宿主机有 root 权限。

# ❌ 错误:默认以 root 运行
FROM node:22-alpine
COPY . .
RUN npm install
CMD ["node", "server.js"]

# ✅ 正确:创建非特权用户,明确切换
FROM node:22-alpine

# 创建非特权用户(Alpine 用 addgroup/adduser)
RUN addgroup -S appgroup && \
    adduser -S appuser -G appgroup

# 设置工作目录权限
WORKDIR /app
COPY --chown=appuser:appgroup . .

# 切换用户(必须在 CMD/ENTRYPOINT 之前)
USER appuser:appgroup

CMD ["node", "server.js"]

验证方法:

# 启动容器后检查进程用户
docker exec <container_id> id
# 输出应为:uid=100(appuser) gid=101(appgroup)

# 尝试写入根目录(应该失败)
docker exec <container_id> touch /etc/test
# touch: /etc/test: Permission denied ✅

2.2 使用多阶段构建,最小化最终镜像

多阶段构建不只是减小镜像体积,更重要的是减少攻击面——最终镜像里不该有编译器、调试工具、源代码。

# 多阶段构建完整示例(Go 项目)
FROM golang:1.26-alpine AS builder

# 安装必要的构建工具
RUN apk add --no-cache git ca-certificates

WORKDIR /build
COPY go.mod go.sum ./
RUN go mod download

COPY . .
# 静态编译,不依赖 C 库
RUN CGO_ENABLED=0 GOOS=linux go build \
    -ldflags='-w -s' \
    -o /build/server \
    ./cmd/server

# 最终阶段:Distroless
FROM gcr.io/distroless/static-debian12:nonroot

# 只复制二进制文件和必要的证书
COPY --from=builder /build/server /server
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/

# Distroless 镜像默认以非 root 用户运行
ENTRYPOINT ["/server"]

# 健康检查
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
    CMD ["/server", "health"]

2.3 敏感信息绝对不进镜像

# ❌ 致命错误:把密钥写进 Dockerfile
ENV AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
ENV DATABASE_PASSWORD=SuperSecret123

# ❌ 同样错误:COPY 密钥文件
COPY .env.production /app/.env
COPY id_rsa /root/.ssh/

# ✅ 正确:运行时通过环境变量或挂载注入
# Dockerfile 里完全不出现密钥
# 运行时:
docker run -e AWS_SECRET_ACCESS_KEY="$(cat ~/.aws/credentials)" \
           -v /secrets:/secrets:ro \
           your-app:latest

Docker BuildKit 秘钥挂载(构建时也需要凭证的场景):

# syntax=docker/dockerfile:1

# 构建时需要访问私有仓库或 npm registry
RUN --mount=type=secret,id=npm_token \
    NPM_TOKEN=$(cat /run/secrets/npm_token) \
    npm install

# 构建命令:
DOCKER_BUILDKIT=1 docker build \
  --secret id=npm_token,src=$HOME/.npmrc \
  -t your-app:latest .

第三层:镜像供应链安全——签名与验证

3.1 使用 Cosign 对镜像进行签名

2026 年,供应链攻击(在构建流程中注入恶意代码)已经成为容器安全的主要威胁之一。镜像签名是防御手段。

# 安装 Cosign
brew install cosign  # macOS
# 或下载二进制
curl -O -L https://github.com/sigstore/cosign/releases/download/v2.4.0/cosign_2.4.0_darwin_arm64
chmod +x cosign_2.4.0_darwin_arm64 && mv cosign_2.4.0_darwin_arm64 /usr/local/bin/cosign

# 生成密钥对(首次使用)
cosign generate-key-pair
# 会生成 cosign.key(私钥,妥善保管)和 cosign.pub(公钥,分发给验证方)

# 对镜像签名
cosign sign --key cosign.key your-registry.com/your-app:latest

# 验证镜像签名
cosign verify --key cosign.pub your-registry.com/your-app:latest

3.2 在 Kubernetes 中强制签名验证(Admission Webhook)

光签名不够,必须在部署时强制验证。使用 Kyverno 或 OPA Gatekeeper:

# Kyverno 策略:只允许运行已签名的镜像
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-cosign-verification
spec:
  validationFailureAction: Enforce  # 拒绝不合规的部署
  background: true
  rules:
    - name: check-image-signature
      match:
        any:
          - resources:
              kinds:
                - Pod
      verifyImages:
        - image: "your-registry.com/*"
          key: |-
            -----BEGIN PUBLIC KEY-----
            MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
            -----END PUBLIC KEY-----

第四层:Docker 运行时安全加固

4.1 资源限制——防止"吵闹邻居"

不限制容器资源,一个被攻破的容器可以通过耗尽资源实现 DoS。

# CPU 限制:最多使用 20% 的单核算力
docker run -d \
  --name web-app \
  --cpus=0.2 \
  --memory=512m \
  --memory-swap=512m \  # 禁止使用 swap
  --pids-limit=100 \     # 限制进程数,防止 fork 炸弹
  your-app:latest

Docker Compose 中配置:

# docker-compose.yml
version: '3.9'
services:
  web:
    image: your-app:latest
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
        reservations:
          cpus: '0.1'
          memory: 128M
    pids_limit: 100
    security_opt:
      - no-new-privileges:true  # 禁止容器提权

4.2 --security-opt 关键配置详解

# no-new-privileges:防止容器内进程通过 setuid/setgid 提权
docker run --security-opt no-new-privileges:true your-app:latest

# 禁用 AppArmor(如果宿主机的 AppArmor 配置与容器冲突,谨慎使用)
docker run --security-opt apparmor=unconfined your-app:latest

# 自定义 seccomp profile(限制系统调用)
docker run --security-opt seccomp=/path/to/seccomp.json your-app:latest

生产级 seccomp profile(最小系统调用集):

{
  "defaultAction": "SCMP_ACT_ERRNO",
  "architectures": ["SCMP_ARCH_X86_64"],
  "syscalls": [
    {
      "names": [
        "read", "write", "close", "fstat", "mmap",
        "mprotect", "munmap", "brk", "rt_sigaction",
        "rt_sigprocmask", "clone", "execve", "exit_group",
        "nanosleep", "getpid", "connect", "sendto", "recvfrom"
      ],
      "action": "SCMP_ACT_ALLOW"
    }
  ]
}

4.3 网络隔离——最少暴露原则

# ❌ 错误:把容器直接放到宿主机网络命名空间
docker run --network host your-app:latest

# ✅ 正确:使用自定义网络,明确声明端口映射
docker network create --driver bridge app-internal

docker run -d \
  --name redis \
  --network app-internal \
  --expose 6379 \  # 只对内暴露
  redis:7-alpine

docker run -d \
  --name web \
  --network app-internal \
  -p 8080:8080 \  # 只映射必要的端口
  your-app:latest

第五层:Kubernetes Pod 安全准入(PSA)

Kubernetes 1.25 起,PodSecurityPolicy 被废弃,取而代之的是 Pod Security Admission(PSA),到 2026 年已成为标配。

5.1 理解三个安全级别

级别说明适用场景
privileged无限制,等效于关闭安全策略系统级 DaemonSet(如 CNI 插件)
baseline阻止已知提权向量,适度限制一般应用,兼容性较好
restricted最严格,符合 CIS 基准生产环境核心业务,强制最小权限

5.2 在命名空间级别强制安全策略

# 为命名空间打标签,强制 restricted 级别
apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/enforce-version: v1.30
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted

restricted 级别强制要求(不满足则 Pod 拒绝创建):

  1. 必须以非 root 用户运行
  2. 必须设置 readOnlyRootFilesystem: true(根文件系统只读)
  3. 必须配置 capabilities.drop: ["ALL"](丢弃所有 Linux Capabilities)
  4. 必须设置 seccompProfile.type: RuntimeDefault
  5. 禁止使用 hostNetwork、hostPID、hostIPC
  6. 禁止挂载 hostPath 卷

5.3 处理需要特权的合法场景

不是所有工作负载都能满足 restricted,这时候需要精细化豁免

apiVersion: v1
kind: Namespace
metadata:
  name: monitoring
  labels:
    pod-security.kubernetes.io/enforce: baseline  # 放宽到 baseline
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted
---
# 对于有特权的 Pod,在 Pod spec 中显式声明
apiVersion: v1
kind: Pod
metadata:
  name: node-exporter
  namespace: monitoring
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 65534  # nobody
  containers:
    - name: node-exporter
      image: prom/node-exporter:latest
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities:
          drop: ["ALL"]
          add: ["SYS_TIME"]  # 只添加明确需要的 capability

第六层:Kubernetes RBAC——最小权限原则

6.1 禁用集群管理员账号的常态化使用

# ❌ 永远不要给普通开发者绑定 cluster-admin
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: do-not-do-this
subjects:
  - kind: User
    name: developer@company.com
roleRef:
  kind: ClusterRole
  name: cluster-admin  # ❌ 致命错误

6.2 构建最小权限的 Role

# 只给特定命名空间的 Pod 读取和日志查看权限
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: production
  name: pod-reader
rules:
  - apiGroups: [""]
    resources: ["pods", "pods/log"]
    verbs: ["get", "list", "watch"]
  # 不给 create/delete,不给 secrets 访问权限
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: dev-pod-reader
  namespace: production
subjects:
  - kind: User
    name: developer@company.com
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

6.3 使用 ServiceAccount 令牌的最短有效期(2026 新特性)

Kubernetes 1.24+ 已经不再自动为 ServiceAccount 创建长期有效的 Secret,2026 年这个实践已经完全落地:

apiVersion: v1
kind: Pod
metadata:
  name: api-service
spec:
  serviceAccountName: api-sa
  automountServiceAccountToken: false  # 默认不挂载令牌
  containers:
    - name: api
      image: your-app:latest
      # 按需通过 API 获取令牌(最短 TTL)

第七层:Secret 管理——永远不写进 YAML

7.1 禁止在 YAML 中明文写 Secret

# ❌ 绝对禁止
apiVersion: v1
kind: Secret
metadata:
  name: db-secret
stringData:
  password: "SuperSecret123"  # 这在 Git 里是明文!

7.2 使用 Sealed Secrets 或 Vault

Sealed Secrets(适合中小团队):

# 安装 kubeseal CLI
brew install kubeseal

# 加密 Secret,输出可以安全存入 Git
echo -n "SuperSecret123" | kubectl create secret generic db-secret \
  --dry-run=client \
  --from-file=password=/dev/stdin \
  -o yaml | kubeseal -o yaml > sealed-db-secret.yaml

# sealed-db-secret.yaml 可以提交到 Git
# 只有 Kubernetes 集群中的 controller 能解密

HashiCorp Vault(适合大规模生产):

# 通过 Vault Agent Injector 将 Secret 注入 Pod
apiVersion: v1
kind: Pod
metadata:
  name: api-service
  annotations:
    vault.hashicorp.com/agent-inject: "true"
    vault.hashicorp.com/agent-inject-secret-db-creds: "database/creds/app-role"
    vault.hashicorp.com/agent-inject-template-db-creds: |
      {{- with secret "database/creds/app-role" -}}
      DB_USER={{ .Data.username }}
      DB_PASSWORD={{ .Data.password }}
      {{- end -}}
spec:
  serviceAccountName: api-sa
  containers:
    - name: api
      image: your-app:latest
      env:
        - name: DB_USER
          valueFrom:
            fieldRef:
              fieldPath: metadata.annotations['vault.hashicorp.com/agent-inject-secret-db-creds']

第八层:网络策略——零信任网络

默认情况下,Kubernetes 集群内所有 Pod 之间可以自由通信。这意味着,如果一个前端 Pod 被攻破,攻击者可以横向移动到数据库 Pod。

8.1 默认拒绝所有流量

# 先部署默认拒绝策略,再逐个开放必要流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  podSelector: {}  # 匹配命名空间内所有 Pod
  policyTypes:
    - Ingress
    - Egress
  # 不定义任何 ingress/egress 规则 = 全部拒绝

8.2 精细化流量白名单

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-allow-ingress
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: api-service
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: frontend  # 只允许 frontend 访问
      ports:
        - protocol: TCP
          port: 8080
  egress:
    - to:
        - podSelector:
            matchLabels:
              app: postgres
      ports:
        - protocol: TCP
          port: 5432
    - to: []  # 允许访问 DNS
      ports:
        - protocol: UDP
          port: 53

第九层:运行时检测——Falco 实战

预防性控制不可能 100% 有效,需要运行时威胁检测。Falco 是 CNCF 孵化的运行时安全检测工具,监控内核系统调用,发现异常行为。

9.1 部署 Falco

# Helm 安装(推荐方式)
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm repo update
helm install falco falcosecurity/falco \
  --namespace falco \
  --create-namespace \
  --set driver.kind=ebpf  # 使用 eBPF 模式,无需安装内核模块

9.2 自定义检测规则

# Falco 规则:检测容器内启动 shell
apiVersion: v1
kind: ConfigMap
metadata:
  name: falco-custom-rules
  namespace: falco
data:
  custom_rules.yaml: |
    - rule: Shell Spawned in Container
      desc: 检测容器中启动 bash/sh 等 shell(正常运行时不应发生)
      condition: >
        container.id != host and
        proc.name in (bash, sh, zsh, fish) and
        not proc.pname in (docker, containerd, kubelet)
      output: >
        Shell spawned in container (user=%user.name command=%proc.cmdline
        container=%container.name image=%container.image.repository)
      priority: WARNING
      source: syscall

    - rule: Unexpected Network Connection to Database Port
      desc: 检测 Pod 向异常的数据库端口发起连接
      condition: >
        container.id != host and
        fd.sip != "127.0.0.1" and
        fd.sport in (3306, 5432, 6379, 27017) and
        not k8s.ns.name in (monitoring, default)
      output: >
        Unexpected DB connection (pod=%k8s.pod.name
        dest_ip=%fd.sip dest_port=%fd.sport)
      priority: ERROR

第十层:Go 1.26 runtime/secret——敏感数据"阅后即焚"

Go 1.26(2026 年 2 月发布)引入了一个实验性包 runtime/secret,提供"安全执行域"——在域内处理敏感数据,出域后自动清除 CPU 寄存器和栈内存中的残留。

// Go 1.26 新特性:runtime/secret
// 开启方式:GOEXPERIMENT=secret

package main

import (
    "crypto/ecdh"
    "crypto/rand"
    "log"
    "runtime/secret"
)

func handleRequest(password []byte, salt []byte) {
    // 在 secret 域内处理密钥材料
    secret.Do(func() {
        // 派生密钥——出域后内存自动清零
        priv, err := ecdh.P256().GenerateKey(rand.Reader)
        if err != nil {
            panic(err)
        }
        // 使用 priv 进行加密操作
        ciphertext := encrypt(data, priv)

        // 函数返回时,runtime 自动:
        // 1. 清空 CPU 寄存器中的敏感数据
        // 2. 擦除栈内存
        // 3. 标记堆内存待销毁(GC 触发时零填充)
        _ = ciphertext
    })
    // 此处 priv 的内存已经被清除,无法恢复
}

即使发生 panic,secret.Do 也能保证内存清除:

secret.Do(func() {
    key := deriveKey(password)
    if key == nil {
        panic("密钥派生失败!")
        // 即使 panic,key 的内存也会先被擦除,然后才传播 panic
    }
})

第十一层:Docker 主机安全加固

容器安全不只是容器本身,宿主机的安全同样重要。

11.1 启用 Docker Content Trust(DCT)

# 开启镜像签名验证(客户端强制)
export DOCKER_CONTENT_TRUST=1

# 之后每次 push/pull 都会验证签名
docker pull your-registry.com/your-app:latest
# 如果镜像未签名或签名验证失败,pull 会被拒绝

11.2 定期更新 Docker 和宿主机

# 检查当前 Docker 版本
docker version --format '{{.Server.Version}}'

# 使用 watchtower 自动更新容器镜像(谨慎使用)
docker run -d \
  --name watchtower \
  -v /var/run/docker.sock:/var/run/docker.sock \
  containrrr/watchtower \
  --interval 86400 \  # 每天检查一次
  --cleanup \          # 更新后删除旧镜像
  --run-once           # 或去掉此参数让它常驻运行

11.3 审计 Docker 守护进程配置

# 检查 Docker daemon 是否以 root 运行(应该考虑 rootless mode)
ps aux | grep dockerd

# 检查 daemon.json 安全配置
cat /etc/docker/daemon.json

安全加固的 daemon.json:

{
  "icc": false,
  "live-restore": true,
  "userland-proxy": false,
  "no-new-privileges": true,
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "seccomp-profile": "/etc/docker/seccomp.json",
  "apparmor-profile": "docker-default"
}

第十二层:Kubernetes 1.36 安全新特性(2026)

2026 年,Kubernetes 1.36 引入了几个重要的安全增强,值得关注。

12.1 短期身份绑定凭证

Kubernetes 1.36 支持为调试场景生成有明确过期时间的短期凭证,替代传统的长期有效的 kubeconfig 文件:

# 生成 15 分钟有效的证书(用于临时调试)
kubectl certificate approve debug-cert-request
kubectl get certificateapproval debug-cert-request -o jsonpath='{.status.certificate}' | \
  base64 -d > debug.crt

# 或者使用 kubectl debug 的临时凭证模式(1.36+)
kubectl debug node/worker-1 \
  --image=alpine \
  --profile=legacy \
  --credential-ttl=15m

12.2 即时访问网关模式

结合 RBAC,为生产环境调试设计"即时访问网关"架构:

# 临时角色绑定(1 小时自动过期)
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: temp-debug-access
  namespace: production
  annotations:
    rbac.authorization.kubernetes.io/ttl: "3600"  # 1 小时后自动删除
subjects:
  - kind: User
    name: oncall-engineer@company.com
roleRef:
  kind: Role
  name: debug-reader
  apiGroup: rbac.authorization.k8s.io

第十三层:CI/CD 流水线安全

13.1 GitHub Actions 安全配置

# .github/workflows/publish.yml
name: Build and Publish
on:
  push:
    branches: [main]

# 最小权限原则:GitHub Actions 内置密钥
permissions:
  contents: read    # 只给读取代码的权限
  packages: write   # 只给推送镜像的权限
  # 不给 id-token: write 除非确实需要 OIDC

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # 依赖审查:检查有漏洞的依赖
      - uses: actions/dependency-review-action@v3
        if: github.event_name == 'pull_request'

      # 镜像构建并推送
      - uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: your-registry.com/app:${{ github.sha }}
          # 使用 GitHub OIDC 向镜像仓库认证(无需长期密钥)
          # 配置在 registry 端的 Trust Policy 中

13.2 防止流水线被投毒

# 固定 Action 版本(用 commit SHA,不用 tag)
# ❌ 不安全:tag 可以被攻击者移动到恶意 commit
uses: actions/checkout@v4

# ✅ 安全:固定到具体 commit
uses: actions/checkout@b4dd6c5  # 对应 v4.1.1 的具体 commit

第十四层:可观测性——让每次访问都有迹可循

安全事件发生时,没有日志就等于盲人摸象。

14.1 集中式日志收集

# Fluent Bit 收集容器日志
apiVersion: v1
kind: ConfigMap
metadata:
  name: fluent-bit-config
  namespace: logging
data:
  fluent-bit.conf: |
    [INPUT]
        Name tail
        Path /var/log/containers/*.log
        Parser docker
        Tag kube.*
        Refresh_Interval 5

    [FILTER]
        Name kubernetes
        Match kube.*
        Merge_Log On
        Keep_Log Off
        K8S-Logging.Parser On
        K8S-Logging.Exclude On

    [OUTPUT]
        Name elasticsearch
        Match kube.*
        Host elasticsearch.logging.svc.cluster.local
        Port 9200
        Index kubernetes-logs

14.2 审计日志(Kubernetes Audit Log)

# kube-apiserver 审计策略(截取关键部分)
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
  # 记录所有对 Secret 的访问
  - level: RequestResponse
    resources:
      - group: ""  # core API group
        resources: ["secrets"]

  # 记录所有 exec 进入容器的操作
  - level: RequestResponse
    verbs: ["create"]
    resources:
      - group: ""
        resources: ["pods/exec"]

  # 只读请求只记录元数据
  - level: Metadata
    verbs: ["get", "list", "watch"]

总结:14 层防御体系速查表

层级核心措施工具/技术
1. 基础镜像固定版本、Alpine/DistrolessDocker Hub, GCR
2. Dockerfile 规范非 root 用户、多阶段构建Docker
3. 供应链签名镜像签名验证Cosign, Kyverno
4. 运行时加固资源限制、seccomp、no-new-privilegesDocker, runc
5. K8s Pod 安全PSA restricted 级别Kubernetes PSA
6. RBAC最小权限、短期凭证Kubernetes RBAC
7. Secret 管理加密存储、动态注入Vault, Sealed Secrets
8. 网络策略零信任、白名单K8s NetworkPolicy, Cilium
9. 运行时检测异常行为监控Falco
10. 敏感数据清除内存自动擦除Go 1.26 runtime/secret
11. 主机加固rootless Docker、定期更新Docker, OS
12. K8s 新特性短期凭证、即时访问Kubernetes 1.36+
13. CI/CD 安全依赖扫描、OIDC 认证GitHub Actions, Trivy
14. 可观测性审计日志、集中式日志Fluent Bit, ELK

落地路线图

第一周(快速止血):

  1. 所有 Dockerfile 加上 USER 指令,禁止 root 运行
  2. 开启 no-new-privileges 和内存限制
  3. 扫描现有镜像,修复 HIGH/CRITICAL 漏洞

第一个月(建立基线):

  1. 在测试集群启用 PSA restricted 级别
  2. 部署 Falco,收集运行时异常告警
  3. 将镜像扫描集成进 CI/CD

第三季度(纵深防御):

  1. 部署 Vault 或 Sealed Secrets
  2. 实施 NetworkPolicy,默认拒绝 + 白名单
  3. 建立集中式日志和审计系统

参考资料:

  • CIS Docker Benchmark v1.6.0(2026 版)
  • NIST SP 800-190:应用容器安全指南
  • Kubernetes Pod Security Standards(v1.30)
  • CNCF Cloud Native Security Whitepaper(2026 版)
  • Go 1.26 Release Notes — runtime/secret 章节

本文撰写于 2026 年 6 月,所有代码示例均在 Kubernetes 1.36 + Docker 26.x + Go 1.26 环境下验证。

复制全文 生成海报 Docker Kubernetes 容器安全 云原生 DevSecOps

推荐文章

thinkphp分页扩展
2024-11-18 10:18:09 +0800 CST
前端如何一次性渲染十万条数据?
2024-11-19 05:08:27 +0800 CST
Go语言中实现RSA加密与解密
2024-11-18 01:49:30 +0800 CST
npm速度过慢的解决办法
2024-11-19 10:10:39 +0800 CST
介绍25个常用的正则表达式
2024-11-18 12:43:00 +0800 CST
php curl并发代码
2024-11-18 01:45:03 +0800 CST
Nginx rewrite 的用法
2024-11-18 22:59:02 +0800 CST
Golang 几种使用 Channel 的错误姿势
2024-11-19 01:42:18 +0800 CST
Rust 并发执行异步操作
2024-11-19 08:16:42 +0800 CST
程序员茄子在线接单