当前位置: 首页 > 科技观察

云原生环境下数据库服务治理的思考

时间:2023-03-13 18:10:26 科技观察

了解更多开源请访问:51CTO开源基础软件社区https://ost.51cto.com从服务治理到数据库ServiceGovernanceMicroserviceGovernance从服务治理到数据库服务治理,我们仍然需要从微服务治理入手。从单体服务到微服务,随着业务越来越复杂多样,基础设施规模越来越大,服务之间的调用关系变得非常复杂。对于微服务的治理行为,仍然停留在流量控制、可观察性、安全访问、配置管理和高可用等几个方面。要让微服务架构更快的上线和部署,必须要有一个自动化的框架。对于运维,我们也希望尽可能的标准化。这时候出现了Kubernetes这样的容器编排框架。Kubernetes起源于谷歌内部的Borg,它带来了很多谷歌的大工厂属性。大厂不是说技术有多厉害,而是规模很大。只有在特别大的规模上,运维的复杂性才会体现出来,会更多地依赖平台或者工具来提升自动化能力。这种自动化能力,我们称之为基础设施即代码,只要一个SRE同学写一个这样的配置文件,然后把文件提交给Kubernetes,Kubernetes会根据里面描述的行为做出相应的指令,但是这个指令是一个声明式的API,应用程序的自动启动就是在这个过程中完成的。说到Kubernetes,如果有几万个节点,上面可能有10万个pod,我们如何做它的服务治理?如果你还在用之前的服务发现框架,在兼容Kubernetes的时候会有些不适应。在Kubernetes之上是否有一种本地方式来进行服务治理?这是服务网格。ServiceMeshServiceMesh最早由Linkerd项目于2016年提出,ServiceMesh将服务治理的行为或能力下沉到基础设施。ServiceMesh可以被认为是服务治理行为的编排框架。通过一些声明式的配置,ServiceMesh可以交付给基础框架和基础设施来代表我们执行相关任务。服务网格有一个特别典型的图,就是下图。我们可以假设蓝色部分是我们的业务应用,黄色部分是我们的服务网格代理。服务网格使用这样一个透明代理来接管应用程序的所有流量,然后对其进行管理。通过这种接管的方式,实现了服务发现等各种服务治理能力。Istio简介说到ServiceMesh,就不能不提Istio项目。2016年,Linkerd对ServiceMesh的理解可能还不是特别成熟。我们称那个时代为第一代ServiceMesh。直到Istio的出现,才真正成为我们现在看到的ServiceMesh架构。我们称Istio为第二代服务网格。Istio的主要架构如下图,下方是一个控制面板。控制面板称为控制平面,其中包含Istiod。在1.0早期,Istiod由多个独立的组件组成,如Pilot、Galley、Citadel,分别负责一些证书,比如可观察性的聚合。.它本来就有一个Mixer,还有各种Pilot相关的配置等等。微服务治理与数据库服务治理的异同有人会问:既然Istio可以代理应用流量,为什么还要谈一个数据库服务治理呢?我们可以让Istio劫持我们数据库的协议或者让它代理所有的数据库流量来达到治理的效果。如果我们把数据库看成是微服务中一个特殊的微服务,它可能是服务链接的最后一环。我们确实可以通过ServiceMesh来访问和管理数据库,包括服务发现的能力。但是数据库也有一些特殊的治理属性或者要求,比如数据库协议,它的MySQL协议或者PG协议或者Redis协议都有特殊性。比如我们用MySQL协议建立连接的时候,服务器会先给我们发一个包,这里面也有资源管理。或许对于微服务之间的业务应用,我们不需要太在意它所消耗的运行时间。资源,应该是整个服务的性能指标。但是对于数据库,可能会有一些差异。当它反映在可观察性中时,例如数据库指标,它可能涉及缓慢的SQL或SQL延迟。对于流量管理的部分,数据库也有其特殊性。无论是Redis、MongoDB还是MySQL,我们在做分片的时候,很难仅仅依靠流量本身来进行分发。如果我们随机转发相应的请求,我们可能会得到错误的答案。另外,对于分库分表等场景,所谓的负载均衡是基于数据属性的判断,不能粗暴的随意发往不同的数据源。最后,还有访问控制。一般来说,对于业务应用,我们有一个微服务级别的访问控制,可能会涉及到一个全局的认证或者身份授权。在很多情况下,我们需要表级甚至列级的访问。控制,只有通过特殊的治理手段,才能达到这种特殊的治理效果。如何设计Mesh模型我们从ServiceMesh中学到了什么让我们回到刚刚提到的ServiceMesh,我们可以从ServiceMesh中学到什么?首先,ServiceMesh是一种控制面和数据面分离的部署结构。其次,如果我们将控制平面和数据平面的协议标准化,我们可以为数据平面提供更多的选择。第三,我们可以通过Kubernetes机制实现基础设施即代码的配置能力。第四,可以通过插件支持各种协议扩展。这个时候我们就会想,数据库的DatabaseMesh和我们的ServiceMesh是不是存在包含关系呢?还是有两种完全不同的场景?DatabaseMesh的概念是在2018年提出来的,ShardingSphere的创始人张亮在他的《未来架构》一书中,其实设想了如果将ServiceMesh治理的思想应用到数据库治理中会发生什么。影响?ShardingSphere项目主要管理数据库流量,如分库分表、数据加密、数据伸缩等。是否可以有一个ShardingSpheresidecar,和业务应用一起部署,如下图,正常的业务请求通过ServiceMesh进行微服务,业务间的服务发现,以及相关的调用。对于数据库流量,通过ShardingSidecar代理到数据库,整个ShardingSidecar也依赖一个控制平面进行相关的注册和发现。ShardingSidecar和ShardingSphere现有的Proxy和JDBC能力应该是一样的。这样就可以完美屏蔽JDBC和Proxy的缺点。ShardingSidecar以Sidecar的形式部署在业务应用旁边。如果业务应用程序是分布式的或多副本的,它将有多个副本。业务应用和它们之间的通信也可以实现这种语言解耦,而不用局限于特定的语言栈。这个架构只是弹性伸缩+零入侵+去中心化的云基础设施吗?这是2018年关于DatabaseMesh的一个想法。DatabaseMesh的现状从2018年到现在的短短四年时间里,DatabaseMesh的概念其实已经在很多公司得到了充分的探索和实践。总结起来,有3种典型的方案。第一个是ShardingSphereSidecar的形式。数据库治理的特性以Sidecar的形式提供给业务Pod。第二种,可能在一些大厂比较常见,就是统一Mesh控制。第三种称为分布式数据库。这三种方式有一个共同点,就是都集中在数据库服务管理中流量管理的部分。如果我们把这个阶段称为1.0阶段,那么假设我们要把它升级到2.0,它应该有什么样的特性呢?DatabaseMesh1.0vs2.0经过充分考虑,我们觉得应该有更多的可扩展性和更好的用户体验,所以我们提出了DatabaseMesh2.0的概念。我们现在有一个专门的网站,其口号是“通过可编程性和高性能扩展来应对云上数据库的治理挑战”。我们希望通过这种可配置、可插拔或可编程的方式,实现涵盖数据库流量、运行时资源和稳定性保障的治理框架。不管是什么类型的数据库,我们都希望有一个标准的接口,然后对其进行管理。这是DatabaseMesh2.0所期望的功能。对于DatabaseMesh2.0,其实有一点需要强调的是,我们在设计的时候,一直在思考Mesh到底是什么意思。其实一开始我们会认为Sidecar就是Mesh。我们通过Sidecar与其他事物进行交互,形成一个网格,也就是Mesh。但是后来我们发现并不是这样的。Mesh的核心不是Sidecar,Mesh只是它的一种形式。下面我们来看一下DatabaseMesh2.0的全景。全景图左半部分的上半部分实际上是根据用户划分的。上半部分是Developers,也就是开发者对DatabaseMesh的感受。右边,对于SRE或者DBA同学来说,他们想看的东西更多,无论是访问控制、审计、风控、可观察性,还是事件。右边,对于SRE或者DBA同学来说,他们想看的东西更多,无论是访问控制、审计、风控、可观察性,还是事件。总结一下:首先,在DatabaseMesh2.0中,我们认为数据库是一等公民,所有这些抽象都是围绕数据库进行的,也就是我们刚才所说的VirtualDatabase。其次,我们希望它是一种面向工程师的体验,无论是开发人员还是SRE或DBA,他们都关心数据库的实际位置。第三,cloud-native,应该是面向云的环境,用户不用担心这个东西被厂商锁了。如何使用Kubernetes实现数据库Mesh在最后一部分,我们将介绍我们如何使用Kubernetes来实现这样一个模型。Kubernetes的扩展模式Kubernetes被称为平台的平台。我们是基于Kubernetes的,之前也出现了很多的创业公司和一些PaaS服务商,在上面构建各种能力。Kubernetes的扩展能力是其生命力的关键。它的第一种扩展模式叫做Sidecar;第二种扩展方式是AdmissionWebhook;第三种扩展方式,也是一个特别强大的能力,就是用户自定义资源定义。Pisanix设计与实现介绍完Kubernetes,我们再来看看Pisanix项目。Pisanix是SphereEx团队提供的DatabaseMesh的解决方案。Pisanix是用Go和Rust编写的。我们已经适配了Kubernetes环境,目前支持MySQL协议。它包含三个主要组件:Pisa-Controller:Pisanix项目的核心组件。Pisa-Controller负责控制界面。它是在Golang中实现的,是一个必需的组件。Pisa-Proxy:Pisa-Proxy是负责代理流量的数据平面。Pisa-Proxy以sidecar的形式部署在Pod中。它是用Rust实现的,也是一个必需的组件。Pisa-Daemon(即将发布):负责资源优化的数据平面。它是一个DaemonSet。Kubernetes集群中的每个节点都会有一个守护进程。它是一个可选组件。三个组件实现的结果:首先,实现了SQL感知流量管理。其次,面向运行时的资源是可编程的。三、数据库可靠性工程,也叫DRE。我们将专注于Pisa-Proxy。Pisa-Proxy是我们最重要的核心组件,所有的能力其实都依赖于它。我们选择Rust来实现的主要原因之一是因为Rust的生命力非常顽强。Pisa-Proxy可以看作是数据库流量的负载均衡器。主要工作流程如下:目前Pisa-Proxy支持MySQL协议,伪装成数据库服务器。应用连接配置只需要修改访问地址即可建立连接:Pisa-Proxy通过读取应用发送的握手请求和数据包获取应用要执行的SQL。对SQL进行词法语法分析后,得到对应的AST。基于AST实现高级访问控制和SQL防火墙功能。SQL在访问控制和防火墙通过后提交执行。SQL执行阶段的指标将作为Prometheus指标收集。根据负载均衡策略获取执行语句的后端数据库连接。如果连接池为空,则根据配置建立到后端数据库的连接。SQL将从该连接发送到后端数据库,并读取相应的返回结果。SQL执行结果组装返回给业务应用。最后是Pisa-Daemon。Pisa-Daemon离不开eBPF技术。eBPF现在挺流行的,eBPF技术本身就像一个容器,并不是特别新鲜。eBPF是ExtendedBPF的缩写,可以在Linux内核中构建沙箱并运行各种程序。eBPF是一种安全高效的内核扩展机制,常用于:可观察性:eBPF可以在内核态收集各种可观察的指标,并生成多样化的图表。系统安全:通过eBPF可以观察到所有的系统调用,配合网络包或socket的管理和进程上下文的跟踪能力,可以实现更细粒度的安全控制。网络:eBPF的编程扩展能力天然适用于不离开内核网络处理上下文的网络流量包的处理。跟踪调优:通过对用户态进程和系统调用的检测,实现零侵入的关联跟踪和性能分析体验。对于Pisa-Daemon,它声称是资源可编程的。Pisa-Daemon使用内核机制提供资源管理能力。此资源是运行时资源。通过Pisa-Daemon和Pisa-Proxy的配合,我们可以识别来自不同优先级服务的数据库流量。未来我们希望做一个扩展机制,以可插拔或可编程的方式支持更多类型的运行时资源管理。如何在Kubernetes中使用Pisanix最后,我们可以看看如何在Kubernetes中使用Pisanix项目。由于Pisanix是DatabaseMesh的一个实现,我们也遵循它的规范。首先,我们使用三个CRD,分别称为VirtualDatabase、TrafficStrategy和DatabaseEndpoint。VirtualDatabase是我们前面介绍DatabaseMesh的时候,它的聚合根,它对DatabaseMesh治理的所有能力都在VirtualDatabase中体现。VirtualDatabase中有一个名为TrafficStrategy的字段,它标识了我们希望它用来管理对该数据库的访问的策略。随机给谁?它在TrafficStrategy中具有Selector。Selector使用Label来选择后端的DatabaseEndpoint。这三个CRD可以涵盖业务应用对后端数据源和MySQL代理的相关配置信息。接下来就是Pisa-Controller拿到CRD,然后根据里面的配置内容转换成Pisa-Proxy的配置,然后推送到对应的Sidecar。Pisa-Proxy拿到这个配置,然后根据里面的内容和后端实际的数据库建立连接,同时前端监听端口,接收请求。最后,对于应用程序来说,它只需要访问其中配置的端口即可。其实我们也在想Pisa-Proxy可以单独使用。有些Kubernetes并不适合每个公司或每个企业。如果我们也需要对数据库进行这种管理,尤其是流量的统一接入,其实可以单独部署Pisa-Proxy的治理。这个时候的用法就跟我们用一个Nginx来组成一个集群是一样的。不管你后面是什么数据库,比如RDS或者TiDB或者ShardingSphere,你都可以使用Pisa-Proxy来做数据库的统一访问层,为它做一个代理,实现无感这种高可用的切换,实现面向SQL的可观察性等等。了解更多开源信息,请访问:51CTO开源基础软件社区https://ost.51cto.com。