背景
本文基于Flink 1.13.x
Flink on K8S
分析
基于原生K8S(基于ConfigMap) HA的数据交互图如下:
基于Zookeeper HA的数据交互图如下:
可以看到这两者的最大的区别在于:
基于原生K8S的Active JobManager 会在选举成功后,持续向configMap中修改control-plane.alpha.kubernetes.io/leader
的值,control-plane.alpha.kubernetes.io/leader
的值如下:
annotations: control-plane.alpha.kubernetes.io/leader: '{"holderIdentity":"2ab0efc8-1bbc-4aae-800e-135e5d349092","leaseDuration":15.000000000,"acquireTime":"2022-10-08T04:03:26.033000Z","renewTime":"2022-10-11T13:55:46.342000Z","leaderTransitions":58949}'
- 基于Zookeeper的Active JobManager在选举成功后,不会周期性的修改zknode里面的内容
这是为什么?
这是因为两者领导选举机制的实现不一样:
基于K8S原生HA的实现是基于组件KubernetesLeaderElector
基于k8s的HA最终是基于ConfigMap来实现的(谁先创建了configMap就是leader),必须定期的修改configMap里面的某一项值(内部实现是基于renewTime等),来向其他StandBy的JobManger表明,当前Active JobManager是活着的,具体的实现细节参考:KubernetesLeaderElector.run
基于Zookeeper的HA的实现是基于组件LeaderLatch
该方法的实现原理是基于zk的顺序的临时节点来实现的(谁先创建了该节点就是leader),而该方法的实现不需要Active JobManager周期修改里面的数据,因为Zookeeper的临时节点的特性就是,如果创建该节点的客户端挂了,该临时节点会自动删除,这样,其他standBy的JobManager可以通过该临时节点存在与否来判断是否Active节点存在,从而进行领导选举,具体的实现细节见LeaderLatch.internalStart
结论
通过以上分析,我们可以得到如下优劣:
基于K8S原生的HA,会定期修改ConfigMap的值,导致watch该ConfigMap的客户端会定期收到很多事件,而这种定期事件,最终会影响到K8S的ETCD集群的稳定性,从而影响K8S集群的稳定性
基于Zookeeper的HA,只有在Active节点下线以后,watch的节点才会收到对应的事件,相比K8S那种方式,对ZK的压力会小很多。