分享嘉宾朱雷,腾讯 IEG 运维 PaaS 平台技术负责人。
蓝鲸(全名“蓝鲸智云”)是一套孵化于腾讯 IEG(互动娱乐事业群)内部,服务于多业务与各内部平台的研运一体化 PaaS。 其作用是在 CI、CD 和 CO 三个阶段,对公司业务提供全生命周期的服务。
既然是为内部业务服务,那么腾讯游戏的业务都有哪些特点呢?
大家在日常生活中肯定也接触过很多腾讯出品的游戏。在腾讯内部,可能有上千款的游戏业务,除部分自研游戏外,大部分都属于代理类。代理业务的特点在于,它们是由不同公司所开发,因此各产品使用的语言、依赖的存储或者整个架构风格可能都是千差万别的。
面对这种包含大量异构架构的复杂业务场景,蓝鲸作为一个服务于内部的平台产品,在建设时就需要做到以下几点:
考虑到现实中的业务环境与内部业务需求,最终蓝鲸平台的整体架构如下图所示。
中间的蓝色部分是 PaaS 层,其中最大的一块是前面提到的各类原子能力。包括用户管理、统一权限中心、统一配置平台等。
上层的橙色部分是 SaaS 层,主要由很多不同角色针对特定需求场景开发的 SaaS 构成。这些 SaaS 在开发过程中,或多或少地都需要通过 API 使用 PaaS 层最核心的各平台原子能力。在这种情况下,就势必需要一个统一的 API 网关。
以上就是最初想要打造蓝鲸 API 网关的原因。将前面的架构图做一些抽象,就会得到一个如下简单的网关画像。
蓝鲸是一个比较复杂的平台,它对于统一网关的需求也会比较复杂。除了最基础的作为代理去调用原子平台的 API 之外,还需要提供一些额外的网关能力。比如服务发现、统一用户认证和鉴权、限流限速,等等。
另一方面,随着云原生技术的发展,如今内部很多 SaaS 和原子平台也开始部署在 K8s 集群中。这类场景又向网关提出了新的要求,比如需要通过统一流量网关或 API 网关来将外部的调用请求流量统一管控。同时,内部还存在一些业务系统,本身使用了蓝鲸平台的一些基础架构能力,如容器管理或监控等,它们也需要一个统一的服务网关来管理所有调用流量。
面对外部技术的趋势与内部业务的发展要求,蓝鲸的 API 网关需要支持的场景开始变得越来越多样化。
蓝鲸 API 网关到目前为止经历了三个阶段的迭代。
蓝鲸 API 网关的 1.0 版本,主要是让原子平台的调用方(含各 SaaS 和流程引擎)不再直接对接各个原子平台,而是可以直接调用 API 网关,通过网关完成协议转换、权限校验等相关功能。
那时的架构也比较简单,如下图所示整体分为两大块:服务端和管理端。原子平台需要把自身服务注册到 API 网关上,首先得访问管理端,配置好平台的 API 资源地址和各自对应的权限等等。
当原子平台通过管理端提供了网关所需的配置细节后,数据会被写入到 MySQL 中,供服务端读取。之后,当 SaaS 请求某原子平台的 API 时,首先经过前端的 NGINX 负载均衡器,然后透到网关服务端,服务端读取了相关配置后,再由将请求通过路由转发功能传给后方的各原子平台,完成整套请求流程。为了提升性能,这套架构也引入了 Redis 处理了一些缓存加速等场景。
1.0 版本的架构在内部运行了几年后,随着请求量的增长和场景的复杂化,缺点开始逐渐显现出来。比如:
同时还进行了其他优化变动。比如在内存中维护了一个更高效的路由实现;在中间层引入了基于内存的缓存,以减少对 Redis 的依赖。新架构也增加了对网关多版本和多环境的生命周期管理,引入扩展插件机制,方便开发者通过插件对网关能力进行扩展。
总体来说,2.0 版本解决了 1.0 版本中遇到的性能问题和大部分痛点。但随着时间的推移,新的问题也开始慢慢浮出水面。
进入云原生时代后,我们发现网关 2.0 版本在一些方面渐渐无法满足业务需求,主要的问题包括以下几点:
分布式网关架构的组件主要分为两类:管理端和微网关实例。管理端统一管控着各个微网关,由各网关的管理员对网关进行配置和管理。微网关实例是独立部署的各个网关服务,各自独立承担特定的某一组服务的访问流量,根据管理端的设定进行相关访问控制。所有微网关实例由同一套管理端管控。
在微网关的技术选型方面,我们当时参考了市面上比较流行的各网关开源产品,从流行度、技术栈、协议支持等各个层面对比后,最终选择了使用 APISIX 作为微网关最重要的后端技术。
之所以选择 APISIX,是因为它是基于 NGINX+Lua 实现的,所以整体性能相比 Go 而言是有优势的。同时 APISIX 的扩展性非常好,还支持通过多语言插件去扩展能力,在当时也有非常多的成熟的用户案例。
不过,APISIX 在当时对于我们的内部使用场景来说,还是存在一些缺不足的。比如它的控制面能力有些缺乏,控制面板比较简陋。因此在 APISIX 的基础上,我们按照内部需求去实现定制了 APISIX 的控制面。
云原生环境下,K8s 就是我们需要关注的最重要的基础组件。因为整个微网关都是面向云原生设计,所以 3.0 版本的网关就基于 K8s 去做了新的架构设计。其中最核心的部分,就是使用 K8s 提供的 CRD 自定义资源,实现了对网关的整套操作和扩展。
如上图所示,网关引入了一整套 K8s 的 CRD 资源定义,包括:BkGatewayStage(网关环境)、BkGatewayService(后端服务)等。通过这些 CRD,我们得以控制每个微网关实例的具体行为。
图中的几个“Operator”是这套架构中最核心的部分。上方是 Plugin Operators 服务,里面包含一系列的插件 Operator。比如负责服务发现的 Operator,会将后端服务注册在服务发现中心的地址写入到 K8s 集群中。
中间的核心 Operator 监听着所有和网关相关的 CRD 资源。其中的资源调和器(reconciler),负责将读取到的网关配置转换成 APISIX 微网关实例能理解的格式,从而实现微网关的全套生命周期管理。
目前,这套微网关主要分为两种部署类型:
从上图可以看到,管理端统一只有一套,因此它的能力并不提供任何差异化,像多环境管理、权限管理等功能都是所有网关共有。但在它所管理的不同类型的微网关实例中,所支持的特性集就会互有差异。
拿共享网关实例来说,它所支持的特性集是比较基础的。主要包含统一的登录鉴权、限流熔断和多协议支持等。而到了每个业务独立的专享网关实例,就可以拥有一些不一样的个性化能力。因为专享网关和业务同属一个集群,所以它可轻松实现动态路由、自定义服务发现等能力,也利用 APISIX 的强拓展性去自定义更多能力。
基于这套架构和模式,蓝鲸 API 网关 3.0 版本在 APISIX 能力的加持下,提供了更加丰富的功能。
服务发现是微服务架构所需的一个基本能力,在内部,我们主要通过自定义资源 CRD 去实现。一份有效的服务发现 YAML 定义如下图右侧代码所示。
将上述 CRD 资源写入 K8s 集群后,就会触发服务发现相关的控制器的相关动作。之后调和器(Reconciler)会捕获到对应的服务发现配置,创建服务发现相关的程序对象。
然后它会通过内置的服务发现接口(包含 Watcher、Lister)读取服务发现中心的相关地址信息,将获取到的地址通过 BkGatewayEndpoints 这个 CRD 资源重新写回到 K8s 集群内。再经由右侧的核心 Operator 进行一些复杂处理后,这些 endpoints 最终被同步到 APISIX 对应的上游中,一次完整的服务发现流程就此完成。
为了方便开发,我们实现了一个通用的服务发现框架。它提供了统一的开发接口和规范,使用它可以低成本地支持其他类型的服务发现场景。
统一认证部分比较简单。在业务实践中,我们需要支持来自三种不同来源的请求,分别是浏览器、平台和个人用户。我们基于 APISIX 实现了一个认证插件,来实现统一认证。
具体实现流程如上图所示。请求进来后,插件会从 Header 中读取相关的凭据信息,然后统一调用 BK-Auth 认证服务去校验该凭据,并读取对应的 SaaS 信息。之后再用和后端约定好的私钥,签发一个 JWT token 并将其写入请求头中,最后写入 APISIX 变量。
除统一认证外,内部业务中也存在一些复杂的鉴权场景。其主要解决的问题是,当一个 SaaS 调用某原子平台的某个资源时,判断该 SaaS 有没有这个权限。目前统一的资源鉴权,也是通过 APISIX 插件实现,这里我们使用了 Go 语言实现,如下图所示。
当客户端的请求过来后,会首先经过认证环节拿到 SaaS 应用信息。然后经过 ext-plugin 处,基于 RPC 与鉴权插件进行交互。此时鉴权插件会直接去查询缓存中的鉴权相关数据(通过全量和增量机制由管理端同步),之后完成鉴权。
比较典型的动态路由应用场景来自蓝鲸的容器管理平台。蓝鲸容器平台管理着非常多的 K8s 集群,有一些是业务的服务集群,有一些是业务的数据集群。
作为用户,常常需要请求这些集群的 APIserver 去完成一些事情。当用户请求进入到微网关时,网关需要根据请求路径,判断该将其转发到哪个集群的 APIserver 中。具体实现流程如下图所示。
请求进入后,动态路由插件首先提取出集群的 ID 信息,然后对路由进行重写,之后判断该集群是否为直连集群。
在我们的业务场景中,有一类原子系统在将资源注册到网关时,使用的是比较复杂的客户端证书验证模式。因此,如果某个用户要请求它的资源,就必须提供一份有效的客户端证书。
具体实现如上图所示。对于网关管理者,首先要在管理端配置好网关在不同环境中使用的客户端证书。创建完成后,证书会被发布到对应的微网关所在的 K8s 集群中。这个过程会使用一些 CRD 资源和 K8s 官方的 Secret 资源,并由核心的 Operator 服务进行持续地调和处理,比如根据域名寻找对应证书等。有效的客户端证书配置,最终会体现在 APISIX Service 的相关配置中(如上图右上方代码红框处)。
本文从蓝鲸 API 网关的诞生背景与迭代过程入手,为大家呈现了一个 API 网关产品的从 0 到 1 的探索过程。也带来了选择 APISIX 进行网关产品迭代的过程中,一些业务实践场景的细节分享。希望对于想要使用 APISIX 进行网关迭代的企业有一些建设性的启发。
下一篇:第五章 Docker 自定义镜像