我们最近将数百个ZooKeeper实例从单独的服务器实例迁移到了Kubernetes,而期间没有停机。我们使用了强大的Kubernetes功能(例如端点)来简化流程,本文主要把迁移心得分享给大家,方便有同样需求的小伙伴们参考。有关一些重要的前提条件,比如网络,请参见最后。
传统ZooKeeper迁移
ZooKeeper是许多分布式系统的基础,这些分布式系统主要依靠ZooKeeper来组成集群,从而发挥分布式系统的威力。在幕后,它依靠一致性方法来组成集群:每个服务器实例都有一个配置文件,其中列出了所有成员主机名和数字ID,并且所有服务器都具有相同的服务器列表,如下所示:
server.1=host1:2888:3888
server.2=host2:2888:3888
server.3=host3:2888:3888
每个服务器都有一个名为myid的唯一文件,以告诉它与该列表对应的数字id。
只要不违反关键规则,就可以添加和删除主机:每台服务器必须能够达到其配置文件中列出的服务器的法定人数(定义为简单多数)。传统方式将ZooKeeper服务器迁移到新实例的涉及到较多方面:
- 在服务器列表中使用“server.4 = host:4…”配置并启动新主机
- 更新现有主机上的配置文件以添加新服务器条目,并从其服务器列表中删除已淘汰的主机
- 滚动重启旧主机(3.4x分支中没有动态服务器配置)
- 更新客户端中的连接字符串(如果客户端在错误时重新解析DNS,则可能只是更改CNAME记录)
这种方法的缺点是许多配置文件更改和滚动重新启动,您可能没有可靠的自动化解决方案。当我们开始将ZooKeeper迁移到Kubernetes时,我们开始考虑这种方法,但想出了一种更简单的方法。因为根据我们的经验,每次新领导人选举都有很小的风险,即花费足够长的时间来压倒依赖他们的系统。
新方法
我们的方法是将现有的ZooKeeper服务器部署在Kubernetes服务中,然后使用相同的ZooKeeper ID进行一对一的服务器到Pod替换,这只需要一次滚动重启就可以重新配置现有的ZK实例,然后逐个关闭服务器。我们不会在这里讨论为ZooKeeper配置Kubernetes拓扑的方法,也不会讨论简单的只读健康检查,这是很细节的,因为不同的方法可以实现同一个目的,只不过每种方法有优点和缺点。下面讨论的概念也是一样的。
我们将分五个步骤进行:
- 完成前提条件,以确保我们的ZooKeeper集群已准备好迁移
- 在部署ZooKeeper服务的Kubernetes中创建ClusterIP服务
- 配置ZooKeeper客户端以连接到ClusterIP服务
- 配置ZooKeeper服务器实例以通过ClusterIP服务地址执行对等事务
- 用KubernetesPod中的ZooKeeper实例替换服务器上运行的每个ZooKeeper实例
对于下面的每个步骤,我们都将包含一个基础架构拓扑图,这些图将仅包含两个ZooKeeper实例,以便于理解,即使一个不想创建少于三个的集群也是如此。
完成先决条件
从一个可用的ZooKeeper集群开始,我们将要确保主机上的服务能够与我们的Kubernetes集群进行通信。在本文结尾处,我们提供了几种方法来实现这一点。
创建 ClusterIP 服务
为每个ZooKeeper服务器创建具有匹配的Endpoint资源的ClusterIP服务,它们应该暴露客户端端口(2181)和集群内部端口(2888,3888)。完成后,您应该能够通过以下方式连接到ZooKeeper集群。Kubernetes ClusterIP服务在这里很有用,因为它们为您提供了充当后端Pod的负载平衡器的静态IP地址,在这种情况下,我们将它们与服务到Pod的1:1映射一起使用,因此我们拥有静态每个Pod的IP地址。
重新配置ZooKeeper client
一旦能够通过Kubernetes ClusterIP服务连接到ZooKeeper群集,则是暂停并重新配置所有客户端的好时机。如果您在ZooKeeper连接字符串中使用CNAME记录,请更改DNS记录。最简单的方法是重新启动所有客户端。否则它们将在连接失败时重新解析DNS条目;如果您不使用CNAME记录,则需要使用新的连接字符串并重新启动所有客户端进程。在此时,新的连接字符串和旧的链接字符串仍然可以使用。
重新配置ZooKeeper实例
接下来,我们将使ZooKeeper服务器通过这些ClusterIP服务进行对等通信,为此,我们将修改配置文件以合并ClusterIP服务的地址。配置zk_quorum_listen_all_ips也很重要:没有它,ZK实例将无法尝试绑定到主机上任何接口上都不存在的ip地址,因为它是K8S服务IP。
server.1=zk1-kube-svc-0:2888:3888
server.2=zk2-kube-svc-1:2888:3888
server.3=zk3-kube-svc-2:2888:3888
zk_quorum_listen_all_ips: true
滚动重启这些主机,现在我们准备开始用pod替换主机。
用Pod 替换 ZooKeeper 主机
一次替换一台服务器,我们将执行以下步骤:
- 选择一个ZK服务器及其对应的ClusterIP服务
- 关闭服务器上的ZK进程
- 启动一个配置为与关闭的ZK服务器相同的服务器列表和myid文件的Pod
- 等待Pod中的ZK启动并同步来自其他ZK节点的数据
就是这样,您的ZooKeeper集群现在已经在Kubernetes中运行,并且具有所有先前的数据。
网络先决条件
为了使这些步骤正常工作,需要处理一些网络设置。您需要采取步骤来确保以下各项:
- 需要从所有需要连接到ZooKeeper的服务器上路由Kubernetes Pod IP地址
- 所有连接到ZooKeeper的服务器都必须能够解析Kubernetes服务主机名
- Kube-proxy必须在所有需要连接到ZooKeeper的服务器上运行,以便它们可以访问ClusterIp服务
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。