上一篇【第57篇】Secret管理的最佳实践——原生Secret不加密?Vault/SealedSecrets来救场
下一篇【第59篇】K8s安全审计——你不能忽视的那些安全配置检查项


摘要

前面讲了SecurityContext(容器降权配置)、讲了SA的Token安全。但这些都是"靠开发者自觉写对"的——万一有人偷懒写了个privileged: true的Pod,集群就多了一个宿主机逃逸的口子。

需要一个"强制标准"在集群入口拦住不安全的Pod。老的PSP(Pod Security Policy)干这活,但太难用,K8s 1.25直接删了。接棒的是Pod Security Standards (PSS) + Pod Security Admission (PSA)——官方定义三档安全基线,用namespace label一键强制。

这篇文章讲清PSS的三档标准(Privileged/Baseline/Restricted)差在哪、PSA的三种模式怎么用、以及如何从宽松平滑迁移到最严的Restricted。


一、PSS三档标准

1.1 从松到严

【Pod Security Standards 三档】

  ┌──────────────────────────────────────────────────────┐
  │ Privileged (宽松档)                                    │
  │   • 完全放开,几乎不限制                               │
  │   • 允许特权容器、hostNetwork、hostPID                  │
  │   • 只用于: 系统组件(CNI/CSI)、 trusted workload       │
  │   • ⚠️ 业务Pod千万别用                                │
  └──────────────────────────────────────────────────────┘
        ▲ 升一档
  ┌──────────────────────────────────────────────────────┐
  │ Baseline (中等档)                                      │
  │   • 禁止明显的危险操作                                 │
  │   • 禁止: 特权容器、hostNetwork/hostPID/hostIPC        │
  │   • 禁止: 已知的危险capability(如SYS_ADMIN)            │
  │   • 允许: 大部分正常业务Pod                            │
  │   • ✅ 大多数场景的推荐起点                            │
  └──────────────────────────────────────────────────────┘
        ▲ 再升一档
  ┌──────────────────────────────────────────────────────┐
  │ Restricted (最严档)                                    │
  │   • 在Baseline基础上进一步收紧                         │
  │   • 要求: runAsNonRoot=true (禁止root)                 │
  │   • 要求: 非root用户执行、seccomp=RuntimeDefault       │
  │   • 要求: 不允许添加危险capability                      │
  │   • 要求: 卷类型白名单(禁止hostPath等)                 │
  │   • ✅ 高安全场景(金融/多租户)的目标                    │
  └──────────────────────────────────────────────────────┘

1.2 三档对比表

检查项 Privileged Baseline Restricted
特权容器 ✅ 允许 ❌ 禁止 ❌ 禁止
hostNetwork/PID/IPC
runAsNonRoot 不要求 不要求 ✅ 必须
危险capability 允许 禁止 禁止
seccompProfile 不要求 不要求 ✅ RuntimeDefault
卷类型限制 ✅ 白名单

要点:三档是"递进"关系——Restricted ⊂ Baseline ⊂ Privileged(Restricted最严,包含Baseline的所有限制再加码)。业务Pod至少用Baseline,金融/多租户等高安全场景冲Restricted。Privileged只留给真正的系统组件。


二、PSA:用label强制

2.1 三种模式

PSA(Pod Security Admission)是内置的准入控制器,用namespace的label来控制。每个标准有三套模式:

【PSA 三种模式——"宽严怎么定"】

  enforce (强制): 违反标准 → 直接拒绝创建  ← 最硬
  audit   (审计): 违反标准 → 记审计日志,不拦截  ← 观察用
  warn    (警告): 违反标准 → 返回警告,不拦截  ← 迁移过渡用

  典型迁移路径:
  阶段1: warn=baseline, audit=baseline  (只看不拦,评估影响)
  阶段2: enforce=baseline               (强制baseline)
  阶段3: warn=restricted, audit=restricted (评估restricted影响)
  阶段4: enforce=restricted             (强制最严)

2.2 实际操作

# 给prod ns强制restricted标准
kubectl label ns prod \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/enforce-version=latest \
  pod-security.kubernetes.io/audit=restricted \
  pod-security.kubernetes.io/warn=restricted

# 试创建特权容器 → 被拒
kubectl run hack --image=nginx --privileged -n prod
# Error: pods "hack" is forbidden: violates PodSecurity
# "restricted:latest": privileged (container "hack") must not be set

# kube-system等系统ns用privileged(那里跑的是CNI/CSI)
kubectl label ns kube-system \
  pod-security.kubernetes.io/enforce=privileged

三、从宽松平滑迁移到Restricted

3.1 痛苦的真相

【迁移到 Restricted 常见的"拦路虎"】

  1. 镜像默认以root跑
     → 需要在Dockerfile里 USER 1000,或Pod里runAsUser

  2. 应用要绑80/443端口(需要NET_BIND_SERVICE)
     → 加capability或改成非特权端口

  3. 用了hostPath卷(日志收集常见)
     → Restricted禁止!改用emptyDir或DaemonSet专用ns放宽

  4. 没设seccompProfile
     → 加 annotation: seccomp.security.alpha.kubernetes.io/pod: runtime/default

3.2 迁移策略

# 先设 warn+audit 观察(不拦),收集违规情况
apiVersion: v1
kind: Namespace
metadata:
  name: prod
  labels:
    pod-security.kubernetes.io/warn: restricted
    pod-security.kubernetes.io/warn-version: latest
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/audit-version: latest
# 观察 kubectl get events 里有没有 PodSecurity 警告
# 没警告了,再切 enforce=restricted

# 系统组件namespace单独放宽
kubectl label ns kube-system pod-security.kubernetes.io/enforce=privileged
kubectl label ns ingress-nginx pod-security.kubernetes.io/enforce=baseline

要点:迁移到Restricted最常见的阻碍是"镜像以root跑"。解决方法是改Dockerfile加USER指令,或在Deployment里设runAsUser+runAsNonRoot: true。别想着一次性全强制——先用warn/audit模式观察一两周,确认没有误伤再切enforce。系统组件的ns(kube-system、Ingress等)需要放宽到baseline/privileged,因为它们本来就要用hostNetwork等能力。


四、和SecurityContext的关系

【PSS vs SecurityContext——"标准" vs "实现"】

  SecurityContext (第055篇):
    • 单个Pod/容器的具体降权配置
    • 是"实现手段"

  PSS/PSA (本篇):
    • 整个namespace的"强制标准"
    • 是"检查机制"——检查你的SecurityContext够不够安全

  关系:你用SecurityContext把Pod配安全,
        PSA用PSS标准检查"够不够安全",不够就拒。

本篇小结

PSS把Pod安全分成三档:Privileged(放开,只给系统组件)、Baseline(禁特权/禁host命名空间,业务推荐起点)、Restricted(强制非root+seccomp+卷白名单,高安全目标)。PSA用namespace label + enforce/audit/warn三模式强制。

迁移口诀:先warn+audit观察,再enforce强制;系统ns放宽,业务ns收紧;镜像默认root是最大拦路虎,改Dockerfile加USER解决。配合SecurityContext,这就是K8s Pod安全的完整闭环。下篇做安全审计——用CIS Benchmark和工具给你的集群"体检"。


上一篇【第57篇】Secret管理的最佳实践——原生Secret不加密?Vault/SealedSecrets来救场
下一篇【第59篇】K8s安全审计——你不能忽视的那些安全配置检查项


Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐