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

Note

Pod 安全准入(PSA)在 v1.23 及更高版本默认启用, 因为它已进阶为 Beta。 Pod 安全准入是在创建 Pod 时应用 的准入控制器。 本教程将向你展示如何在集群级别实施 Pod 安全标准, 该标准将标准配置应用于集群中的所有名字空间。

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

如果你正在运行 v1.27 以外的 Kubernetes 版本, 请查阅该版本的文档。

在你的工作站中安装以下内容:

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

Pod 安全准入 允许你使用以下模式应用内置的 : enforceauditwarn

要收集信息以便选择最适合你的配置的 Pod 安全标准,请执行以下操作:

  1. 创建一个没有应用 Pod 安全标准的集群:

    输出类似于:

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

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

    输出类似于:

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

    1. kubectl get ns

    输出类似于:

    1. NAME STATUS AGE
    2. default Active 9m30s
    3. kube-node-lease Active 9m32s
    4. kube-public Active 9m32s
    5. kube-system Active 9m32s
    6. local-path-storage Active 9m26s
    1. Privileged

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

      输出类似于:

    2. Baseline

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

      输出类似于:

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

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

      输出类似于:

      1. namespace/default labeled
      2. namespace/kube-public labeled
      3. Warning: existing pods in namespace "kube-system" violate the new PodSecurity enforce level "restricted:latest"
      4. Warning: coredns-7bb9c7b568-hsptc (and 1 other pod): unrestricted capabilities, runAsNonRoot != true, seccompProfile
      5. 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
      6. Warning: kindnet-vzj42: non-default capabilities, host namespaces, hostPath volumes, allowPrivilegeEscalation != false, unrestricted capabilities, restricted volume types, runAsNonRoot != true, seccompProfile
      7. Warning: kube-proxy-m6hwf: host namespaces, hostPath volumes, privileged, allowPrivilegeEscalation != false, unrestricted capabilities, restricted volume types, runAsNonRoot != true, seccompProfile
      8. Warning: existing pods in namespace "local-path-storage" violate the new PodSecurity enforce level "restricted:latest"
      9. Warning: local-path-provisioner-d6d9f7ffc-lw9lh: allowPrivilegeEscalation != false, unrestricted capabilities, runAsNonRoot != true, seccompProfile
      10. namespace/local-path-storage labeled

从前面的输出中,你会注意到应用 privileged Pod 安全标准不会显示任何名字空间的警告。 然而,baselinerestricted 标准都有警告,特别是在 kube-system 名字空间中。

在本节中,你将以下 Pod 安全标准应用于最新(latest)版本:

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

baseline Pod 安全标准提供了一个方便的中间立场,能够保持豁免列表简短并防止已知的特权升级。

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

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

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

  2. kube-system 名字空间进行赦免会允许 Pod 在其中以 privileged 模式运行。 对于实际使用,Kubernetes 项目强烈建议你应用严格的 RBAC 策略来限制对 kube-system 的访问, 遵循最小特权原则。

    1. mkdir -p /tmp/pss
    2. cat <<EOF > /tmp/pss/cluster-level-pss.yaml
    3. apiVersion: apiserver.config.k8s.io/v1
    4. kind: AdmissionConfiguration
    5. plugins:
    6. - name: PodSecurity
    7. configuration:
    8. apiVersion: pod-security.admission.config.k8s.io/v1
    9. kind: PodSecurityConfiguration
    10. defaults:
    11. enforce: "baseline"
    12. enforce-version: "latest"
    13. audit: "restricted"
    14. audit-version: "latest"
    15. warn: "restricted"
    16. warn-version: "latest"
    17. exemptions:
    18. usernames: []
    19. runtimeClasses: []
    20. namespaces: [kube-system]
    21. EOF

    说明:

    pod-security.admission.config.k8s.io/v1 配置需要 v1.25+。 对于 v1.23 和 v1.24,使用 。 对于 v1.22,使用 v1alpha1

  3. 在创建集群时配置 API 服务器使用此文件:

    1. cat <<EOF > /tmp/pss/cluster-config.yaml
    2. kind: Cluster
    3. apiVersion: kind.x-k8s.io/v1alpha4
    4. nodes:
    5. - role: control-plane
    6. kubeadmConfigPatches:
    7. - |
    8. kind: ClusterConfiguration
    9. apiServer:
    10. extraArgs:
    11. admission-control-config-file: /etc/config/cluster-level-pss.yaml
    12. extraVolumes:
    13. hostPath: /etc/config
    14. mountPath: /etc/config
    15. readOnly: false
    16. pathType: "DirectoryOrCreate"
    17. extraMounts:
    18. - hostPath: /tmp/pss
    19. containerPath: /etc/config
    20. # default false
    21. readOnly: false
    22. # optional: if set, the mount needs SELinux relabeling.
    23. # default false
    24. selinuxRelabel: false
    25. # optional: set propagation mode (None, HostToContainer or Bidirectional)
    26. # see https://kubernetes.io/docs/concepts/storage/volumes/#mount-propagation
    27. # default None
    28. propagation: None
    29. EOF

    说明:

    如果你在 macOS 上使用 Docker Desktop 和 KinD, 你可以在菜单项 Preferences > Resources > File Sharing 下添加 /tmp 作为共享目录。

  4. 创建一个使用 Pod 安全准入的集群来应用这些 Pod 安全标准:

    输出类似于:

    1. Creating cluster "psa-with-cluster-pss" ...
    2. Ensuring node image (kindest/node:v1.27.0) 🖼
    3. Preparing nodes 📦
    4. Writing configuration 📜
    5. Starting control-plane 🕹️
    6. Installing CNI 🔌
    7. Installing StorageClass 💾
    8. Set kubectl context to "kind-psa-with-cluster-pss"
    9. You can now use your cluster with:
    10. kubectl cluster-info --context kind-psa-with-cluster-pss
    11. Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community 🙂
  5. 将 kubectl 指向集群

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

    输出类似于:

    1. Kubernetes control plane is running at https://127.0.0.1:63855
    2. CoreDNS is running at https://127.0.0.1:63855/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
    3. To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
  6. 在 default 名字空间下创建一个 Pod:

    1. cat <<EOF > /tmp/pss/nginx-pod.yaml
    2. apiVersion: v1
    3. kind: Pod
    4. metadata:
    5. name: nginx
    6. spec:
    7. containers:
    8. - image: nginx
    9. name: nginx
    10. ports:
    11. - containerPort: 80
    12. EOF
  7. 在集群中创建 Pod:

    1. kubectl apply -f https://k8s.io/examples/security/example-baseline-pod.yaml

    这个 Pod 正常启动,但输出包含警告:

    1. 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")
    2. pod/nginx created

现在通过运行以下命令删除你上面创建的集群:

  1. kind delete cluster --name psa-wo-cluster-pss
  • 运行一个 一次执行前面的所有步骤:
    1. 创建一个基于 Pod 安全标准的集群级别配置
    2. 创建一个文件让 API 服务器消费这个配置
    3. 创建一个集群,用这个配置创建一个 API 服务器
    4. 设置 kubectl 上下文为这个新集群
    5. 创建一个最小的 Pod yaml 文件
    6. 应用这个文件,在新集群中创建一个 Pod
  • Pod 安全准入