參考文章:使用 Nginx 實(shí)現(xiàn)灰度發(fā)布
什么是灰度發(fā)布
- 【百度百科】灰度發(fā)布(又名金絲雀發(fā)布)是指在黑與白之間步责,能夠平滑過渡的一種發(fā)布方式悼沿。 在其上可以進(jìn)行A/B testing卫键,即讓一部分用戶繼續(xù)用產(chǎn)品特性A潜慎,一部分用戶開始用產(chǎn)品特性B抹剩,如果用戶對B沒有什么反對意見嗽测,那么逐步擴(kuò)大范圍绪励,把所有用戶都遷移到B上面來。
- 除了AB test灰度發(fā)布另一種思想是唠粥,只發(fā)布給一小部分用戶疏魏,如:App在發(fā)布之前,針對性的給一小批用戶測試下新版本晤愧,用小流量發(fā)布的方式來檢驗(yàn)新版會不會有問題大莫。
- 灰度發(fā)布可以保證整體系統(tǒng)的穩(wěn)定,在初始灰度的時候就可以發(fā)現(xiàn)养涮、調(diào)整問題葵硕,以保證其影響度眉抬。
Openshift上實(shí)現(xiàn)藍(lán)綠部署
image.png
在openshift上的部署兩個版本的Service:service01, service02贯吓。在創(chuàng)建Route的時候懈凹,可以非常簡單地指定同一個Route流量訪問兩個service的百分比service01(25%流量), service02(75%流量)。所有請求該Route的流量會被按指定的比例訪問后service悄谐。
配置發(fā)布75%-25%.png
Route詳情展示.png
對應(yīng)的Route yaml配置文件如下:
apiVersion: route.openshift.io/v1
kind: Route
metadata:
labels:
app: grey-test
name: grey-test
namespace: grey
spec:
alternateBackends:
- kind: Service
name: service_v2
weight: 75
host: grey-test.sample.com
port:
targetPort: web
to:
kind: Service
name: service_v1
weight: 25
wildcardPolicy: None
金絲雀發(fā)布的不足
- openshift中Route自帶的金絲雀發(fā)布配置非常簡單介评,也很實(shí)用。但是它沒辦法對請求的流量進(jìn)行定義控制爬舰。
- 例如根據(jù)IP们陆,指定IP為'202.38.12.10'的用戶訪問service_v2,那么Openshift中Route自帶的分流就無法實(shí)現(xiàn)。
- 所以必須對特定用戶訪問特定版本的問題情屹,我們需要尋求其它辦法坪仇。使用傳統(tǒng)的方法,Nginx是一個比較常見的選擇垃你。在openshift的灰度方案中椅文,我們也嘗試使用Nginx來實(shí)現(xiàn)對特定用戶的灰度發(fā)布。
Nginx配置實(shí)現(xiàn)灰度發(fā)布
- 創(chuàng)建兩個upstream
- 針對remote_addr進(jìn)行分流惜颇,默認(rèn)訪問default的upstream皆刺,如果ip為'202.38.12.10',則訪問api_v2的upstream凌摄。
無需多解釋羡蛾,直接上配置。
upstream default{
server 172.30.198.194:8080 max_fails=1 fail_timeout=60;
}
upstream api_v2{
server 172.30.198.194:8080 max_fails=1 fail_timeout=60;
}
server {
listen 80;
server_name _;
set $group default;
if ($remote_addr ~ "202.38.12.10") {
set $group api_v2;
}
location / {
proxy_pass http://$group;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
index index.html index.htm;
}
}
對配置作進(jìn)一步優(yōu)化
怎么獲取客戶端IP锨亏?
- 如果直接訪問Nginx服務(wù)的話痴怨,在Nginx上通過 $remote_addr 能夠獲得客戶端IP,但是我們知道在Openshift高可用部署中器予,我們使用了負(fù)載均衡器浪藻。通過負(fù)載均衡器轉(zhuǎn)發(fā)后,Nginx webserver獲得的$remote_addr其實(shí)是負(fù)載均衡器的IP劣摇,而不是客戶端真實(shí)IP珠移。
-
為了能在Nginx webserver中獲得客戶端IP,需要在附加HTTP頭字段開啟客戶端真實(shí)IP末融。同時在Nginx的配置中使用$http_x_forwarded_for來檢查客戶端IP.
IaaS上創(chuàng)建負(fù)載均衡器.png - 新的配置如下
upstream default{
server 172.30.198.194:8080 max_fails=1 fail_timeout=60;
}
upstream api_v2{
server 172.30.198.194:8080 max_fails=1 fail_timeout=60;
}
server {
listen 80;
server_name _;
set $group default;
if ($http_x_forwarded_for ~ "202.38.12.10") {
set $group api_v2;
}
location / {
proxy_pass http://$group;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
index index.html index.htm;
}
}
如何實(shí)現(xiàn)高可用钧惧?
這個非常簡單,只需要在Openshift上將為Nginx的DeploymentConfig增加Pod數(shù)增就可以了勾习。
我要有多個IP加入白名單浓瞪,有沒有更方便的配置方法?
Nginx有map函數(shù)巧婶,能將IP與訪問的后臺服務(wù)乾颁。
map $http_x_forwarded_for $group {
default 172.30.198.194:8080;
~202.38.12.10 172.30.198.194:8080;
}
server{
listen 8080;
server_name _;
location /{
proxy_pass http://$group;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded_For $proxy_add_x_forwarded_for;
index index.html index.htm;
}
}
明明有域名為啥只能是IP涂乌?
- Openshift對于Service除了有固定的IP外,還有固定的域名英岭,一般域名形式為:servername-projectname.svc湾盒。我們能否用域名代替IP,讓這個配置的可讀性更高,什么IP訪問什么服務(wù)一目了然诅妹。
- 但是直接將IP更改為對應(yīng)Service的域名罚勾,在啟動Nginx時會報無法解析域名的錯誤。
- Nginx需要在map配置中解析域名需要指定dns吭狡。
- 最終配置如下(172.30.0.1為Openshif集群默認(rèn)的內(nèi)部DNS尖殃,可在master的配置文件中查看):
resolver 172.30.0.1;
map $http_x_forwarded_for $group {
default api_v1.server.svc:8080;
~202.38.12.10 api_v2.server.svc:8080;
}
server{
listen 8080;
server_name _;
location /{
proxy_pass http://$group;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded_For $proxy_add_x_forwarded_for;
index index.html index.htm;
}
}
Openshift中對于443端口的負(fù)載均衡器使用的是TCP協(xié)議,無法轉(zhuǎn)發(fā)X_forward_for划煮,那https服務(wù)要怎么弄送丰?
如何應(yīng)用請求為Https,無法直接使用TCP負(fù)載均衡器弛秋,而Openshift部署時是通過TCP負(fù)載均衡器來作443端口的負(fù)載的器躏。
- 這就需要創(chuàng)建一個Https負(fù)載均衡器, 后臺Openshift Nginx的Route設(shè)置為正常的Http铐懊。其它配置一樣邀桑。既能將clientIP傳給后臺webserver,同時又滿足了該業(yè)務(wù)請求為Http協(xié)議科乎。
-
最終的流程圖如下:
Nginx作負(fù)載均衡器圖.png
拓展思考
- 是否一定要在Openshift上部署呢?【必然不需要】
- Nginx實(shí)現(xiàn)灰度發(fā)布除了支持ip還支持啥壁畸?【對Header頭信息等】
- 除了對頁面HTTP請求實(shí)現(xiàn)這種灰度,那么對于TCP服務(wù)呢茅茂,比如說數(shù)據(jù)庫捏萍?【也是OK的】