将 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 放置存在以下注意事项:

  • 集群必须与请求的可用区位于同一 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 位置

如需验证 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

后续步骤