在 GKE 中配置工作负载隔离


本页面介绍如何指示 Google Kubernetes Engine (GKE) 将 Pod 安排到一起、将 Pod 安排到不同的节点上,或在特定位置安排 Pod。

借助工作负载隔离,您可以使用污点和容忍指示 GKE 将 Pod 隔离到不同的节点上、将 Pod 放置在符合特定条件的节点上,或者将特定工作负载安排在一起。配置工作负载隔离需要执行的操作取决于您的 GKE 集群配置。下表介绍了它们之间的差异:

工作负载隔离配置

将特定键值对的容忍添加到 Pod 规范,然后使用 nodeSelector 选择该键值对。 GKE 会创建节点,应用相应的节点污点,并在节点上安排 Pod。

如需了解相关说明,请参阅本页面中的“在 Autopilot 集群中隔离工作负载”

未启用节点自动预配的 Standard
  1. 使用节点污点和节点标签创建节点池
  2. 将该污点的容忍添加到 Pod 规范

如需了解相关说明,请参阅在专用节点池中隔离工作负载

本指南使用一个示例场景,您希望将批量作业和 Web 服务器这两个工作负载负载隔离开。

何时在 GKE 中使用工作负载隔离

如果您的工作负载执行不同的角色并且不应在同一底层机器上运行,则工作负载隔离非常有用。以下是一些示例场景:

  • 您有一个批量协调器工作负载,用于创建要隔离开的作业。
  • 您运行一个游戏服务器,并且希望将它运行的配对工作负载与会话 Pod 隔离。
  • 您想要将栈的某些部分彼此隔离,例如将服务器与数据库分开。
  • 出于合规性或政策原因,您需要隔离某些工作负载。

价格

在 Autopilot 集群中,您需要为 Pod 在运行时请求的资源付费。如需了解详情,请参阅 Autopilot 价格。与常规 Pod 相比,使用工作负载隔离的 Pod 强制执行更高的资源请求下限

在 Standard 集群中,无论节点是否在节点上运行,您都需要根据每个节点的硬件配置和大小付费。如需了解详情,请参阅 Standard 价格

准备工作

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

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

在 Autopilot 集群中隔离工作负载

如需将工作负载彼此隔离,请向每个工作负载规范添加容忍和节点选择器,以定义工作负载应在其中运行的节点。此方法也适用于启用了节点自动预配功能的 Standard 集群。

  1. 将以下清单保存为 web-server.yaml

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: web-server
    spec:
      replicas: 6
      selector:
        matchLabels:
          pod: nginx-pod
      template:
        metadata:
          labels:
            pod: nginx-pod
        spec:
          tolerations:
          - key: group
            operator: Equal
            value: "servers"
            effect: NoSchedule
          nodeSelector:
            group: "servers"
          containers:
          - name: web-server
            image: nginx
    

    此清单包含以下字段:

    • spec.tolerations:GKE 可以将 Pod 放置在具有 group=servers:NoSchedule 污点的节点上。GKE 无法在这些节点上安排没有此容忍的 Pod。
    • spec.nodeSelector:GKE 必须将 Pod 放置在具有 group: servers 节点标签的节点上。

    GKE 会将相应的标签和污点添加到 GKE 自动预配以运行这些 Pod 的节点。

  2. 将以下清单保存为 batch-job.yaml

    apiVersion: batch/v1
    kind: Job
    metadata:
      name: batch-job
    spec:
      completions: 5
      backoffLimit: 3
      ttlSecondsAfterFinished: 120
      template:
        metadata:
          labels:
            pod: pi-pod
        spec:
          restartPolicy: Never
          tolerations:
          - key: group
            operator: Equal
            value: "jobs"
            effect: NoSchedule
          nodeSelector:
            group: "jobs"
          containers:
          - name: pi
            image: perl
            command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
    

    此清单包含以下字段:

    • spec.tolerations:GKE 可以将 Pod 放置在具有 group=jobs:NoSchedule 污点的节点上。GKE 无法在这些节点上安排没有此容忍的 Pod。
    • spec.nodeSelector:GKE 必须将 Pod 放置在具有 group: jobs 节点标签的节点上。

    GKE 会将相应的标签和污点添加到 GKE 自动预配以运行这些 Pod 的节点。

  3. 部署工作负载:

    kubectl apply -f batch-job.yaml web-server.yaml
    

当您部署工作负载时,GKE 会对每个工作负载执行以下操作:

  1. GKE 会查找具有清单中指定的相应节点污点和节点标签的现有节点。如果节点存在且有可用资源,则 GKE 会在节点上安排工作负载。
  2. 如果 GKE 未找到符合条件的现有节点来安排工作负载,则 GKE 会创建一个新节点,并根据清单应用相应的节点污点和节点标签。GKE 会将 Pod 放置在新节点上。

节点污点中存在 NoSchedule 效果可确保没有容忍的工作负载不会被放置在该节点上。

验证工作负载隔离

列出 Pod 以查找节点的名称:

kubectl get pods --output=wide

输出内容类似如下:

NAME                          READY   ...   NODE
batch-job-28j9h               0/1     ...   gk3-sandbox-autopilot-nap-1hzelof0-ed737889-2m59
batch-job-78rcn               0/1     ...   gk3-sandbox-autopilot-nap-1hzelof0-ed737889-2m59
batch-job-gg4x2               0/1     ...   gk3-sandbox-autopilot-nap-1hzelof0-ed737889-2m59
batch-job-qgsxh               0/1     ...   gk3-sandbox-autopilot-nap-1hzelof0-ed737889-2m59
batch-job-v4ksf               0/1     ...   gk3-sandbox-autopilot-nap-1hzelof0-ed737889-2m59
web-server-6bb8cd79b5-dw4ds   1/1     ...   gk3-sandbox-autopilot-nap-1eurxgsq-f2f3c272-n6xm
web-server-6bb8cd79b5-g5ld6   1/1     ...   gk3-sandbox-autopilot-nap-1eurxgsq-9f447e18-275z
web-server-6bb8cd79b5-jcdx5   1/1     ...   gk3-sandbox-autopilot-nap-1eurxgsq-9f447e18-275z
web-server-6bb8cd79b5-pxdzw   1/1     ...   gk3-sandbox-autopilot-nap-1eurxgsq-ccd22fd9-qtfq
web-server-6bb8cd79b5-s66rw   1/1     ...   gk3-sandbox-autopilot-nap-1eurxgsq-ccd22fd9-qtfq
web-server-6bb8cd79b5-zq8hh   1/1     ...   gk3-sandbox-autopilot-nap-1eurxgsq-f2f3c272-n6xm

此输出显示 batch-job Pod 和 web-server Pod 始终在不同节点上运行。

使用污点和容忍隔离工作负载的限制

您不能使用以下键前缀来隔离工作负载:

  • 特定于 GKE 和 Kubernetes 的键
  • *cloud.google.com/
  • *kubelet.kubernetes.io/
  • *node.kubernetes.io/

您应该使用自己的唯一键来隔离工作负载。

在未启用节点自动预配功能的 Standard 集群中隔离工作负载

如需在未启用节点自动预配功能的 Standard 集群中隔离工作负载,您需要手动创建具有适当节点污点和节点标签的节点池,以容纳您的工作负载。如需了解相关说明,请参阅在专用节点池中隔离工作负载。请仅在存在具体要求,需要您手动管理节点池时使用此方法。

创建具有节点污点的集群

在 GKE 中创建集群时,您可以将节点污点分配给集群。此操作会将污点分配给使用集群创建的所有节点。

如果创建节点池,该节点池并不会从集群继承污点。如果您想要为节点设置污点,则必须在创建节点池时使用 --node-taints 标志。

如果您创建具有 NoSchedule 效果或 NoExecute 效果的节点污点的标准集群,则 GKE 无法在当您创建群集时 GKE 创建的默认节点池上安排某些 GKE 管理的组件,例如 kube-dnsmetrics-server。GKE 无法安排这些组件,因为它们没有相应的节点污点容忍机制。您必须添加满足以下条件之一的新节点池:

  • 无污点
  • 具有 PreferNoSchedule 效果的污点
  • components.gke.io/gke-managed-components=true:NoSchedule 个污点

满足上述任何条件后,GKE 便可在新节点池中安排 GKE 管理的组件。

如需了解相关说明,请参阅在专用节点上隔离工作负载

gcloud

创建具有节点污点的集群

gcloud container clusters create CLUSTER_NAME \
    --node-taints KEY=VALUE:EFFECT

替换以下内容:

  • CLUSTER_NAME:新集群的名称。
  • EFFECT:以下效果之一:PreferNoScheduleNoScheduleNoExecute
  • KEY=VALUE:与 EFFECT 关联的键值对。

控制台

创建具有节点污点的集群

  1. 转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。

    转到 Google Kubernetes Engine

  2. 点击 创建

  3. 根据需要配置集群。

  4. 在导航窗格的节点池下,展开要修改的节点池,然后点击元数据

  5. 节点污点部分中,点击 添加污点

  6. 效果下拉列表中,选择所需的效果。

  7. 字段中输入所需的键值对。

  8. 点击创建

API

当您使用 API 创建集群时,请在 `nodeConfig: 下方添加 nodeTaints 字段。

POST https://container.googleapis.com/v1/projects/PROJECT_ID/zones/COMPUTE_ZONE/clusters

{
  'cluster': {
    'name': 'example-cluster',
    'nodeConfig': {
      'nodeTaints': [
        {
          'key': 'special',
          'Value': 'gpu',
          'effect': 'PreferNoSchedule'
        }
      ]
      ...
    }
    ...
  }
}

从节点池中移除所有污点

如需从节点池移除所有污点,请运行以下命令:

gcloud beta container node-pools update POOL_NAME \
    --node-taints="" \
    --cluster=CLUSTER_NAME

替换以下内容:

  • POOL_NAME:要更改的节点池的名称。
  • CLUSTER_NAME:节点池的集群名称。

后续步骤