创建可扩缩集群指南

本文档提供指导,帮助您确定如何创建、配置和操作 Google Kubernetes Engine (GKE) 集群,以便处理接近 Kubernetes 已知限制的工作负载。

什么是可扩缩性?

在 Kubernetes 集群中,可扩缩性是指集群在实现其服务等级目标 (SLO) 的同时扩大规模的能力。Kubernetes 也有自己的一组 SLO

Kubernetes 是一个复杂的系统,其扩缩能力取决于多种因素。其中一些因素包括节点池中节点的类型和数量、节点池的类型和数量、可用的 Pod 数量、资源分配给 Pod 的方式以及 Service 的数量或 Service 背后的后端数量。

为可用性做好准备

选择区域级或地区级控制平面

由于架构差异,地区级集群更适合用来实现高可用性。地区级集群在一个地区的多个计算区域有多个控制层面,而区域级集群在单个计算区域中有一个控制层面。

如果升级区域级集群,则控制层面虚拟机会停机,在此期间,Kubernetes API 不可用,直到升级完成为止。

在地区级集群中,控制层面在集群维护(例如轮替 IP 地址、升级控制层面虚拟机或者调整集群或节点池的大小)期间仍然可用。升级地区级集群时,总共会有三分之二的控制层面虚拟机始终会在滚动升级期间运行,因此 Kubernetes API 仍然可用。同样,单区域故障不会导致地区级控制层面停机。

不过,可用性较高的地区级集群也有一些弊端:

  • 更改集群的配置会花费较长的时间,因为所做的更改必须传播到地区级集群中的所有控制层面,而不是区域级集群中的单个控制层面。

  • 您可能无法像区域级集群那样频繁地创建或升级地区级集群。如果无法在其中一个地区创建虚拟机(无论是因为容量不足还是因为其他暂时性问题),则您无法创建或升级集群。

由于存在这些弊端,因此地区级集群和区域级集群适用于不同的使用场景:

  • 如果您对可用性的要求较低,请使用地区级集群快速创建或升级集群。
  • 如果可用性比灵活性更重要,请使用区域级集群。

创建集群时,请谨慎选择集群类型,因为您在创建集群后无法更改集群类型。如需作出调整,您必须创建新的集群,然后将流量迁移到该集群。您可以在集群之间迁移生产流量,但难以进行大规模迁移。

选择多区域或单区域节点池

如需实现高可用性,Kubernetes 控制层面及其节点需要分布在不同区域。GKE 提供了两种类型的节点池:单区域节点池和多区域节点池。

如需部署高可用性应用,请使用跨地区均匀分布节点的多地区节点池,将您的工作负载分布到某个区域中的多个计算地区

如果您的所有节点都位于同一个地区,则当该地区变为无法到达的地区时,您将无法调度 Pod。使用多地区节点池会有一些弊端:

  • GPU 只能在特定的地区中使用。您可能无法在区域的所有地区中获取这些 GPU。

  • 单个区域内各个可用区之间的往返延迟可能比单个区域内各个资源之间的往返延迟更高。对于大多数工作负载而言,这种差异应该无关紧要。

  • Compute Engine 价格页面提供了同一地区中的不同区域之间的出站流量价格。

准备扩缩

基础架构

Kubernetes 工作负载需要网络、计算资源和存储空间。您需要提供足够的 CPU 和内存才能运行 Pod。不过,底层的基础架构有更多参数可能会影响 GKE 集群的性能和可扩缩性。

集群网络

GKE 提供了两种类型的集群网络:基于路由的较旧集群网络和较新的 VPC 原生集群网络

  • 基于路由的集群:每次添加节点时,系统都会向 VPC 网络中的路由表添加自定义路由

  • VPC 原生集群:在此模式下,VPC 网络的所有 Pod IP 地址都有一个次要范围。随后,系统会为每个节点分配其自身 Pod IP 地址的次要范围片段。这样,VPC 网络就可以自然而然地知道如何将流量路由到 Pod,而无需依赖于自定义路由。单个 VPC 网络最多可以连接 15000 个虚拟机。如需详细了解此限制的后果,请参阅每个 VPC 网络的虚拟机数限制部分。

专用集群

在常规 GKE 集群中,所有节点都具有公共 IP 地址。在专用集群中,节点仅具有内部 IP 地址,用于将节点隔离,防止其与互联网之间建立入站和出站连接。GKE 使用 VPC 网络对等互连将运行 Kubernetes API 服务器的虚拟机连接到集群的其余部分。这样便可以提高 GKE 控制层面和节点之间的吞吐量,因为流量不是通过公共互联网路由的。

使用专用集群具有额外的安全优势,即节点不会向互联网公开。

集群负载平衡

GKE Ingress 和 Cloud Load Balancing 配置和部署负载平衡器,以在集群外部及向公共互联网公开 Kubernetes 工作负载。GKE Ingress 和 Service 控制器会代表 GKE 工作负载部署转发规则、网址映射、后端服务和网络端点组等对象。这些资源都有固有的配额和限制,这些限制也适用于 GKE。如果任何特定 Cloud Load Balancing 资源达到其配额,它会阻止正确部署给定的 Ingress 或 Service,并且资源的事件中会出现错误。

下表介绍了使用 GKE Ingress 和 Service 时的扩缩限制:

负载平衡器 每个集群的节点限制
内部 TCP/UDP 负载平衡器
网络负载平衡器 每个区域 1000 个节点
外部 HTTP(S) 负载平衡器
内部 HTTP(S) 负载平衡器 没有节点限制

如果您需要进一步扩大规模,请与您的 Google Cloud 销售团队联系以提升此限制界限。

DNS

GKE 中的服务发现通过 kube-dns 提供,kube-dns 是集中资源,用于为集群内运行的 Pod 提供 DNS 解析。对于大型集群或请求负载较高的工作负载,这可能会成为瓶颈。GKE 会根据集群大小自动扩缩 kube-dns,以增加其容量。如果此容量仍然不够,GKE 会针对具有 NodeLocal DNSCache 的每个节点提供 DNS 查询的分布式本地解析。这将在每个 GKE 节点上提供在本地对查询做出响应的本地 DNS 缓存,从而分配负载并缩短响应时间。

管理 VPC 原生集群中的 IP 地址

VPC 原生集群使用节点的主要 IP 地址范围以及 Pod 和 Service 的两个次要 IP 地址范围。VPC 原生集群中的最大节点数可能会受到可用 IP 地址的限制。节点数由主要范围(节点子网)和次要范围(Pod 子网)决定。Pod 和 Service 的最大数量不仅由集群的次要范围大小决定,而且还分别由 Pod 子网和 Service 子网决定。

默认情况下:

  • Pod 次要范围默认为 /14(262144 个 IP 地址)。
  • 每个节点都有为其 Pod 分配的 /24 范围(用于其 Pod 的 256 个 IP 地址)。
  • 节点的子网为 /20(4092 个 IP 地址)。

不过,这两个范围(节点范围和 Pod 范围)中必须有足够的地址,您才能预配新的节点。如果使用默认设置,则由于 Pod IP 地址的数量限制,您只能创建 1024 个节点

默认情况下,每个节点最多可以有 110 个 Pod,并且集群中的每个节点都为其 Pod 分配了 /24 范围。这会导致每个节点有 256 个 Pod IP 地址。通过将可用 IP 地址数量设为约 Pod 数量的两倍,Kubernetes 可以在 Pod 添加到节点以及从节点中移除时减少 IP 地址的重复使用现象。不过,对于某些计划为每个节点调度较少 Pod 的应用,这样做有点浪费。借助灵活的 Pod CIDR 功能,您可以为 Pod 配置每个节点的 CIDR 块大小,并使用较少的 IP 地址。

如果您需要的 IP 地址多于 RFC 1918 的专用空间内的 IP 地址,我们建议您使用非 RFC 1918 地址

默认情况下,Service 的次要范围设置为 /20(4096 个 IP 地址),从而将集群中的 Service 数量限制为 4096 个。

配置节点以获得更好的性能

GKE 节点是常规的 Google Cloud 虚拟机。它们的一些参数(例如核心数量或磁盘大小)可能会影响 GKE 集群的性能。

出站流量

在 Google Cloud 中,分配给实例的机器类型和核心数决定其网络容量。出站带宽上限介于 1 到 32 Gbps 之间,而默认 e2-medium-2 机器的出站带宽上限为 2 Gbps。如需详细了解带宽限制,请参阅共享核心机器类型

IOPS 和磁盘吞吐量

在 Google Cloud 中,永久性磁盘的大小决定了磁盘的 IOPS 和吞吐量。GKE 通常使用永久性磁盘作为启动磁盘以及支持 Kubernetes 的永久性卷。增加磁盘大小会增加 IOPS 和吞吐量,直至达到特定限制

每个永久性磁盘写入操作都会占用虚拟机实例的累计网络出站流量上限。因此,磁盘(尤其是 SSD)的 IOPS 性能除了取决于磁盘大小以外,还取决于该实例中的 vCPU 数量。由于网络出站流量对写入吞吐量的限制,核心数量较少的虚拟机具有较低的写入 IOPS 上限。

如果虚拟机实例的 CPU 不足,则您的应用将无法接近 IOPS 上限。一般说来,您应该针对每 2000-2500 IOPS 的预期流量准备一个可用的 CPU。

对于需要高容量或大量磁盘的工作负载,您需要考虑单个虚拟机可以挂接的永久性磁盘的数量上限。对于常规虚拟机,该上限为 128 个磁盘(总大小为 64 TB),而共享核心虚拟机的上限为 16 个永久性磁盘(总大小为 3 TB)。Google Cloud(而不是 Kubernetes)会强制实施此上限。

与可扩缩性相关的限制和配额

每个 VPC 网络限制的虚拟机数

单个 VPC 网络最多可以连接 15000 个虚拟机,超过了 GKE 1.17 及更低版本中每个集群所支持的限制(5000 个节点)。对于 GKE 1.18 及更高版本(最多支持 15000 个节点),VPC 原生集群几乎可以拥有 15000 个节点 - 所谓“几乎”,是因为必须将少量地址保留给 GKE 控制层面使用。

请注意,如果您配置了网络对等互连,则对等互连网络会默认应用 15000 个虚拟机这一限制。

Compute Engine API 配额

GKE 控制层面使用 Compute Engine API 来发现集群中节点的元数据或将永久性磁盘挂接到虚拟机实例。

默认情况下,Compute Engine API 允许每 100 秒发出 2000 次读取请求,这对于包含 100 个以上节点的集群来说可能还不够。

如果您计划创建包含 100 个以上节点的集群,我们建议将 Read requests per 100 secondsRead requests per 100 seconds per user 配额增加到至少 4000。您可以在 Google Cloud Console 中更改这些设置。

日志记录和监控配额

随着集群规模的增加,Cloud Logging API(默认值为每分钟 120000 个日志插入请求)和 Cloud Monitoring API(默认值为每分钟 6000 时间序列插入请求)的配额可能需要增加。

节点配额

从 GKE 1.18 开始,节点数上限为 5000 个,可以按需增加到 15000 个。如需了解详情,请参阅超过 5000 个节点的集群部分。

了解限制

与其他任何系统一样,Kubernetes 也有一些限制,您在设计应用和规划其发展时需要考虑这些限制。

1.17 版及更低版本的 GKE 在单个集群中支持 5000 个节点。GKE 1.18 及更高版本最多支持 15000 个节点。不过,Kubernetes 是一个复杂的系统,具有大型的功能集合。节点数只是 Kubernetes 可以扩缩的多个维度之一。其他维度包括 Pod 总数、Service 总数或一项 Service 背后的后端总数。如需了解与创建大型集群相关的注意事项,请参阅超过 5000 个节点的集群部分。

您目前不应该扩展多个维度。即使在较小的集群中,这种压力也可能会导致问题。

例如,尝试在一个具有 5000 个节点的集群中为每个节点调度 110 个 Pod 可能不会成功,因为 Pod 的数量、每个节点的 Pod 数以及节点数将扩展得太多。

维度限制

您可以参阅官方的 Kubernetes 限制列表

此列表和以下示例均不构成 Kubernetes 限制的详尽列表。这些数字是使用未安装扩展程序的普通 Kubernetes 集群获得的。使用 webhook 或 CRD 扩展 Kubernetes 集群很常见,但可能会限制您扩缩集群的能力。

在这些限制中,大多数都没有强制实施,因此您可以超越这些限制。超出限制不会使集群立即无法使用。性能会降低(有时表现出来的是未达到 SLO),然后才会操作失败。此外,某些限制针对的是可能最大型的集群。如果集群较小,则限制将按比例降低。

  • 每个节点的 Pod 数。GKE 有一个硬性限制,即每个节点最多 110 个 Pod。此限制假设每个 Pod 的平均容器数为两个或更少。容器过多可能会使 110 这一上限减少,因为某些资源是按容器分配的。

  • Service 总数应低于 10000。如果服务过多或某项 Service 背后有大量后端,则 iptables 的性能会下降。

  • 单个 Service 背后的 Pod 数如果低于 250 则是合适的。Kube 代理会在每个节点上运行,并监控端点和 Service 的所有更改。因此,集群越大,必须发送的数据就越多。该硬性限制大约为 5000,具体取决于 Pod 名称的长度及其命名空间。如果长度较长,则 etcd 中会存储较多字节,其中 Endpoint 对象会超出 etcd 行的最大大小。如果后端流量较多,则更新会变大,尤其是在大型集群(具有 500 个及以上节点)中。只要 Service 背后的 Pod 的流失率保持在最低水平或集群的大小保持在较小水平,您就可以稍微超过此数量。

  • 每个命名空间的 Service 数不应超过 5000。如超过此值,Service 环境变量的数量会超出 shell 限制,导致 Pod 在启动时崩溃。在 Kubernetes 1.13 中,您可以通过将 PodSpec 中的 enableServiceLinks 设置为 false 来停止填充这些变量。

  • 对象总数。集群中的所有对象(包括内置对象和 CRD 对象)都有限制。相关限制取决于它们的大小(etcd 中存储的字节数)、它们的变化频率以及访问模式(例如,频繁读取给定类型的所有对象会更快地停止 etcd)。

超过 5000 个节点的集群

从 1.18 版开始,GKE 在单个集群中最多支持 15000 个节点。然而,必须要指出,上述所有限制仍有效,特别是因 etcd 限制导致的对象数量限制。结果是,并非每个部署在 5000 个节点上的工作负载都会扩容至最多 15000 个节点。

此外,超过 5000 个节点的集群必须为地区专用

因此,如果您想创建节点数大于 5000 的集群,则需要先创建支持服务工单,申请将配额增加到 5000 个节点以上。然后,Google 团队将与您联系,进一步了解您的工作负载,并在必要时对其进行扩缩(或者建议如何修改工作负载以取得更好的可扩缩性)。作为这项活动的一部分,我们还会帮助您以适当方式增加其他相关配额

停用自动装载默认服务帐号

创建 Pod 时,它将自动拥有默认服务帐号。 您可以使用默认服务帐号,使用自动装载的服务帐号凭据从 Pod 内部访问 Kubernetes API。

对于每个已装载的 Secret,kubelet 会监控 kube-apiserver 是否更改了该 Secret。在大型集群中,这将转换为数千次监控,并且可能会在 kube-apiserver 上产生大量负载。如果 Pod 不打算访问 Kubernetes API,您应该停用默认服务帐号

后续步骤