安全
cluster-level-pss

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

注意:本教程仅适用于新集群。

Pod 安全是一种准入控制器,当创建新的 Pod 时,它会依据 Kubernetes Pod 安全标准进行检查。该功能在 v1.25 版本中达到了稳定版本(GA)。本教程将向你展示如何在集群级别强制实施基线 Pod 安全标准,这会将标准配置应用于集群中的所有命名空间。

若要将 Pod 安全标准应用于特定的命名空间,请参考 “在命名空间级别应用 Pod 安全标准”。

如果你运行的 Kubernetes 版本不是 v1.32,请查阅对应版本的文档。

开始之前

在你的工作站上安装以下工具:

  • kind
  • kubectl

本教程将演示对于你完全可控的 Kubernetes 集群,你可以进行哪些配置。如果你正在学习如何为一个你无法配置控制平面的托管集群配置 Pod 安全准入,请阅读 “在命名空间级别应用 Pod 安全标准”。

选择合适的 Pod 安全标准进行应用

Pod 安全准入允许你使用以下模式应用内置的 Pod 安全标准:强制(enforce)、审计(audit)和警告(warn)。

为了收集有助于你选择最适合你配置的 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

使用 --dry-run=server 了解应用不同 Pod 安全标准时会发生什么

特权(Privileged)标准

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

基线(Baseline)标准

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

受限(Restricted)标准

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

从上述输出中,你会注意到应用特权 Pod 安全标准时,任何命名空间都没有警告。然而,基线和受限标准都有警告,特别是在 kube-system 命名空间中。

设置模式、版本和标准

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

  • 以强制(enforce)模式应用基线(baseline)标准。
  • 以警告(warn)和审计(audit)模式应用受限(restricted)标准。

基线 Pod 安全标准提供了一个较为合适的中间选择,它能使豁免列表保持简短,并防止已知的权限提升风险。

此外,为了避免 kube-system 命名空间中的 Pod 运行失败,你将豁免该命名空间,使其不应用 Pod 安全标准。

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

根据应用于集群的风险态势,像受限这样更严格的 Pod 安全标准可能是更好的选择。

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

为了实现上述标准,请执行以下操作:

创建一个可被 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

注意:pod-security.admission.config.k8s.io/v1 配置要求 Kubernetes 版本为 v1.25 及以上。对于 v1.23 和 v1.24 版本,使用 v1beta1。对于 v1.22 版本,使用 v1alpha1。

配置 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.io/docs/concepts/storage/volumes/#mount-propagation
    # default None
    propagation: None
EOF

注意:如果你在 macOS 上使用 Docker Desktop 搭配 kind,你可以在菜单项 “Preferences> Resources > File Sharing” 下将 /tmp 添加为共享目录。

创建一个使用 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.sigs.k8s.io/#community 🙂

将 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'.

在默认命名空间中创建一个 Pod

# security/example-baseline-pod.yaml
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

上述两条命令分别删除了名为 psa-with-cluster-pss 和 psa-wo-cluster-pss 的集群。

kind delete cluster 命令用于删除由 kind 工具创建的 Kubernetes 集群,通过指定 --name 参数来明确要删除的集群名称。

执行这些命令后,相应集群的所有资源(包括节点、Pod、服务等)都会被移除,从而释放相关的计算资源和存储空间,使得环境恢复到创建集群之前的状态。