论跨Kubernetes集群Pod通信的必要性和实现方式_java





跨Kubernetes集群pod通通信的必要性

截止到2020年,K8S已经基本统一了容器调度平台。也就是说,K8S、OpenShift已经像Linux那样,成为了一种平台产品(当然层级不同)。一个产品一旦成为平台,那随之对其高可用、灾备,甚至双活的需求就来了。

OCP(OpenShift的简称)的高可用设计此前很多文章已经介绍过了,我去年发行的那本《OpenShift在企业中的实践》也讲的十分细致,不再赘述。

论跨Kubernetes集群Pod通信的必要性和实现方式_java_02


但目前无论是OCP还是K8S,都不能实现真正意义上的双活。

什么是真正意义上的双活?就是两个数据中心的两个OCP集群上,部署一个应用,当主数据中心出现问题,业务不受到影响。

在虚拟机时代,我们要实现双活,很关键一点是打通大二层。也就是说,两个DC的VM不仅可以直接通讯,而且要在一个二层网络里,这样才能让应用双活。


在K8S时代,情况类似,想要在两个DC部署一个应用,就必须要能做到pod的跨集群通信。如果解决不了这个问题,那么双活只能是在两个DC两个OCP集群各部署一套应用(建议使用模板),然后前面接负载均衡器。



跨Kubernetes集群pod通信的实现

在目前阶段,针对OCP,如果想实现pod跨集群访问,主要有两种方法:

(1) 通过使用OCP4的多网络平面,将pod的第二个虚拟网卡的IP与数据中心拉齐。这样技术跨DC,只要网络可达,那么pod之间就可以直接通信了。这里我推荐使用macvlan。关于多网络平面的macvlan的配置步骤,我之前已经分享过了。这种方法好处是:性能高(macvlan性能好)、配置简便。缺点是:IP用的多,如果把OCP部署到公有云上,IP资源是按照个数收钱的。

(2)Submariner开源项目

Submariner是一种用于连接不同Kubernetes群集的覆盖网络的工具。虽然大多数测试都是针对启用了Flannel / Canal / Weavenet / OpenShiftSDN的Kubernetes集群执行的,但是Submariner应该与任何与CNI兼容的集群网络提供商兼容,因为它利用了StrongSwan / Charon等现成的组件来建立IPsec隧道。


请注意,Submariner处于预Alpha阶段,不应用于生产目的。



Submariner的架构

Submariner由可以在Kubernetes自定义资源定义(CRD)中运行的一些组件组成。Submariner CRD是clusters.submariner.io和endpoints.submariner.io。


Submariner的前提:

  • At least 2 Kubernetes clusters, one of which is designated to serve as the central broker that is accessible by all of your connected clusters; this can be one of your connected clusters, but comes with the limitation that the cluster is required to be up in order to facilitate interconnectivity/negotiation

  • 至少有两个K8S集群,其中一个是central broker,负责多个集群之间的信息交互枢纽。

  • Different cluster/service CIDR's (as well as different kubernetes DNS suffixes) between clusters. This is to prevent traffic selector/policy/routing conflicts. Note: Submariner also supports clusters with Overlapping CIDRs via Globalnet Controller.

  • 不同集群使用不同的CIDR

  • Direct IP connectivity between instances through the internet (or on the same network if not running Submariner over the internet). Submariner supports 1:1 NAT setups, but has a few caveats/provider specific configuration instructions in this configuration.

  • 如果Submariner在互联网上运行,那么不同Submariner实例之间需要使用IP直连。

  • Knowledge of each cluster's network configuration

  • Helm version that supports crd-install hook (v2.12.1+)

  • Worker node IPs on all the clusters must be outside of the cluster/service CIDR ranges.

  • OCP集群worker node的ip不能和Submariner集群在一个网段


相连集群中的两个主要Submariner组件是:

  • Submariner gateway(DaemonSet)

  • submariner-route-agent(DaemonSet)

Submariner gateway Pod在带有网关标签的节点上运行,并在它们之间进行leader选举,以选择活动的IPsec端点。submariner-route-agent组件在每个节点上运行,并且知道当前的活动网关。当在活动网关节点上运行时,submariner-route-agent将通过与活动网关节点的VTEP建立VXLAN隧道,创建一个VxLAN VTEP接口,其他工作节点上运行的submariner-route-agent实例将连接到该接口。submariner-route-agent还配置路由并编写必要的iptable规则,以实现与远程集群的完全连接。Submariner VxLAN隧道的MTU是基于主机上默认接口的MTU减去VxLAN开销来配置的。


启动后,被选为leader的Submariner gateway pod将执行协调过程,以确保它是该群集的唯一端点。这就是为什么在群集之间具有唯一的群集ID很重要的原因之一,因为具有相同ID的两个群集将相互协调而不存在。


发生故障后,另一个submariner-gateway pod(在其他网关节点之一上)将获得领导权并执行和解,以确保它是活动的leader。完成后,远程群集将IPsec端点与新端点协调,并重新建立连接。此外,submariner-route-agent pod将更新每个节点上的路由表,以指向新的活动网关节点。


Submariner使用center broker促进信息交换并在群集之间同步CRD。数据存储同步器在leader选举的Submariner pod内作为控制器运行,并负责在数据存储区和Submariner CRD的本地群集之间执行双向同步。datastoresyncer仅将CRD数据推送到本地集群的中央代理(基于集群ID),并且当数据与本地集群不匹配时,将从本地代理将来自代理的所有数据同步到本地集群(以防止循环循环)




现在OCP4上已经有Submariner Operator了。

论跨Kubernetes集群Pod通信的必要性和实现方式_java_03

论跨Kubernetes集群Pod通信的必要性和实现方式_java_04

论跨Kubernetes集群Pod通信的必要性和实现方式_java_05

由于这个方案处于初期(使用大概率会遇到bug),我们暂不进行功能验证。


结论

在目前情况下,如果跨OCP集群pod的通信是小范围使用,建议使用多网络平面+macvlan。我在项目中遇到的比较典型的场景是:两个OCP集群都运行SpringCloud,但服务注册中心在第三个OCP集群上,这时候就需要pod与注册中心直连。