Rainbond 对接 Istio 原理讲解和代码实现分析

简介: 现有的 ServiceMesh 框架有很多,如 Istio、linkerd等。对于用户而言,在测试环境下,需要达到的效果是快、开箱即用。但在生产环境下,可能又有熔断、延时注入等需求。那么单一的 ServiceMesh 框架无法同时满足用户不同的需求。在之前的 Rainbond 版本中,Rainbond 支持了多种不同的应用治理模式,作为应用级的插件,实现了Istio 治理模式的切换。本文将对Rainbond 实现Istio治理模式进行原理解析。

一、背景

现有的 ServiceMesh 框架有很多,如 Istio、linkerd等。对于用户而言,在测试环境下,需要达到的效果是快、开箱即用。但在生产环境下,可能又有熔断、延时注入等需求。那么单一的 ServiceMesh 框架无法同时满足用户不同的需求。

在之前的 Rainbond 版本中,Rainbond 支持了多种不同的应用治理模式,作为应用级的插件,实现了Istio 治理模式的切换。

本文将对Rainbond 实现Istio治理模式进行原理解析。

二、基本原理

动态准入控制

首先我们需要了解一个知识,Istio 是如何实现自动注入的。实际上,Istio、linkerd 等不同的 ServiceMesh 框架都使用到了 Kubernetes 中的一个非常重要的功能,叫作 Dynamic Admission Control,也叫作:Initializer。

这个功能会在 API 对象创建之后会被立刻调用到。在 API 对象被正式处理前,完成一些初始化的准备工作。所以在部署了 Istio 控制平面以后,当你提交了 API 对象的 Yaml 文件,会被 Istio 的准入控制器捕获,完成一些 PATCH 操作,比如加上对应的 Sidecar 容器字段。最终将这个 PATCH 过后的 API 对象交给 Kubernetes 处理。接下来就详细介绍下 ServiceMesh 框架的注入机制。

如何自动注入

用户需要先在集群中部署 Istio 的控制平面。它会包含一个用来为 Pod 自动注入 Envoy 容器的 Initializer。 首先, Istio 会将 Envoy 容器本身的定义,以 ConfigMap 的方式保存在 Kubernetes 当中。当 Initializer 的控制器,通过 Admission-Webhooks 监听到符合规则【此处指对应的 Annoations】的 API 对象被创建后,读取对应的 ConfigMap 获取到 Envoy 容器的配置。并将相关的字段,自动添加到用户提交的 Pod 的 API 对象里。详见下图和说明。

Process.png

上图为提交yaml文件到Kubernetes集群后,集群所做的处理,大概分为以下几步:

  1. Yaml 文件提交到 APIServer,APIServer 会过滤这个请求,并完成一些前置性的工作,比如授权、超时处理、审计等。

  2. APIServer 会找到该 Pod 对应的类型定义,如果存在,则会将这个 Pod 转换为对象。

  3. 接下来进行 Admission 操作,Admission 操作是在创建之后会被立刻调用到的一组代码,它可以完成一些初始化操作,比如在对象创建前加上某些 Labels,但是由于它本身是被编译到 APIServer 中的,所以用户修改后,需要重新编译并重启 APIServer。幸运的是:Kubernetes 提供了一种“热插拔”式的 Admission 机制,即 Initializer。

  4. 目前 istio、linkerd 等项目均实现了 Initializer 机制,也就是说,当提交的 Yaml 文件包含其指定的Annoations 字段时,那么它们部署的准入控制器则会捕获到对应的 API 对象,在这个阶段为 Pod 进行初始化操作,即添加上 Sidecar 容器的相关配置。

  5. 接下来会进行 Validation,验证 API 对象的字段是否合法。

  6. 验证完毕后,会将对应的信息保存到etcd中,一次API对象的创建就此完成。

三、扩展应用治理模式

在了解了现有的 ServiceMesh 框架的注入机制后,我们就可以基于此开发 Rainbond 的应用级插件,用于扩展应用的治理能力。我们知道由于现有的 ServiceMesh 框架大多采用了标准的 Initializer 实现。所以我们只需要完成以下两步即可。

  1. 部署对应 ServiceMesh 框架的 Initializer 控制器,通常情况下意味着部署它们的控制平面,此处基于 Rainbond 已有的对接 helm 商店的功能,可以方便的进行部署。

  2. 实现基于应用的数据平面的注入。

Istio治理模式的开发

接下来以 Istio 治理模式的开发为例,详细介绍如何自行扩展应用的治理能力。

前端展示支持 Istio 应用治理模式:

Rainbond 主要分为两层,即业务层和数据中心层,具体可参考 Rainbond 技术架构 。

rainbond-ui 为业务层的前端项目,首先需要支持 Istio 治理模式,由于 Rainbond 是以应用为中心的应用管理平台,所以 Istio 治理模式也是针对应用来说的。

如下图所示:在应用页面,可以切换治理模式。我们需要在这里增加 Istio 治理模式。

istio-ui.png

治理模式有效性校验

Initializer 的机制决定了,需要有一个准入控制器,去处理符合条件的 API 对象。通常情况下准入控制器包含在对应 ServiceMesh 框架的控制平面中。

所以我们在切换治理模式时,需要去校验集群中是否已经部署过对应 ServiceMesh 框架的控制平面,这一步应该在切换时进行校验。如果未部署对应的控制平面,则不具有对应的治理能力。也就不能切换。

根据 Rainbond 技术架构 ,我们可以知道,rainbond-console 属于业务层的后端。它需要与数据中心端进行通信,才能获取集群的状态。因此在 rainbond-console 和 rainbond 这两个项目中,都需要对治理模式的有效性进行校验。

rainbond-console 对治理模式有效性的校验

参考如下代码,类GovernanceModeEnum 定义了支持的治理模式。首先我们需要在治理模式这里增加ISTIO_SERVICE_MESH,用于在业务层判断治理模式是否有效。当此处校验通过后,我们需要请求数据中心端的接口,检测此种治理模式是否已安装了对应的控制平面。

/console/enum/app.py

  1. classGovernanceModeEnum(AutoNumber):
  2.    BUILD_IN_SERVICE_MESH =()
  3.    KUBERNETES_NATIVE_SERVICE =()
  4.    ISTIO_SERVICE_MESH =()
  5.    @classmethod
  6.    def choices(cls):
  7.        return[(key.value, key.name)for key in cls]
  8.    @classmethod
  9.    def names(cls):
  10.        return[key.name for key in cls]

rainbond 对治理模式有效性的校验

在接收到来自业务端的校验请求时,我们需要检测在该集群是否已部署了对应的 ServiceMesh 框架的控制平面。参考如下代码,由于部署 Istio 控制平面后,在每个命名空间下都可以查看到istio-ca-root-cert这个 ConfigMap,所以我们这里使用该 ConfigMap 作为判断 Istio 控制平面部署的依据。 当确认 Istio 控制平面已安装后,我们返回给业务端结果。最终完成切换。

/api/handler/app_governance_mode/adaptor/istio.go

  1. func (i *istioServiceMeshMode)IsInstalledControlPlane()bool{
  2.        ctx, cancel := context.WithTimeout(context.Background(),5*time.Second)
  3.        defer cancel()
  4.        cmName := os.Getenv("ISTIO_CM")
  5.        if cmName ==""{
  6.                cmName ="istio-ca-root-cert"
  7.        }
  8.        _, err := i.kubeClient.CoreV1().ConfigMaps("default").Get(ctx, cmName, metav1.GetOptions{})
  9.        if err !=nil{
  10.                returnfalse
  11.        }
  12.        returntrue
  13. }

实现基于应用的数据平面的注入

仅仅完成治理模式的切换还不够,我们需要让 Istio 的控制平面为指定的应用注入 Sidecar,即数据平面。Rainbond 自身通过 Worker 组件将 Rainbond-Application Model 进行实例化转化为 Kubernetes 资源模型。控制应用的生命周期。

因此,我们需要在 Worker 组件转化资源时,自动为用户完成对应用的注入。参考 Istio 注入策略。我们可以发现 Istio 依赖于 Label"sidecar.istio.io/inject":"true" 完成注入。而在 Rainbond的代码中,我们可以看到如下代码。这是将 Rainbond 的应用模型转化为 Deployment 的部分代码。在这里,我们为 Deployment 添加了对应的 injectLabels。

有了这些初始化操作。当 API 对象被创建出来时,便会被 Istio 的准入控制器处理,完成数据平面的注入。

/worker/appm/conversion/service.go

  1. func initBaseDeployment(as*v1.AppService, service *dbmodel.TenantServices){
  2.   as.ServiceType= v1.TypeDeployment
  3.   ......
  4.   injectLabels := getInjectLabels(as)
  5.   deployment.Labels=as.GetCommonLabels(
  6.      deployment.Labels,
  7.      map[string]string{
  8.         "name":    service.ServiceAlias,
  9.         "version": service.DeployVersion,
  10.      },
  11.      injectLabels)
  12.   ......
  13.   as.SetDeployment(deployment)
  14. }
  15. func getInjectLabels(as*v1.AppService) map[string]string{
  16.   mode, err := governance_mode.NewAppGoveranceModeHandler(as.GovernanceMode,nil)
  17.   if err !=nil{
  18.      logrus.Warningf("getInjectLabels failed: %v", err)
  19.      returnnil
  20.   }
  21.   injectLabels := mode.GetInjectLabels()
  22.   return injectLabels
  23. }

对于不同的应用治理模式,我们可以参考 应用治理模式扩展 的代码。实现如下接口,便可以完成应用下治理模式的切换和注入。

其中IsInstalledControlPlane这个接口的实现在前面已经体现。它主要用于判断控制平面是否已完成安装,可以正常使用。而GetInjectLabels则主要用于 Worker 组件转化应用模型为 Kubernetes 资源时,添加上指定的 Labels,以便被部署的准入控制器处理。

/api/handler/app_governance_mode/adaptor/app_governance_mode.go

  1. type AppGoveranceModeHandlerinterface{
  2.        IsInstalledControlPlane()bool
  3.        GetInjectLabels() map[string]string
  4. }

四、总结

本文我们主要介绍了应用治理模式的注入机制和开发,用户可以通过查阅需要注入的 ServiceMesh 插件官方文档,通过以上两步完成应用下治理模式的切换。使应用获得不同的治理能力。

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
缓存 监控 安全
Istio架构及工作原理
【2月更文挑战第17天】从 Istio 的设计和实现原理可以看出,它是采用模块化设计,并且各个模块之间高度解耦,Proxy 专注于负责服务之间的通信,Pilot 专注于流量控制,Mixer 专注于策略控制以及监控日志功能,而 Citadel 专注于安全。
|
测试技术 开发者
KubeVela 对接 Istio 实现应用灰度发布实践|学习笔记(二)
快速学习 KubeVela 对接 Istio 实现应用灰度发布实践
KubeVela 对接 Istio 实现应用灰度发布实践|学习笔记(二)
|
Prometheus 监控 Kubernetes
进阶:对接 Istio 实现应用灰度发布实践| 学习笔记
快速学习进阶:对接 Istio 实现应用灰度发布实践。
进阶:对接  Istio 实现应用灰度发布实践| 学习笔记
istio 原理简介
Istio 的架构分为控制平面和数据平面 数据平面:由一组智能代理(Envoy)以 sidecar 模式部署,协调和控制所有服务之间的网络通信。 控制平面:负责管理和配置代理路由流量,以及在运行时执行的政策。
istio 原理简介
|
Kubernetes 容器 Perl
阿里云Kubernetes容器服务Istio实践之常见问题分析
在使用阿里云Kubernetes容器服务Istio 1.0的过程中,如果遇到以下类似问题,请参考具体的问题分析。 我们会持续更新遇到的问题及其解决方法。
5035 0
|
网络协议 测试技术 应用服务中间件
Istio流量管理实践之(3): 基于Istio实现流量对比分析
流量镜像提供一种尽可能低的风险为生产带来变化的强大功能。镜像会将实时流量的副本发送到镜像服务,镜像流量发生在主服务的关键请求路径之外。一旦我们能够可靠地镜像流量,就可以开始做一些有价值的事情,例如通过请求流量对比工具Diffy,可以将引入测试集群的流量与生产集群中的预期行为进行比较。
2341 0
|
负载均衡 微服务 Perl
istio网络转发分析
通过demo分析istio的网络转发流程,从而对istio实现原理有更为直观的认识。本文先介绍了涉及到的相关概念和背景知识,然后对具体应用进行分析。背景知识概念分散,参考文章较多,敬请谅解。
8989 0
|
监控 安全 Cloud Native
云原生安全:Istio在微服务架构中的安全策略与实践
【10月更文挑战第26天】随着云计算的发展,云原生架构成为企业数字化转型的关键。微服务作为其核心组件,虽具备灵活性和可扩展性,但也带来安全挑战。Istio作为开源服务网格,通过双向TLS加密、细粒度访问控制和强大的审计监控功能,有效保障微服务间的通信安全,成为云原生安全的重要工具。
261 2
|
Kubernetes 安全 微服务
使用 Istio 缓解电信 5G IoT 微服务 Pod 架构的安全挑战
使用 Istio 缓解电信 5G IoT 微服务 Pod 架构的安全挑战
269 8
|
Kubernetes 安全 微服务
使用 Istio 缓解电信 5G IoT 微服务 Pod 架构的安全挑战
在5G电信领域,Kubernetes集群中部署微服务至关重要,但也带来了重大的安全挑战。Istio作为一个强大的开源服务网格,能有效地管理这些微服务间的通信,通过其控制平面自动将Sidecar代理注入到各微服务Pod中,确保了安全且高效的通信。Istio的架构由数据平面和控制平面组成,其中Sidecar代理作为Envoy代理运行在每个Pod中,拦截并管理网络流量。此外,Istio支持多种Kubernetes发行版和服务,如EKS等,不仅增强了安全性,还提高了应用性能和可观测性。
310 2
使用 Istio 缓解电信 5G IoT 微服务 Pod 架构的安全挑战