通过阿里云K8S Ingress Controller实现路由配置的动态更新
簡介
在Kubernetes集群中,Ingress作為集群內(nèi)服務(wù)對外暴露的訪問接入點,其幾乎承載著集群內(nèi)服務(wù)訪問的所有流量。我們知道,Nginx Ingress Controller是Kubernetes社區(qū)很重要的一個子項目,其內(nèi)部主要依托于高性能的負載均衡軟件Nginx,將Kubernetes Ingress資源對象實時地自動化轉(zhuǎn)換為Nginx配置規(guī)則來對外提供期望的授權(quán)訪問入口。
現(xiàn)實問題
當隨著Kubernetes集群中部署的微服務(wù)越來越多,對外暴露的路由規(guī)則越來越復(fù)雜,服務(wù)后端Endpoint變化的越來越頻繁,那么對應(yīng)地都會引起Nginx Ingress Controller組件內(nèi)Nginx配置文件的變化越來越頻繁;而我們知道,任何一行Nginx配置的變化,都需要Reload Nginx才能生效,這在變化頻率較低的場景下索性還能接受,但在高頻率變化的場景下就會引起Nginx的頻繁Reload。
而Nginx頻繁Reload帶來的問題,這已是一個老生常談的話題了,其問題本質(zhì)主要還是源于Nginx本身最初的架構(gòu)設(shè)計模型:
一般在Linux服務(wù)器中,我們會配置使用Nginx的EPOLL多進程模式;當我們修改了Nginx配置文件后,需要通過
nginx -s reload命令來重新熱加載新的Nginx配置規(guī)則;
當Nginx Master進程接收到reload signal后,其會從指定路徑重新加載新的Nginx配置文件內(nèi)容,并校驗配置規(guī)則的有效性,若檢驗為有效的配置文件,則會依據(jù)新的配置文件中的worker_processes值fork出指定數(shù)量的新的Nginx Worker進程,此時新fork出來的子進程完全繼承了父進程的內(nèi)存數(shù)據(jù)ngx_cycle(其包含了新的解析后的Nginx配置規(guī)則),同時將配置中的每一個Listen Socket FD注冊到內(nèi)核的EPOLL事件監(jiān)聽中,此時這些新的Nginx Worker進程可以接收處理來自客戶端的請求;
同時Nginx Master進程會發(fā)送QUIT signal通知老的Nginx Worker進程平滑退出,當老的Nginx Worker進程接收到QTUI信號后,將其之前注冊到EPOLL中的監(jiān)聽Event移除,至此不再接收處理新的客戶端請求,并依據(jù)老配置文件中設(shè)置的worker_shutdown_timeout值來設(shè)置定時器,然后繼續(xù)處理完已接收的客戶端請求;若在worker_shutdown_timeout之前處理完已有的客戶端請求,則自動退出,若未處理完,則被強制Kill退出,此時就會導(dǎo)致該客戶端請求響應(yīng)異常。
因此,對于在高頻率變化的場景下,Nginx頻繁Reload會帶來較明顯的請求訪問問題:
動態(tài)更新
為緩解Nginx頻繁Reload帶來的影響,我們需要通過動態(tài)更新的方式來加載Nginx配置規(guī)則,即在不Fork新Nginx Worker進程的情況下來實時更新已加載到內(nèi)存中的Nginx配置規(guī)則。
首先我們看下Nginx的配置文件樣式,主要包含下面幾部分配置章節(jié):
# 1. main configuration daemon off; worker_processes 4;events {# 2. event configurationmulti_accept on;worker_connections 1024;use epoll; }http {# 3. http main configurationaccess_log /var/log/nginx/access.log;error_log /var/log/nginx/error.log;upstream {# 4. upstream configurationserver 0.0.0.1;}server {# 5. server configurationserver_name _ ;listen 80 default_server;location / {# 6. location configurationproxy_pass http://upstream_balancer;} }而在Kubernetes集群中,一個Ingress資源對象主要被解析映射到Nginx的HTTP Main Block、Server Block、Upstream Block和Location Block等章節(jié)的配置規(guī)則上,因此我們可以將這幾部分頻繁變化的配置內(nèi)容以Shared Memory的方式統(tǒng)一維持在內(nèi)存中,同時在Ingress Controller內(nèi)部暴露出管控端口,通過API的方式來實時管理Nginx路由規(guī)則配置:
當K8S Ingress Controller監(jiān)控到集群內(nèi)Ingress及相關(guān)聯(lián)的資源發(fā)生變化時,均可通過Internal API將最新的Nginx配置規(guī)則推送到統(tǒng)一的共享內(nèi)存配置中,而不用再通過Reload Nginx的方式來使新配置生效,至此當Nginx處理任何新接收的客戶端請求時,都可以基于最新的共享內(nèi)存中的配置進行規(guī)則匹配和路由轉(zhuǎn)發(fā);
配置說明
1、目前阿里云容器服務(wù)Kubernetes集群中最新版本的Nginx Ingress Controller組件默認已開啟Upstream的動態(tài)更新,同時支持應(yīng)用服務(wù)的灰度發(fā)布和藍綠發(fā)布功能,具體配置說明可參考這里;
我們可以通過如下命令來查看當前共享內(nèi)存中的Nginx Upstream的配置列表:
kubectl -n kube-system exec -it <NGINX-INGRESS-CONOTROLLER-POD-NAME> -- curl http://127.0.0.1:18080/configuration/backends2、同時也支持HTTPS證書的動態(tài)更新,可通過修改nginx-ingress-controller deployment的如下參數(shù)配置來開啟Nginx Ingress Controller的證書動態(tài)更新:
- args:- /nginx-ingress-controller- --configmap=$(POD_NAMESPACE)/nginx-configuration- --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services- --udp-services-configmap=$(POD_NAMESPACE)/udp-services- --annotations-prefix=nginx.ingress.kubernetes.io- --publish-service=$(POD_NAMESPACE)/nginx-ingress-lb- --enable-dynamic-certificates=true ### 添加該配置- --v=2當開啟HTTPS證書的動態(tài)更新后,Ingress的TLS證書都統(tǒng)一維護在Nginx的共享內(nèi)存中,我們可通過如下命令來查看當前共享內(nèi)存中配置的證書列表:
kubectl -n kube-system exec -it <NGINX-INGRESS-CONOTROLLER-POD-NAME> -- curl http://127.0.0.1:18080/configuration/certs3、進一步地我們也支持Nginx Server和Location配置的動態(tài)更新,可通過修改nginx-ingress-controller deployment的如下參數(shù)配置來開啟Nginx Ingress Controller的Server和Location的動態(tài)更新:
- args:- /nginx-ingress-controller- --configmap=$(POD_NAMESPACE)/nginx-configuration- --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services- --udp-services-configmap=$(POD_NAMESPACE)/udp-services- --annotations-prefix=nginx.ingress.kubernetes.io- --publish-service=$(POD_NAMESPACE)/nginx-ingress-lb- --enable-dynamic-certificates=true ### 添加該配置- --enable-dynamic-servers=true ### 添加該配置,同時也要enable-dynamic-certificates- --v=2同樣地,當我們開啟了Nginx Ingress Controller的Server動態(tài)更新后,所有Nginx Server和Location的配置都統(tǒng)一維護在共享內(nèi)存中,我們同樣可以通過如下命令來查看當前共享內(nèi)存中的Server配置列表:
kubectl -n kube-system exec -it <NGINX-INGRESS-CONOTROLLER-POD-NAME> -- curl http://127.0.0.1:18080/configuration/servers注意說明:當開啟Server的動態(tài)更新特性后,部分Ingress Annotation配置暫不支持,正在逐步優(yōu)化支持中,相應(yīng)地您可直接通過ConfigMap方式來進行配置;
原文鏈接
本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
總結(jié)
以上是生活随笔為你收集整理的通过阿里云K8S Ingress Controller实现路由配置的动态更新的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【机器学习PAI实战】—— 玩转人工智能
- 下一篇: 阿里云 MaxCompute 2018-