「Kubernetes」- 部署 NGINX Ingress Controller 組件 @20210427


問題描述

僅當在 Kubernetes Cluster 中部署 Ingress Controller 之后,我們定義的 Ingress 資源才能生效。當然 Ingress Controller 有很多實現,比如 NGINX Ingress Controller、Traefik Ingress Controller、HAProxy Ingress 等等(參考 Ingress Controllers | Kubernetes 頁面)。

針對我們的場景,我們使用 NGINX Ingress Controller 實現,這完全是基於我們具有很多 Nginx 使用經驗,此外 Nginx 完全能滿足我們的需要。即使日后 NGINX Ingress Controller 無法滿足需求,我們亦可安裝其他 Ingress Controller 實現,它們之間能夠並存。

該筆記將記錄:在 Kubernetes Cluster 中,如何部署 NGINX Ingress Controller 組件,以及相關問題處理。

解決方案

我們參照官方 Installation Guide 文檔,並結合我們自身需求,我們整理出此文,所以該筆記是環境相關的,並不一定適合每種環境。我們強烈建議參照官方文檔,並結合自己的環境進行部署。

部署環境

我們為 Kubernetes v1.18.9 on Bare-metal 環境,即自建 Kubernetes 集群,如果是在 minikube、AWS、Azure 中部署,需要執行不同的命令,參考 Installation Guide 文檔。

第一步、下載並且部署

官方提供 deploy.yaml 部署文件(如果無法下載,使用 ./deploy.yaml 文件):

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.45.0/deploy/static/provider/baremetal/deploy.yaml

# 注意事項,因為 Deploymnet 的 nodeSelector: kubernetes.io/os: linux 設置,
# 因此保證 lable 包含 kubernetes.io/os: linux 的節點存在於集群中,額外留意就好,一般無需設置。

kubectl apply -f deploy.yaml

第二步、查看容器狀態

查看 NGINX Ingress Controller 組件的狀態:

# kubectl get pods --all-namespaces -l app.kubernetes.io/name=ingress-nginx --watch
NAMESPACE       NAME                                       READY   STATUS      RESTARTS   AGE
ingress-nginx   ingress-nginx-admission-create-hq52n       0/1     Completed   0          6m52s
ingress-nginx   ingress-nginx-admission-patch-9xqhj        0/1     Completed   0          6m52s
ingress-nginx   ingress-nginx-controller-cdfb85746-5qqlp   1/1     Running     0          6m52s

第三步、關於 Ingress 訪問

在這之前,我們已經完成 Ingress 部署,但是還有個非常重要的問題:Ingress Controller 的本質作用是作為 WebServer 存在,接收 HTTP 與 HTTPS 請求,然后它根據 Ingress 資源的定義來完成請求的傳發。但是 Ingress Controller 是以 Pod 運行的,它所監聽的端口是內部網絡可見,外部是無法直接訪問的。即使通過 Service NodePort 暴露出來,也並非 80 443 端口,因此用戶訪問的時候,需要使用 http://hostname:nodePort/ 的形式來訪問站點。很顯然,這是不能接受的。

注意事項:我們這些的討論都是基於 Bare-metal 部署的(即自建 Kubernetes 集群),其他部署環境也許會有類似問題。

針對該問題,官方文檔(Bare-metal considerations)提出以下解決方案:
1)MetalLB(純軟件解決方案)
2)NodePort
3)Host network
4)Using a self-provisioned edge(NodePort + LoadBalancer)
5)External IPs

篇幅原因,我們這里不再贅述,建議詳細閱讀官方文檔。針對我們的場景,方案 1 3 4 皆可,我們最終選擇 4 方案(這里面有些不可抗力的存在)。而我們在測試環境中采用 3 方案,因為測試在內網,沒有不是 LoadBalancer 服務。方案 1 其實是最好的,但是我們不想折騰了:-)

針對 4 方案,我們還有個需要考慮的問題:使用三層(TCP),還是七層(HTTP(s)):

 

1)如果采用三層(TCP):我們需要將 Nginx Ingress 的 NodePort 固定為 30080 30443 端口,然后外部的 LoadBalancer 將 80 請求轉發到 30080 端口,將 443 請求轉發到 30443 端口。但是,這會損失客戶端的原始請求地址,需要使用 PROXY 協議又會增加復雜度。

 

 

2)如果采用七層(HTTP(s)):后端 Nginx Ingress 收到的將完全是 HTTP 請求,僅需監聽 30080 端口,然后 LoadBalancer 將請求轉發到 30080 端口。這樣能夠保留客戶端的網絡地址。但是,我們無法使用 Cert Manager 來使用 Let's Encrypt 的免費 SSL 證書。

 

 

3)如果采用二層:實際上就是 1 方案,MetalLB 能運行在二層模式下,這里就不再討論,當我們遇到問題再說吧。

 

最后,我們選擇方案 4 的三層(TCP)做法。這么完全就是為了使用 Let's Encrypt 免費證書。如果我們出現需要客戶端正式地址的方案,我們將在部署七層(HTTP(s))。最后會形成“三層與七層並存,針對不用業務采用不同 LoadBalancer 線路”的做法。

這里沒有很多需要配置的東西,更多的是各種技術方案的取舍。唯一需要我們配置的就是:修改 Service 的 NodePort 為 固定為 30080 30443 端口,然后配置 LoadBalancer 進行 80 443 的轉發,這里不再展開。

第四步、部署測試資源

當部署 NGINX Ingress Controller 組件部署完成時,便能夠定義 Ingress、Server、Deployment 資源進行驗證。

定義資源文件並應用(./ingress-example.yaml):

kubectl apply -f ingress-example.yaml

然后,在瀏覽器中訪問,以驗證 Ingress 能夠正常工作。

簡單 Ingress 管理

# 查看生成的配置文件
kubectl exec -it -n "ingress-nginx" nginx-ingress-controller-67956bf89d-fv58j cat /etc/nginx/nginx.conf

# 查看當前 Nginx 版本
kubectl exec -it $POD_NAME -n $POD_NAMESPACE -- /nginx-ingress-controller --version

補充說明

部署 Ingress Controller 時,不建議使用 DaemonSet 類型,而應該使用 Deployment 類型,然后將 POD 示例固定在某個節點上,或者使用 NodePort 方式。為什么這樣做?假如我們的集群有 1000 個節點時,在每個節點都運行 Ingress Controller 並不是最優的。如此大規模的集群,一般僅會有少數節點接受外部請求。

常見問題匯總

nginx-ingress-controller in pending state

當我們部署 deploy.yaml 后,ingress-nginx Pod 一直處於 Pending 狀態。當我們部署自定義的 Deployment 進行測試時,該普通的 Deployment 也處於 Pending 狀態。

當我們向集群添加新節點后,調度到新節點的 Pod 能夠正常運行,而不是 Pending 狀態。因此我們懷疑是節點存在問題,而且其他節點的 Docker 版本是 19.3 版本,而這個節點是 20.10 版本(都是自己埋的坑)。

# 04/22/2021 因此我們嘗試重啟節點……然后問題得到解決(這並不算解決問題。也許是以為某些熱修改的配置沒有正確加載)。

# 04/23/2021 今天這個問題又出現了,我們查看節點的 kubelet 日志,發現 CNI 插件相關的錯誤。不管怎樣,這個問題與 NGINX Ingress Controller 無關,因此這里不再討論。

相關文章

「NGINX Ingress Controller」- 修改默認重定向狀態碼(IE8 無法跳轉)
「K8s」- Traefik Installation
「Kubernetes」- Traefik Kubernetes Ingress

參考文獻

Accessing Kubernetes Pods from Outside of the Cluster
Deployments | Kubernetes
How to sign in kubernetes dashboard? - Stack Overflow
ingress is not listening on port 80 #4799
Installing the Ingress Controller
k8s之nginx-ingress、 Daemonset實現生產案例
NGINX Ingress Controller for Kubernetes
NGINX Ingress Controller/Installation Guide
NGINX Ingress Controller/Troubleshooting
Bare-metal considerations - NGINX Ingress Controller



免責聲明!

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



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