背景
我們有一個前端使用 Angular 的項目,采用 Kubenetes 默認部署方式 rolling updates 發布時,在更新 pod 的階段有時會出現灰屏的現象,問題源於新舊 pod 的前端靜態文件不兼容,想通過 kubernetes 的藍綠部署(blue-green deployments)解決這個問題。
原理
藍綠部署聽上去高上大,但對 k8s 來說是小菜一碟,就是基於同一個 deployment
配置,以 label
作為區分,創建對應不同應用程序版本(blue和green)的 deployment
資源,通過修改 service
配置中 selector
的 label
選擇對應的 deployment
資源,將流量在 blue 與 green 之間切換。
准備配置文件與部署腳本
在 deployment 配置文件中添加基於環境變量的 version
配置項,用它區分藍綠版本
apiVersion: apps/v1
kind: Deployment
metadata:
name: i-web-${VERSION}
spec:
template:
metadata:
labels:
app: i-web
version: "${VERSION}"
編寫部署綠色(green)版的腳本 deploy-green.sh
export VERSION=$2
for filename in deployments/$1/*.yaml
do
envsubst < $filename | kubectl apply -f -
done
在 service 配置文件中添加 version
配置項,用於在藍色(blue)版與綠色(green)版之間切換流量。
apiVersion: v1
kind: Service
metadata:
name: i-web
spec:
type: NodePort
selector:
app: i-web
version: "${VERSION}"
編寫切換藍綠版的腳本 toggle.sh
export VERSION=$2
for filename in services/$1/*.yaml
do
envsubst < $filename | kubectl apply -f -
done
編寫刪除藍色版的腳本 remove-blue.sh
kubectl delete deployment/$1-web-$2
進行一次藍綠發布
當前 blue 版本
$ kubectl get pods -l app=i-web
NAME READY STATUS RESTARTS AGE
i-web-2.1.54-69cbb6cdbd-6glzq 1/1 Running 0 174m
用下面的命令獲取當前 blue 版的版本號
$ kubectl get service i-web -o=json | jq '.spec.selector.version' | tr -d '"'
2.1.54
部署 green 版,版本號是 2.1.55(對應的容器鏡像已生成)
./deploy-green.sh i 2.1.55
查看部署結果,等 green 版 pod 啟動成功
kubectl get pods -l app=i-web
NAME READY STATUS RESTARTS AGE
i-web-2.1.54-69cbb6cdbd-6glzq 1/1 Running 0 3h11m
i-web-2.1.55-5d5dbd7f7d-hvp44 1/1 Running 1 4m55s
green 版已部署成功,blue 版與 green 版的 pod 都在運行
將流量切換到 green 版
./toggle.sh i 2.1.55
切換之后如果有問題,切回 blue 版
./toggle.sh i 2.1.54
如果沒有問題,等一段時間,刪除 blue 版
./remove-blue.sh i 2.1.54
手動擋藍綠部署完成。