使用 PodSecurity 以应用预定义的 Pod 级层安全政策


本页面介绍如何使用 PodSecurity 准入控制器在 Google Kubernetes Engine (GKE) 集群中应用预定义的 Pod 级层安全控制机制。

如需详细了解 PodSecurity 的工作原理,请参阅 Pod 安全准入

概览

PodSecurity 是一个 Kubernetes 准入控制器,允许您向 GKE 集群上运行的 Pod 应用 Pod 安全标准。Pod 安全标准是预定义的安全政策,涵盖 Kubernetes 中 Pod 安全性的高层次需求。这些政策的范围各有不同,从高度宽松到高度严格。

您可以将以下 Pod 安全标准应用于您的 GKE 集群:

  • 特权:不受限制的政策,提供最宽泛的权限。允许已知的提权。
  • 基准:具有最低限制性的政策,这是默认指定的最低限度的 Pod 配置。禁止已知的提权。
  • 受限:遵循 Pod 安全强化最佳做法的严格受限政策。

您可以使用 PodSecurity 准入控制器按以下模式应用 Pod 安全标准:

  • 强制执行:如违反政策,则拒绝 Pod 创建。系统会在审核日志中添加审核事件。
  • 审核:政策违规会触发在审核日志中添加审核事件。允许创建 Pod。
  • 警告:政策违规会触发面向用户的警告。允许创建 Pod。

PodSecurity 准入控制器会将这些政策嵌入到 Kubernetes API 之中。

如果要在 Pod 级层创建和应用自定义安全政策,请考虑改用 Gatekeeper 准入控制器。

准备工作

在开始之前,请确保您已执行以下任务:

  • 启用 Google Kubernetes Engine API。
  • 启用 Google Kubernetes Engine API
  • 如果您要使用 Google Cloud CLI 执行此任务,请安装初始化 gcloud CLI。 如果您之前安装了 gcloud CLI,请运行 gcloud components update 以获取最新版本。

使用要求

默认情况下,运行以下 GKE 版本的集群上提供并启用 PodSecurity 准入控制器:

  • 1.25 版或更高版本:稳定版
  • 1.23 版和 1.24 版:Beta 版

如需检查 GKE 版本是否可用以及是否为发布渠道的默认版本,请参阅发布时间表

使用 PodSecurity 应用 Pod 安全标准

要使用 PodSecurity 准入控制器,必须在特定模式下将特定 Pod 安全标准应用于特定命名空间。为此,您可以使用命名空间标签来。在本练习中,您将执行以下任务:

  • 创建两个新的命名空间
  • 为各命名空间应用安全政策
  • 对已配置的政策进行测试

在以下 GKE 版本中,GKE 会忽略您应用于 kube-system 命名空间的政策:

  • 1.23.6-gke.1900 及更高版本
  • 1.24.0-gke.1200 及更高版本

在早期的 GKE 版本中,请避免在 kube-system 中强制执行政策。

创建新的命名空间

在集群中创建命名空间:

kubectl create ns baseline-ns
kubectl create ns restricted-ns

此命令会创建以下命名空间:

  • baseline-ns:适用于宽容型工作负载
  • restricted-ns:适用于限制性极强的工作负载

使用标签应用安全政策

应用以下 Pod 安全标准:

  • baseline:在 warn 模式下应用于 baseline-ns
  • restricted:在 enforce 模式下应用于 restricted-ns
kubectl label --overwrite ns baseline-ns pod-security.kubernetes.io/warn=baseline
kubectl label --overwrite ns restricted-ns pod-security.kubernetes.io/enforce=restricted

这些命令可实现以下结果:

  • 允许 baseline-ns 命名空间中违反 baseline 政策的工作负载,并且客户端会显示警告消息。
  • 拒绝 restricted-ns 命名空间中违反 restricted 政策的工作负载,并且 GKE 会在审核日志中添加条目。

确认是否已添加标签:

kubectl get ns --show-labels

输出类似于以下内容:

baseline-ns       Active   74s   kubernetes.io/metadata.name=baseline-ns,pod-security.kubernetes.io/warn=baseline
restricted-ns     Active   18s   kubernetes.io/metadata.name=restricted-ns,pod-security.kubernetes.io/enforce=restricted
default           Active   57m   kubernetes.io/metadata.name=default
kube-public       Active   57m   kubernetes.io/metadata.name=kube-public
kube-system       Active   57m   kubernetes.io/metadata.name=kube-system

对已配置的政策进行测试

为了验证 PodSecurity 准入控制器是否按预期工作,将违反 baselinerestricted 政策的工作负载部署到这两个命名空间。以下示例清单部署了一个 nginx 容器,该容器允许提权。

  1. 将以下清单保存为 psa-workload.yaml

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        securityContext:
          privileged: true
    
  2. 将该清单应用于 baseline-ns 命名空间:

    kubectl apply -f psa-workload.yaml --namespace=baseline-ns
    

    输出类似于以下内容:

    Warning: would violate PodSecurity "baseline:latest": privileged (container "nginx" must not set securityContext.privileged=true)
    

    baseline 政策允许 Pod 部署到命名空间中。

  3. 确认 Pod 是否已成功部署:

    kubectl get pods --namespace=baseline-ns -l=app=nginx
    
  4. 将该清单应用于 restricted-ns 命名空间:

    kubectl apply -f psa-workload.yaml --namespace=restricted-ns
    

    输出内容类似如下:

    Error from server (Forbidden): error when creating "workload.yaml": pods "nginx"
    is forbidden: violates 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 不会部署到命名空间中。系统在日志中添加了一条审核条目。

在审核日志中查看政策违规行为

auditenforce 模式下的政策违规行为已记录在集群的审核日志中。您可以使用 Google Cloud 控制台中的日志浏览器查看这些日志。

  1. 转到 Google Cloud 控制台中的日志浏览器页面。

    进入日志浏览器

  2. 查询字段中,指定以下内容以检索 auditenforce 模式审核日志:

    resource.type="k8s_cluster"
    protoPayload.resourceName:"/pods/nginx"
    protoPayload.methodName="io.k8s.core.v1.pods.create"
    (labels."pod-security.kubernetes.io/audit-violations":"PodSecurity" OR protoPayload.response.reason="Forbidden")
    
  3. 点击运行查询

  4. 查询结果部分中,展开 Forbidden 日志条目以检查 enforce 模式拒绝日志。详细信息如下所示:

    {
      ...
      protoPayload: {
        @type: "type.googleapis.com/google.cloud.audit.AuditLog"
        authenticationInfo: {1}
        authorizationInfo: [1]
        methodName: "io.k8s.core.v1.pods.create"
        request: {6}
        requestMetadata: {2}
        resourceName: "core/v1/namespaces/restricted-ns/pods/nginx"
        response: {
          @type: "core.k8s.io/v1.Status"
          apiVersion: "v1"
          code: 403
          details: {2}
          kind: "Status"
          message: "pods "nginx" is forbidden: violates PodSecurity "restricted:latest": privileged
                  (container "nginx" must not set securityContext.privileged=true),
                  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")"
          metadata: {0}
          reason: "Forbidden"
          status: "Failure"
          }
          serviceName: "k8s.io"
          status: {2}
        }
      receiveTimestamp: "2022-02-01T19:19:25.353235326Z"
      resource: {2}
      timestamp: "2022-02-01T19:19:21.469360Z"
    }
    
  5. 展开 audit-violations 日志条目以检查 audit 模式日志。详细信息如下所示:

    {
      ...
      labels: {
        ...
        pod-security.kubernetes.io/audit-violations: "would violate PodSecurity "baseline:latest": privileged
                                                    (container "nginx" must not set securityContext.privileged=true)"
        pod-security.kubernetes.io/enforce-policy: "privileged:latest"
      }
      operation: {4}
      protoPayload: {10}
      receiveTimestamp: "2023-12-26T05:18:04.533631468Z"
      resource: {2}
      timestamp: "2023-12-26T05:17:36.102387Z"
    }
    

清理

为避免系统向您的 Google Cloud 账号收取费用,请删除命名空间:

kubectl delete ns baseline-ns
kubectl delete ns restricted-ns

PodSecurity 的替代方案

除了使用内置 Kubernetes PodSecurity 准入控制器来应用 Pod 安全标准之外,您还可以使用 Gatekeeper(基于 Open Policy Agent (OPA),用于创建和应用自定义 Pod 级层的安全控制措施。

后续步骤