腾讯微服务平台TSFMesh统一容

北京哪里看白癜风 https://wapjbk.39.net/yiyuanzaixian/bjzkbdfyy/

导读

随着业务的增长,一些传统企业对诸如灰度发布、服务路由、服务熔断、服务限流等服务治理的需求越来越强烈,但他们又不想对业务代码做大量的改造,因而ServiceMesh成了他们比较好的选择;不幸的是业内比较成熟能落地的ServiceMesh方案如Istio都是基于各种容器平台构建的,而这些传统企业很多没有接入容器平台也不想做容器化改造,这就导致Servicemesh很难应用于这些传统企业或者一些非容器化的场景。

作者介绍

张培培

腾讯云微服务团队高级工程师

TSFMesh研发及负责人

热衷于云原生和开源技术,在容器、ServiceMesh、消息队列、区块链等领域拥有丰富经验,目前致力于ServiceMesh技术的落地和推广

前言

为了兼容Servicemesh的非容器化场景,TSFMesh基于Istio构建了Servicemesh微服务平台,对原生Istio实现进行了适当的改造,支持应用同时运行于容器环境和虚拟机环境(同时也打通了SpringCloud框架,实现Mesh服务和SpringCloud服务互联互通,服务统一治理)。

TSFMesh对容器和虚拟机统一化的改造主要体现在以下几个方面:

应用部署和Sidecar注入流量劫持服务注册与发现

针对这几点,下面会先剖析对比Istioservicemesh基于K8s的实现方案,再讲述TSFMesh是如何实现的,做了哪些改造。

应用部署和Sidecar注入

首先,回顾下Istioservicemesh的应用部署和Sidecar注入方式:

应用部署:Istioservicemesh依赖K8s进行应用的生命周期管理,包括应用的部署和管理(扩缩容、自动恢复、发布)

Sidecar注入:分为手动注入和自动注入,如下图所示:

手工注入通过手工执行istioctlkube-inject来重新构造应用的CRDyaml

自动注入通过K8s的mutablewebhook回调istio-sidecar-injector服务来重新构造应用的CRDyaml

无论是手工注入还是自动注入,Sidecar注入的本质是将运行Sidecar所需要的镜像地址、启动参数、所连接的Istio集群(Pilot、Mixes、Citadel)及配置信息填充到注入模版,并添加到应用的CRDyaml中,最终通过K8s持久化资源并拉起应用和Sidecar的POD。

那TSFMesh如何做应用部署和Sidecar注入的呢?

由于TSFMesh需要同时支持容器和虚拟机环境,则首先需要解决虚拟机部署的问题,要实现等同K8s的部署能力,需要解决以下几个问题:

资源和配置管理,如Istio集群信息、配置信息等对应于容器的镜像,虚拟机就是程序包,那就涉及到包管理虚拟机应用生命周期的管理虚拟机Sidecar注入

为了解决容器和虚拟机统一部署问题,不能再用K8s的存储方式,而是需要更高层的管理模式,我们引入了tsf-resource资源管控模块来负责容器和虚拟机相关资源的统一管理,像Istio集群相关的信息在控制平台部署时会持久化在TSF的DB中。

对于容器平台,当用户从TSF控制台部署一个容器应用时,tsf-resource从DB中获取像容器的镜像地址、Istio集群信息、配置、启动参数等,进行K8sCRD的组装,组装完将CRD创建请求发送给容器平台完成应用POD的拉起,其实这里在组装CRD时已经实现了Sidecar的自动注入,注入时的动态参数由控制台传递,静态参数如Sidecar镜像地址、启动参数等从DB中获取。

对于虚拟机平台,TSF引入了以下几个模块来解决程序包管理和应用部署的问题:

tsf-repo,程序包仓库管理,存储应用程序包及相关依赖tsf-master,虚拟机节点管理master,发送部署/下线/启动/停止等任务给tsf-agenttsf-agent,虚拟机节点管理agent,部署在应用机器上,负责初始化机器环境、执行应用部署/下线/启动/停止等任务

对于虚拟机应用的变更,如例如应用部署、启动、停止、下线,TSF通过任务的方式来跟踪每个变更,在任务下发的具体流程中,所有任务都是异步执行的,tsf-resource将任务转发给tsf-master后就返回给TSF控制台,并由tsf-master完成任务的下发和状态跟踪;用户在TSF控制台执行操作后,可以根据返回的任务ID查询执行结果。

流量劫持

Servicemesh需要透明的进行服务治理,也就需要透明的接管服务进出流量,将流量劫持到Sidecar,由Sidecar进行流量管理,传统的方式是iptables流量劫持(也可采用BPF、IPVS等方式),同样下面先回顾下Istio的Servicemesh方案具体是如何劫持流量的,然后再看下TSFmesh为了统一容器和虚拟机做了哪些改造。

查看经过Sidecar注入后的应用YAML文件,发现istio-sidecar-injector服务在注入Sidecar容器本身时,还注入了istio-init容器,istio-init容器属于init容器(init容器在应用程序容器启动之前运行,用来初始化一些应用镜像中不存在的实用工具或安装脚本),下面是官方例子中注入的init容器部分:

initContainers:-args:--p-""--u-""--m-REDIRECT--i-*--x-""--b-,--d-""image:istio/istio-release-proxy_init:1.0.1imagePullPolicy:IfNotPresentname:istio-initresources:{}securityContext:capabilities:add:-NET_ADMINprivileged:true...

可以看出init容器istio-init,被赋予了NET_ADMIN的POD网络空间权限,具体执行了哪些初始化还看不出来,那再来看下istio/istio-release-proxy_init:1.0.1镜像的Dockerfile。

FROMubuntu:xenialRUNapt-getupdateapt-getinstall-y\iproute2\iptables\rm-rf/var/lib/apt/lists/*ADDistio-iptables.sh/usr/local/bin/ENTRYPOINT["/usr/local/bin/istio-iptables.sh"]

istio-init容器的ENTRYPOINT是/usr/local/bin/istio-iptables.sh脚本,顾名思义用于Istioiptables流量劫持的脚本,组合上面istio-init容器的启动参数,完整命令为:

/usr/local/bin/istio-iptables.sh-p-u-mREDIRECT-i*-x""-b-d""

该命令的主要作用是,将应用容器中访问端口的流量(inbound流量)和所有出站流量(outbound流量)重定向到Sidecar(即envoy)的端口。

总结下来,Istio是通过init容器完成了流量劫持到Sidecar的初始化工作。

TSFMesh如何实现流量劫持的呢?

TSFMesh同样采用iptables方式,不过要兼顾虚拟机平台,需要解决两个主要问题:

虚拟机下如何执行iptables应用劫持策略虚拟机下如何劫持流量,不能劫持虚拟机整个网络空间的流量

问题1的解决比较简单,我们对pilot-agent做些一些扩展,在pilot-agent中执行iptables脚本,pilot-agent一个主要工作是生成envoy的bootstrap配置并启动envoy、管理envoy的生命周期,类似容器环境下做envoy启动前的init准备,在启动envoy前执行iptables脚本,也比较合理。

问题2的解决就比较麻烦了,但又非常重要,不像K8s的POD,POD间网路是隔离的,一个POD一般只会运行一个应用,劫持整个POD网路空间里的流量完全没有问题,而虚拟机中可能还有其它进程的存在,这些进程可能也有Outbound的流量,因此我们不能劫持虚拟机所有的流量,一种比较合理的劫持方案应该是:

对于Inbound流量,只劫持到部署应用的端口,这个原生Istio已经做到,无需改造对于Outbound流量,只劫持注册中心已注册服务的流量

下面来具体讲下TSFMesh如何针对服务来劫持Outbound流量的。

其实我们的方案和K8s的kube-DNS+kube-proxy的服务发现机制类似,TSFMesh在数据平面引入了一个mesh-dns模块,通过连接pilot-discovery同步获取注册中心的服务变更来更新本地的DNScache,对于来自注册中心的服务会被解析到一个特定的IP,然后在iptables策略中把目的地址到这个特定IP的流量重定向envoy,当然,还需要劫持DNS53端口的流量,先把DNS请求引到mesh-dns,可以看下iptablesnat表中完整的规则内容:

Inbound流量劫持跟原生Istio实现类似就不赘述了,下图显示的是Outbound流量iptables劫持的详细过程,其中红色部分为新增的DNS劫持规则。

注册服务的域名劫持,除了引入了mesh-dns自研模块,还涉及到pilot-discovery和pilot-agent的改造:

pilot-discovery改造点

pilot-discovery扩展一个ServiceInfos的grpc服务,提供注册服务变更同步接口pilot-discovery早期的consulcontroller实现是,定时通过Consul的RestAPI获取服务数据并和上一次的查询结果进行对比,如果数据发生了变化则通知Pilotdiscovery进行更新,这里我们进行了优化,采用Consul的watch机制来代替轮询(下面服务注册与发现中也有提到),并在ServiceInfos服务初始化时向consulcontroller注册了服务变更的event通知ServiceInfos服务在mesh-dns请求第一次到来时同步全量的服务注册表,之后则根据服务的变更情况增量同步

mesh-dns实现

DNS服务基于github.



转载请注明地址:http://www.sanbaicaoasb.com/scls/8471.html
  • 上一篇文章:
  • 下一篇文章:
  • 热点文章

    • 没有热点文章

    推荐文章

    • 没有推荐文章