NGINX Ingress Controller 設計原理


 

ingress controller 如何工作

這篇文檔的目的是解釋 nginx ingress 控制器是如何工作的,特別是 nginx 模型的構建以及為什么需要它。

 

Nginx 配置

nginx ingress 控制器目標是組織 nginx 配置文件, 當 nginx 的配置文件發生任何更改時都需要重新加載,當配置文件中upstream 的內容有變更時(例如 當部署的應用中的 endpoints 變更時), nginx 的配置文件不會被重新加載,我們使用 ngx_http_lua_module 模塊完成 endpoints 的變更,請繼續往下看是如何操作的。

 

nginx 模型

通常來說,k8s 控制器利用同步循環模式去檢查控制器中資源的變更或者更新,為了達到這個目的,我們需要使用來自集群中不同的對象來構建一個模型,特別是(沒有順序要求) ingresses、Services, Endpoints, Secrets, and Configmaps 來生成一份和時間點相關的配置文件用來反映集群的狀態。為了從集群中獲取對象,我們使用 Kubernetes Informers 特別是FilteredSharedInformer,Informers 允許通過回掉機制對每一個獨立的資源對象在添加、刪除、更新時做出相關的反映,不幸的是,沒有一種方式能夠知道 nginx 的配置文件中具體哪一處發生了變化,因此,當每次發生變更時,我們不得不重新構建一次完成的配置模型與當前正在運行的模型進行比較,如果新的模型和當前的相等,那就避免生成新的配置從而去觸發 nginx 重載,除此之外,我們檢查如果僅僅是 Endpoints 不一樣, 我們發送一個 HTTP POST 到 lua 處理模塊,它運行在 nginx server 內部,從而避免重新生成新的配置觸發 nginx 重新加載,如果新的配置模型和正在運行的模型比較后不僅僅是 Endpoints 不一樣,那么就基於新的配置模型生成配置文件替換正在運行的配置文件觸發 nginx 重新加載,

利用模型一是為了避免不必要的 reload 發生再一個是為了檢查配置的定義沖突。

nginx 的最終配置文件來源於 Go template, 利用新的模型作為模版的需要的變量。

 

構建 nginx 模型

構建模型是一個昂貴的操作,由於這個原因,使用同步循環是必須的,通過使用 work queue 可以避免變更丟失,同時去掉 sync.Mutex的使用,額外的在循環開始和循環結束時創建時間窗允許丟棄不必要的更新,很重要的一件事情是集群中的任何變更都會都過 informer 發送到控制器中,這也是使用 work queue 的一個原因。

構建模型步驟

  • 通過CreationTimestamp 字段對 ingress 規則進行排序,比如 舊規則優先
  • 如果在多個 ingress 中相同主機的的相同路徑被定義,最后的定義生效
  • 如果多個 ingress 包含了相同主機的相同 TLS 部分內容,最后的定義生效
  • 如果多個 ingresses 定義的一個注解影響了 server 部分的配置,那么最后的定義生效
  • 創建 nginx servers 的列表(每一個主機)
  • 創建 nginx upstreams 列表
  • 如果多個 ingresses 定義了同一個主機的不同路徑,ingress controller 會降這些定義合並
  • 注解會被應用到 ingress 中所有的路徑
  • 每一個 ingresses 可以定義不同的注解,這些注解不會被共享

 

什么時候需要 reload

以下列表描述了需要 reload 的場景

  • 新的 ingress 資源被創建
  • TLS section 添加到已經存在的 ingress 中
  • 更改 ingress 的注解不僅僅影響到了 upstream 的配置,例如 load-balance 注解更改不需要執行 reload 操作
  • 從 ingress 中添加或者移除路徑
  • 移除 Ingress, Service, Secret
  • 一些缺失的對象從 ingress 中可以獲得,比如 Service 或者 Secret
  • Secret 被更新

 

避免 reload

某種情況下應該避免 reload, 特別是 endpoints 的變更, 比如 pod 的啟動或者替換,完全刪除重新加載超出了Ingress 控制器的范圍。這將需要大量工作,並且在某些時候沒有任何意義。 僅當 NGINX 更改了讀取新配置的方式時,這才可以更改,基本上,新的更改不會替代工作進程

 

避免 reload 當 Endpoints 變更時

當每一次 endpoint 變更時,控制器能夠從看得見的 services 中獲取 endpoints,生成相關的后端對象,然后將這些對象發送到運行在 ngixn 內部的 lua 處理模塊中, Lua 代碼反過來將這些對象存儲在共享內存區域, 每一次請求到來時 balancer_by_lua 會通過配置的負載均衡算法選擇一個后端對象來處理,nginx 則關心其余的事情,這種方式避免了當 endpoint 變化時發生 reload,注意當 upstream 的注解發生變更時也會避免發生 reload。

在具有頻繁部署應用程序的相對較大的群集中,此功能可以節省大量 Nginx 重載,否則會影響響應延遲,負載均衡質量(每次重載 Nginx 都會重置負載平衡狀態)等等

vi設計http://www.maiqicn.com 辦公資源網站大全https://www.wode007.com

避免錯誤配置導致中斷

因為 ingress 制器使用同步循環工作模式,所以它將配置應用於所有匹配的對象。如果某些 Ingress 對象的配置損壞,例如nginx.ingress.kubernetes.io/configuration-snippet 批注中的語法錯誤,則生成的配置將變為無效,不會重新加載,因此沒有 ingress 將會被考慮。

為了防止這種情況的發生,nginx 入口控制器選擇性的暴漏一個 准入驗證 Webhook 服務器,以確保傳入的 ingress 對象的有效性。 Webhook 進來的 ingress 加入到 ingresses 列表中,生成配置並調用 nginx 以確保配置沒有語法錯誤。


免責聲明!

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



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