coredns是實現pods之間通過域名訪問,如果外部需要訪問service服務,需訪問對應的NodeIP:Port。但是由於NodePort需要指定宿主機端口,一旦服務多起來,多個端口就難以管理。那么,這種情況下,使用Ingress暴露服務更加合適。
四層和七層區別(不明白就這樣去理解,七層最常見就是應用層的http,也就是url,四層是傳輸層,為tcp/udp端口)
Ingress 是一個規則的集合,它允許集群外的流量通過一定的規則到達集群內的 Service 。如下圖:
Ingress三個組件:
反向代理負載均衡器
Ingress Controller
Ingress
反向代理負載均衡器,即常見的負載均衡軟件,如 nginx、Haproxy 等。
Ingress Controller 與 kubernetes API 進行交互,實時的感知后端 service、pod 等變化, Ingress Controller 再結合下文的 Ingress 生成配置,然后更新反向代理負載均衡器,並刷新其配置,實現動態服務發現與更新。
Ingress是規則集合;定義了域名與Kubernetes的service的對應關系;這個規則將與 Ingress Controller 結合, Ingress Controller 將其動態寫入到負載均衡器配置中,從而實現整體的服務發現和負載均衡。
Kubernetes外部訪問流程圖
https://www.kubernetes.org.cn/2812.html
LVS主要是用來實現ingress的高可用,LVS可以是F5.也可以keepalve等
這里k8s中的ingress組件急速openshift中的router組件
https://www.kubernetes.org.cn/2812.html
簡化應用發布的操作流程,域名與服務實現了自動更新與配置,只需定義ingress與添加外部DNS條目兩步操作,即可完成應用的對外發布,減少操作流程,提高維護效率。
Kubernetes 提供了兩種內建的雲端負載均衡機制( cloud load balancing )用於發布公共應用, 一種是工作於傳輸層的 Service 資源,它實現的是 TCP 負載均衡器”,另一種是Ingress 資源,它 現的是“ HTTP(S )負載均衡器”
( 1) TCP 載均衡器
無論是 iptables 還是ipvs 模型的 Service 資源都配置於 Linux 內核中的 Netfilter 之上進行四層調度,是一種類型更為通用的調度器, 支持調度 HTTP、MySQL 應用層服務。不過,也正是由於 作於傳輸層從而使得它無法做到類似卸載 HTTPS 中的 SSL 會話等一類作,也不支持基於 URL 的請求調度機制,而且, Kubernetes 也不支持為此類負載均衡器配置任何類型的健康狀態檢查機制
( 2) HTTP(S )負載均衡器
HTTP(S )負載均衡器是應用層負載均衡機制的 種,支持根據環境做出更好的調度決策。與傳輸層調度器相比,它提供了諸如可自定義 URL 映射和 TLS 卸載 功能,並支持多種類型 的后端服務器健康狀態檢查機制
k8s的ingress實現證書卸載功能
對於Kubernetes的Service,無論是Cluster-Ip和NodePort均是四層的負載,集群內的服務如何實現七層的負載均衡,這就需要借助於Ingress,Ingress控制器的實現方式有很多,比如nginx, Contour, Haproxy, trafik, Istio,我們以nginx的實現為例做演示。
Ingress-nginx是7層的負載均衡器 ,負責統一管理外部對k8s cluster中service的請求。主要包含:
-
ingress-nginx-controller:根據用戶編寫的ingress規則(創建的ingress的yaml文件),動態的去更改nginx服務的配置文件,並且reload重載使其生效(是自動化的,通過lua腳本來實現);
-
ingress資源對象:將Nginx的配置抽象成一個Ingress對象,每添加一個新的Service資源對象只需寫一個新的Ingress規則的yaml文件即可(或修改已存在的ingress規則的yaml文件)
1)ingress controller通過和kubernetes api交互,動態的去感知集群中ingress規則變化2)然后讀取ingress規則(規則就是寫明了哪個域名對應哪個service),按照自定義的規則,生成一段nginx配置3)再寫到nginx-ingress-controller的pod里,這個Ingress controller的pod里運行着一個Nginx服務,控制器把生成的nginx配置寫入/etc/nginx.conf文件中4)然后reload一下使配置生效。以此達到域名分別配置和動態更新的問題。
上面的案例中ingress-control按照的時候使用的是本地網絡,安裝在label為inggess的機器上面的,這台機器的ip地址是192.168.136.128
在生產上面ingress-control是高可用要安裝多台,我們可以使用haproxy使用高可用實現一個vip,或者利用F5使用vip,這里配置dns的時候,就要配置vip集群的ip
第二個如何實現ingress的證書https卸載
相當的經典呀,這里證書卸載是在ingress中進行卸載的,類似nginx進行證書的卸載,如果ingress前面使用了f5,證書卸載也可以放在f5中進行卸載管理
ingrees-control生產的是一組pod資源,這組pod資源的外部的是externalLB, externalLB可能是F5,也可能是其他高可用的負載
部署 Ingress 控制器( Nginx)
Ingress 控制器自身是運行 Pod 中的容器應用,一般是 Nginx或Envoy -類的具有代理及負載均衡功能的守護進程,它監視着來自於API Server的Ingress 對象狀態,並以其規則生成相應的應用程序專有格式的配置文件並通過重載或開啟守護進程而使新配置生效。例如,對於 Nginx 來說,Ingress 規則需要轉換為 Nginx 的配置信息,簡單來說, Ingress 控制器其實就是托管於Kubemetes 系統之上的用於實現在應用層發布服務的Pod 資源,它將跟跟蹤Ingress 資源並實時生成配置規則。那么,同樣運行為 Pod 資源的 Ingress 控制器進程又該如何接入外部的請求流量那? 常用的解決方案有如下兩種:
以 Deployment 控制器管理Ingress 控制器的 Pod 資源,並通過 NodePort或Load Balancer 類型的 Service 對象為其接入集群外部的請求流量,這就意味着,定義一個Ingress 控制器時,必須在其前端定義一個專用的 Service 資源:如圖 所示
2.借助於 DaemonSet 控制器,將 Ingress控制器的 Pod 資源各自以單一實例的方式運行於集群的所有或部分工作節點之上,並配置這類Pod對象以hostPort(如圖a)或 hostNetwork (如圖b)的方式在當前節點接入外部流量
上面博客部署采用的是方式2中的b模式來進行部署 ,參加博客http://www.kendd.cn/?p=2492
博客2:http://www.dockone.io/article/9745
淺談Kubernetes Ingress控制器的技術選型
淺談Kubernetes Ingress控制器的技術選型
名詞解釋
閱讀本文需要熟悉以下基本概念:- 集群:是指容器運行所需雲資源的集合,包含了若干台雲服務器、負載均衡器等雲資源。
- 實例(Pod):由相關的一個或多個容器構成一個實例,這些容器共享相同的存儲和網絡空間。
- 工作負載(Node):Kubernetes 資源對象,用於管理 Pod 副本的創建、調度以及整個生命周期的自動控制。
- 服務(Service):由多個相同配置的實例(Pod)和訪問這些實例(Pod)的規則組成的微服務。
- Ingress:Ingress 是用於將外部 HTTP(S)流量路由到服務(Service)的規則集合。
Kubernetes 訪問現狀
Kubernetes 的外部訪問方式
在 Kubernetes 中,服務跟 Pod IP 主要供服務在集群內訪問使用,對於集群外的應用是不可見的。怎么解決這個問題呢?為了讓外部的應用能夠訪問 Kubernetes 集群中的服務,通常解決辦法是 NodePort 和 LoadBalancer。
這兩種方案其實各自都存在一些缺點:
- NodePort 的缺點是一個端口只能掛載一個 Service,而且為了更高的可用性,需要額外搭建一個負載均衡。
- LoadBalancer 的缺點則是每個服務都必須要有一個自己的 IP,不論是內網 IP 或者外網 IP。更多情況下,為了保證 LoadBalancer 的能力,一般需要依賴於雲服務商。
在Kubernetes的實踐、部署中,為了解決像 Pod 遷移、Node Pod 端口、域名動態分配,或者是 Pod 后台地址動態更新這種問題,就產生了 Ingress 解決方案。
Ingress 選型
Nginx Ingress 的缺點
Ingress 是 Kubernetes 中非常重要的外網流量入口。在Kubernetes中所推薦的默認值為Nginx Ingress,為了與后面Nginx 提供的商業版 Ingress 區分開來,我就稱它為Kubernetes Ingress。Kubernetes Ingress,顧名思義基於 Nginx 的平台,Nginx 現在是世界上最流行的 Nginx HTTP Sever,相信大家都對 Nginx 也比較熟悉,這是一個優點。它還有一個優點是 Nginx Ingress 接入 Kubernetes 集群所需的配置非常少,而且有很多文檔來指引你如何使用它。這對於大部分剛接觸 Kubernetes 的人或者創業公司來說,Nginx Ingress 的確是一個非常好的選擇。
但是當 Nginx Ingress 在一些大環境上使用時,就會出現很多問題:
- 第一個問題:Nginx Ingress用了一些 OpenResty 的特性,但最終配置加載還是依賴於原有的 Nginx config reload。當路由配置非常大時,Nginx reload 會耗時很久,時間長達幾秒甚至十幾秒,這樣就會嚴重影響業務,甚至造成業務中斷。
- 第二個問題: Nginx Ingress 的插件開發非常困難。如果你認為 Nginx Ingress 本身插件不夠用,需要使用一些定制化插件,這個額外的開發任務對程序員來說是十分痛苦的。 因為Nginx Ingress自身的插件能力和可擴展性非常差。
Ingress 選型原則
既然發現了 Nginx Ingress 有很多問題,那是不是考慮選擇其他開源的、更好用的 Ingress?市場上比 Kubernetes Ingress 好用的Ingress起碼有十幾家,那么如何從這么多 Ingress 中選擇適合自己的呢?Ingress 最終是基於 HTTP 網關的,市面上 HTTP 網關主要有這么幾種:Nginx、Golang 原生的網關,以及新崛起的 Envoy 。但是每個開發人員所擅長的技術棧不同,所以適合的 Ingress 也會不一樣。
那么問題來了,我們如何選擇一個更加好用的 Ingress 呢?或者縮小點范圍,熟悉 Nginx 或 OpenResty 的開發人員,應該選擇哪一個 Ingress 呢?
下面來介紹一下我對 Ingress 控制器選型的一些經驗。
選型原則
基本特點
首先我認為 Ingress 控制器應該具備以下基本功能,如果連這些功能都沒有,那完全可以直接pass。
- 必須開源的,不開源的無法使用。
- Kubernetes 中 Pod 變化非常頻繁,服務發現非常重要。
- 現在 HTTPS 已經很普及了,TLS 或者 SSL 的能力也非常重要,比如證書管理的功能。
- 支持 WebSocket 等常見協議,在某些情況下,可能還需要支持 HTTP2、QUIC 等協議。
基礎軟件
前面有提到,每個人擅長的技術平台不一樣,所以選擇自己更加熟悉的 HTTP 網關也顯得至關重要。比如 Nginx、HAProxy、Envoy 或者是 Golang 原生網關。因為你熟悉它的原理,在使用中可以實現快速落地。
在生產環境上,高性能是一個很重要的特性,但比之更重要的是高可用。這意味着你選擇的網關,它的可用性、穩定性一定要非常強,只有這樣,服務才能穩定。
功能需求
拋開上述兩點,就是公司業務對網關的特殊需求。你選擇一個開源產品,最好肯定是開箱能用的。比如你需要 GRPC 協議轉換的能力,那當然希望選的網關具備這樣的功能。這里簡單列一下影響選擇的因素:
- 協議:是否支持 HTTP2、HTTP3;
- 負載均衡算法:最基本的WRR、一致性哈希負載均衡算法是否能夠滿足需求,還是需要更加復雜的類似EWMA負載均衡算法。
- 鑒權限流:僅需要簡單的鑒權,或更進階的鑒權方式。又或者需要集成,能夠快速的開發出像騰訊雲 IM 的鑒權功能。Kubernetes Ingress除了前面我們提到的存在Nginx reload 耗時長、插件擴展能力差的問題,另外它還存在后端節點調整權重的能力不夠靈活的問題。
選擇 APISIX 作為 Ingress controller
相比Kubernetes Ingress,我個人更推薦 APISIX。雖然它在功能上比 Kong 會少很多,但是 APISIX 很好的路由能力、靈活的插件能力,以及本身的高性能,能夠彌補在 Ingress 選型上的一些缺點。對於基於 Nginx 或 Openresty 開發的程序員,如果對現在的 Ingress 不滿意,我推薦你們去使用 APISIX 作為 Ingress。如何將 APISIX 作為 Ingress 呢?我們首先要做出一個區分,Ingress 是 Kubernetes 名稱的定義或者規則定義,Ingress controller 是將 Kubernetes 集群狀態同步到網關的一個組件。但 APISIX 本身只是 API 網關,怎么把 APISIX 實現成 Ingress controller 呢?我們先來簡要了解一下如何實現 Ingress。
實現 Ingress,本質上就只有兩部分內容:
- 第一部分:需要將 Kubernetes 集群中的配置、或 Kubernetes 集群中的狀態同步到 APISIX 集群。
- 第二部分:需要將 APISIX中 的一些概念,比如像服務、upstream 等概念定義為 Kubernetes 中的 CRD。
如果實現了第二部分,通過 Kubernetes Ingress 的配置,便可以很快的產生 APISIX。通過 APISIX Ingress controller 就可以產生 APISIX 相關的配置。當前為了快速的將 APISIX 落地為能夠支持 Kubernetes 的 Ingress,我們創建了一個開源項目,叫 Ingress controller。
Ingress controller 架構圖
上圖為Ingress controller 項目的整體架構圖。左邊部分為 Kubernetes 集群,這里可以導入一些 yaml 文件,對 Kubernetes 的配置進行變更。右邊部分則是 APISIX 集群,以及它的控制面和數據面。從架構圖中可以看出,APISIX Ingress 充當了 Kubernetes 集群以及 APISIX 集群之間的連接者。它主要負責監聽 Kubernetes 集群中節點的變化,將集群中的狀態同步到 APISIX 集群。另外,由於Kubernetes 倡導所有組件都要具備高可用的特性,所以在 APISIX Ingress 設計之初,我們通過雙節點或多節點的模式來保證 APISIX Ingress controller 的保障高可用。
總結
各類 Ingress 橫向對比
相對於市面上流行的 Ingress 控制器,我們簡單對比來看看 APISIX Ingress 有什么優缺點。上圖是外國開發人員針對 Kubernetes Ingress 選型做的一張表格。我在原來表格的基礎上,結合自己的理解,將 APISIX Ingress 的功能加入了進來。我們可以看到,最左邊的是APISIX,后邊就是 Kubernetes Ingress 和 Kong Ingress,后面的 Traefik,就是基於 Golang 的 Ingress。HAproxy 是比較常見的,過去是比較流行的負載均衡器。Istio 和 Ambassador 是國外非常流行的兩個Ingress。
接下來我們總結下這些 Ingress各自的優缺點:
- APISIX Ingress:APISIX Ingress 的優點前面也提到了,它具有非常強大的路由能力、靈活的插件拓展能力,在性能上表現也非常優秀。同時,它的缺點也非常明顯,盡管APISIX開源后有非常多的功能,但是缺少落地案例,沒有相關的文檔指引大家如何使用這些功能。
- Kubernetes Ingress:即 Kubernetes 推薦默認使用的 Nginx Ingress。它的主要優點為簡單、易接入。缺點是Nginx reload耗時長的問題根本無法解決。另外,雖然可用插件很多,但插件擴展能力非常弱。
- Nginx Ingress:主要優點是在於它完全支持 TCP 和 UDP 協議,但是缺失了鑒權方式、流量調度等其他功能。
- Kong:其本身就是一個 API 網關,它也算是開創了先河,將 API 網關引入到 Kubernetes 中當 Ingress。另外相對邊緣網關,Kong 在鑒權、限流、灰度部署等方面做得非常好。Kong Ingress 還有一個很大的優點:提供了一些 API、服務的定義,可以抽象成 Kubernetes 的 CRD,通過Kubernetes Ingress 配置便可完成同步狀態至 Kong 集群。缺點就是部署特別困難,另外在高可用方面,與 APISIX 相比也是相形見絀。
- Traefik:基於 Golang 的 Ingress,它本身是一個微服務網關,在 Ingress 的場景應用比較多。他的主要平台基於 Golang,自身支持的協議也非常多,總體來說是沒有什么缺點。如果大家熟悉 Golang 的話,也推薦一用。
- HAproxy:是一個久負盛名的負載均衡器。它主要優點是具有非常強大的負載均衡能力,其他方面並不占優勢。
- Istio Ingress 和 Ambassador Ingress 都是基於非常流行的 Envoy。說實話,我認為這兩個 Ingress 沒有什么缺點,可能唯一的缺點是他們基於 Envoy 平台,大家對這個平台都不是很熟悉,上手門檻會比較高。
綜上所述,大家在了解了各個 Ingress 的優劣勢后,可以結合自身情況快速選擇適合自己的 Ingress。
Ingress 總覽: https://github.com/Miss-you/awesome-ingress
作者:厲輝,騰訊雲中間件API網關核心研發成員,Apache APISIX PPMC。熱愛開源,樂於分享,活躍於Apache APISIX社區。
參考博客2:https://www.jianshu.com/p/4b7ae360b3b6
1.1 Ingress簡介
1.1.1需求
coredns是實現pods之間通過域名訪問,如果外部需要訪問service服務,需訪問對應的NodeIP:Port。但是由於NodePort需要指定宿主機端口,一旦服務多起來,多個端口就難以管理。那么,這種情況下,使用Ingress暴露服務更加合適。
1.1.2 Ingress組件說明
使用Ingress時一般會有三個組件:反向代理負載均衡器、Ingress Controller、Ingress
1、反向代理負載均衡器
反向代理負載均衡器很簡單,說白了就是 nginx、apache 等中間件,新版k8s已經將Nginx與Ingress Controller合並為一個組件,所以Nginx無需單獨部署,只需要部署Ingress Controller即可。在集群中反向代理負載均衡器可以自由部署,可以使用 Replication Controller、Deployment、DaemonSet 等等方式
2、Ingress Controller
Ingress Controller 實質上可以理解為是個監視器,Ingress Controller 通過不斷地跟 kubernetes API 打交道,實時的感知后端 service、pod 等變化,比如新增和減少 pod,service 增加與減少等;當得到這些變化信息后,Ingress Controller 再結合下文的 Ingress 生成配置,然后更新反向代理負載均衡器,並刷新其配置,達到服務發現的作用
3、Ingress
Ingress 簡單理解就是個規則定義;比如說某個域名對應某個 service,即當某個域名的請求進來時轉發給某個 service;這個規則將與 Ingress Controller 結合,然后 Ingress Controller 將其動態寫入到負載均衡器配置中,從而實現整體的服務發現和負載均衡
整體關系如下圖所示:

從上圖中可以很清晰的看到,實際上請求進來還是被負載均衡器攔截,比如 nginx,然后 Ingress Controller 通過跟 Ingress 交互得知某個域名對應哪個 service,再通過跟 kubernetes API 交互得知 service 地址等信息;綜合以后生成配置文件實時寫入負載均衡器,然后負載均衡器 reload 該規則便可實現服務發現,即動態映射。
3.1.3 Nginx-Ingress工作原理
ingress controller通過和kubernetes api交互,動態的去感知集群中ingress規則變化;然后讀取它,按照自定義的規則,規則就是寫明了哪個域名對應哪個service,生成一段nginx配置;再寫到nginx-ingress-control的pod里,這個Ingress controller的pod里運行着一個Nginx服務,控制器會把生成的nginx配置寫入/etc/nginx.conf文件中;然后reload一下使配置生效。以此達到域名分配置和動態更新的問題。
說明:基於nginx服務的ingress controller根據不同的開發公司,又分為:
- k8s社區的ingres-nginx(https://github.com/kubernetes/ingress-nginx)
- nginx公司的nginx-ingress(https://github.com/nginxinc/kubernetes-ingress)
3.2.4 Ingress Controller高可用架構
作為集群流量接入層,Ingress Controller的高可用性顯得尤為重要,高可用性首先要解決的就是單點故障問題,一般常用的是采用多副本部署的方式,我們在Kubernetes集群中部署高可用Ingress Controller接入層同樣采用多節點部署架構,同時由於Ingress作為集群流量接入口,建議采用獨占Ingress節點的方式,以避免業務應用與Ingress服務發生資源爭搶。

如上述部署架構圖,由多個獨占Ingress實例組成統一接入層承載集群入口流量,同時可依據后端業務流量水平擴縮容Ingress節點。當然如果您前期的集群規模並不大,也可以采用將Ingress服務與業務應用混部的方式,但建議進行資源限制和隔離。 ingree單獨找機器部署,不要和k8s的業務節點混在一起,ingress的前面采用slb進行負載
在openshift中的router就是這里k8s中的ingress,生產中ingress都是找單獨的機器進行部署,前面采用f5進行負載ingress
https://blog.csdn.net/w50feng/article/details/106539476
kubernetes部署ingress+keepalived高可用
參考博客:https://blog.csdn.net/w50feng/article/details/106539476
kubernetes版本:1.17.3(快速安裝:https://blog.csdn.net/w50feng/article/details/106470888)
ingress定義
Ingress 公開了從集群外部到集群內 services 的HTTP和HTTPS路由。 流量路由由 Ingress 資源上定義的規則控制。具體詳解見官方文檔:https://v1-17.docs.kubernetes.io/zh/docs/concepts/services-networking/ingress/
keepalived介紹:
Keepalived提供了用於負載平衡和高可用性的框架。負載平衡框架依賴於廣為人知的Linux虛擬服務器(IPVS)內核模塊,該模塊提供第4層負載平衡。Keepalived實施一組運行狀況檢查器,以根據其運行狀況動態,自適應地維護和管理負載平衡的服務器池。虛擬冗余路由協議(VRRP)實現了高可用性。VRRP是路由器故障轉移的基礎磚。此外,keepalived還實現了一組VRRP有限狀態機的掛鈎,從而提供了低級和高速協議交互。每個Keepalived框架可以獨立使用,也可以一起使用以提供彈性基礎架構。附官方文檔:https://www.keepalived.org/doc/index.html
ingress部署:
給需要安裝ingress的node打標簽,例為node01和node02
kubectl label nodes node01 ingress=true
kubectl label nodes node02 ingress=true
查詢label:kubectl get node --show-labels
ingress的yaml文件下載:https://github.com/kubernetes/ingress-nginx/blob/nginx-0.30.0/deploy/static/mandatory.yaml
修改文件:
kind: Deployment改成kind: DaemonSet;
注釋#spec.replicas: 1;
spec.spec內增加配置:
hostNetwork: true #使用hostNetwork:true配置網絡,pod中運行的應用程序可以直接看到宿主主機的網絡接口,宿主主機所在的局域網上所有網絡接口都可以訪問到該應用程序
dnsPolicy: ClusterFirstWithHostNet #該設置是使POD使用的k8s的dns,如果不加上dnsPolicy: ClusterFirstWithHostNet ,pod默認使用所在宿主主機使用的DNS,這樣也會導致容器內不能通過service name 訪問k8s集群中其他POD
nodeSelector:
ingress: 'true' #node標簽
運行文件:kubectl apply -f mandatory1.yaml
查看pod啟動狀態:kubectl get pod -n ingress-nginx
、
dashboard查看部署node為node01和node02
keepalived安裝:
node01和node02使用yum安裝:yum install keepalived -y
修改配置文件,node01為MASTER,node02為BACKUP
vi /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id k8singress #標識信息,隨便取
}
vrrp_instance VI_1 {
state MASTER #角色,node01為MASTER,node02為BACKUP
interface eth0 #vip綁定的網絡端口
virtual_router_id 66 #讓master和backup在同一個虛擬路由里,id號必須相同
priority 120 #優先級,誰的優先級高誰就是master;node01為120,node02為110
advert_int 1 #心跳間隔時間
authentication {
auth_type PASS #認證
auth_pass 1111 #密碼
}
virtual_ipaddress {
192.168.2.11 #虛擬ip
}
}
啟動keepalived:systemctl start keepalived
自啟動:systemctl enable keepalived
查詢VIP:node01上可見VIP,node02沒有
node01:
node02:
驗證VIP飄移,斷開node01,vip飄移到node02,成功驗證
注:可添加腳本監控ingress狀態,后續更新。。。
驗證ingree+vip:
vim nginx.yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx-test
namespace: ingress-nginx
labels:
name: nginx-test
spec:
replicas: 1
template:
metadata:
labels:
name: nginx-test
spec:
containers:
- name: nginx-test
image: nginx:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-test
namespace: ingress-nginx
labels:
name: nginx-test
spec:
type: ClusterIP
ports:
- port: 80
protocol: TCP
targetPort: 80
name: http
selector:
name: nginx-test
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-test
namespace: ingress-nginx
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: test.nginx.com
http:
paths:
- path:
backend:
serviceName: nginx-test
servicePort: 80
啟動應用:kubectl apply -f nginx.yaml
查看pod狀態
更改客戶端的hosts文件(windows路徑:C:\Windows\System32\drivers\etc):
192.168.2.11 test.nginx.com
瀏覽器測試,訪問成功:
-----------日常記錄---------------
————————————————
版權聲明:本文為CSDN博主「叼不起的煙斗」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/w50feng/article/details/106539476
https://blog.51cto.com/u_12643266/2455788
Kubernetes Ingress-Nginx實現高可用
原創JasonMingHao2019-12-03 18:27:28©著作權
文章分類kubernetes閱讀數4823
假定我們在Kubernetes 指定兩個worker節點中部署了ingress nginx來為后端的pod做proxy,這時候我們就需要通過keepalived實現高可用,提供對外的VIP
首先我們要先確保有兩個worker節點部署了ingress nginx
在本實驗中,環境如下:
IP地址 | 主機名 | 描述 |
---|---|---|
10.0.0.31 | k8s-master01 | |
10.0.0.34 | k8s-node02 | ingress nginx、keepalived |
10.0.0.35 | k8s-node03 | ingress nginx、keepalived |
1、查看ingress nginx狀態
創建一個用於測試環境的namespace
2、部署一個Deployment(用於測試)
執行kubectl create 創建deployment
查看deployment是否部署成功
3、在兩個worker節點部署keepalived
VIP:10.0.0.130,接口:eth0
1.安裝keepalived
1.k8s-node03節點作為master配置keepalived
2.k8s-node03節點作為配置keepalived
3.k8s-node02節點配置keeplived
4.兩個節點啟動keepalived並加入開機啟動
啟動完成后檢查k8s-node03的IP地址是否已有VIP
5.在宿主機上配置hosts文件,實現IP和域名的解析
6.瀏覽器測試訪問
4.測試vip漂移
現在我將k8s-node03的keepalived進程關閉,那么vip就會漂移到k8s-node02
再次訪問
這篇文章相當的經典呀:https://segmentfault.com/a/1190000019908991/
k8s ingress原理及ingress-nginx部署測試
前篇文章說了service,這篇文章來折騰下ingress這個玩意。
ingress是啥東東
上篇文章介紹service時有說了暴露了service的三種方式ClusterIP、NodePort與LoadBalance,這幾種方式都是在service的維度提供的,service的作用體現在兩個方面,對集群內部,它不斷跟蹤pod的變化,更新endpoint中對應pod的對象,提供了ip不斷變化的pod的服務發現機制,對集群外部,他類似負載均衡器,可以在集群內外部對pod進行訪問。但是,單獨用service暴露服務的方式,在實際生產環境中不太合適:
ClusterIP的方式只能在集群內部訪問。
NodePort方式的話,測試環境使用還行,當有幾十上百的服務在集群中運行時,NodePort的端口管理是災難。
LoadBalance方式受限於雲平台,且通常在雲平台部署ELB還需要額外的費用。
所幸k8s還提供了一種集群維度暴露服務的方式,也就是ingress。ingress可以簡單理解為service的service,他通過獨立的ingress對象來制定請求轉發的規則,把請求路由到一個或多個service中。這樣就把服務與請求規則解耦了,可以從業務維度統一考慮業務的暴露,而不用為每個service單獨考慮。
舉個例子,現在集群有api、文件存儲、前端3個service,可以通過一個ingress對象來實現圖中的請求轉發:
ingress規則是很靈活的,可以根據不同域名、不同path轉發請求到不同的service,並且支持https/http。
ingress與ingress-controller
要理解ingress,需要區分兩個概念,ingress和ingress-controller:
- ingress對象:
指的是k8s中的一個api對象,一般用yaml配置。作用是定義請求如何轉發到service的規則,可以理解為配置模板。 - ingress-controller:
具體實現反向代理及負載均衡的程序,對ingress定義的規則進行解析,根據配置的規則來實現請求轉發。
簡單來說,ingress-controller才是負責具體轉發的組件,通過各種方式將它暴露在集群入口,外部對集群的請求流量會先到ingress-controller,而ingress對象是用來告訴ingress-controller該如何轉發請求,比如哪些域名哪些path要轉發到哪些服務等等。
ingress-controller
ingress-controller並不是k8s自帶的組件,實際上ingress-controller只是一個統稱,用戶可以選擇不同的ingress-controller實現,目前,由k8s維護的ingress-controller只有google雲的GCE與ingress-nginx兩個,其他還有很多第三方維護的ingress-controller,具體可以參考官方文檔。但是不管哪一種ingress-controller,實現的機制都大同小異,只是在具體配置上有差異。一般來說,ingress-controller的形式都是一個pod,里面跑着daemon程序和反向代理程序。daemon負責不斷監控集群的變化,根據ingress對象生成配置並應用新配置到反向代理,比如nginx-ingress就是動態生成nginx配置,動態更新upstream,並在需要的時候reload程序應用新配置。為了方便,后面的例子都以k8s官方維護的nginx-ingress為例。
ingress
ingress是一個API對象,和其他對象一樣,通過yaml文件來配置。ingress通過http或https暴露集群內部service,給service提供外部URL、負載均衡、SSL/TLS能力以及基於host的方向代理。ingress要依靠ingress-controller來具體實現以上功能。前一小節的圖如果用ingress來表示,大概就是如下配置:
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: abc-ingress annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/use-regex: "true" spec: tls: - hosts: - api.abc.com secretName: abc-tls rules: - host: api.abc.com http: paths: - backend: serviceName: apiserver servicePort: 80 - host: www.abc.com http: paths: - path: /image/* backend: serviceName: fileserver servicePort: 80 - host: www.abc.com http: paths: - backend: serviceName: feserver servicePort: 8080
與其他k8s對象一樣,ingress配置也包含了apiVersion、kind、metadata、spec等關鍵字段。有幾個關注的在spec字段中,tls用於定義https密鑰、證書。rule用於指定請求路由規則。這里值得關注的是metadata.annotations字段。在ingress配置中,annotations很重要。前面有說ingress-controller有很多不同的實現,而不同的ingress-controller就可以根據"kubernetes.io/ingress.class:"來判斷要使用哪些ingress配置,同時,不同的ingress-controller也有對應的annotations配置,用於自定義一些參數。列如上面配置的'nginx.ingress.kubernetes.io/use-regex: "true"',最終是在生成nginx配置中,會采用location ~來表示正則匹配。
ingress的部署
ingress的部署,需要考慮兩個方面:
- ingress-controller是作為pod來運行的,以什么方式部署比較好
- ingress解決了把如何請求路由到集群內部,那它自己怎么暴露給外部比較好
下面列舉一些目前常見的部署和暴露方式,具體使用哪種方式還是得根據實際需求來考慮決定。
Deployment+LoadBalancer模式的Service
如果要把ingress部署在公有雲,那用這種方式比較合適。用Deployment部署ingress-controller,創建一個type為LoadBalancer的service關聯這組pod。大部分公有雲,都會為LoadBalancer的service自動創建一個負載均衡器,通常還綁定了公網地址。只要把域名解析指向該地址,就實現了集群服務的對外暴露。
Deployment+NodePort模式的Service
同樣用deployment模式部署ingress-controller,並創建對應的服務,但是type為NodePort。這樣,ingress就會暴露在集群節點ip的特定端口上。由於nodeport暴露的端口是隨機端口,一般會在前面再搭建一套負載均衡器來轉發請求。該方式一般用於宿主機是相對固定的環境ip地址不變的場景。
NodePort方式暴露ingress雖然簡單方便,但是NodePort多了一層NAT,在請求量級很大時可能對性能會有一定影響。
DaemonSet+HostNetwork+nodeSelector
用DaemonSet結合nodeselector來部署ingress-controller到特定的node上,然后使用HostNetwork直接把該pod與宿主機node的網絡打通,直接使用宿主機的80/433端口就能訪問服務。這時,ingress-controller所在的node機器就很類似傳統架構的邊緣節點,比如機房入口的nginx服務器。該方式整個請求鏈路最簡單,性能相對NodePort模式更好。缺點是由於直接利用宿主機節點的網絡和端口,一個node只能部署一個ingress-controller pod。比較適合大並發的生產環境使用。
ingress測試
我們來實際部署和簡單測試一下ingress。測試集群中已經部署有2個服務gowebhost與gowebip,每次請求能返回容器hostname與ip。測試搭建一個ingress來實現通過域名的不同path來訪問這兩個服務:
測試ingress使用k8s社區的ingress-nginx,部署方式用DaemonSet+HostNetwork。
部署ingress-controller
部署ingress-controller pod及相關資源
官方文檔中,部署只要簡單的執行一個yaml
https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
mandatory.yaml這一個yaml中包含了很多資源的創建,包括namespace、ConfigMap、role,ServiceAccount等等所有部署ingress-controller需要的資源,配置太多就不粘出來了,我們重點看下deployment部分:
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-ingress-controller namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx template: metadata: labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx annotations: prometheus.io/port: "10254" prometheus.io/scrape: "true" spec: serviceAccountName: nginx-ingress-serviceaccount containers: - name: nginx-ingress-controller image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.25.0 args: - /nginx-ingress-controller - --configmap=$(POD_NAMESPACE)/nginx-configuration - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services - --udp-services-configmap=$(POD_NAMESPACE)/udp-services - --publish-service=$(POD_NAMESPACE)/ingress-nginx - --annotations-prefix=nginx.ingress.kubernetes.io securityContext: allowPrivilegeEscalation: true capabilities: drop: - ALL add: - NET_BIND_SERVICE # www-data -> 33 runAsUser: 33 env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace ports: - name: http containerPort: 80 - name: https containerPort: 443 livenessProbe: failureThreshold: 3 httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 10 readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 10254 scheme: HTTP periodSeconds: 10 successThreshold: 1 timeoutSeconds: 10
可以看到主要使用了“quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.25.0”這個鏡像,指定了一些啟動參數。同時開放了80與443兩個端口,並在10254端口做了健康檢查。
我們需要使用daemonset部署到特定node,需要修改部分配置:先給要部署nginx-ingress的node打上特定標簽,這里測試部署在"node-1"這個節點。
$ kubectl label node node-1 isIngress="true"
然后修改上面mandatory.yaml的deployment部分配置為:
# 修改api版本及kind
# apiVersion: apps/v1 # kind: Deployment apiVersion: extensions/v1beta1 kind: DaemonSet metadata: name: nginx-ingress-controller namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx spec: # 刪除Replicas # replicas: 1 selector: matchLabels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx template: metadata: labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx annotations: prometheus.io/port: "10254" prometheus.io/scrape: "true" spec: serviceAccountName: nginx-ingress-serviceaccount # 選擇對應標簽的node nodeSelector: isIngress: "true" # 使用hostNetwork暴露服務 hostNetwork: true containers: - name: nginx-ingress-controller image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.25.0 args: - /nginx-ingress-controller - --configmap=$(POD_NAMESPACE)/nginx-configuration - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services - --udp-services-configmap=$(POD_NAMESPACE)/udp-services - --publish-service=$(POD_NAMESPACE)/ingress-nginx - --annotations-prefix=nginx.ingress.kubernetes.io securityContext: allowPrivilegeEscalation: true capabilities: drop: - ALL add: - NET_BIND_SERVICE # www-data -> 33 runAsUser: 33 env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace ports: - name: http containerPort: 80 - name: https containerPort: 443 livenessProbe: failureThreshold: 3 httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 10 readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 10254 scheme: HTTP periodSeconds: 10 successThreshold: 1 timeoutSeconds: 10
修改完后執行apply,並檢查服務
$ kubectl apply -f mandatory.yaml
namespace/ingress-nginx created
configmap/nginx-configuration created
configmap/tcp-services created
configmap/udp-services created
serviceaccount/nginx-ingress-serviceaccount created
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created
role.rbac.authorization.k8s.io/nginx-ingress-role created rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created daemonset.extensions/nginx-ingress-controller created # 檢查部署情況 $ kubectl get daemonset -n ingress-nginx NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE nginx-ingress-controller 1 1 1 1 1 isIngress=true 101s $ kubectl get po -n ingress-nginx -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-ingress-controller-fxx68 1/1 Running 0 117s 172.16.201.108 node-1 <none> <none>
可以看到,nginx-controller的pod已經部署在在node-1上了。
暴露nginx-controller
到node-1上看下本地端口:
[root@node-1 ~]# netstat -lntup | grep nginx tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 2654/nginx: master tcp 0 0 0.0.0.0:8181 0.0.0.0:* LISTEN 2654/nginx: master tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 2654/nginx: master tcp6 0 0 :::10254 :::* LISTEN 2632/nginx-ingress- tcp6 0 0 :::80 :::* LISTEN 2654/nginx: master tcp6 0 0 :::8181 :::* LISTEN 2654/nginx: master tcp6 0 0 :::443 :::* LISTEN 2654/nginx: master
由於配置了hostnetwork,nginx已經在node主機本地監聽80/443/8181端口。其中8181是nginx-controller默認配置的一個default backend。這樣,只要訪問node主機有公網IP,就可以直接映射域名來對外網暴露服務了。如果要nginx高可用的話,可以在多個node
上部署,並在前面再搭建一套LVS+keepalive做負載均衡。用hostnetwork的另一個好處是,如果lvs用DR模式的話,是不支持端口映射的,這時候如果用nodeport,暴露非標准的端口,管理起來會很麻煩。
配置ingress資源
部署完ingress-controller,接下來就按照測試的需求來創建ingress資源。
# ingresstest.yaml
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress-test annotations: kubernetes.io/ingress.class: "nginx" # 開啟use-regex,啟用path的正則匹配 nginx.ingress.kubernetes.io/use-regex: "true" spec: rules: # 定義域名 - host: test.ingress.com http: paths: # 不同path轉發到不同端口 - path: /ip backend: serviceName: gowebip-svc servicePort: 80 - path: /host backend: serviceName: gowebhost-svc servicePort: 80
部署資源
$ kubectl apply -f ingresstest.yaml
測試訪問
部署好以后,做一條本地host來模擬解析test.ingress.com到node的ip地址。測試訪問
可以看到,請求不同的path已經按照需求請求到不同服務了。
由於沒有配置默認后端,所以訪問其他path會提示404:
關於ingress-nginx
關於ingress-nginx多說幾句,上面測試的例子是非常簡單的,實際ingress-nginx的有非常多的配置,都可以單獨開幾篇文章來討論了。但本文主要想說明ingress,所以不過多涉及。具體可以參考ingress-nginx的官方文檔。同時,在生產環境使用ingress-nginx還有很多要考慮的地方,這篇文章寫得很好,總結了不少最佳實踐,值得參考。
最后
- ingress是k8s集群的請求入口,可以理解為對多個service的再次抽象
- 通常說的ingress一般包括ingress資源對象及ingress-controller兩部分組成
- ingress-controller有多種實現,社區原生的是ingress-nginx,根據具體需求選擇
- ingress自身的暴露有多種方式,需要根據基礎環境及業務類型選擇合適的方式
參考
Kubernetes Document
NGINX Ingress Controller Document
Kubernetes Ingress Controller的使用介紹及高可用落地
通俗理解Kubernetes中Service、Ingress與Ingress Controller的作用與關系