使用nginx的ngx_upstream_jdomain模塊實現k8s容器的負載均衡


使用背景
最近一直在准備k8s上線事宜,目前已經在測試環境中全面部署並通過壓力測試環境檢驗。離正式上線基本只剩下時間問題。我們目前測試環境中的容器負載均衡大量使用到了nginx,就是借助了ngx_upstream_jdomain模塊,從而放棄了k8s官方的ingress。

在這里簡單說下k8s的ingress。k8s官方的ingress controller其實也是通過nginx來實現的,但是Ingress本身依賴於service,它通過查詢service的映射,來找到service后端的pod的真實ip,並將其掛載到ingress controll的upstream中來實現負載均衡。這本身其實並沒有什么問題。但由於在我們的k8s中,鑒於標准service基於kube-proxy的轉發效率不高,我們放棄了標准service。轉而直接采用了headless service的方式。這種方式的好處是,dns解析會直接解析到每個pod的ip,而不再解析到service ip,也不再需要kube-proxy來實現轉發。缺點是負載均衡只能依賴dns輪循,沒有靈活的調度策略,但毫無疑問,由於去除了kube-proxy這個中間層,轉發效率得到了提高。另外,由於我們直接打通了Pod與物理服務器之間的網絡,物理網絡中的主機可以與Pod之間通信,如果在中間采用標准的service,service的ip反而無法與物理網絡直接實現通信。

這樣一來,我們外部的負載均衡就沒辦法再去依賴Ingress了,我們采用了在外部部署nginx來實現負載均衡的方法,由於upstream里的pod ip會動態變化,所以我們不能直接在upstream里寫死pod的ip地址,而只能用service的域名來替代,並讓nginx自己去解析這個域名,我們知道headless service的域名由於沒有內部的service ip,所以是直接解析到pod ip上的,這樣就等於動態拿到了pod ip。在這種情況下,nginx_upstream_jdomain模塊就登場了。


配置

在具體的配置之前,還得說下,nginx_upstream_jdomain這個模塊嚴重依賴dns解析,另外由於其代理的后端的upstream中的pod ip經常性發生變化,所以dns緩存時間還不能太長,不過這個可以在nginx_upstream_jdomain模塊參數中配置


ngx_upstream_jdomain的詳細配置可以參考這里:https://www.nginx.com/resources/wiki/modules/domain_resolve/

我這里就給出一個示例配置:

 

resolver 192.168.1.1;
resolver_timeout 3s;
upstream www-stress-80 {
  jdomain www-stress.default.svc.wh01 port=80 interval=20;  #每隔20s做一次解析
}

server {
  server_name www.stress.test.com;
  listen 80;
  #set $proxy_upstream_name "-";
  location / {

    #Proxy Settings
    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header CDN-SRC-IP $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
    proxy_max_temp_file_size 0;
    proxy_connect_timeout 30;
    proxy_send_timeout 90;
    proxy_read_timeout 90;
    proxy_buffer_size 4k;
    proxy_buffers 4 32k;
    proxy_busy_buffers_size 64k;
    proxy_temp_file_write_size 64k;

    proxy_pass http://www-stress-80;
  }

}

 

另外,還需要說明的是,通過這種方式代理到后端的服務,后端服務接收到的$host的值即為www-stress-80,如果后端服務以主機頭的方式來接受服務,這顯然是不能接受的。所以在代理配置中,必須加上如下配置以將主機頭傳遞給后端服務器:

proxy_set_header Host $host;

 





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM