Linkerd + Namerd,實現Kubernetes 叢集的灰度釋出
主要內容源於 https://blog.buoyant.io/2016/11/04/a-service-mesh-for-kubernetes-part-iv-continuous-deployment-via-traffic-shifting/ ,砍掉了 Jenkins 等附加部分,更換了更加易於理解的示例應用,以保證主幹突出。
Kubernetes 所提供的 rolling-update 功能提供了一種漸進式的更新過程,然而其滾動過程並不容易控制,對於灰度釋出的需要來說,仍稍顯不足,這裡介紹一種利用 Linkerd 方案進行流量切換的思路。
官網介紹:linker∙d is a transparent proxy that adds service discovery, routing, failure handling, and visibility to modern software applications。
本文從實際操作入手,上線兩個版本的簡單應用,利用這一組合完成流量的切換和測試過程。
測試目標
- 同時上線兩個版本的應用。兩個應用均可工作,利用不同輸出進行區分。
- 動態調整分配給兩個版本的流量。
- 利用 CURL 進行流量分配的測試。
準備工作
這裡利用一個 1.2 以上版本的 Kubernetes 叢集進行演示:
- API Server / Registry:10.211.55.62
- Node:10.211.66.63
另外因某些原因,需要有能力獲取 Dockerhub 的映象。
例子程式很簡單,用一個 PHP 檔案顯示環境變數中的內容:
<?php
echo getenv("VAR_LABEL" );
Docker file 繼承自 dustise/lamp:latest
,檔案內容如下:
FROM dustise/lamp
COPY index.php /web/codebase
利用 Docker build 建立映象,這裡命名為 lamp:gray,備用。
建立工作負載
做一個簡單的 yaml 檔案來載入藍綠兩組應用,名字、環境變數和埠三個位置需要更改:
---
kind:ReplicationController
apiVersion: v1
metadata:
name: green
# 此處省略若干
env:- name: VAR_LABEL
value :'green'---
kind:Service
apiVersion: v1
# 此處省略若干
type:NodePort
ports:- protocol: TCP
nodePort:32001
port:80
targetPort:80
name: http
selector:
name: green
利用 kubectl create -f green.yaml
( 以及 blue.yaml )之後,可以利用 curl 或者瀏覽器檢查執行情況,如果正常,兩個埠的訪問應該分別會返回 green
和 blue
。
另外這裡的埠命名很重要,這一名稱會被後面的規則引用到。
注意,這裡 NodePort 並非必須,僅為測試方便。
執行 Namerd
此處 yaml 主要來自於官網 https://raw.githubusercontent.com/BuoyantIO/linkerd-examples/master/k8s-daemonset/k8s/namerd.yml 為適應本地環境,將原有 Loadbalancer 型別的服務改為 NodePort
略微做一下講解。
整個 yaml 由四部分組成:
ThirdPartyResource
這部分被用於做 Namerd 的儲存後端。
Configmap
作為 Namerd 的配置,其中定義了這樣幾個內容(詳情可參見 https://linkerd.io/config/0.8.5/namerd/index.html#introduction):
- 管理埠 9990
- storage:儲存定義,通過 8001 埠同 Kube Api Server 通訊,完成在 ThrdPartyResource 中的訪問(8001 埠由 kubectl proxy 指令開通)
- namer:定義服務發現能力由 Kubernetes 提供。
- interface 部分則是定義了兩種支援協議。其中 HTTP Controller 可以接收 namerctl 的控制指令。
RC
這部分不新鮮,除了 namerd 之外,還利用 kubectl proxy 提供通訊埠給 namerd,頗有蛇足之嫌。正確的開啟方式應該是直接和 Kube API Server 進行通訊。
Service
這裡注意服務型別的變更( LoadBalancer -> NodePort ),需要暴露 4180 和 9990 兩個埠,分別作為控制埠和介面埠。
利用 kubectl 啟用之後,就可以在指定的埠檢視管理介面了。此時的管理介面沒有做任何配置,因此比較單薄。
新增規則
下面來安裝 namerd 的控制工具,namerctl
go get-u github.com/buoyantio/namerctl
go install github.com/buoyantio/namerctl
接下來建立一條規則:
/host=>/#/io.l5d.k8s/default/http;/http/*/*/*=>8*/host/blue&2*/host/green;
這段程式碼表示該服務同時連線 blue 和 green 兩個後端服務,按照 80/20 的比例進行流量分配。
利用 namerctl dtab create [file name] --base-url
這裡 base-url 取值就是我們給 namerd 設定的 Nodeport。
接下來就能夠看到管理介面上顯示出新的規則了。
執行 Linkerd
這裡同樣基於官方的 https://raw.githubusercontent.com/BuoyantIO/linkerd-examples/master/k8s-daemonset/k8s/linkerd-namerd.yml
需要注意的是,官方給出的 yaml 檔案中有一處 bug,使得這個 yaml 只能在預設的 namespace 和 domain suffix 下執行。需要糾正對 namerd 的訪問方式,刪除 Namerd 後面的default.svc.cloud.local
即可。
同樣的,他的服務埠和管理埠都應該改用 NodePort 方式進行暴露。
執行後,同樣可以看到 Linkerd 的管理介面。
測試
下面可以做一個簡單的測試,來證明流量分配的有效性:
for((i=1;i<=300;i++));do curl -s "http://10.211.55.63:30001/";echo "";done| grep -i blue| wc -l
可以看到,隨著迴圈次數的增加,其結果越來越趨近於 80/20 的分配比例。
接下來,我們修改上面的 dtab 為如下內容:
/host=>/#/io.l5d.k8s/default/http;/http/*/*/*=>8*/host/blue&8*/host/green;
重新進行測試,就可以看到,流量分配已經發生了變化。另外,還可以在 Linkerd 的管理介面上看到網路流量的變化情況。
結語
這一組合基本能夠滿足流量漸變分配的功能需求,同時也有如豆瓣這樣的大廠使用,但他的 dtab 還是個相對複雜的東西,如果在生產上進行使用,還是需要進一步的學習。
另外,按照其文件中所陳述的功能範圍內容來看,僅用來做流量分配還是頗有點大材小用的味道,從個人來說,我傾向於一些更輕量級的解決方法。