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 插件官方文档,通过以上两步完成应用下治理模式的切换。使应用获得不同的治理能力。

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
5天前
|
缓存 监控 安全
Istio架构及工作原理
【2月更文挑战第17天】从 Istio 的设计和实现原理可以看出,它是采用模块化设计,并且各个模块之间高度解耦,Proxy 专注于负责服务之间的通信,Pilot 专注于流量控制,Mixer 专注于策略控制以及监控日志功能,而 Citadel 专注于安全。
|
测试技术 开发者
KubeVela 对接 Istio 实现应用灰度发布实践|学习笔记(二)
快速学习 KubeVela 对接 Istio 实现应用灰度发布实践
369 0
KubeVela 对接 Istio 实现应用灰度发布实践|学习笔记(二)
|
Prometheus 监控 Kubernetes
进阶:对接 Istio 实现应用灰度发布实践| 学习笔记
快速学习进阶:对接 Istio 实现应用灰度发布实践。
155 0
进阶:对接  Istio 实现应用灰度发布实践| 学习笔记
istio 原理简介
Istio 的架构分为控制平面和数据平面 数据平面:由一组智能代理(Envoy)以 sidecar 模式部署,协调和控制所有服务之间的网络通信。 控制平面:负责管理和配置代理路由流量,以及在运行时执行的政策。
istio 原理简介
|
网络协议 测试技术 应用服务中间件
Istio流量管理实践之(3): 基于Istio实现流量对比分析
流量镜像提供一种尽可能低的风险为生产带来变化的强大功能。镜像会将实时流量的副本发送到镜像服务,镜像流量发生在主服务的关键请求路径之外。一旦我们能够可靠地镜像流量,就可以开始做一些有价值的事情,例如通过请求流量对比工具Diffy,可以将引入测试集群的流量与生产集群中的预期行为进行比较。
2135 0
|
Kubernetes 容器 Perl
阿里云Kubernetes容器服务Istio实践之常见问题分析
在使用阿里云Kubernetes容器服务Istio 1.0的过程中,如果遇到以下类似问题,请参考具体的问题分析。 我们会持续更新遇到的问题及其解决方法。
4663 0
|
负载均衡 微服务 Perl
istio网络转发分析
通过demo分析istio的网络转发流程,从而对istio实现原理有更为直观的认识。本文先介绍了涉及到的相关概念和背景知识,然后对具体应用进行分析。背景知识概念分散,参考文章较多,敬请谅解。
7982 0
|
7月前
|
Kubernetes 监控 Go
在Kubernetes上安装和配置Istio:逐步指南,展示如何在Kubernetes集群中安装和配置Istio服务网格
在Kubernetes上安装和配置Istio:逐步指南,展示如何在Kubernetes集群中安装和配置Istio服务网格
90 0
|
7月前
|
存储 Kubernetes 负载均衡
【Kubernetes的Service Mesh发展历程及Istio架构、存储供应使用NFS flexvolume CSI接口】
【Kubernetes的Service Mesh发展历程及Istio架构、存储供应使用NFS flexvolume CSI接口】
|
8月前
|
Kubernetes Cloud Native 开发者
15分钟在笔记本上搭建 Kubernetes + Istio开发环境-阿里云开发者社区
15分钟在笔记本上搭建 Kubernetes + Istio开发环境-阿里云开发者社区
15分钟在笔记本上搭建 Kubernetes + Istio开发环境-阿里云开发者社区