扩展 Google Distributed Cloud 集群

与任何 Kubernetes 集群一样,Google Distributed Cloud 集群可伸缩性具有许多相互关联的维度。本文档旨在帮助您了解可以调整哪些关键维度,以在不中断工作负载的情况下扩容集群。

了解限制

Google Distributed Cloud 是一个集成表面很大的复杂系统。影响集群可伸缩性的维度有很多。例如,节点数只是 Google Distributed Cloud 可根据其扩缩的多个维度之一。其他维度包括 Pod 总数和 Service 总数。其中许多维度(例如每个节点的 Pod 数和每个集群的节点数)是相互关联的。如需详细了解会影响可伸缩性的维度,请参阅 GitHub 上 Kubernetes 社区仓库的“可伸缩性特别兴趣小组 (SIG)”部分中的 Kubernetes 可伸缩性阈值

可伸缩性限制对集群运行所在的硬件和节点配置也极为敏感。本文档中所述的限制是在可能与您的环境不同的环境中进行验证的。因此,当底层环境成为限制因素时,您可能无法重现相同的数字。

如需详细了解适用于 Google Distributed Cloud 集群的限制,请参阅配额和限制

准备扩缩

在准备扩缩 Google Distributed Cloud 集群时,请考虑以下部分中所述的要求和限制。

控制平面节点的 CPU 和内存要求

下表概述了运行生产工作负载的集群的控制平面节点的建议 CPU 和内存配置:

集群节点数 建议的控制平面 CPU 建议的控制平面内存
1-50 8 核 32 GiB
51 - 100 16 核 64 GiB

Pod 和 Service 的数量

集群中可以有多少个 Pod 和 Service 由以下设置控制:

Pod CIDR 和节点数上限

为集群中的 Pod 预留的 IP 地址总数是扩容集群的限制因素之一。此设置与每个节点的 Pod 数上限设置相结合,可确定您在集群中可拥有的节点数上限,以免耗尽 Pod 的 IP 地址。

请考虑以下事项:

  • 为集群中的 Pod 预留的 IP 地址总数通过 clusterNetwork.pods.cidrBlocks 指定,后者采用 CIDR 表示法指定的 IP 地址范围。例如,预填充的值 192.168.0.0/16 指定了从 192.168.0.0192.168.255.255 的 65,536 个 IP 地址的范围。

  • 可在单个节点上运行的 Pod 数上限通过 nodeConfig.podDensity.maxPodsPerNode 指定。

  • 根据每个节点的 Pod 数上限设置,Google Distributed Cloud 会为节点预配大约是该数量两倍的 IP 地址。额外的 IP 地址有助于防止在短时间内意外重复使用 Pod IP。

  • 将 Pod IP 地址总数除以每个节点上预配的 Pod IP 地址数量,即可得出您在集群中可拥有的节点总数。

例如,如果您的 Pod CIDR 为 192.168.0.0/17,则您总共有 32,768 个 IP 地址 (2(32-17) = 215 = 32,768)。如果您将每个节点的 Pod 数上限设置为 250,Google Distributed Cloud 会预留大约 500 个 IP 地址,这大致相当于一个 /23 CIDR 地址块 (2(32-23) = 29 = 512)。因此本例中的节点数上限为 64(215 个地址/集群除以 29 个地址/节点 = 2(15-9) 个节点/集群 = 26 = 64 个节点/集群)。

clusterNetwork.pods.cidrBlocksnodeConfig.podDensity.maxPodsPerNode 都是不可变的,因此请仔细规划集群的未来增长,以免用尽节点容量。如需了解基于测试的每个集群的 Pod 数上限、每个节点的 Pod 数上限和每个集群的节点数上限的建议值,请参阅限制

服务 CIDR

在扩容集群时,您可以更新 Service CIDR 以添加更多 Service。但是,您无法缩小 Service CIDR 范围。如需了解详情,请参阅扩大服务网络范围

为系统守护程序预留的资源

默认情况下,Google Distributed Cloud 会自动在节点上为系统守护程序(例如 sshdudev)预留资源。节点上的 CPU 和内存资源为系统守护程序预留,以便这些守护程序具有所需的资源。如果没有此功能,Pod 可能会消耗节点上的大部分资源,从而使系统守护程序无法完成其任务。

具体来说,Google Distributed Cloud 会在每个节点上为系统守护程序预留 80 millicore CPU (80 mCPU) 和 280 兆比字节 (280 MiB) 内存。请注意,CPU 单位 mCPU 代表核心的千分之一,因此每个节点上的核心的 80/1000 (8%) 会预留给系统守护程序。预留资源量很小,对 Pod 性能没有显著影响。但是,如果 Pod 使用 CPU 或内存的数量超过分配给它们的数量,则节点上的 kubelet 可能会逐出 Pod。

使用 MetalLB 进行网络连接

您可能需要增加 MetalLB speaker 数量,以解决以下方面的问题:

  • 带宽:负载均衡服务的整个集群带宽取决于 speaker 数量和每个 speaker 节点的带宽。网络流量增加需要更多 speaker。

  • 容错性:增加 speaker 数量可降低单个 speaker 发生故障的总体影响。

MetalLB 需要负载均衡节点之间具有第 2 层连接。在这种情况下,您可能会受到具有第 2 层连接的节点数量的限制,您可以在这些节点上放置 MetalLB speaker。

仔细规划您希望在集群中拥有多少个 MetalLB speaker,并确定您需要多少个第 2 层节点。如需了解详情,请参阅 MetalLB 可伸缩性问题

使用捆绑式负载均衡模式时,控制平面节点还需要位于同一第 2 层网络下。手动负载均衡没有此限制。如需了解详情,请参阅手动负载均衡器模式

运行多个节点、Pod 和 Service

添加节点、Pod 和 Service 是一种扩容集群的方法。以下部分介绍了在增加集群中的节点、Pod 和 Service 数量时应考虑的一些其他设置和配置。如需了解这些维度的限制以及它们之间的关系,请参阅限制

创建不含 kube-proxy 的集群

如需创建可扩容以使用大量 Service 和端点的高性能集群,我们建议您在不使用 kube-proxy 的情况下创建集群。如果没有 kube-proxy,集群会在 kube-proxy-replacement 模式下使用 GKE Dataplane V2。此模式可避免维护大量 iptables 规则所需的资源消耗。

您无法对现有集群停用 kube-proxy。您必须在创建集群时设置此配置。如需了解相关说明和详细信息,请参阅在不使用 kube-proxy 的情况下创建集群

CoreDNS 配置

本部分介绍了 CoreDNS 中影响集群可伸缩性的方面。

Pod DNS

默认情况下,Google Distributed Cloud 集群会向 Pod 注入 resolv.conf,如下所示:

nameserver KUBEDNS_CLUSTER_IP
search <NAMESPACE>.svc.cluster.local svc.cluster.local cluster.local c.PROJECT_ID.internal google.internal
options ndots:5

选项 ndots:5 表示主机名中包含的点数少于 5 个,因此不被视为完全限定域名 (FQDN)。DNS 服务器会在查找最初请求的主机名之前附加所有指定的搜索网域,这会在解析 google.com 时按以下顺序查找:

  1. google.com.NAMESPACE.svc.cluster.local
  2. google.com.svc.cluster.local
  3. google.com.cluster.local
  4. google.com.c.PROJECT_ID.internal
  5. google.com.google.internal
  6. google.com

每个查找操作都会针对 IPv4(A 记录)和 IPv6(AAAA 记录)执行,因此每个非 FQDN 查询都会产生 12 个 DNS 请求,这会显著放大 DNS 流量。为缓解此问题,我们建议您通过添加尾随点 (google.com.) 声明要查找的主机名作为 FQDN。此声明需要在应用工作负载级别进行。如需了解详情,请参阅 resolv.conf 手册页面

IPv6

如果集群未使用 IPv6,则可以通过消除对上游 DNS 服务器的 AAAA 记录查找来将 DNS 请求减少一半。如果您需要停用 AAAA 查询方面的帮助,请与 Cloud Customer Care 联系。

专用节点池

由于 DNS 查询在应用生命周期中的重要性,我们建议您为 coredns Deployment 使用专用节点。此 Deployment 属于与普通应用不同的故障域。如果您需要为 coredns Deployment 设置专用节点方面的帮助,请与 Cloud Customer Care 联系。

MetalLB 可伸缩性问题

MetalLB 在主动-被动模式下运行,这意味着在任何时间点都只有一个 MetalLB speaker 为特定 LoadBalancer VIP 提供服务。

故障切换

在 Google Distributed Cloud 1.28.0 版之前,在大规模情况下,MetalLB 的故障切换可能需要很长时间,并且可能会对集群带来可靠性风险。

连接限制

如果有特定的 LoadBalancer VIP(例如 Ingress Service)预计将接近或超过 30000 个并发连接,则处理 VIP 的扬声器节点可能会耗尽可用的端口。由于架构限制,MetalLB 无法缓解此问题。在创建集群之前,请考虑改用使用 BGP 进行捆绑式负载均衡,或者使用其他入站流量类。如需了解详情,请参阅 Ingress 配置

负载均衡器 speaker

默认情况下,Google Distributed Cloud 会为控制平面和数据平面使用相同的负载均衡器节点池。如果您未指定负载均衡器节点池 (loadBalancer.nodePoolSpec),则使用控制平面节点池 (controlPlane.nodePoolSpec)。

如需在使用控制平面节点池进行负载均衡时增加 speaker 数量,您必须增加控制平面机器的数量。对于生产部署,我们建议您使用三个控制平面节点以实现高可用性。为了容纳更多 speaker,将控制平面节点数量增加到三个以上可能并不会充分利用您的资源。

入站流量配置

如果您预计单个 LoadBalancer Service VIP 将接收接近 3 万个并发连接,MetalLB 可能无法支持此类连接。

您可以考虑通过其他机制(例如 F5 BIG-IP)公开 VIP。或者,您可以通过使用 BGP 的捆绑式负载均衡创建新集群,该集群不存在相同的限制。

微调 Cloud Logging 和 Cloud Monitoring 组件

在大型集群中,根据应用配置文件和流量模式,Cloud Logging 和 Cloud Monitoring 组件的默认资源配置可能不足。如需了解如何调整可观测性组件的资源请求和限制,请参阅配置 Stackdriver 组件资源

特别是,包含大量服务和端点的集群中的 kube-state-metrics 可能会导致 kube-state-metrics 本身和同一节点上的 gke-metrics-agent 内存用量过多。指标服务器的资源用量也可以根据节点、Pod 和 Service 进行扩缩。如果这些组件上出现资源问题,请与 Cloud Customer Care 联系。

使用 sysctl 配置操作系统

我们建议您对节点的操作系统配置进行微调,以便尽可能满足工作负载应用场景的需求。控制 inotify 资源数量的 fs.inotify.max_user_watchesfs.inotify.max_user_instances 参数通常需要进行调整。例如,如果您看到类似以下内容的错误消息,则可能需要尝试查看是否需要调整这些参数:

The configured user limit (128) on the number of inotify instances has been reached
ENOSPC: System limit for number of file watchers reached...

调整通常因工作负载类型和硬件配置而异。您可以向操作系统供应商咨询特定操作系统的最佳实践。

最佳做法

本部分介绍了扩容集群的最佳实践。

一次扩缩一个维度

为尽量减少问题并更轻松地回滚更改,请一次只调整一个维度。即使在较小的集群中,同时扩容多个维度也可能会导致问题。例如,尝试将每个节点调度的 Pod 数量增加到 110 个,同时将集群中的节点数量增加到 250 个可能不会成功,因为 Pod 的数量、每个节点的 Pod 数量以及节点数量扩展得太多。

分阶段扩缩集群

扩容集群可能会消耗大量资源。为降低集群操作失败或集群工作负载中断的风险,我们建议您不要尝试在单次操作中创建具有多个节点的大型集群。

创建没有工作器节点的混合集群或独立集群

如果您要创建包含超过 50 个工作器节点的大型混合集群或独立集群,最好先创建包含控制平面节点的高可用性 (HA) 集群,然后逐步扩容。集群创建操作使用引导集群,该集群不是高可用性集群,因此可靠性较低。高可用性混合集群或独立集群创建后,您可以使用它扩容到容纳更多节点。

批量增加工作器节点数量

如果您要将集群扩展到容纳更多工作器节点,最好分阶段扩展。我们建议您一次最多添加 20 个节点。对于运行关键工作负载的集群,尤为如此。

启用并行映像拉取

默认情况下,kubelet 会按序逐个拉取映像。如果您与映像注册表服务器的上行连接不良,则不良映像拉取可能会导致给定节点池的整个队列停滞。

为缓解此问题,我们建议您在自定义 kubelet 配置中将 serializeImagePulls 设置为 false。如需了解相关说明和详细信息,请参阅配置 kubelet 映像拉取设置。启用并行映像拉取可能会导致网络带宽或磁盘 I/O 消耗激增。

微调应用资源请求和限制

在密集的环境中,应用工作负载可能会被逐出。Kubernetes 会在发生驱逐时使用所引用的机制对 Pod 进行排序。

设置容器资源的一个良好做法是为请求和限制使用相同数量的内存,并使用更大或无界限的 CPU 限制。如需了解详情,请参阅 Cloud 架构中心的准备云端 Kubernetes 应用

使用存储合作伙伴

我们建议您使用某个 GDC Ready 存储合作伙伴进行大规模部署。请务必与特定存储合作伙伴确认以下信息:

  • 存储部署遵循存储方面的最佳实践,例如高可用性、优先级设置、节点亲和性以及资源请求和限制。
  • 存储版本通过特定 Google Distributed Cloud 版本进行限定。
  • 存储供应商可以支持您要部署的大规模。

配置集群以实现高可用性

请务必审核您的大规模部署,并尽可能确保关键组件已针对高可用性进行配置。Google Distributed Cloud 支持为所有集群类型提供高可用性部署选项。如需了解详情,请参阅选择部署模型。如需查看高可用性部署的集群配置文件示例,请参阅集群配置示例

此外,请务必审核其他组件,包括:

  • 存储供应商
  • 集群 webhook

监控资源使用情况

本部分针对大规模集群提供了一些基本的监控建议。

密切监控利用率指标

监控节点和各个系统组件的利用率,并确保它们具有足够的安全幅度非常重要。如需查看默认提供的标准监控功能,请参阅使用预定义信息中心

监控带宽消耗

密切监控带宽消耗,以确保网络不会饱和,从而导致集群性能下降。

提升 etcd 性能

磁盘速度对 etcd 性能和稳定性至关重要。磁盘速度缓慢会增加 etcd 请求延迟时间,这可能会导致集群稳定性问题。为了提高集群性能,Google Distributed Cloud 将事件对象存储在单独的专用 etcd 实例中。标准 etcd 实例使用 /var/lib/etcd 作为其数据目录,并使用端口 2379 处理客户端请求。etcd-events 实例使用 /var/lib/etcd-events 作为其数据目录,并使用端口 2382 处理客户端请求。

我们建议您将固态磁盘 (SSD) 用于 etcd 存储区。为了实现最佳性能,请将单独的磁盘装载到 /var/lib/etcd/var/lib/etcd-events。使用专用磁盘可确保两个 etcd 实例不共享磁盘 I/O。

etcd 文档提供了其他硬件建议,以确保在生产环境中运行集群时获得最佳 etcd 性能。

如需检查 etcd 和磁盘性能,请在 Metrics Explorer 中使用以下 etcd I/O 延迟时间指标:

  • etcd_disk_backend_commit_duration_seconds:第 99 百分位 (p99) 的时长应少于 25 毫秒。
  • etcd_disk_wal_fsync_duration_seconds:第 99 百分位 (p99) 的时长应少于 10 毫秒。

如需详细了解 etcd 性能,请参阅 etcd 警告“应用条目时间过长”意味着什么?以及 etcd 警告“未能按时发出检测信号”意味着什么?

如果您需要其他帮助,请与 Cloud Customer Care 联系。

后续步骤