基於Kubernetes服務發現機制的探討Non Service
阿新 • • 發佈:2020-05-13
# 服務註冊
註冊中⼼作為一般的RPC/Web服務中的底層設施提供了服務程序元資料(IP, Port, Interface, Group,Method等)儲存,被Watch的功能,每個服務程序均需接⼊同⼀組持久化的K/V介質叢集(⽐如: zookeeper,etcdv3等)。各程序均需將本程序的元資料儲存於註冊中⼼,並且能夠Watch到其他服務程序的元資料變化(包括建立,更新等)。
# Kubernetes
Kubernetes作為容器叢集化管理⽅案管理資源的維度可主觀的分為服務程序管理和服務接⼊管理。服務程序管理,主要體現⽅式為Pod設計模式加控制器模式,控制器保證具有特定標籤(Kubernetes-Label)的Pod保持在恆定的數量(多刪,少補)。服務接⼊管理,主要為Kubernetes-Service,該Service預設為具有特定標籤(KubernetesLabel)的Pod統⼀提供⼀個VIP(Kubernetes-ClusterIP)所有需要請求該組Pod的請求都會按照round-robin的負載策略轉發到真正提供服務的Pod。並且CoreDNS為該Kubernetes-Service提供叢集內唯⼀的域名。
# Service 與 RPC/Web服務存在的衝突點
* Kubernetes-Service標準的資源物件具有的服務描述欄位 中並未提供完整的服務程序元資料欄位因此,⽆法直接使⽤Kubernetes-Service進⾏服務註冊與發現。
* RPC/Web服務的服務註冊是基於每個程序的,每個服務程序均需進⾏獨⽴的註冊。
* Kubernetes-Service預設為服務建立VIP,提供round-robin的負載策略也與RPC/Web服務⾃有的負載策略形成了衝突。
# 拋棄Service物件,選擇Pod物件進⾏註冊
* Kubernetes-Service與RPC/Web服務現有架構的衝突導致RPC/Web服務在選擇服務註冊與發現的時候只能選擇放棄該資源物件。
* RPC/Web服務既然選擇了每個RPC/Web服務程序獨⽴註冊,因此RPC/Web服務選擇將該程序具有的獨有的元資料寫⼊運⾏該RPC/Web服務程序的Pod在Kubernetes中的Pod資源物件的描述資訊中。
* 每個運⾏RPC/Web服務程序的Pod將本程序的元資料寫⼊Kubernetes-Pod Annotations欄位。為了避免與其他使⽤Annotations欄位的Operator或者其他型別的控制器(Istio)的欄位衝突,使⽤Key為 app.io/annotation value為具體儲存的K/V對的陣列的json編碼後的base64
編碼。
## 樣例:
```yml
apiVersion: v1
kind: Pod
metadata:
annotations:
app.io/annotation: 5LiN55So55yL5LqG5bCx5piv5LiA5Liq5paH5pys5Y2P6K6u
```
由於每個RPC/Web服務的Pod均只負責註冊本程序的元資料,因此Annotations欄位⻓度也不會因為運⾏RPC/Web服務程序的Pod數量增加⽽增加。
# 服務發現
解決掉了服務註冊問題,接下來需要解決的是服務發現的問題。Kubernetes Api-Server提供了Watch的功能,可以觀察特定namespace甚⾄整個叢集內各類資源的變化。RPC/Web服務為了避免RPC/Web服務程序watch到與RPC/Web服務程序⽆關的Pod的變化,RPC/Web服務將watch的條件限制在當前Pod所在的namespace,以及 watch 具有 app.io/label Value為app.io-value 的Pod。在Watch到對應Pod的變化後實時更新本地Cache,並通過Registry提供的Subscribe通知建⽴在註冊中⼼之上的服務叢集管理,或者其他功能。
# ⼯作流程
* 啟動RPC/Web服務的Deployment或其他型別控制器使⽤Kubernetes Downward-Api將本Pod所在namespace通過環境變數的形式注⼊RPC/Web服務程序。
* RPC/Web服務程序的Pod啟動後通過環境變數獲得當前的namespace以及該Pod名稱, 調⽤
Kubernetes-Apiserver PATCH 功能為本Pod新增Key為app.io/label Value為app.io-value的label。
* RPC/Web服務程序調⽤Kubernetes-Apiserver 將本程序的元資料通過PATCH接⼝寫⼊當前Pod的Annotations欄位。
* RPC/Web服務程序 LIST 當前namespace下其他具有同樣標籤的Pod,並解碼對應的Annotations欄位獲取其他Pod的資訊。
* RPC/Web服務程序 WATCH 當前namespace下其他具有同樣標籤的Pod的Annotations的欄位變化。
# 總結
Kubernetes已經為其承載的服務提供了⼀套服務發現,服務註冊,以及服務叢集管理機制,⽽傳統基於註冊中心的服務,同時也擁有⾃成體系的服務叢集管理。這兩個功能點形成了衝突,在⽆法調諧兩者的情況,如果選擇保持⾃有的服務叢集管理系,放棄Kubernetes-Service功能,將元資料直接寫⼊到Kubernetes Pod內,依賴Kubernetes提供的Watch功能提供維護服務叢集狀態,也是不錯的