在集群级别应用 Pod 安全标准

Pod 安全是一个准入控制器,当创建新的 Pod 时,它会针对 Kubernetes Pod 安全标准执行检查。它是 v1.25 中 GA 的一项功能。本教程将向您展示如何在集群级别强制执行 baseline Pod 安全标准,该标准将标准配置应用于集群中的所有命名空间。

要将 Pod 安全标准应用于特定的命名空间,请参阅在命名空间级别应用 Pod 安全标准

如果您运行的是 v1.32 以外的 Kubernetes 版本,请查看该版本的文档。

开始之前

在您的工作站上安装以下内容

本教程演示了您可以为完全控制的 Kubernetes 集群配置的内容。如果您正在学习如何为无法配置控制平面的托管集群配置 Pod 安全准入,请阅读在命名空间级别应用 Pod 安全标准

选择要应用的正确的 Pod 安全标准

Pod 安全准入允许您应用内置的 Pod 安全标准,并具有以下模式:enforceauditwarn

要收集有助于您选择最适合您配置的 Pod 安全标准的信息,请执行以下操作

  1. 创建一个未应用任何 Pod 安全标准的集群

    kind create cluster --name psa-wo-cluster-pss
    

    输出类似于

    Creating cluster "psa-wo-cluster-pss" ...
    ✓ Ensuring node image (kindest/node:v1.32.0) 🖼
    ✓ Preparing nodes 📦
    ✓ Writing configuration 📜
    ✓ Starting control-plane 🕹️
    ✓ Installing CNI 🔌
    ✓ Installing StorageClass 💾
    Set kubectl context to "kind-psa-wo-cluster-pss"
    You can now use your cluster with:
    
    kubectl cluster-info --context kind-psa-wo-cluster-pss
    
    Thanks for using kind! 😊
    
  2. 将 kubectl 上下文设置为新集群

    kubectl cluster-info --context kind-psa-wo-cluster-pss
    

    输出类似于此

    Kubernetes control plane is running at https://127.0.0.1:61350
    
    CoreDNS is running at https://127.0.0.1:61350/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
    
    To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
    
  3. 获取集群中命名空间的列表

    kubectl get ns
    

    输出类似于此

    NAME                 STATUS   AGE
    default              Active   9m30s
    kube-node-lease      Active   9m32s
    kube-public          Active   9m32s
    kube-system          Active   9m32s
    local-path-storage   Active   9m26s
    
  4. 使用 --dry-run=server 来了解应用不同 Pod 安全标准时会发生什么

    1. 特权

      kubectl label --dry-run=server --overwrite ns --all \
      pod-security.kubernetes.io/enforce=privileged
      

      输出类似于

      namespace/default labeled
      namespace/kube-node-lease labeled
      namespace/kube-public labeled
      namespace/kube-system labeled
      namespace/local-path-storage labeled
      
    2. 基线

      kubectl label --dry-run=server --overwrite ns --all \
      pod-security.kubernetes.io/enforce=baseline
      

      输出类似于

      namespace/default labeled
      namespace/kube-node-lease labeled
      namespace/kube-public labeled
      Warning: existing pods in namespace "kube-system" violate the new PodSecurity enforce level "baseline:latest"
      Warning: etcd-psa-wo-cluster-pss-control-plane (and 3 other pods): host namespaces, hostPath volumes
      Warning: kindnet-vzj42: non-default capabilities, host namespaces, hostPath volumes
      Warning: kube-proxy-m6hwf: host namespaces, hostPath volumes, privileged
      namespace/kube-system labeled
      namespace/local-path-storage labeled
      
    3. 受限

      kubectl label --dry-run=server --overwrite ns --all \
      pod-security.kubernetes.io/enforce=restricted
      

      输出类似于

      namespace/default labeled
      namespace/kube-node-lease labeled
      namespace/kube-public labeled
      Warning: existing pods in namespace "kube-system" violate the new PodSecurity enforce level "restricted:latest"
      Warning: coredns-7bb9c7b568-hsptc (and 1 other pod): unrestricted capabilities, runAsNonRoot != true, seccompProfile
      Warning: etcd-psa-wo-cluster-pss-control-plane (and 3 other pods): host namespaces, hostPath volumes, allowPrivilegeEscalation != false, unrestricted capabilities, restricted volume types, runAsNonRoot != true
      Warning: kindnet-vzj42: non-default capabilities, host namespaces, hostPath volumes, allowPrivilegeEscalation != false, unrestricted capabilities, restricted volume types, runAsNonRoot != true, seccompProfile
      Warning: kube-proxy-m6hwf: host namespaces, hostPath volumes, privileged, allowPrivilegeEscalation != false, unrestricted capabilities, restricted volume types, runAsNonRoot != true, seccompProfile
      namespace/kube-system labeled
      Warning: existing pods in namespace "local-path-storage" violate the new PodSecurity enforce level "restricted:latest"
      Warning: local-path-provisioner-d6d9f7ffc-lw9lh: allowPrivilegeEscalation != false, unrestricted capabilities, runAsNonRoot != true, seccompProfile
      namespace/local-path-storage labeled
      

从之前的输出中,您会注意到应用 privileged Pod 安全标准不会显示任何命名空间的警告。但是,baselinerestricted 标准都有警告,尤其是在 kube-system 命名空间中。

设置模式、版本和标准

在本节中,您将以下 Pod 安全标准应用于 latest 版本

  • baseline 标准在 enforce 模式下。
  • restricted 标准在 warnaudit 模式下。

baseline Pod 安全标准提供了一个方便的中间地带,允许保持豁免列表简短并防止已知的权限提升。

此外,为了防止 pod 在 kube-system 中失败,您将免除该命名空间应用 Pod 安全标准。

当您在自己的环境中实施 Pod 安全准入时,请考虑以下事项

  1. 根据应用于集群的风险态势,更严格的 Pod 安全标准(如 restricted)可能是一个更好的选择。

  2. 免除 kube-system 命名空间允许 pod 在此命名空间中以 privileged 运行。对于实际使用,Kubernetes 项目强烈建议您应用严格的 RBAC 策略,限制对 kube-system 的访问,遵循最小权限原则。要实现上述标准,请执行以下操作

  3. 创建一个配置文件,该文件可由 Pod 安全准入控制器使用,以实现这些 Pod 安全标准

    mkdir -p /tmp/pss
    cat <<EOF > /tmp/pss/cluster-level-pss.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]
    EOF
    
  4. 配置 API 服务器以在集群创建期间使用此文件

    cat <<EOF > /tmp/pss/cluster-config.yaml
    kind: Cluster
    apiVersion: kind.x-k8s.io/v1alpha4
    nodes:
    - role: control-plane
      kubeadmConfigPatches:
      - |
        kind: ClusterConfiguration
        apiServer:
            extraArgs:
              admission-control-config-file: /etc/config/cluster-level-pss.yaml
            extraVolumes:
              - name: accf
                hostPath: /etc/config
                mountPath: /etc/config
                readOnly: false
                pathType: "DirectoryOrCreate"
      extraMounts:
      - hostPath: /tmp/pss
        containerPath: /etc/config
        # optional: if set, the mount is read-only.
        # default false
        readOnly: false
        # optional: if set, the mount needs SELinux relabeling.
        # default false
        selinuxRelabel: false
        # optional: set propagation mode (None, HostToContainer or Bidirectional)
        # see https://kubernetes.ac.cn/docs/concepts/storage/volumes/#mount-propagation
        # default None
        propagation: None
    EOF
    
  5. 创建一个使用 Pod 安全准入来应用这些 Pod 安全标准的集群

    kind create cluster --name psa-with-cluster-pss --config /tmp/pss/cluster-config.yaml
    

    输出类似于此

    Creating cluster "psa-with-cluster-pss" ...
     ✓ Ensuring node image (kindest/node:v1.32.0) 🖼
     ✓ Preparing nodes 📦
     ✓ Writing configuration 📜
     ✓ Starting control-plane 🕹️
     ✓ Installing CNI 🔌
     ✓ Installing StorageClass 💾
    Set kubectl context to "kind-psa-with-cluster-pss"
    You can now use your cluster with:
    
    kubectl cluster-info --context kind-psa-with-cluster-pss
    
    Have a question, bug, or feature request? Let us know! https://kind.kubernetes.ac.cn/#community 🙂
    
  6. 将 kubectl 指向集群

    kubectl cluster-info --context kind-psa-with-cluster-pss
    

    输出类似于此

    Kubernetes control plane is running at https://127.0.0.1:63855
    CoreDNS is running at https://127.0.0.1:63855/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
    
    To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
    
  7. 在默认命名空间中创建一个 Pod

    apiVersion: v1
     kind: Pod
     metadata:
       name: nginx
     spec:
       containers:
         - image: nginx
           name: nginx
           ports:
             - containerPort: 80
     
    kubectl apply -f https://k8s.io/examples/security/example-baseline-pod.yaml
    

    Pod 正常启动,但输出中包含警告

    Warning: would violate PodSecurity "restricted:latest": allowPrivilegeEscalation != false (container "nginx" must set securityContext.allowPrivilegeEscalation=false), unrestricted capabilities (container "nginx" must set securityContext.capabilities.drop=["ALL"]), runAsNonRoot != true (pod or container "nginx" must set securityContext.runAsNonRoot=true), seccompProfile (pod or container "nginx" must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")
    pod/nginx created
    

清理

现在运行以下命令删除您上面创建的集群

kind delete cluster --name psa-with-cluster-pss
kind delete cluster --name psa-wo-cluster-pss

下一步

上次修改时间:2023 年 11 月 30 日,太平洋标准时间凌晨 1:22:[en] 更新 cluster-level-pss.md,展示用户将应用的代码示例 (310a1221ac)