高可用负载均衡:开源PaaS Rainbond组件Rainbond-Entrance揭秘

负载均衡(Load Balancing)是开源PaaS Rainbond的亮点功能,主要由“软件定义负载均衡”Rainbond-Entrance控制器完成。nginx

本文将围绕设计架构和实现介绍Rainbond-Entrance。git

为何须要负载均衡

Rainbond内部网络划分支持多租户,每一个租户都有一个私有的IP段,不一样租户的网络相互不可见。当咱们把一个容器化应用部署到Rainbond,Rainbond会为该容器分配一个内部IP,用于同一租户中不一样应用在集群内部的通讯,而集群外部没法直接访问,所以咱们须要有一个集群入口控制器,以便用户能够方便地访问这些应用。github

另外,Rainbond中部署的每一个应用均可以有多个实例,即假设咱们为一个WEB应用部署了三个实例,每一个实例分担一部分流量,咱们就须要这三个实例前增长负载均衡控制器来完成分发流量的工做。web

除了上述的基本功能之外,负载均衡控制器还必须支持更多功能,例如:json

  • 入口控制器可以根据数据包信息(如协议、端口号、主机名等)将请求转发给指定的应用
  • 实时发现集群中应用的变化(如添加自定义域名、添加证书、添加端口等)并动态更新自身的转发规则
  • 同时支持HTTP、TLS、TCP、UDP协议,由于有时不仅WEB应用须要向外提供服条,RPC、MySQL等也须要对外开放
  • 支持高可用

综上所述,咱们须要一个同时支持L4或各种应用协议(L7)的负载均衡控制器集群,还必须可以自动发现集群中的应用变化以更新本身的转发规则。api

Rainbond中的负载均衡

总体架构

loadbalancer-architecture

  1. web:表示Rainbond中的一个应用,而且有三个实例
  2. api-server:kubeneters的kube-apiserver组件
  3. entrance:Rainbond的负载均衡控制器通用接口,支持多种负载均衡插件
Entrance实现

Rainbond中的负载均衡是面向应用的,不一样应用可使用不一样的负载均衡。Rainbond的Entrance组件设计,使之能够集成集成多种负载均衡插件,也就是说,Rainbond不只支持经常使用的OpenResty,还能够支持其它负载均衡插件,例如商业支持的F5等。缓存

Entrance的主要工做是从kube-apiserver中监听应用运行节点信息的变化,例如Service、Endpoint、Pod等,而后把这些资源抽象为通用的负载均衡抽象并缓存在etcd中,这些通用抽象包括:服务器

  • Pool:负载均衡池,其中包括多个节点,对应上图中的三个WEB实例
  • Node:Pool中的一个节点,对应上图中的其中一个WEB实例
  • Domain:域名,负载均衡控制器能够识别一个数据包中的域名信息而后将数据转发给对应的Pool
  • VirtualService:监听了某个端口的虚拟主机,还指明了端口的协议名称,主要用来处理L4入口控制和负载均衡
  • Rule:转发规则,用来描述域名跟Pool的对应关系,还指明了端口的协议名称与证书信息,处理L7入口控制和负载均衡

当有资源发生变化时,Entrance会将通用资源转化为相应插件的资源,并根据应用所选择的不一样的插件驱动操做负载均衡控制器。微信

从架构中能够看到,有两个Entrance和两个OpenResty实例,它们的关系是:每一个Entrance中持有全部OpenResty的地址,当有信息须要更新时,Entrance会将信息更新到全部的OpenResty。那两个Entrance之间怎么协调呢?这里咱们利用etcd自己的特性作了分布式锁,保证只有一个Entrance有权限向OpenResty更新信息,如此实现了高可用。网络

OpenResty插件

OpenResty是一个能够用Lua脚原本处理请求和业条逻辑的WEB应用,而且内置了众多Lua相关的指定和函数供开发者使用,很合适开发Restful API服务器,咱们将OpenResty做为Entrance的插件之一缘由以下:

  1. 基于Nginx开发,在稳定性和性能方面表现出色
  2. 接近Rainbond的设计目标,它已经帮咱们把Lua模块编译进去,能够很方便地用Lua脚本丰富负载均衡控制器的功能
  3. 同时支持L7和L4的负载均衡

咱们在OpenResty端嵌入了一个Rest API服务器,这些API是用Lua写的。前面说过OpenResty集成了Lua脚本功能,咱们能够直接用Lua来处理请求,下面是Nginx配置文件的其中一部分:

# custom api of upstream and server
server {
    listen 10002;

    location ~ /v1/upstreams/([-_0-9a-zA-Z.@]+) {
        set $src_name $1;
        content_by_lua_file lua/upstream.lua;
    }

    location ~ /v1/servers/([-_0-9a-zA-Z.@]+) {
        set $src_name $1;
        content_by_lua_file lua/server.lua;
    }

}

当咱们调用下面的API时:

curl -s localhost:10002/v1/servers/app1 -X POST -d "$json_data"

OpenResty会执行相应的Lua脚中,也就是lua/server.lua,前面说过,OpenResty内置了不少Lua相关的指命与函数,可让Lua与Nginx更好地交互,因此咱们在脚本中很容器处理接收到的JSON数据,并将其转换为配置Nginx文件,因为Lua代码较多就不贴出来了,能够在本文的引用部分找到该项目地址。

这里有个须要注意的地方,当收到大量修改server和upstream的请求时,OpenResty须要频繁加载配置文件,这样会增长负载且影响性能。实际上OpenResty有不少第三方插件可使用,有一个叫dyups的插件能够作到动态修改upstream,它的使用方式以下,Lua代码:

-- 增长或更新指定upstream
dyups.update("upstream_name", [[server 127.0.0.1:8088;]])

-- 删除指定upstream
dyups.delete("upstream_name")

执行成功后就已经生效了,不须要咱们执行nginx -s reload命令,这会提升一些效率。

对于server的修改暂时尚未相应用插件作到动态修改,因此实际上咱们的负载均衡控制器分两种状况,若是更新了upstream配置会即时生效,而更新server配置则须要加上nginx -s reload命令。

结语

咱们用Entrance加OpenResty实现了一个可插拔且高可用的负载均衡控制器,总体来讲并不复杂,但愿本文能带给你一些帮助。

目前咱们已经把Rainbond的OpenResty插件分离出来作为一个子项目而且开源在Github上,你能够下载并单独使用:Github地址

引用与参考

  1. Openresty项目
  2. Openresty内置Lua函数使用文档
  3. dyups插件

进一步了解Rainbond v3.5.1

好雨Rainbond(云帮)是一款以应用为中心的开源PaaS,深度整合基于Kubernetes的容器管理、Service Mesh微服务架构最佳实践、多类型CI/CD应用构建与交付、多数据中心资源管理等技术,为用户提供云原生应用全生命周期解决方案,构建应用与基础设施、应用与应用、基础设施与基础设施之间互联互通的生态体系,知足支撑业务高速发展所需的敏捷开发、高效运维和精益管理需求。

相关文章
相关标签/搜索