最近在做一個(gè)需求開(kāi)發(fā):根據(jù)請(qǐng)求后的不同,nginx將請(qǐng)求分發(fā)到不同的后端服務(wù)钧萍;需要修改kubernetes的ingress-nginx-controller的源碼给猾,調(diào)試的時(shí)候遇到了挺多問(wèn)題拗秘,寫(xiě)出來(lái)签舞,有需要的老鐵可以參考贷帮。具體方案就不說(shuō)了戚揭,只說(shuō)一下nginx配置這一塊。
首先貼出組件版本:
ingress-nginx-controller的版本為0.9-beta.18撵枢,可以在github上找到開(kāi)源的項(xiàng)目源碼:
nginx map配置根據(jù)請(qǐng)求頭不同分配流量到不同后端服務(wù)
nginx版本為:nginx version: nginx/1.13.7
map配置的一個(gè)報(bào)錯(cuò):
nginx.conf文件部分如下:
http {
include /etc/nginx/conf.d/server-map.d/*-map.conf;
include /etc/nginx/conf.d/*-upstream.conf;
include /etc/nginx/conf.d/server-map.d/*-server.conf;
....
map_hash_bucket_size 64;
....
}
在/etc/nginx/conf.d/server-map.d/目錄下的flow-ppp-map.conf:
map $http_x_group_env $svc_upstream {
default zxl-test-splitflow-old-version;
~*old zxl-test-splitflow-old-version;
~*new zxl-test-splitflow-new-version;
}
flow-ppp-server.conf
server {
listen 8998;
server_name aa.hc.harmonycloud.cn;
location /testdemo/test {
proxy_pass http://$svc_upstream;
}
}
ingressgroup-upstream.conf
upstream zxl-test-splitflow-old-version {
server 10.168.173.29:8080 max_fails=0 fail_timeout=0;
}
upstream zxl-test-splitflow-new-version {
server 10.168.177.171:8080 max_fails=0 fail_timeout=0;
}
當(dāng)nginx -tc /etc/nginx/nginx.conf測(cè)試配置正確與否時(shí)報(bào)錯(cuò)如下:
Error: exit status 1
nginx: [emerg] "map_hash_bucket_size" directive is duplicate in /etc/nginx/nginx.conf:60
nginx: configuration file c test failed
解決:
這是因?yàn)槭状握{(diào)用map時(shí)會(huì)隱式設(shè)置map_hash_bucket_size民晒,即在nginx中map后寫(xiě)map_hash_bucket_size相當(dāng)于設(shè)置了兩次map_hash_bucket_size,如:
http {
...
map $status $_status {
default 42;
}
map_hash_bucket_size 64;
...
}
因此可以在map之前設(shè)置它锄禽,如下所示潜必。
http {
map_hash_bucket_size 64;
...
map $status $_status {
default 42;
}
...
}
所以include map配置也應(yīng)該放到設(shè)置map_hash_bucket_size之后:
http {
...
map_hash_bucket_size 64;
...
include /etc/nginx/conf.d/server-map.d/*-map.conf;
include /etc/nginx/conf.d/*-upstream.conf;
include /etc/nginx/conf.d/server-map.d/*-server.conf;
}
map配置說(shuō)明:
通過(guò)上面的include三個(gè)配置文件,最終對(duì)nginx生效的配置應(yīng)該是這樣的:
http {
...
map_hash_bucket_size 64;
...
map $http_x_group_env $svc_upstream {
default zxl-test-splitflow-old-version;
~*old zxl-test-splitflow-old-version;
~*new zxl-test-splitflow-new-version;
}
upstream zxl-test-splitflow-old-version {
server 10.168.173.29:8080 max_fails=0 fail_timeout=0;
}
upstream zxl-test-splitflow-new-version {
server 10.168.177.171:8080 max_fails=0 fail_timeout=0;
}
server {
listen 8998;
server_name aa.hc.harmonycloud.cn;
location /testdemo/test {
proxy_pass http://$svc_upstream;
}
}
}
當(dāng)在電腦上hosts文件里配置了aa.hc.harmonycloud.cn域名解析后沃但,訪問(wèn)http://aa.hc.harmonycloud.cn:8998/testdemo/test時(shí)(即server的server_name和listen磁滚、location的配置),nginx將會(huì)把請(qǐng)求轉(zhuǎn)發(fā)到http://$svc_upstream宵晚,這個(gè)$svc_upstream具體是什么垂攘,就是通過(guò)map配置來(lái)賦值的。這里map配置如下:
map $http_x_group_env $svc_upstream {
default zxl-test-splitflow-old-version;
~*old zxl-test-splitflow-old-version;
~*new zxl-test-splitflow-new-version;
}
其中$http_x_group_env可以是nginx內(nèi)置變量淤刃,也可以是自定義的header的key晒他、請(qǐng)求參數(shù)名;$svc_upstream即為自定義變量名钝凶。這里的配置含義為:當(dāng)請(qǐng)求頭里的x-group-env的值old時(shí),$svc_upstream被賦值為zxl-test-splitflow-old-version唁影;當(dāng)請(qǐng)求頭里的x-group-env的值new時(shí)耕陷,$svc_upstream被賦值為zxl-test-splitflow-new-version;默認(rèn)賦值為zxl-test-splitflow-old-version据沈;
(其中正則表達(dá)式如果以 “~” 開(kāi)頭哟沫,表示這個(gè)正則表達(dá)式對(duì)大小寫(xiě)敏感。以 “~*”開(kāi)頭锌介,表示這個(gè)正則表達(dá)式對(duì)大小寫(xiě)不敏感)嗜诀。而zxl-test-splitflow-new-version和zxl-test-splitflow-old-version表示兩個(gè)upstream名稱猾警。
因此nginx將會(huì)把請(qǐng)求轉(zhuǎn)發(fā)到http://$svc_upstream,這里的$svc_upstream會(huì)被替換為upstream的名稱隆敢,最終將得到upstream中的后端服務(wù)IP和Port发皿。
注意:如果我們自定義header為X-Real-IP,通過(guò)第二個(gè)nginx獲取該header時(shí)需要這樣:$http_x_real_ip; (一律采用小寫(xiě),而且前面多了個(gè)http_拂蝎,且中間用_替換)
測(cè)試
當(dāng)請(qǐng)求頭里加x-group-env為new時(shí)穴墅,訪問(wèn)后端打印出的是I am new version
當(dāng)請(qǐng)求頭里加x-group-env為old時(shí),訪問(wèn)后端打印出的是I am old version
最終通過(guò)請(qǐng)求頭不同實(shí)現(xiàn)了將流量分配到不同的后端服務(wù)温自。
將請(qǐng)求頭的key變?yōu)閄-Group-Env玄货,value變?yōu)镺LD或者NEW也沒(méi)關(guān)系: