基於Kubernetes服務發現機制的探討Non Service

YOYOFx發表於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
    編碼。

樣例:

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功能提供維護服務叢集狀態,也是不錯的選擇。

相關文章