“我们的服务跑在 Kubernetes 里,应该很安全吧?”
“Docker 镜像能跑就行,漏洞扫描太麻烦了。”
“Pod 默认用 root 启动,有什么问题吗?”

如果你也有类似想法,那么你的系统可能正暴露在高危攻击面之下。

云原生不是“自动安全”。恰恰相反,容器和编排系统的灵活性带来了更多安全边界:镜像、Pod、网络、API Server、配置策略……任何一个环节疏忽,都可能导致数据泄露或集群沦陷。

本文将带你构建一套最小权限、可审计、自动化的云原生安全体系,覆盖从 Pod 运行时到策略合规的纵深防御链。


一、Pod 安全:从非 root 到只读文件系统

Kubernetes Pod 默认以 root 用户运行,且根文件系统可写——这在安全上是灾难性的。

关键加固措施(通过 securityContext):

apiVersion: v1
kind: Pod
spec:
  securityContext:
    runAsNonRoot: true          # 禁止 root 启动
    runAsUser: 65532            # 指定 UID(如 distroless 的 nonroot)
    readOnlyRootFilesystem: true # 根文件系统只读
    capabilities:
      drop: ["ALL"]             # 剥离所有 Linux 能力
  containers:
    - name: app
      securityContext:
        allowPrivilegeEscalation: false

效果

  • 即使应用被攻破,攻击者也无法写入恶意文件;
  • 无法提权或挂载敏感设备;
  • 符合 CIS Kubernetes Benchmark 安全基线。

若应用需写临时文件,可挂载 emptyDir/tmp

volumeMounts:
  - name: tmp-volume
    mountPath: /tmp
volumes:
  - name: tmp-volume
    emptyDir: {}

二、网络策略:用 NetworkPolicy 实现零信任

默认情况下,K8s 集群内所有 Pod 可互相通信。这违背了“最小权限”原则。

NetworkPolicy 允许你定义“谁可以访问谁”:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
meta
  name: user-svc-policy
spec:
  podSelector:
    matchLabels:
      app: user-service
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              role: frontend
        - podSelector:
            matchLabels:
              app: order-service
      ports:
        - protocol: TCP
          port: 8080
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              name: database
      ports:
        - protocol: TCP
          port: 3306

💡 解读

  • 只允许 frontend 命名空间中的 Pod 或 order-service 访问 user-service
  • user-service 只能向外连接数据库命名空间的 3306 端口。

⚠️ 注意:NetworkPolicy 需 CNI 插件支持(如 Calico、Cilium),Flannel 不支持。


三、镜像安全:Trivy 扫描 + Notary 签名

一个包含 CVE 漏洞的镜像,等于给攻击者留了后门。

1. 镜像漏洞扫描(Trivy)

在 CI 中集成 Trivy:

trivy image --exit-code 1 --severity CRITICAL harbor.example.com/app:v1.0
  • 发现 CRITICAL 漏洞则阻断流水线;
  • 支持 OS 包、Go 模块、Python pip 等多语言依赖扫描。

2. 镜像签名(Notary / Cosign)

防止“镜像被篡改”:

  • 使用 Cosign 对镜像签名:
cosign sign --key cosign.key harbor.example.com/app:v1.0
  • 在部署时验证签名(通过 OPA/Gatekeeper 或 Kyverno)。

目标:确保“只有经过扫描且签名的镜像才能部署”。


四、策略即代码:OPA / Gatekeeper 强制合规

人工审查 YAML 不现实。安全策略应作为代码自动执行

使用 Gatekeeper(OPA 的 K8s 实现):

  1. 定义 ConstraintTemplate(策略模板):
# 禁止 root 用户
violation[{"msg": msg}] {
    container := input.review.object.spec.containers[_]
    not container.securityContext.runAsNonRoot
    msg := sprintf("container <%v> must set runAsNonRoot=true", [container.name])
}
  1. 应用 Constraint(策略实例):
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequireSecurityContext
meta
  name: require-nonroot
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]

🔒 效果:任何未设置 runAsNonRoot: true 的 Pod 创建请求将被 拒绝

类似策略还可覆盖:

  • 禁止使用 latest 标签;
  • 强制资源限制(requests/limits);
  • 禁止特权容器。

五、审计:开启 K8s 审计日志

即使防护到位,也需记录“谁做了什么”,用于事后追溯。

Kubernetes 审计日志(Audit Log) 记录所有 API Server 请求:

  • (user/group)
  • 做了什么(create/delete/update)
  • 操作对象(Pod/Service/Secret)
  • 源 IP

启用方式(kube-apiserver 参数):

--audit-log-path=/var/log/kube-audit/audit.log
--audit-policy-file=/etc/kubernetes/audit-policy.yaml

示例策略(仅记录敏感操作):

apiVersion: audit.k8s.io/v1
rules:
  - level: Metadata
    resources:
      - group: ""
        resources: ["secrets", "configmaps"]
  - level: RequestResponse
    resources:
      - group: "rbac.authorization.k8s.io"
        resources: ["roles", "rolebindings"]

日志可接入 Loki + GrafanaSIEM 系统,实现告警与可视化。


六、安全体系全景图


七、平台层 vs 应用层安全

云原生安全是分层的:

  • 平台层(K8s):负责 mTLS、网络隔离、Pod 安全上下文;
  • 应用层:负责业务逻辑安全,如请求签名、OAuth2 鉴权、敏感数据脱敏。

🔗 mTLS 证书管理由平台层完成(如 Istio),而服务间请求签名仍需在应用层实现(《微服务》【安全篇】)。
例如,即使流量已加密,仍需在 HTTP Header 中携带 HMAC 签名,防止重放攻击。


结语:安全不是功能,而是默认状态

真正的云原生安全,不是“加个防火墙”,而是将最小权限、不可变、可验证、可审计融入交付全流程。

从今天起:

  • 所有 Pod 必须非 root 运行;
  • 所有镜像必须通过 Trivy 扫描;
  • 所有部署必须受 Gatekeeper 策略约束。

让安全成为默认,而非例外。

📌 关注专栏《云原生从入门到精通》,系统掌握从交付到安全的完整能力。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐