做者:單家駿
Kong是一個基於OpenResty (Nginx) 封裝的微服務中間件產品,在微服務架構體系中,做爲API網關以及API中間件(kubernetes ingress)提供服務。因爲其天生具有Nginx的高性能、nginx-lua插件的可定製性,再加上完善的社區以及齊全的文檔,在中小企業用戶羣很是受歡迎,擁有較好的羣衆基礎。nginx
2018年8月,kong發佈了1.0 GA版本,正式宣佈其支持service mesh,並提供社區版以及企業版2個版本。下面咱們從Demo、配置、功能這3方面,對kong mesh進行體驗及分析。git
Kong社區提供了kong mesh的demo (github.com/Kong/kong-m…),該demo是實現的是tcp四層透明代理轉發業務。github
該demo主要作的事情是:提供兩個服務servicea以及serviceb,serviceb做爲服務端,經過ncat監聽8080端口,接受外部的TCP消息;servicea做爲client端,經過ncat將當前server的時間發往serviceb。Demo的運行效果以下:web
在客戶端節點,每隔兩秒會發送一次時間戳到服務端。數據庫
服務端節點,每隔兩秒打印一次時間戳。api
接下來,咱們詳細瞭解一下該demo背後的技術原理。緩存
首先,咱們來分析一下kong-mesh業務總體組網:安全
從組網中能夠看出,kong mesh也分控制面與數據面。bash
控制面爲圖中kong-admin的POD,3副本實例獨立部署,對外提供Admin API供用戶設置各類規則配置。websocket
數據面爲圖中servicea及serviceb的POD,每一個POD中會啓動一個kong容器做爲sidecar,經過iptables規則將外發以及到達的流量劫持到kong容器中,而後kong會根據路由規則將流量轉發到對應的實例。下面咱們看看POD的部署配置:
部署配置關鍵點在於流量接管的設置,POD在啓動應用前,會使用istio/proxy_init鏡像來初始化環境,圖中的參數的含義是,使用TProxy(透明代理)的流量接管模式,將發往8080端口(業務serviceb監聽端口)的流量經過7000端口(kong監聽端口)來進行代理。
瞭解清楚該部署配置後,咱們就能夠比較容易地使用kong來代理http服務了。主要改動點仍是在於POD的部署配置的修改。以下圖所示:
值得注意的是,代理HTTP服務和代替TCP不同,屬於7層轉發,不能使用上文的透明代理方式來進行接管。所以在setup_network的啓動參數中,須要指定流量接管模式爲REDIRECT,經過iptables顯式將報文導入到kong,kong再根據報文內容進行匹配後,再路由到目標服務(你們若是須要http demo的代碼,能夠到github.com/andrewshan/…下載)。
那麼,kong又是根據什麼規則去路由的呢?下面咱們會繼續體驗kong mesh的配置規則。
kong mesh的配置集中存儲在DB中,當前僅支持Postgre以及cassandra。控制面kong-admin會把配置規則寫入到DB中,數據面的Kong會按期從數據庫讀取配置規則並更新緩存。
在demo中,咱們經過k8s Job向kong-admin寫入了兩條數據:
http --ignore-stdin put kong-admin:8001/services/service-b host=serviceb port=8080 protocol=tcp -f
http --ignore-stdin post kong-admin:8001/services/service-b/routes name=service-b sources[1].ip=0.0.0.0/0 protocols=tcp -f 複製代碼
第一條語句是添加一個名字叫service-b的服務;
第二條語句是爲service-b的服務添加路由規則,容許源ip在0.0.0.0/0網段的tcp包能夠轉發到service-b。
規則添加後,分別在services和routes表中能夠查詢到相關的記錄:
那麼問題來了,kong的規則模型具體是什麼含義?這些規則是怎麼組合工做的呢? 首先,咱們先看看kong的規則模型:
從圖上可見,Service是規則模型的核心,一個Service表明一個目標服務URL。
Route表明的是Service的細粒度路由規則,定義了根據不一樣的客戶端請求屬性來選擇目標端Service,一個Service可關聯多個Route規則。可類比istio中的VirtualService。
Upstream定義的是針對具體的目標Service,所採起的負載均衡策略,以及健康檢查相關配置,一個Service可關聯0-1個Upstream。可類比istio中的DestinationRule。
Target定義的是具體的服務節點實例,可定義權重,一個target關聯一個upstream。 具體的詳細規則描述,可參考kong的官方文檔:docs.konghq.com/?_ga=2.4432…。
在k8s環境下部署,若是直接使用k8s平臺所提供的kube-dns的域名解析能力以及ClusterIP/NodePort的負載均衡的話,那麼原則上只須要配置Service以及Route規則就能夠進行工做。Upstream和Target屬於可選配置。
咱們繼續看看,kong-mesh自己如何根據這些規則進行路由。
Kong的路由及負載均衡能力是構建於openresty的access_by_lua以及balancer_by_lua這2個phase之上的。Servicea發送的請求經過iptables將流量導入到客戶端側(servicea-kong),kong收到後,根據請求消息進行route_match,找出匹配的目標service,而後再根據service的可用target進行負載均衡,找到目標serviceb節點實例進行發送。
服務端serviceb-kong收到請求後,因爲啓動前經過環境變量配置好了本地路由規則:
env:
- name: KONG_ORIGINS
value: "tcp://serviceb:8080=tcp://127.0.0.1:8080"複製代碼
根據該規則,kong直接把target爲serviceb:8080的請求直接投遞給serviceb。最終完成整個請求路由過程。
接下來,咱們再看看,kong基於上述的配置模型,能夠提供什麼樣的功能,以及與其餘mesh產品的差別點。
下表將kong mesh (community)與當下熱門的istio+envoy組合進行功能比較,你們能夠了解一下相關的差別(相關數據來源於kong官網)
功能點 | kong-mesh (community) | istio + envoy | 分析 |
---|---|---|---|
服務發現 | 經過admin api添加服務,並只能發現經過api添加的服務 | 支持對接k8s, consul等註冊中心進行服務發現 | 從平臺獨立性來看,kong mesh佔優; 從服務接管易用性來看,istio佔優 |
服務協議 | 支持http, http2, websocket, stream | 支持http, http2, grpc, websocket, stream | istio+envoy佔優 |
服務路由 | 支持根據源、目標地址,method、host、path、protocol等細粒度的路由 | 支持除左側列舉的全部能力外,還支持按header以及subset(標籤)的路由 | istio+envoy佔優 |
負載均衡 | 支持輪詢、權重、一致性hash的負載均衡模式 | 支持除左側列舉的全部負載均衡模式外,還支持隨機、最低負載等模式 | istio+envoy佔優 |
健康檢查 | 支持主動健康檢查以及被動健康檢查(熔斷) | 支持主動健康檢查以及被動健康檢查(熔斷) | 基本對等 |
安全 | 支持Certificate證書管理,支持JWT+TLS加密傳輸 | 支持證書下發及更新,JWT+mTLS加密傳輸 | 基本對等 |
多用戶 | 支持按consumer受權 | 支持RBAC用戶-角色受權 | istio+envoy佔優 |
故障注入 | 不支持 | 支持 | istio+envoy佔優 |
監控統計 | 繼承nginx的統計能力,支持按請求、鏈接、健康狀態等維度的統計 | 支持更細粒度的好比按協議、Zone的統計 | istio+envoy佔優 |
可擴展性 | 背靠openresty,提供強大的自定義插件能力,使用lua進行開發 | 提供lua插件開發能力,但能力比較基礎 | kong mesh佔優 |
學習曲線 | kong自身提供控制面和數據面能力,組網簡單,純lua語言上手較輕鬆 | istio+envoy一塊兒至少4個組件,跨兩種語言,上手較難 | kong mesh佔優 |
整體上來看,kong mesh相對istio+envoy在功能知足度上略佔劣勢,不過勝在簡單、可擴展性強,社區活躍度高(stars稍多於istio),將來結合社區將功能補齊也不是難事。
Kong做爲一個從API網關演變而來的service mesh產品,背靠成熟的OpenResty,擁有不輸istio+envoy的功能知足度、且社區活躍,版本更新較快(平均2週一個release),比較適合中小型團隊以及之前kong的老用戶試水service mesh。