前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >通过“服务镜像”实现多集群Kubernetes

通过“服务镜像”实现多集群Kubernetes

作者头像
CNCF
发布2020-03-04 17:39:14
1.1K0
发布2020-03-04 17:39:14
举报
文章被收录于专栏:CNCFCNCF

作者:Thomas Rampelberg

在我们之前的文章多集群Kubernetes的架构设计,我们概述了构建一个简单但有弹性的Kubernetes多集群方法的三个要求:支持分层网络、保持集群状态的独立性、不引入共享控制平面。

在这篇文章中,我们将提出一个我们认为满足这些约束的解决方案,称为服务镜像(service mirroring)。为了遵循Linkerd的“保持简单”的设计原则,我们已经尽了最大的努力来构建这个纯Kubernetes基本功能的解决方案,并且删除了对Linkerd本身的任何依赖。这使我们能够使任何解决方案尽可能接近Kubernetes本身。换句话说,服务网格应该做的更少,而不是更多。

我们目前正在积极地构建这种方法的原型,希望得到你的反馈。继续往下读,了解更多细节以及如何参与其中。

介绍

构建一个有效的多集群Kubernetes架构面临许多挑战,包括配置、监视、部署和流量管理。在这些挑战中,我们认为服务网格可以直接解决三个特定领域:

  • 可观察性:服务网格可以提供跨集群的应用程序行为的统一视图。
  • 安全性:服务网格可以为跨集群流量提供身份验证、授权和机密性方面的保证。
  • 路由:服务网格可以使一个集群中的应用程序与另一个集群中的应用程序进行通信变得可能和“容易”。

今天,通过跨多个集群独立运行Linkerd、将度量聚合到外部Prometheus或Thanos、在DNS中共享服务信息、使用cert-manager在集群入口控制器上旋转cert,可以构建一个多集群设置来实现上述许多目标。(参见我们的:Multicluster the Kubernetes Way with Linkerd。)

https://docs.google.com/document/d/1yDdd5nC348oNibvFAbxOwHL1dpFAEucpNuox1zcsOFg

虽然功能强大,但是这种方法在跨集群调用方面有几个缺点。与集群内调用不同,这种方法中的跨集群调用没有完整的度量标准,不能跨集群保留源标识,也不能成为流量分割的目标。最重要的是,即使要做出这些部分保证,应用程序本身也必须区分集群内调用和跨集群调用。这与Linkerd不要求更改应用程序的目标背道而驰。

进入服务镜像。

服务镜像

服务镜像的目标是允许像Linkerd这样的服务网格为集群内调用(身份、流量转移等)提供的相同保证也应用于跨集群调用。顾名思义,服务镜像是通过在集群之间“镜像”服务信息来工作的。有了服务镜像,Linkerd的完全可观察性、安全性和路由特性统一应用于集群内和集群调用,应用程序不需要区分这些情况。

服务镜像是Kubernetes操作器(Operator)。安装后,它将在本地镜像远程集群的服务,以提供服务发现并允许pod引用远程服务。它还管理端点的配置,以便将流量发送到正确的IP地址。(更多细节如下。)

敏锐的读者可能会注意到,服务镜像实际上并不需要服务网格。相反,服务镜像是一个独立的组件,可以与其他项目很好地组合在一起。这不仅适用于服务镜像的潜在用户,也适用于服务镜像本身。例如,服务镜像的网关组件可以通过设计进行插件,并且可以由Ambassador、Gloo和Traefik等项目实现。

为了理解服务镜像是如何工作的,让我们快速浏览一下Kubernetes在法国大革命中心的起源。

两个集群的故事

这是最好的时代,也是最坏的时代。我们有两个Kubernetes集群需要在它们之间发送流量。让我们通过描述这些集群并选择一个特定的任务来设置场景。

两个集群

在左边,伦敦(London)有一个名为foo-client的pod。在右边,巴黎(Paris)有一个叫bar的服务。我们如何使foo-client pod向bar服务发出请求成为可能?

第一步:服务发现

伦敦集群中的Pod需要向巴黎的bar服务发送请求。通常,这将使用服务名称来完成。但是,bar在另一个集群上!让我们将服务定义从巴黎复制到伦敦。

复制服务

此时,bar服务已经复制到伦敦。添加远程集群名,既可以避免本地冲突,又可以允许pod显式地选择将请求发送到集群之外。很快,伦敦的pod将能够开始解析完整的服务名称bar-paris.default.svc.cluster.local。在伦敦的bar-paris服务具有ClusterIP类型。伦敦将创建一个虚拟IP地址,用作对pod的响应,解析bar-paris的服务名称。

通过从巴黎复制服务到伦敦,我们正在维护独立的状态--这是我们的要求之一。巴黎有自己的状态,伦敦有自己的状态,它们并不互相依赖。如果伦敦和巴黎之间的连接中断,服务更新将停止。不过没关系!由于网络连接中断,从伦敦到巴黎的通信无法畅通。

不幸的是,我们还不能向目的地传送数据。巴黎bar的pod选择器(selector)和伦敦的pod不匹配。实际上,我们可能应该删除选择器,以防万一。我们打算到达巴黎的通信意外地停在伦敦,这是无意的。删除选择器使我们能够将服务抽象到pod之外,并使用不同的后端。

没有选择器,就无法自动创建端点对象。Kubernetes不知道该看什么,因为我们没有给它足够的信息。拥有一个没有选择器的服务是Kubernetes的设计初衷!像Kubernetes中的所有资源一样,你可以自己创建和管理它们。因此,如果我们可以自己创建一个端点并将其指向某个地方,那么应该将流量转发到哪里呢?

https://kubernetes.io/docs/concepts/services-networking/service/#services-without-selectors

第二步:端点杂耍

可以将所有端点连同服务定义从巴黎复制到伦敦。根据服务中有多少pod,这可能是很多数据!看看endpointslice,了解跨集群复制端点会消耗多少带宽。即使有了这个问题的解决方案,复制单独的pod IP地址也不支持分层网络--这是我们的另一个要求。与其在集群之间移动所有这些状态,不如引入一个端点来负责将流量路由到正确的目的地。

复制端点

我们在巴黎推出了一项新服务。使用LoadBalancer类型,网关服务将分配一个负载均衡器。这个负载均衡器将有一个公共IP地址,可以在巴黎内部转发流量。我们现在有了伦敦的请求应该发送到哪里的答案!

为了让一切正常工作,我们现在可以创建一个包含这个公共IP地址的端点资源,并将流量发送到那里。此时,在伦敦发出的请求将解析到bar-paris的集群IP,并被重写到巴黎网关服务的公共IP地址。如果网关服务的选择器目标是与bar相同的pod,那么此时一切都可以正常工作。

到目前为止,我们的计划有两个重要的问题。云负载平衡器很昂贵,公共ip地址很少,而且间隔很远。为集群内的每个服务创建外部负载均衡器将很快耗尽ip地址,并将成本推高到无法接受的水平。

也许更重要的是,如果网关服务直接指向bar,那么在更大的internet上就可以使用潜在敏感的内部服务。可以在单个负载均衡器上多路复用服务并限制与授权客户端的连接性的是什么?

第三步:网关

如果你认为这个问题的解决方案听起来很像一个入口控制器(ingress controller),那么你是对的!入口资源允许为一般情况配置。由于入口规范不支持通配符,因此不可能直接使用入口资源来实现这一点。幸运的是,大多数入口控制器都支持这个用例!事实上,你选择了的入口控制器很可能已经可以在Kubernetes中进行通配符的配置。

网关

现在可以追踪一个请求的生命周期,它起始于伦敦,最终到达巴黎。从伦敦出发,pod将向bar-paris.default.svc.cluster.local发出请求。当pod查询DNS时,它将接收在伦敦的服务的集群IP。在连接时,集群IP将被重写为Paris网关服务的公共IP地址。然后,伦敦的pod将连接到这个IP地址,并将其请求转发给在巴黎的入口控制器。入口控制器可以查看传入请求的主机头并将其重写为本地bar服务。重写后,请求最终可以到达目的地pod,在巴黎bar-server。

通过在Paris运行的负载均衡器传递请求的另一个好处是,可以在集群上本地而不是远程地做出决策。由于本地负载均衡器总是能够更好地了解本地发生的情况,因此决策可能比来自集群外部的决策更优。这里肯定有一个额外的跃点,引入额外的组件将最终在本地集群中进行路由,这确实带来了一些额外的延迟。折衷之处在于,多集群通信并不是特殊情况,服务就像第三方服务一样暴露,而且内部和外部服务之间的工具是相同的。

由于本例中没有私有网络,数据将通过公共internet。因此,对所有跨集群通信进行加密变得至关重要。Linkerd自动完成mTLS开箱即用,透明地处理加密。在集群之间共享根证书允许Linkerd验证连接的两端并对它们之间的所有通信进行加密。共享的根证书允许Linkerd在两个集群中的控制平面完全独立,满足最终的需求。当Linkerd自动化mTLS时,可以配置网关来提供通配符证书,如*.default.svc.cluster.local,然后客户端可以验证该证书。流量将被客户端加密和验证。

注意,网关既适用于TCP,也适用于HTTP,但有一个警告。任意基于TCP的协议将不包含网关将请求转发到正确目的地所需的信息。网关负载均衡器可以映射TCP端口,为每个内部服务保留一个端口。在管理服务和端点时,可以在不需要客户端或服务的情况下进行端口重写。这个简单的解决方案实际上可以通过在TLS层上使用ALPN或SNI之类的东西来显著改进。不幸的是,这些解决方案通常不受支持或不可配置。

简而言之,这就是服务镜像。

想参与吗?

我们希望得到你对服务镜像的反馈。请给我们关于服务镜像设计文档的反馈。你也可以发邮件给cncf-linkerd-dev邮件列表,或者在Linkerd社区Slack上找到我们。我们今天正在积极地构建这个解决方案的原型,希望很快就能有一个功能实现。

Linkerd是一个社区项目,由CNCF托管。如果你有功能需求、问题或评论,我们欢迎你加入我们快速成长的社区!Linkerd代码由GitHub托管,我们在Slack、Twitter和邮件列表上有一个蓬勃发展的社区。快来加入我们的行列吧!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-02-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CNCF 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档