2

我们运行一个兼容 Kubernetes (OKD 3.11) 的本地/私有云集群,后端应用程序与用作缓存和 K/V 存储的低延迟 Redis 数据库通信。新的架构设计即将在两个地理分布的数据中心(“区域”)之间平均划分工作节点。我们可以假设节点名称和区域之间是静态配对的,现在我们还添加了带有区域名称的节点标签。

保护与内存数据库的低延迟通信的推荐方法是什么,使客户端应用程序坚持与允许使用的数据库相同的区域?增加数据库的额外副本是可行的,但不会阻止两个区域之间的循环路由......

相关:单个集群中的 Kubernetes 节点不同区域

4

2 回答 2

1

因此,有效的区域锁定解决方案比仅nodeAffinity在“首选”版本中使用更复杂。仅这一点就会给你带来很多不可预知的惊喜,因为 Kubernetes 的固执己见的特性具有硬编码的区域传播,正如在这个Github 问题中所看到的那样,他们显然试图将至少一些鸡蛋放在另一个篮子中,并将区域选择视为一种反模式。

在实践中,nodeAffinity单独的用处仅限于 pod 副本数量非常有限的场景,因为当 pod 数量超过区域中的节点数量时(即通常用于 2-nodes / 2-regions 设置中的第 3 个副本),调度程序将开始“纠正”或“战斗”与用户偏好权重(即使不平衡为 100:1)非常有利于传播,在每个区域的每个节点上放置至少一个“代表性”pod(包括非- 最小可能权重为 1) 的首选。

但是,如果您创建一个将充当“主”或“锚”的单副本容器(一个自然示例是数据库),则可以克服此默认区域传播问题。对于这个单 pod,“master”nodeAffinity仍然可以正常工作——当然在 HA 变体中,即“preferred”而不是“required”版本。至于其余的多 pod 应用程序,您使用其他东西 - podAffinity(这次是在“必需”版本中),这将使“从属”pod 在区域之间跟随它们的“主”,因为设置任何基于 pod 的传播都会禁用默认区域传播。您可以拥有任意数量的“从属”pod 副本,并且永远不会遇到一个放错位置的 pod(至少在计划时间),因为“必需” 用于“奴隶”的亲和力。请注意,已知的限制nodeAffinity在这里也适用:“主”pod 副本的数量不得超过一个区域中的节点数量,否则“区域扩展”将启动。

下面是一个示例,说明如何正确标记“主”pod,以便podAffinity使用部署配置 YAML 文件:https ://stackoverflow.com/a/70041308/9962007

于 2021-11-19T23:21:18.957 回答
1

将此评论发布为社区 wiki 以获得更好的可见性,请随时编辑和扩展。


解决这个问题的最佳选择是使用istio - Locality Load Balancing. 链接中的要点:

位置定义了网格中工作负载实例的地理位置。以下三元组定义了一个位置:

  • Region:代表一个大的地理区域,比如us-east。一个区域通常包含许多可用区。在 Kubernetes 中,标签 topology.kubernetes.io/region 确定节点的区域。

  • 区域:区域内的一组计算资源。通过在一个区域内的多个区域中运行服务,可以在区域内的区域之间发生故障转移,同时保持与最终用户的数据本地性。在 Kubernetes 中,标签 topology.kubernetes.io/zone 确定节点的区域。

  • 子区域:允许管理员进一步细分区域以获得更细粒度的控制,例如“同机架”。Kubernetes 中不存在子区域的概念。因此,Istio 引入了自定义节点标签 topology.istio.io/subzone 来定义一个子区域。

这意味着在barregion 的 zone 中运行的 pod 不被认为是在 zone的 zone 中foo运行的 pod 的本地。barbaz


评论中建议了另一个可以考虑流量平衡调整的选项:

用于nodeAffinity实现调度podsnodes特定“区域”之间的一致性。

目前有两种类型的节点亲和性,称为 requiredDuringSchedulingIgnoredDuringExecutionpreferredDuringSchedulingIgnoredDuringExecution。您可以将它们分别视为“硬”和“软”,因为前者指定了将 pod 调度到节点上必须满足的规则(类似于 nodeSelector,但使用更具表现力的语法),而后者指定调度程序将尝试强制执行但不保证的首选项。名称中的“IgnoredDuringExecution”部分意味着,类似于 nodeSelector 的工作方式,如果节点上的标签在运行时发生更改,从而不再满足 pod 上的亲和性规则,则 pod 会继续在节点上运行。未来我们计划提供与 podrequiredDuringSchedulingRequiredDuringExecution相同的功能,requiredDuringSchedulingIgnoredDuringExecution 只是它将从不再满足 pod 的节点亲和性要求的节点中驱逐 pod。

因此,一个示例requiredDuringSchedulingIgnoredDuringExecution 是“仅在具有 Intel CPU 的节点上运行 pod”,另一个示例 preferredDuringSchedulingIgnoredDuringExecution是“尝试在故障区域 XYZ 中运行这组 pod,但如果不可能,则允许一些在其他地方运行”。

更新:根据@mirekphd 的评论,它仍然不能以它被要求的方式完全运作:

事实证明,在实践中,Kubernetes 并没有真正让我们关闭辅助区域,只要我们启动了实际数量的 pod 副本(只需几个就足以看到它)......它们至少保留一些 pod 在其他区域/DC/区域的设计(当您意识到它消除了对 docker 注册表生存的依赖时,这很聪明,至少在标记图像的默认 imagePullPolicy 下), GibHub 问题 #99630 - NodeAffinity preferredDuringSchedulingIgnoredDuringExecution 不能正常工作

请参考@mirekphd 的回答

于 2021-11-19T14:22:05.503 回答