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

本页面介绍如何使用 PodSecurity 准入控制器在 Google Kubernetes Engine (GKE) 集群中应用预定义的 Pod 级安全控制措施。对 Pod 应用安全控制措施有助于您满足安全性和合规性要求。在本页面中,您将详细了解 PodSecurity 以及如何将其应用于 Pod。

本页面适用于希望向 GKE 集群应用安全控制措施的安全专家。如需详细了解我们在 Google Cloud 内容中提及的常见角色和示例任务,请参阅常见的 GKE 用户角色和任务。

在阅读本页面之前,请确保您熟悉以下概念:

关于 PodSecurity

PodSecurity 是一个 Kubernetes 准入控制器,可让您将 Pod 安全标准应用于 GKE 集群上运行的 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 命令来获取最新版本。较早版本的 gcloud CLI 可能不支持运行本文档中的命令。

要求

默认情况下,运行以下 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 准入控制器是否按预期工作,将违反 baseline 和 restricted 政策的工作负载部署到这两个命名空间。以下示例清单部署了一个 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 不会部署到命名空间中。系统在日志中添加了一条审核条目。

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

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

  1. 前往 Google Cloud 控制台中的 Logs Explorer 页面。

    转到日志浏览器

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

    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 级层的安全控制措施。

后续步骤