| name | implementing-pod-security-admission-controller |
| description | 使用内置准入控制器在命名空间级别实施 Kubernetes Pod Security Admission(Pod 安全准入),强制执行基线和受限安全配置文件。 |
| domain | cybersecurity |
| subdomain | container-security |
| tags | ["kubernetes","pod-security-admission","psa","pod-security-standards","admission-controller"] |
| version | 1.0 |
| author | mahipal |
| license | Apache-2.0 |
实施 Pod Security Admission 控制器
概述
Pod Security Admission(PSA,Pod 安全准入)是 Kubernetes 内置的准入控制器(v1.25 起稳定版),在命名空间级别强制执行 Pod 安全标准(Pod Security Standards)。它替代了已弃用的 PodSecurityPolicy(PSP),提供三种安全配置文件:Privileged(特权)、Baseline(基线)和 Restricted(受限),以及三种强制模式:enforce(强制)、audit(审计)和 warn(警告)。
前置条件
- Kubernetes v1.25+(PSA 为稳定/GA 版)
- 具有 cluster-admin 权限的 kubectl
- 无需依赖外部工具 - PSA 内置于 kube-apiserver
Pod 安全标准
Privileged(特权)配置文件
- 无限制 - 不施加任何限制
- 用例:系统级 Pod(kube-system、监控)
Baseline(基线)配置文件
- 最低限制 - 防止已知权限提升
- 阻止:特权容器、hostPID、hostIPC、hostNetwork、hostPorts、某些卷类型、超出运行时默认值的能力添加
Restricted(受限)配置文件
- 严格限制 - 遵循安全最佳实践
- 要求:非 root 运行、放弃所有能力、seccomp RuntimeDefault、考虑只读根文件系统
- 阻止:基线配置文件中的一切,加上 root 运行、权限提升、非批准的卷类型
强制模式
| 模式 | 行为 | 用例 |
|---|
| enforce | 拒绝违反策略的 Pod | 生产强制执行 |
| audit | 将违规记录到审计日志 | 强制执行前评估 |
| warn | 向用户显示警告 | 开发者反馈 |
实施
通过 Label 应用到命名空间
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: v1.28
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/audit-version: v1.28
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/warn-version: v1.28
apiVersion: v1
kind: Namespace
metadata:
name: staging
labels:
pod-security.kubernetes.io/enforce: baseline
pod-security.kubernetes.io/enforce-version: v1.28
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/audit-version: v1.28
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/warn-version: v1.28
apiVersion: v1
kind: Namespace
metadata:
name: kube-system
labels:
pod-security.kubernetes.io/enforce: privileged
使用 kubectl 应用 Label
kubectl label namespace production \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/enforce-version=v1.28 \
pod-security.kubernetes.io/audit=restricted \
pod-security.kubernetes.io/warn=restricted
kubectl label namespace staging \
pod-security.kubernetes.io/enforce=baseline \
pod-security.kubernetes.io/audit=restricted \
pod-security.kubernetes.io/warn=restricted
kubectl get namespace production -o jsonpath='{.metadata.labels}' | jq .
演练测试
kubectl label --dry-run=server --overwrite namespace staging \
pod-security.kubernetes.io/enforce=restricted
集群范围默认值(AdmissionConfiguration)
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: PodSecurity
configuration:
apiVersion: pod-security.admission.config.k8s.io/v1
kind: PodSecurityConfiguration
defaults:
enforce: baseline
enforce-version: latest
audit: restricted
audit-version: latest
warn: restricted
warn-version: latest
exemptions:
usernames: []
runtimeClasses: []
namespaces:
- kube-system
- kube-public
- kube-node-lease
- calico-system
- gatekeeper-system
- monitoring
- falco
应用到 API Server
spec:
containers:
- command:
- kube-apiserver
- --admission-control-config-file=/etc/kubernetes/psa-config.yaml
volumeMounts:
- name: psa-config
mountPath: /etc/kubernetes/psa-config.yaml
readOnly: true
volumes:
- name: psa-config
hostPath:
path: /etc/kubernetes/psa-config.yaml
type: File
合规 Pod 示例
符合 Restricted 要求的 Pod
apiVersion: v1
kind: Pod
metadata:
name: restricted-pod
namespace: production
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
seccompProfile:
type: RuntimeDefault
automountServiceAccountToken: false
containers:
- name: app
image: myregistry/myapp:v1.0.0
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
resources:
limits:
cpu: 500m
memory: 256Mi
requests:
cpu: 100m
memory: 128Mi
volumeMounts:
- name: tmp
{}
符合 Baseline 要求的 Pod
apiVersion: v1
kind: Pod
metadata:
name: baseline-pod
namespace: staging
spec:
containers:
- name: app
image: myregistry/myapp:v1.0.0
securityContext:
allowPrivilegeEscalation: false
resources:
limits:
cpu: 500m
memory: 256Mi
从 PodSecurityPolicy 迁移
步骤 1:审计当前状态
kubectl get psp
kubectl get clusterrolebinding -o json | \
jq '.items[] | select(.roleRef.name | startswith("psp-")) | {name: .metadata.name, subjects: .subjects}'
步骤 2:将 PSP 映射到 PSA 配置文件
for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
echo "命名空间:$ns"
kubectl label --dry-run=server namespace $ns \
pod-security.kubernetes.io/enforce=restricted 2>&1 | head -5
done
步骤 3:应用 PSA Label(先审计)
kubectl label namespace production \
pod-security.kubernetes.io/audit=restricted \
pod-security.kubernetes.io/warn=restricted
步骤 4:审查并修复违规
kubectl get events --field-selector reason=FailedCreate -A
步骤 5:启用强制执行
kubectl label namespace production \
pod-security.kubernetes.io/enforce=restricted
监控
kubectl get events --all-namespaces --field-selector reason=FailedCreate
kubectl logs -n kube-system kube-apiserver-* | grep "pod-security.kubernetes.io"
kubectl get namespaces -L pod-security.kubernetes.io/enforce
最佳实践
- 先用审计+警告,在强制执行前评估影响
- 使用演练测试,应用前测试强制执行效果
- 豁免系统命名空间(kube-system、监控),在集群默认值中排除
- 固定版本(enforce-version),确保跨升级的可预测行为
- 将集群范围基线设为默认值,然后针对特定命名空间收紧
- 与 Gatekeeper 结合,实现 PSA 之外的额外自定义策略
- 所有生产工作负载使用受限配置文件
- 记录豁免并附清晰理由