psa 的 enforce/audit/warn 分别拦截 pod 创建(403拒绝)、记录违规日志(放行)和返回warning头(黄色提示),三者独立不降级;仅通过命名空间 annotation 控制,格式为 pod-security.admission.control.k8s.io/{enforce,audit,warn}=level:version,restricted:v1 要求 runasnonroot、seccompprofile、allowprivilegeescalation 等多项硬性约束。

PSA 的 enforce / audit / warn 到底在拦什么?
PSA 不是“开关式”策略,而是三类独立生效的策略执行层:enforce 确实会拒绝 Pod 创建;audit 会在 API Server 日志里记下违规但放行;warn 是 kube-apiserver 返回 HTTP 200 + 一个 Warning 头(客户端能看到,kubectl 会打印成黄色提示)。三者互不替代,也不会自动降级——比如开了 enforce 和 warn,违规 Pod 就直接被拒,根本不会走到 warn 那步。
-
enforce生效于 admission chain 的 MutatingAdmissionWebhook 之后、ValidatingAdmissionWebhook 之前,失败直接返回 403 -
audit和warn都依赖PodSecurity内置插件的日志/响应逻辑,不改变请求结果 - 同一命名空间不能混用不同级别:比如你给 ns A 设了
enforce: baseline:v1,就不能再加audit: restricted:v1—— PSA 只认一个pod-security.admission.control.k8s.io/annotation
怎么配才真正生效?看 annotation 写法和命名空间边界
PSA 策略只通过命名空间级别的 annotation 控制,没别的入口。常见错误是写错 key、value 格式,或误以为 cluster-wide 配置能覆盖 namespace。
- 必须用标准 annotation key:
pod-security.admission.control.k8s.io/enforce、pod-security.admission.control.k8s.io/audit、pod-security.admission.control.k8s.io/warn - value 必须是
level:version格式,比如baseline:v1,不能写成baseline或v1单独出现 - annotation 只对所在命名空间新创建的 Pod 生效,已存在的 Pod 不受影响(哪怕重启也不会重检)
- 如果命名空间没设任何 PSA annotation,就完全不触发 PSA 检查——不是“默认宽松”,是“彻底绕过”
示例:
kubectl annotate ns myapp \ pod-security.admission.control.k8s.io/enforce=restricted:v1 \ pod-security.admission.control.k8s.io/audit=baseline:v1 \ pod-security.admission.control.k8s.io/warn=restricted:v1
restricted:v1 拦住哪些东西?别只盯着 root 用户
很多人以为 restricted:v1 就是“禁止 root”,其实它是一组硬性组合规则,漏掉任意一条都会被 enforce 拒绝:
-
runAsNonRoot必须为true(或容器指定了非 0runAsUser) -
seccompProfile.type必须是RuntimeDefault或Localhost(不能是Unconfined) -
allowPrivilegeEscalation必须为false -
capabilities.drop至少包含ALL(允许额外 add,但 drop 不能空) -
hostNetwork、hostPID、hostIPC全部必须为false -
volumes类型受限:不允许hostPath、emptyDir的medium: Memory等高风险类型
注意:audit 和 warn 模式下,这些字段只是被记录或提示,但 Pod 仍能跑起来——所以线上先开 audit 观察一周,比直接上 enforce 更稳妥。
为什么 kubectl apply 后没报错,但 Pod 一直 Pending?
典型现象:你加了 enforce: restricted:v1,然后 kubectl apply -f pod.yaml 返回 success,但 kubectl get pod 显示 Pending,describe 里看不到明显拒绝信息。
这是因为 PSA 拒绝发生在 admission 阶段,API Server 直接返回 403,而 kubectl apply 默认不显示服务端 warning 或 error body(尤其当 server 返回的是纯 JSON 错误时)。
- 真正要看拒绝原因,得加
--v=6:kubectl apply -f pod.yaml --v=6 2>&1 | grep -A5 "admission control"
- 或者直接用 curl 模拟 POST,看原始响应体里的
message字段 - 常见隐形坑:Deployment 里没写
securityContext,但用了 Helm chart 自带的 serviceAccount,而该 SA 绑定了privilegedClusterRole —— PSA 不管 RBAC,但它会拦下最终生成的 Pod spec,而这个 spec 可能因 controller 注入(如 Istio sidecar)意外带上hostNetwork: true
PSA 的 enforce 模式不报错、不提示、不妥协,它只做一件事:匹配失败就 403。所以验证策略前,务必用 kubectl auth can-i 辅助判断权限是否足够,但更要直接试跑最小 Pod YAML,别信文档里的“应该可以”。










