当前位置: 首页 > 科技观察

我们如何在没有停机的情况下将ZooKeeper迁移到Kubernetes

时间:2023-03-20 11:11:49 科技观察

我们最近将数百个ZooKeeper实例在没有停机的情况下迁移到了Kubernetes。我们利用endpoints等Kubernetes强大的特性来简化迁移过程,和我们一样想做Zookeeper迁移的人可以在本文中找到答案。迁移所需的网络条件在文末列出。1、传统的ZooKeeper迁移方式ZooKeeper是很多分布式系统的基础,它为这些系统聚集在一起形成集群提供了一个强大的平台。它提供了一种比较基本的集群形成方法:每个服务器实例都有一个配置文件,其中列出了集群成员的主机名和数字ID,所有服务器都有相同的集群成员列表,如下所示:server.1=host1:2888:3888server.2=host2:2888:3888server.3=host3:2888:3888每个服务器都有一个名为myid的文件,用来表示它对应于列表ID中的第几号。集群可以随意添加和删除服务器,只要不违反这个关键规则:每个服务器必须能够与配置文件中列出的仲裁服务器通信。传统的ZooKeeper服务器迁移步骤主要包括:启动一个新主机,在服务器列表配置中添加“server.4=host:4...”;更新现有主机上的配置文件,添加新的服务器条目,或删除退役的主机;滚动重启旧主机(3.4x版本分支不提供动态服务器配置);更新客户端的连接字符串。这种方法的缺点是它需要大量的配置文件修改和滚动重启,这可能无法可靠地自动化。在将ZooKeeper迁移到Kubernetes之前,我们也考虑过这种方法,但发现了一种更简单的方法。这种方法要安全得多,因为根据我们的经验,每次新领导人选举都有可能导致依赖它们的系统崩溃。2、新的迁移方式我们将现有的ZooKeeper服务器打包成一个Kubernetes服务,然后使用相同的ZooKeeperID从服务器到Pod进行一对一的替换。这只需要滚动重启来重新配置现有的ZooKeeper实例,然后一个接一个地关闭服务器。但是,我们不会深入探讨如何为ZooKeeper配置Kubernetes拓扑,也不会深入探讨底层就绪检查机制,因为有很多方法可以做到这一点。我们将分五个步骤进行迁移:确保ZooKeeper集群已准备好进行迁移;在Kubernetes中创建一个ClusterIP服务,将Zookeeper包装成一个服务;修改ZooKeeper客户端,使其连接到ClusterIP服务;配置ZooKeeper服务器实例,使其可以基于ClusterIP服务地址进行点对点事务;通过KubernetesPod运行ZooKeeper实例。对于以下每个步骤,我们将提供基础架构拓扑图。为了便于理解,这些图中只包含两个ZooKeeper实例(实际上,通常不会创建少于三个节点的集群)。先决条件到位让我们从一个工作的ZooKeeper集群开始,确保主机上的服务可以与Kubernetes集群通信。文末介绍了几种方法。图1:初始状态,具有两个实例和一些客户端的ZooKeeper集群创建一个ClusterIP服务为每个ZooKeeper服务器创建一个ClusterIP服务,具有匹配的端点,允许客户端端口(2181)和集群内部端口(2888、3888)通过。完成后,您可以通过这些服务主机名连接到ZooKeeper集群。KubernetesClusterIP服务此时很有用,因为它们提供静态IP地址,可以充当后端pod的负载均衡器。我们将它们用于从服务到Pod的一对一映射,有效地为每个Pod提供一个静态IP地址。图2:我们的集群可通过ClusterIP服务访问(ZooKeeper仍在物理硬件上运行)重新配置客户端一旦您可以通过KubernetesClusterIP服务连接到ZooKeeper集群,就该重新配置客户端了。如果您在ZooKeeper连接字符串中使用CNAME记录,请修改DNS记录。如果客户端在连接失败时没有重新解析DNS条目,则重新启动客户端。如果您不使用CNAME记录,则需要使用新的连接字符串并重新启动客户端。此时,新旧连接字符串都可以使用。图3:客户端现在通过ClusterIP服务实例与ZooKeeper集群通信重新配置ZooKeeper实例接下来,我们将让ZooKeeper服务器通过ClusterIP服务进行对等通信。为此,我们将修改配置文件以合并ClusterIP服务的地址。zk_quorum_listen_all_ips标志也需要在这里配置,否则ZooKeeper实例将无法成功绑定到主机接口上不存在的IP地址,因为它是Kube服务IP。server.1=zk1-kube-svc-0:2888:3888server.2=zk2-kube-svc-1:2888:3888server.3=zk3-kube-svc-2:2888:3888zk_quorum_listen_all_ips:trueserver.1=zk1-kube-svc-0:2888:3888server.2=zk2-kube-svc-1:2888:3888server.3=zk3-kube-svc-2:2888:3888zk_quorum_listen_all_ips:true滚动重启这些主机,后面就可以开始准备了host被pod取代。图4:ZooKeeper实例现在通过ClusterIP服务与其他实例通信使用Pod而不是ZooKeepermasters我们将执行这些步骤,一次一个服务器:选择一个ZooKeeper服务器及其对应的ClusterIP服务;关闭服务器上的ZooKeeper进程;使用与被关闭的ZooKeeper具有相同服务器列表配置和myid文件的Pod;等待Pod中的ZooKeeper启动并与其他ZooKeeper节点同步数据。就是这样,ZooKeeper集群现在在Kubernetes中运行,其中包含所有以前的数据。图5:更换后的集群。ZK1在Pod中运行,ZK2不需要知道发生了什么。网络先决条件要成功完成这些步骤,您需要确保某些网络设置符合要求。您需要确保:Kubernetespod的IP地址可以从所有需要连接到ZooKeeper的服务器重新路由;所有需要连接到ZooKeeper的服务器都必须能够解析Kubernetes服务主机名;所有需要连接到ZooKeeper的服务器都必须运行能够访问ClusterIP服务。这些可以通过多种方式实现。我们使用内部网络插件,类似于Lyft插件:https://github.com/aws/amazon-vpc-cni-k8s或AWS插件:https://github.com/lyft/cni-ipvlan-vpc-k8s可以直接将AWSVPCIP地址分配给pod,而不是使用虚拟覆盖网络,因此可以从任意实例重新路由pod的IP。Overlay网络(比如flannel)也是可以的,只要所有服务器都能连接到overlay网络即可。