作者:單家駿
Kong是一個基於OpenResty (Nginx) 封裝的微服務中介軟體產品,在微服務架構體系中,作為API閘道器以及API中介軟體(kubernetes ingress)提供服務。由於其天生具備Nginx的高效能、nginx-lua外掛的可定製性,再加上完善的社群以及齊全的文件,在中小企業使用者群非常受歡迎,擁有較好的群眾基礎。
2018年8月,kong釋出了1.0 GA版本,正式宣佈其支援service mesh,並提供社群版以及企業版2個版本。下面我們從Demo、配置、功能這3方面,對kong mesh進行體驗及分析。
Demo體驗
Kong社群提供了kong mesh的demo (github.com/Kong/kong-m…),該demo是實現的是tcp四層透明代理轉發業務。
該demo主要做的事情是:提供兩個服務servicea以及serviceb,serviceb作為服務端,通過ncat監聽8080埠,接受外部的TCP訊息;servicea作為client端,通過ncat將當前server的時間發往serviceb。Demo的執行效果如下:
在客戶端節點,每隔兩秒會傳送一次時間戳到服務端。
服務端節點,每隔兩秒列印一次時間戳。
接下來,我們詳細瞭解一下該demo背後的技術原理。
首先,我們來分析一下kong-mesh業務整體組網:
從組網中可以看出,kong mesh也分控制面與資料面。
控制面為圖中kong-admin的POD,3副本例項獨立部署,對外提供Admin API供使用者設定各種規則配置。
資料面為圖中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。