将 GKE Pod 放置在特定的可用区中

本页面介绍如何指示 Google Kubernetes Engine (GKE) 使用可用区级拓扑在特定 Google Cloud 可用区内的节点上运行 Pod。此类放置在以下情况下非常有用:

  • Pod 必须访问存储在可用区级 Compute Engine 永久性磁盘中的数据。
  • Pod 必须与其他可用区级资源(例如 Cloud SQL 实例)一起运行。

您还可以将可用区放置与拓扑感知流量路由结合使用,以缩短客户端和工作负载之间的延迟时间。如需详细了解拓扑感知流量路由,请参阅拓扑感知路由

使用可用区拓扑控制 Pod 位置是一种高级 Kubernetes 机制,您应该仅在需要 Pod 在特定可用区运行时才使用这种机制。在大多数生产环境中,我们建议您尽可能使用区域级资源(即 GKE 默认值)。

可用区放置方法

可用区拓扑内置于 Kubernetes 中,带有 topology.kubernetes.io/zone: ZONE 节点标签。如需指示 GKE 将 Pod 放置在特定可用区中,请使用以下任一方法:

  • nodeAffinity:在 Pod 规范中为一个或多个 Google Cloud 可用区指定 nodeAffinity 规则。此方法比 nodeSelector 更灵活,因为它让您可以将 Pod 放置在多个可用区中。
  • nodeSelector:在 Pod 规范中为单个 Google Cloud 可用区指定 nodeSelector。

  • 计算类:配置 Pod 以使用 GKE 计算类。这种方法可让您定义 Google Cloud 可用区集的优先级列表。这样一来,工作负载便可动态迁移到首选的可用区集(如果这些可用区中有节点可用)。如需了解详情,请参阅自定义计算类简介

注意事项

使用可用区拓扑的可用区级 Pod 放置存在以下注意事项:

  • 集群必须与请求的可用区位于同一 Google Cloud 区域中。
  • 在 Standard 集群中,您必须使用节点自动预配功能,或在请求的可用区中创建具有节点的节点池。Autopilot 集群会自动为您管理此过程。
  • Standard 集群必须是区域级集群。

价格

可用区拓扑是一种 Kubernetes 调度功能,在 GKE 中免费提供。

如需详细了解价格,请参阅 GKE 价格

准备工作

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

  • 启用 Google Kubernetes Engine API。
  • 启用 Google Kubernetes Engine API
  • 如果您要使用 Google Cloud CLI 执行此任务,请安装初始化 gcloud CLI。 如果您之前安装了 gcloud CLI,请运行 gcloud components update 以获取最新版本。
  • 确保现有 GKE 集群与要放置 Pod 的可用区位于同一Google Cloud 区域中。如需创建新集群,请参阅创建 Autopilot 集群

使用 nodeAffinity 将 Pod 放置在多个可用区中

Kubernetes nodeAffinity 提供灵活的调度控制机制,支持多个标签选择器和逻辑运算符。若要让 Pod 在一组可用区中的其中一个可用区运行(例如在 us-central1-aus-central1-f 中),请使用 nodeAffinity。

  1. 将以下清单保存为 multi-zone-affinity.yaml

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: nginx-multi-zone
      template:
        metadata:
          labels:
            app: nginx-multi-zone
        spec:
          containers:
          - name: nginx
            image: nginx:latest
            ports:
            - containerPort: 80
          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  - key: topology.kubernetes.io/zone
                    operator: In
                    values:
                    - us-central1-a
                    - us-central1-f
    

    此清单会创建一个具有三个副本的 Deployment,并根据节点可用性将 Pod 放置在 us-central1-aus-central1-f 中。

    确保您的集群位于 us-central1 区域。如果您的集群位于其他区域,请将清单值字段中的可用区更改为集群区域中的有效可用区。

  2. 创建 Deployment:

    kubectl create -f multi-zone-affinity.yaml
    

    GKE 会在其中一个指定可用区的节点中创建 Pod。多个 Pod 可能在同一节点上运行。您可以选择使用 Pod 反亲和性,指示 GKE 将每个 Pod 放在单独的节点上。

使用 nodeSelector 将 Pod 放置在单个可用区中

如需将 Pod 放在单个可用区中,请在 Pod 规范中使用 nodeSelector。nodeSelector 等效于指定了单个可用区的 requiredDuringSchedulingIgnoredDuringExecution nodeAffinity 规则。

  1. 将以下清单保存为 single-zone-selector.yaml

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-singlezone
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: nginx-singlezone
      template:
        metadata:
          labels:
            app: nginx-singlezone
        spec:
          nodeSelector:
            topology.kubernetes.io/zone: "us-central1-a"
          containers:
          - name: nginx
            image: nginx:latest
            ports:
            - containerPort: 80
    

    此清单指示 GKE 将 Deployment 中的所有副本放在 us-central1-a 可用区中。

  2. 创建 Deployment:

    kubectl create -f single-zone-selector.yaml
    

使用计算类优先在所选可用区中放置 Pod

GKE 计算类提供了一种控制机制,可让您定义节点配置优先级列表。通过可用区偏好设置,您可以定义希望 GKE 将 Pod 放置在哪些可用区中。如要在计算类中定义可用区偏好设置,需要使用 GKE 1.33.1-gke.1545000 版或更高版本。

以下示例创建了一个计算类,用于指定 Pod 的首选可用区列表。

这些步骤假定您的集群位于 us-central1 区域。如果您的集群位于其他区域,请将清单中的可用区值更改为集群区域中的有效可用区。

  1. 将以下清单保存为 zones-custom-compute-class.yaml

    apiVersion: cloud.google.com/v1
    kind: ComputeClass
    metadata:
      name: zones-custom-compute-class
    spec:
      priorities:
      - location:
        zones: [us-central1-a, us-central1-b]
      - location:
        zones: [us-central1-c]
      activeMigration:
        optimizeRulePriority: true
      nodePoolAutoCreation:
        enabled: true
      whenUnsatisfiable: ScaleUpAnyway
    

    此计算类清单会按如下方式更改扩缩行为:

    1. GKE 会尝试将 Pod 放置在 us-central1-aus-central1-b 中。
    2. 如果 us-central1-aus-central1-b 没有可用容量,GKE 会尝试将 Pod 放置在 us-central1-c 中。
    3. 如果 us-central1-c 没有可用容量,whenUnsatisfiable: ScaleUpAnyway 字段会使 GKE 将 Pod 放置在该区域内的任何可用的可用区中。
    4. 如果计算类中优先级较高的某个可用区稍后变为可用,activeMigration.optimizeRulePriority: true 字段会使 GKE 将 Pod 从任何优先级较低的可用区移至该可用区。此迁移使用 Pod 中断预算来确保服务可用性。
  2. 创建自定义计算类:

    kubectl create -f zones-custom-compute-class.yaml
    

    GKE 会创建一个自定义计算类,供您的工作负载引用。

  3. 将以下清单保存为 custom-compute-class-deployment.yaml

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-zonal-preferences
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: nginx-zonal-preferences
      template:
        metadata:
          labels:
            app: nginx-zonal-preferences
        spec:
          nodeSelector:
            cloud.google.com/compute-class: "zones-custom-compute-class"
          containers:
          - name: nginx
            image: nginx:latest
            ports:
            - containerPort: 80
    
  4. 创建 Deployment:

    kubectl create -f custom-compute-class-deployment.yaml
    

验证 Pod 位置

如需验证 Pod 位置,请列出 Pod 并检查节点标签。多个 Pod 可能会在单个节点中运行,因此,如果您使用 nodeAffinity,可能看不到分布在多个可用区中的 Pod。

  1. 列出 Pod:

    kubectl get pods -o wide
    

    输出是正在运行的 Pod 和相应的 GKE 节点的列表。

  2. 描述节点:

    kubectl describe node NODE_NAME | grep "topology.kubernetes.io/zone"
    

    NODE_NAME 替换为该节点的名称。

    输出类似于以下内容:

    topology.kubernetes.io/zone: us-central1-a
    

如果您希望 GKE 在多个可用区中均匀分布 Pod,以改善多个故障域的故障切换,请使用 topologySpreadConstraints

后续步骤