如何使用Higress快速實(shí)現(xiàn)金絲雀與藍(lán)綠發(fā)布
背景
現(xiàn)如今,越來(lái)越多的應(yīng)用采用了微服務(wù)架構(gòu),這也導(dǎo)致了應(yīng)用數(shù)量相比傳統(tǒng)模式更多,管理更加復(fù)雜,發(fā)布更加頻繁,如果直接將新版本上線發(fā)布給全部用戶。一旦遇到線上事故(或BUG),對(duì)用戶的影響極大,解決問題周期較長(zhǎng),甚至有時(shí)不得不回滾到前一版本,嚴(yán)重影響了用戶體驗(yàn)。為了保證整體系統(tǒng)的穩(wěn)定,風(fēng)險(xiǎn)降到最低,我們可以采用灰度發(fā)布與藍(lán)綠發(fā)布等不同的發(fā)布方式。
什么是金絲雀發(fā)布
金絲雀發(fā)布,又稱灰度發(fā)布,是指通過讓小部份用戶流量引入的新版本進(jìn)行測(cè)試,如果一切順利,則可以增加(可能逐漸增加)百分比,逐步替換舊版本。如在過程中出現(xiàn)任何問題,則可以中止并快速回滾到舊版本。最簡(jiǎn)單的方式是隨機(jī)選擇百分比請(qǐng)求到金絲雀版本,但在更復(fù)雜的方案下,則可以基于請(qǐng)求的內(nèi)容、特定范圍的用戶或其他屬性等。
圖片
什么是藍(lán)綠發(fā)布
藍(lán)綠發(fā)布,提供了一種零宕機(jī)的部署方式,是一種以可觀測(cè)的方式發(fā)布應(yīng)用的方式,目的減少發(fā)布過程中停止時(shí)間。在保留老版本的同時(shí)部署新版本,將兩個(gè)版本同時(shí)在線,新版本和老版本相互熱備,通過切換路由權(quán)重的方式(非0即100)實(shí)現(xiàn)應(yīng)用的不同版本上線或者下線,如果有問題可以快速地回滾到老版本。這樣做的好處是無(wú)需停機(jī),并且風(fēng)險(xiǎn)較小。
圖片
Higress 部署
# 環(huán)境為Kubernetes v1.27.3
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready control-plane 9h v1.27.3
# 通過Helm安裝
$ helm repo add higress.io https://higress.io/helm-charts
"higress.io" already exists with the same configuration, skipping
$ helm install higress -n higress-system higress.io/higress --create-namespace --render-subchart-notes --set global.local=true --set higress-console.o11y.enabled=false --set higress-console.domain=console.higress.io --set higress-console.admin.password.value=admin
NAME: higress
LAST DEPLOYED: Thu Aug 10 20:37:40 2023
NAMESPACE: higress-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Higress successfully installed!
To learn more about the release, try:
$ helm status higress -n higress-system
$ helm get all higress -n higress-system
1. Use the following URL to access the console:
http://console.higress.io/
Since Higress Console is running in local mode, you may need to add the following line into your hosts file before accessing the console:
127.0.0.1 console.higress.io
2. Use following commands to get the credential and login:
export ADMIN_USERNAME=$(kubectl get secret --namespace higress-system higress-console -o jsnotallow="{.data.adminUsername}" | base64 -d)
export ADMIN_PASSWORD=$(kubectl get secret --namespace higress-system higress-console -o jsnotallow="{.data.adminPassword}" | base64 -d)
echo -e "Username: ${ADMIN_USERNAME}\nPassword: ${ADMIN_PASSWORD}"
NOTE: If this is an upgrade release, your current password won't be changed.
3. If you'd like to change the credential, you can edit this secret with new values: higress-system/higress-console
# 查看密碼
$ export ADMIN_USERNAME=$(kubectl get secret --namespace higress-system higress-console -o jsnotallow="{.data.adminUsername}" | base64 -d)
$ export ADMIN_PASSWORD=$(kubectl get secret --namespace higress-system higress-console -o jsnotallow="{.data.adminPassword}" | base64 -d)
$ echo -e "Username: ${ADMIN_USERNAME}\nPassword: ${ADMIN_PASSWORD}"
Username: admin
Password: admin
# 配置Hosts
$ cat /etc/hosts
127.0.0.1 demo.kubesre.com console.higress.io
# 轉(zhuǎn)發(fā)一下端口本地可以訪問
$ kubectl port-forward service/higress-gateway -n higress-system 80:80
訪問地址:http://console.higress.io/plugin
Username: admin Password: admin
圖片
示例應(yīng)用部署
部署示例版本:
$ cat demo.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo
labels:
app: demo
spec:
replicas: 1
selector:
matchLabels:
app: demo
template:
metadata:
labels:
app: demo
spec:
containers:
- name: demo
imagePullPolicy: Always
image: registry.cn-shanghai.aliyuncs.com/kubesre01/demo:v1
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: demo-svc
spec:
type: ClusterIP
selector:
app: demo
ports:
- port: 8080
targetPort: 8080
$ kubectl apply -f demo.yml
deployment.apps/demo created
配置Higress路由規(guī)則
在域名管理中創(chuàng)建域名:
圖片
在路由配置中創(chuàng)建路由:
圖片
驗(yàn)證訪問
# 通過如下命令進(jìn)行訪問,出現(xiàn)如下內(nèi)容則說明部署成功!
$ curl http://demo.kubesre.com/info
{"message":"云原生運(yùn)維圈!"}
部署新版本示例
部署新版本:
$ cat demo_new.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-new
labels:
app: demo-new
spec:
replicas: 1
selector:
matchLabels:
app: demo-new
template:
metadata:
labels:
app: demo-new
spec:
containers:
- name: demo-new
imagePullPolicy: Always
image: registry.cn-shanghai.aliyuncs.com/kubesre01/demo:v2
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: demo-new-svc
spec:
type: ClusterIP
selector:
app: demo-new
ports:
- port: 8080
targetPort: 8080
$ kubectl apply -f demo_new.yml
deployment.apps/demo_new created
基于客戶端請(qǐng)求頭的流量切分
假設(shè)線上已運(yùn)行了一套對(duì)外提供的七層demo應(yīng)用,此時(shí)開發(fā)了一些新的功能,需要上線新版本demo應(yīng)用,但是又不想直接替換成新版本demo應(yīng)用,而是希望將請(qǐng)求頭包含user=kubesre的客戶端請(qǐng)求轉(zhuǎn)發(fā)到新版本demo應(yīng)用中,進(jìn)行驗(yàn)證測(cè)試新版本demo應(yīng)用,等測(cè)試驗(yàn)證通過并穩(wěn)定后,可將所有流量從老版本demo應(yīng)用切換到新版本demo應(yīng)用中,再平滑地將老版本demo應(yīng)用下線。
創(chuàng)建新版本Higress路由規(guī)則:
圖片
目標(biāo)服務(wù),選擇最新版本
測(cè)試驗(yàn)證:
# 請(qǐng)求頭為user: kubesre,訪問到新的版本
$ curl -H "user: kubesre" http://demo.kubesre.com/info
{"message":"云原生運(yùn)維圈!新版本"}
# 其他則訪問到老的版本
$ curl http://demo.kubesre.com/info
{"message":"云原生運(yùn)維圈!"}
基于客戶端來(lái)源IP的流量切分
假設(shè)線上已運(yùn)行了一套對(duì)外提供的七層demo應(yīng)用,此時(shí)開發(fā)了一些新的功能,需要上線新版本demo應(yīng)用,又不想直接替換成新版本demo應(yīng)用,而是只希望公司內(nèi)部人員能訪問到新版本demo應(yīng)用中,進(jìn)行測(cè)試驗(yàn)證新版本demo應(yīng)用,非公司內(nèi)部人員訪問還是訪問到老版本應(yīng)用中。等公司內(nèi)部人員測(cè)試驗(yàn)證通過并穩(wěn)定后,可將所有流量從老版本demo應(yīng)用切換到新版本demo應(yīng)用中,再平滑地將老版本demo應(yīng)用下線。創(chuàng)建新版本Higress路由規(guī)則:
圖片
測(cè)試驗(yàn)證:
# 通過請(qǐng)求頭模擬來(lái)源IP,真實(shí)環(huán)境不需要
$ curl -H "X-Forwarded-For:123.456.789.123" http://demo.kubesre.com/info
{"message":"云原生運(yùn)維圈!新版本"}
# 其他則訪問到老的版本
$ curl http://demo.kubesre.com/info
{"message":"云原生運(yùn)維圈!"}
基于服務(wù)權(quán)重的流量切分
假設(shè)線上已運(yùn)行了一套對(duì)外提供的七層demo應(yīng)用,此時(shí)修復(fù)了一些問題,需要上線新版本demo應(yīng)用,又不想直接替換成新版本demo應(yīng)用,而是希望將20%的流量切換新版本。待運(yùn)行一段時(shí)間穩(wěn)定后,可將所有流量從老版本demo應(yīng)用切換到新版本demo應(yīng)用中,再平滑地將老版本demo應(yīng)用下線。
創(chuàng)建新版本Higress路由規(guī)則:
選擇最新目標(biāo)服務(wù)即可,其他不需要任何特殊配置:
圖片
配置權(quán)重:
$ kubectl edit ingress -n higress-system demo-new-canary
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
higress.io/canary: "true" # 開啟灰度
higress.io/canary-weight: "30" # 權(quán)重設(shè)置為30
higress.io/destination: demo-new-svc.default.svc.cluster.local:8080
higress.io/ignore-path-case: "false"
creationTimestamp: "2023-10-07T07:04:40Z"
generation: 1
labels:
higress.io/domain_demo.kubesre.com: "true"
higress.io/resource-definer: higress
name: demo-new-canary
namespace: higress-system
resourceVersion: "221188"
uid: bf833256-6993-4e56-bc3e-f96fe606e278
spec:
ingressClassName: higress
rules:
....
驗(yàn)證測(cè)試:
$ for i in {1..20}; do curl http://demo.kubesre.com/info; done;
{"message":"云原生運(yùn)維圈!"}
{"message":"云原生運(yùn)維圈!"}
{"message":"云原生運(yùn)維圈!"}
{"message":"云原生運(yùn)維圈!新版本"}
{"message":"云原生運(yùn)維圈!新版本"}
{"message":"云原生運(yùn)維圈!"}
{"message":"云原生運(yùn)維圈!"}
{"message":"云原生運(yùn)維圈!"}
{"message":"云原生運(yùn)維圈!"}
{"message":"云原生運(yùn)維圈!新版本"}
{"message":"云原生運(yùn)維圈!"}
{"message":"云原生運(yùn)維圈!"}
{"message":"云原生運(yùn)維圈!"}
{"message":"云原生運(yùn)維圈!"}
{"message":"云原生運(yùn)維圈!"}
{"message":"云原生運(yùn)維圈!"}
{"message":"云原生運(yùn)維圈!新版本"}
{"message":"云原生運(yùn)維圈!新版本"}
{"message":"云原生運(yùn)維圈!新版本"}
{"message":"云原生運(yùn)維圈!"}
注解說明
- higress.io/canary-weight:設(shè)置請(qǐng)求到指定服務(wù)的百分比(值為0~100的整數(shù))
- higress.io/canary-weight-totatl:設(shè)置權(quán)重總和,默認(rèn)為100
- higress.io/canary-by-header:基于Request Header的名稱進(jìn)行流量切分。當(dāng)請(qǐng)求包含該Header并其值為always時(shí),請(qǐng)求流量會(huì)被分配到灰度服務(wù)入口;其他情況時(shí),請(qǐng)求流量不會(huì)分配到灰度服務(wù)。
總結(jié)
本文介紹了金絲雀與藍(lán)綠發(fā)布及不同的應(yīng)用場(chǎng)景,并基于Higress結(jié)合企業(yè)實(shí)戰(zhàn)案例進(jìn)行演示,讓大家更容易理解上手,接下來(lái)的文章會(huì)講解Higress更多企業(yè)級(jí)應(yīng)用實(shí)戰(zhàn),請(qǐng)敬請(qǐng)期待!