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

Note

本教程仅适用于新集群。

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

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

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

准备开始

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

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

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

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

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

    1. kind create cluster --name psa-wo-cluster-pss --image kindest/node:v1.24.0

    输出类似于:

    1. Creating cluster "psa-wo-cluster-pss" ...
    2. Ensuring node image (kindest/node:v1.24.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
  4. 使用 --dry-run=server 来了解应用不同的 Pod 安全标准时会发生什么:

    1. Privileged

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

      输出类似于:

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

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

    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,使用 v1beta1。 对于 v1.22,使用 v1alpha1

  4. 在创建集群时配置 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. - name: accf
    14. hostPath: /etc/config
    15. mountPath: /etc/config
    16. readOnly: false
    17. pathType: "DirectoryOrCreate"
    18. extraMounts:
    19. - hostPath: /tmp/pss
    20. containerPath: /etc/config
    21. # optional: if set, the mount is read-only.
    22. # default false
    23. readOnly: false
    24. # optional: if set, the mount needs SELinux relabeling.
    25. # default false
    26. selinuxRelabel: false
    27. # optional: set propagation mode (None, HostToContainer or Bidirectional)
    28. # see https://kubernetes.io/docs/concepts/storage/volumes/#mount-propagation
    29. # default None
    30. propagation: None
    31. EOF

    说明:

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

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

    1. kind create cluster --name psa-with-cluster-pss --image kindest/node:v1.24.0 --config /tmp/pss/cluster-config.yaml

    输出类似于:

    1. Creating cluster "psa-with-cluster-pss" ...
    2. Ensuring node image (kindest/node:v1.24.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 🙂
  6. 将 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'.
  7. 创建以下 Pod 规约作为在 default 名字空间中的一个最小配置:

    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
  8. 在集群中创建 Pod:

    1. kubectl apply -f /tmp/pss/nginx-pod.yaml

    输出类似于:

    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

清理

运行 kind delete cluster --name psa-with-cluster-psskind delete cluster --name psa-wo-cluster-pss 来删除你创建的集群。

接下来

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