实施 Kubernetes Pod 安全标准
概述
Pod 安全标准(PSS)定义了三个安全策略级别——特权级(Privileged)、基线级(Baseline)和受限级(Restricted)——由 Kubernetes 1.25+ 内置的 Pod 安全准入(PSA)控制器强制执行。PSA 取代了已废弃的 PodSecurityPolicy,提供命名空间级别的强制执行,支持三种模式:enforce(强制)、audit(审计)和 warn(警告)。
前提条件
- Kubernetes 集群 1.25+(PSA GA 版本)
- 已配置集群管理员访问权限的 kubectl
- 了解 Linux 能力和安全上下文
核心概念
三个安全配置文件
| 配置文件 |
用途 |
限制 |
| Privileged(特权级) |
不受限制,用于系统工作负载 |
无 |
| Baseline(基线级) |
防止已知提权 |
禁止 hostNetwork、hostPID、hostIPC、特权容器、危险能力 |
| Restricted(受限级) |
强化的最佳实践 |
非 root、丢弃所有能力、需要 seccomp、建议只读 rootfs |
三种强制执行模式
| 模式 |
行为 |
| enforce(强制) |
拒绝违反策略的 Pod |
| audit(审计) |
在审计日志中记录违规但允许 Pod 创建 |
| warn(警告) |
向用户返回警告但允许 Pod 创建 |
实施步骤
步骤 1:为命名空间打 PSA 标签
# 受限命名空间 - 生产工作负载
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/audit-version: latest
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/warn-version: latest
# 基线命名空间 - 通用工作负载
apiVersion: v1
kind: Namespace
metadata:
name: staging
labels:
pod-security.kubernetes.io/enforce: baseline
pod-security.kubernetes.io/enforce-version: latest
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/audit-version: latest
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/warn-version: latest
# 特权命名空间 - 仅限系统组件
apiVersion: v1
kind: Namespace
metadata:
name: kube-system
labels:
pod-security.kubernetes.io/enforce: privileged
pod-security.kubernetes.io/enforce-version: latest
步骤 2:对现有命名空间应用标签
# 对生产环境应用受限强制执行
kubectl label namespace production \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/audit=restricted \
pod-security.kubernetes.io/warn=restricted \
--overwrite
# 对预发布环境应用基线级别,带受限级别警告
kubectl label namespace staging \
pod-security.kubernetes.io/enforce=baseline \
pod-security.kubernetes.io/audit=restricted \
pod-security.kubernetes.io/warn=restricted \
--overwrite
# 检查所有命名空间的标签
kubectl get namespaces -L pod-security.kubernetes.io/enforce
步骤 3:创建符合要求的 Pod 规格
# 符合受限级别要求的 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: secure-app
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: secure-app
template:
metadata:
labels:
app: secure-app
spec:
automountServiceAccountToken: false
securityContext:
runAsNonRoot: true
runAsUser: 65534
runAsGroup: 65534
fsGroup: 65534
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: myregistry.com/myapp:v1.0.0@sha256:abc123
ports:
- containerPort: 8080
protocol: TCP
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
runAsNonRoot: true
runAsUser: 65534
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "500m"
volumeMounts:
- name: tmp
mountPath: /tmp
- name: cache
mountPath: /var/cache
volumes:
- name: tmp
emptyDir:
sizeLimit: 100Mi
- name: cache
emptyDir:
sizeLimit: 50Mi
步骤 4:渐进式迁移策略
# 阶段 1:审计模式 - 发现违规而不阻断
kubectl label namespace my-namespace \
pod-security.kubernetes.io/audit=restricted \
pod-security.kubernetes.io/warn=restricted
# 检查审计日志中的违规
kubectl logs -n kube-system -l component=kube-apiserver | grep "pod-security"
# 阶段 2:强制基线级别,对受限级别发出警告
kubectl label namespace my-namespace \
pod-security.kubernetes.io/enforce=baseline \
pod-security.kubernetes.io/warn=restricted \
--overwrite
# 阶段 3:完全受限级别强制执行
kubectl label namespace my-namespace \
pod-security.kubernetes.io/enforce=restricted \
--overwrite
步骤 5:试运行强制执行测试
# 测试应用受限级别后会发生什么
kubectl label --dry-run=server --overwrite namespace my-namespace \
pod-security.kubernetes.io/enforce=restricted
# 示例输出:
# Warning: existing pods in namespace "my-namespace" violate the new
# PodSecurity enforce level "restricted:latest"
# Warning: nginx-xxx: allowPrivilegeEscalation != false,
# unrestricted capabilities, runAsNonRoot != true, seccompProfile
基线配置文件限制
| 控制项 |
受限要求 |
要求说明 |
| HostProcess |
不得设置 |
Pod 不能使用 Windows HostProcess |
| 主机命名空间 |
不得设置 |
禁止 hostNetwork、hostPID、hostIPC |
| 特权 |
不得设置 |
禁止 privileged: true |
| 能力 |
仅基线列表 |
仅允许 NET_BIND_SERVICE,受限级别需丢弃 ALL |
| HostPath 卷 |
不得使用 |
禁止 hostPath 卷挂载 |
| 主机端口 |
不得使用 |
容器规格中禁止 hostPort |
| AppArmor |
默认/运行时 |
不能设置为 unconfined |
| SELinux |
受限类型 |
仅允许 container_t、container_init_t、container_kvm_t |
| /proc 挂载类型 |
仅默认 |
必须使用默认 proc 挂载 |
| Seccomp |
RuntimeDefault 或 Localhost |
受限级别必须指定 seccomp 配置文件 |
| Sysctls |
仅安全集合 |
仅限安全的 sysctls |
验证命令
# 验证命名空间标签
kubectl get ns --show-labels | grep pod-security
# 测试针对策略的 Pod 创建
kubectl run test-pod --image=nginx --namespace=production --dry-run=server
# 检查审计日志中的违规
kubectl get events --field-selector reason=FailedCreate -A
# 使用 Kubescape 扫描 PSS 合规性
kubescape scan framework nsa --namespace production
参考资料