PSA未覆盖的规则如何落地?

1 人参与

把一个条目写进 Pod Security Standards,和让集群真的拒绝违规 Pod,是两件事。从 Kubernetes v1.34 开始,Restricted 策略新增了对探针与生命周期回调中 httpGet.host 的限制,但这条规则被列在 Known list 之下——内置的 Pod Security Admission 控制器并不执行它。命名空间打上 pod-security.kubernetes.io/enforce=restricted 标签,也不会拦住带 host 字段的 Pod 被创建。依赖 Restricted 作为安全基线的集群,如果只信这个标签,就会在这类"写了但没生效"的条目上留下缺口。

先分清哪些规则归 PSA 管

判断依据是官方文档的 Pod Security Standards 页面:条目是否出现在 Known list 中,以及它的版本边界。这条 Host Probes / Lifecycle Hooks 限制只存在于 v1.34 及更高版本,v1.33 及更早的 Restricted 策略里没有它。像 hostNetwork、hostPort 这类已由 PSA 支持的字段,靠命名空间标签就够了;Known list 里的条目必须另建强制通道,两者不能混为一谈。

PSA未覆盖的规则如何落地?

三层强制通道

落地这类规则,通常不是单点方案,而是分层补位。

  • CI 阶段:对渲染后的 YAML 做静态扫描,用 conftest、kube-linter 或 Polaris 匹配探针与回调里的 host 字段,命中就阻断合并。成本最低,但只覆盖走流水线的改动。
  • 准入阶段:用 ValidatingAdmissionPolicy、Kyverno 或 OPA Gatekeeper 编写拒绝规则,在 Pod 创建和更新时检查各容器类型(含 initContainers 与 ephemeralContainers)。因为是新条目,建议先在审计模式下运行一段时间,确认不误伤合法工作负载,再切换到拒绝模式。
  • 运行时盘点:用 kubectl 配合 jq 扫全集群 Pod 的实际 spec,捕捉绕过流水线或手工 apply 的配置。

有一个容易踩的认知误区:kubectl apply --dry-run=server 不会因为 host 字段报错,因为 PSA 根本不校验它。部署前的验证只能依赖策略引擎。

删字段不等于修完

发现违规配置后直接删除 httpGet.host,风险在于行为会变。kubelet 改用 Pod IP 发起探测,如果容器内应用只监听 127.0.0.1,探测就会失败,Pod 可能反复重启。修复前需要确认 host 当前的值、应用实际监听的地址、探针路径的用途,以及 preStop 这类回调是否依赖特定主机。

如果无法调整应用监听地址,替代方案是改成 exec 探针或 exec 回调,代价是镜像内需要有 wget、curl 之类工具,且 preStop 的执行时间不能超过 terminationGracePeriodSeconds。变更建议在低峰期逐工作负载滚动,而不是一次性批量修改所有 Deployment;修复后观察探针事件与容器重启计数,异常就暂停后续批次。

更实际的做法是把这类检查固化成常规动作:统计违规工作负载的数量与 host 取值分布,纳入 CI 与准入策略,同时定期对照官方文档确认该条目是否已被内置 PSA 支持。基线检查按季度跑一次,比只在版本升级时做一次更能兜住新增的受限字段。

参与讨论

1 条评论
  • 傲骨寒霜

    打了restricted标签也不代表全拦住,还得自己补策略