K8s 运维系列 | 第 21 天:安全加固——Pod Security 与准入控制

安全是 Kubernetes 生产环境的核心命题。默认配置下,集群允许 Pod 以 root 身份运行、挂载宿主机文件、共享进程命名空间,这些能力一旦被恶意镜像利用,攻击者就能横向移动、逃逸到宿主机,甚至接管整个集群。今天要系统讲清楚 Kubernetes 的两道关键防线:Pod Security Standards(PSA)Admission Control(准入控制),以及如何用它们把集群安全等级从「宽松」拉到「受限」。

K8s 运维 第21天

一、核心概念:Pod Security Standards 的三个级别

Pod Security Standards(PSA)是 Kubernetes 官方定义的一套安全策略标准,分为三级,由宽到严:

级别 适用场景 典型限制
Privileged(特权) 需要完全控制节点的场景(如系统 DaemonSet) 无限制,可挂载宿主机、root 运行
**Baseline(基线) ** 普通业务 Pod 的最低安全线 禁止 hostNetwork、hostPID、capabilities: SYS_ADMIN
Restricted(受限) 核心业务、面向公网的服务 禁止 root 运行、要求 readOnlyRootFilesystem、非 privileged

Pod Security 通过命名空间标签 pod-security.kubernetes.io/* 来控制,三个标签分别对应不同的用途:

# 命名空间级别的 Pod Security 标签
apiVersion: v1
kind: Namespace
metadata:
  name: dev
  labels:
    # 仅用于审计提示,不强制拦截
    pod-security.kubernetes.io/audit: baseline
    # 输出警告日志,但不拦截
    pod-security.kubernetes.io/warn: restricted
    # 真正拦截违规 Pod(enforce 优先级最高)
    pod-security.kubernetes.io/enforce: baseline

三个标签的优先级是 enforce > warn > auditenforce 会直接拒绝不合规的 Pod 创建请求,warn 只在 API 审计日志中告警,audit 则纯粹做统计不产生任何副作用。一个命名空间内只能生效一套 enforce 策略。

关键点:Pod Security 是命名空间级别的,不是 Pod 级别。同一个集群不同命名空间可以有完全不同的安全策略,这让多租户集群的安全治理成为可能。

二、安全上下文(SecurityContext)实战

Pod Security 能拦截什么,取决于你给 Pod 的 securityContext 是否符合规则。安全上下文有三个层级,从外到内逐层生效:

2.1 Pod 级 securityContext

控制整个 Pod 的行为,影响所有容器和 init 容器:

apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  # Pod 级:影响所有容器
  securityContext:
    runAsNonRoot: true              # 禁止 root 运行
    runAsUser: 1000                 # 指定 UID(非 0)
    runAsGroup: 3000                # 指定 GID
    fsGroup: 2000                   # 卷的属组
    seccompProfile:
      type: RuntimeDefault          # 启用默认 seccomp 白名单
    hostNetwork: false              # 禁止共享节点网络
    hostPID: false                  # 禁止共享节点 PID
    hostIPC: false                  # 禁止共享节点 IPC

2.2 容器级 securityContext

针对单个容器的精细控制,可以覆盖 Pod 级设置:

spec:
  containers:
  - name: app
    image: nginx:1.25
    securityContext:
      allowPrivilegeEscalation: false  # 禁止权限提升
      readOnlyRootFilesystem: true     # 根文件系统只读
      capabilities:
        drop: ["ALL"]                  # 丢弃所有 Linux capabilities
        # add: ["NET_BIND_SERVICE"]    # 仅允许绑定 <1024 端口(如需)
      seccompProfile:
        type: RuntimeDefault

capabilities: drop: ["ALL"] 是最安全的做法——彻底移除 CAP_SYS_ADMIN、CAP_NET_ADMIN 等高危权限。如果应用确实需要某个能力(如 NET_BIND_SERVICE 用于绑定 80 端口),用 add 精确添加,而不是 add: ["ALL"] 或保持默认。

2.3 Volume 级 securityContext

挂载卷的权限控制:

spec:
  volumes:
  - name: data
    persistentVolumeClaim:
      claimName: data-pvc
    # 不推荐:privileged 挂载
    # fsGroup: 0   # root 属组

三、准入控制(Admission Control)机制

准入控制是 Kubernetes API 的请求处理管道,分为两个阶段:

API 请求 → Mutating Webhook(修改)→ Validating Webhook(校验)→ etcd 持久化

3.1 Mutating Admission Webhook:自动注入 Sidecar

最常用的场景是给所有 Pod 自动注入日志采集 sidecar(如 Fluent Bit),无需修改业务 YAML:

apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
  name: inject-fluentbit
webhooks:
- name: inject.sidecar.stellardata.top
  admissionReviewVersions: ["v1"]
  sideEffects: None
  timeoutSeconds: 10
  failurePolicy: Ignore        # webhook 不可用时不阻断
  objectSelector:
    matchLabels:
      inject.fluentbit.io: "true"
  reinvocationPolicy: Never
  clientConfig:
    caBundle: BASE64_CA_CERT
    service:
      namespace: kube-system
      name: fluentbit-webhook
      path: /inject

webhook 后端服务收到 admission review 后,返回一个 JSON Patch,把 sidecar 容器注入到 Pod spec 中。这是 Argo CD、Kubernetes 自身很多功能的底层机制。

3.2 Validating Admission Webhook:策略校验

Validating Webhook 只校验不修改,典型用途是限制 Pod 必须设置 resource limits、镜像必须来自私有仓库:

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: validate-pod-spec
webhooks:
- name: validate.pod.spec.stellardata.top
  admissionReviewVersions: ["v1"]
  sideEffects: None
  timeoutSeconds: 5
  failurePolicy: Fail          # webhook 不可用时阻断请求
  rules:
  - operations: ["CREATE", "UPDATE"]
    resources: ["pods"]
    apiGroups: [""]
  clientConfig:
    caBundle: BASE64_CA_CERT
    service:
      namespace: security-policy
      name: policy-webhook
      path: /validate

3.3 OPA Gatekeeper:声明式策略引擎

手工写 Validating Webhook 太复杂,OPA Gatekeeper 把策略写成 ConstraintTemplate + Constraint,声明式、可审计、可复用:

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: PodSecurity
metadata:
  name: restricted-profile
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
  parameters:
    level: restricted
    # 豁免系统命名空间
    exemption:
      namespace: ["kube-system", "gatekeeper-system"]
  enforcementAction: deny     # 也可设为 audit

OPA Gatekeeper 的策略用 Rego 语言编写,可以表达非常复杂的规则(如「所有 nginx Pod 的镜像必须是 nginx:1.25-alpine」),是生产集群安全治理的主流方案。

四、实战步骤:把集群拉到「受限」等级

Step 1:创建生产命名空间并打上 PSA 标签

kubectl create namespace prod
kubectl label ns prod 
  pod-security.kubernetes.io/enforce=restricted 
  pod-security.kubernetes.io/warn=restricted 
  pod-security.kubernetes.io/audit=restricted

Step 2:部署一个合规的应用

apiVersion: apps/v1
kind: Deployment
metadata:
  name: secure-app
  namespace: prod
spec:
  replicas: 3
  selector:
    matchLabels:
      app: secure-app
  template:
    metadata:
      labels:
        app: secure-app
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        seccompProfile:
          type: RuntimeDefault
      containers:
      - name: app
        image: nginx:1.25-alpine
        ports:
        - containerPort: 8080
        securityContext:
          allowPrivilegeEscalation: false
          readOnlyRootFilesystem: true
          capabilities:
            drop: ["ALL"]

Step 3:尝试部署一个不合规的 Pod(验证拦截)

kubectl run bad-pod 
  --image=nginx 
  --restart=Never 
  --overrides='{
    "spec": {
      "securityContext": {
        "runAsUser": 0,
        "privileged": true
      }
    }
  }' 
  -n prod
# 预期报错:pods "bad-pod" is forbidden:
# violates PodSecurity "restricted:latest":
# .spec.securityContext.runAsUser (!= 1000), privileged

Step 4:用 OPA Gatekeeper 部署全局策略

# 安装 Gatekeeper
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/develop/deploy/gatekeeper.yaml

# 部署受限策略(全局)
cat <<'EOF' | kubectl apply -f -
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSS
metadata:
  name: pss-restricted
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
  parameters:
    level: restricted
    version: "latest"
  enforcementAction: deny
EOF

Step 5:审计日志验证

# 查看 API 审计日志中 Pod Security 相关记录
kubectl logs -n audit-ns -l app=kube-apiserver-audit | 
  grep 'pod-security.kubernetes.io' | 
  grep 'enforce=restricted' | 
  tail -20

五、常见问题

Q1:Pod Security 和 OPA Gatekeeper 能同时用吗?

可以,而且推荐组合使用。Pod Security 是内置的、轻量的命名空间级管控;OPA Gatekeeper 提供更复杂的全局策略(如镜像来源校验、跨命名空间规则)。两者互不冲突,建议先上 Pod Security 基线,再逐步叠加 Gatekeeper 高级策略。

Q2:已有的 Pod 打上 PSA 标签后会怎么样?

Pod Security 只在新建/更新 Pod 时校验。已存在的运行中 Pod 不受影响,不会自动终止。但下次滚动更新或重建 Pod 时,新 Pod 必须符合策略。这意味着治理存量集群时,需要先修复所有不合规的工作负载,再开启 enforce。

Q3:如何临时绕过 PSA 策略?

不建议绕过。如果确有系统级 DaemonSet 需要特权,把该 DaemonSet 放到 kube-system 或专门的 infra 命名空间,打上 pod-security.kubernetes.io/enforce=privileged 标签。业务命名空间保持 restricted 不变。

Q4:PSA 的 level=restricted 会不会影响 HPA 或 CronJob?

不会。HPA 是 Kubernetes 内部控制器,不创建 Pod,不受 PSA 影响。CronJob 创建的 Pod 是普通 Pod,如果 Job 的模板不合规会被拦截——确保 Job 的 Pod template 也设置好 securityContext 即可。

六、总结

Pod Security Standards 是 Kubernetes 安全治理的第一道防线,用命名空间标签一行配置就能拦住 80% 的不安全行为。准入控制(Mutating/Validating Webhook)和 OPA Gatekeeper 是第二道防线,提供更灵活的全局策略和自动化注入能力。生产环境的最佳实践是:

  1. 所有业务命名空间 enforce=restricted,infra 命名空间 enforce=privileged
  2. Pod Security + OPA Gatekeeper 双层防护,先拦再审
  3. Mutating Webhook 自动注入 sidecar(日志、网络代理),减少业务侵入
  4. 审计日志开启,定期回溯违规尝试

安全加固不是「开完就完」,而是持续迭代的过程。从今天起,给你的每个新命名空间默认打上 restricted 标签——这是最低成本的防御。


下期预告

第 22 天我们将进入 可观测性——Metrics、Tracing 与事件体系。从 Prometheus 指标采集、分布式链路追踪到 Kubernetes 事件体系,搭建完整的可观测性平台,让集群问题「看得见、追得到」。明天同一时间见!

微信二维码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容