界面已本地化;技能介绍与说明文档按所选语言由 AI 自动翻译,代码、命令、路径和专业术语保留原文,以原作者文档为准。
探索技能
部署与运维 · SKILL.md

implementing-pod-security-admission-controller

implementing-pod-security-admission-controller

【部署与运维】使用内置准入控制器在命名空间级别实施 Kubernetes Pod Security Admission(Pod 安全准入),强制执行基线和受限安全配置文件。

独立 GitHub 快照 · 自动分类 · 以原作者文档为准

技能说明

GitHub

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
# staging 使用基线强制执行
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

# 检查当前 label
kubectl get namespace production -o jsonpath='{.metadata.labels}' | jq .

演练测试

# 测试在命名空间上应用受限策略的效果
kubectl label --dry-run=server --overwrite namespace staging \
  pod-security.kubernetes.io/enforce=restricted

# 输出显示已有哪些 Pod 会违反该策略
# 警告:命名空间 "staging" 中的现有 Pod 违反了新的 PodSecurity enforce 级别 "restricted:latest"

集群范围默认值(AdmissionConfiguration)

# /etc/kubernetes/psa-config.yaml
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

# 添加到 kube-apiserver 清单
# /etc/kubernetes/manifests/kube-apiserver.yaml
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
          mountPath: /tmp
  volumes:
    - name: tmp
      emptyDir: {}

符合 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:审计当前状态

# 检查现有 PSP
kubectl get psp

# 检查哪些 ServiceAccount 使用了哪个 PSP
kubectl get clusterrolebinding -o json | \
  jq '.items[] | select(.roleRef.name | startswith("psp-")) | {name: .metadata.name, subjects: .subjects}'

步骤 2:将 PSP 映射到 PSA 配置文件

# 对每个命名空间确定所需的 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

监控

# 检查事件中的 PSA 违规
kubectl get events --all-namespaces --field-selector reason=FailedCreate

# 检查审计日志
kubectl logs -n kube-system kube-apiserver-* | grep "pod-security.kubernetes.io"

# 列出命名空间的 PSA label
kubectl get namespaces -L pod-security.kubernetes.io/enforce

最佳实践

  1. 先用审计+警告,在强制执行前评估影响
  2. 使用演练测试,应用前测试强制执行效果
  3. 豁免系统命名空间(kube-system、监控),在集群默认值中排除
  4. 固定版本(enforce-version),确保跨升级的可预测行为
  5. 将集群范围基线设为默认值,然后针对特定命名空间收紧
  6. 与 Gatekeeper 结合,实现 PSA 之外的额外自定义策略
  7. 所有生产工作负载使用受限配置文件
  8. 记录豁免并附清晰理由
我的收藏