高可用負載均衡:開源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應用構建與交付、多數據中心資源管理等技術,爲用戶提供雲原生應用全生命週期解決方案,構建應用與基礎設施、應用與應用、基礎設施與基礎設施之間互聯互通的生態體系,知足支撐業務高速發展所需的敏捷開發、高效運維和精益管理需求。

相關文章
相關標籤/搜索