理解Kubernetes的NodePort、LoadBalancer和Ingress
這三個東西都可以實現將集群內的服務暴露到集群外,那么它們到底有什么不同,要如何正確地使用這些組件,希望通過這篇文章,可以給大家一些啟示。首先明確一點,NodePort和LoadBalancer指Kubernetes Service組件的兩種類型。
在正式開始之前,有必要對Service做簡單介紹。Service是一組Pod的抽象,雖然在集群中Pod可以通過IP直達,但是Pod不穩定,它可能會經常死掉,這時集群會重新啟動一個Pod,這是一個全新的Pod,它的IP地址會發生變化,這樣不利于客戶端訪問。為了解決這個問題,Kubernetes引入了Service組件,從Pod創建之初到人為刪除這段時間,為其創建的Service訪問方式都是穩定的,即它的訪問IP不變,再配合集群內置的DNS服務,客戶端可以利用不變的Service名稱或Service IP訪問到目標Pods,而且Service還實現了簡單的負載均衡功能。
到這里,還有一個很重要的問題沒有解決,在Kubernetes集群外如何訪問集群內的服務,這就引出了標題中列舉的三個對象,下面逐一介紹。
NodePort
Nodeport是Service的三種類型之一(ExternalName不常用故除外),其他兩種是ClusterIP和LoadBalancer。當Service工作在NodePort類型時,默認每個Node會在全部網絡接口開啟一個端口來轉發對集群內服務的請求。當請求到來時,Node會轉發請求到集群中的服務。這樣就帶來一個問題,請求的目標Node可能會Down掉或其他別的原因導致網絡不能訪問,NodePort還有一個問題就是對外暴露的端口有限制,默認端口范圍是30,000-32,767。這就限制了可以對外暴露服務的個數,使用這些不易記錄的端口訪問服務也是讓人頭疼的問題,這就引入了下一個Service類型:LoadBalancer。
LoadBalancer
大多數公有云平臺都支持創建這種類型的服務,每個服務可以支持多種協議和多個端口,使用單個IP來訪問。因為需要在集群外訪問內部服務,所以這個IP地址是公有的,這會產生額外的費用。如果暴露的服務很多,使用時需要慎重。在私有云環境中,不能創建此類的服務,可以創建NodePort類型的服務然后使用HAproxy來充當Load Balancer,這樣和公有云平臺的LoadBalancer差別不大。Service的三種類型:ClusterIP、NodePort、LoadBalancer,后一種是前一種的增強,NodePort類型Service會創建ClusterIP類型Service,LoadBalancer類型Service會創建NodePort和ClusterIP類型Service。Service組件依賴操作系統中的iptables或ipvs,這是Service的靈魂。有一點需要注意,當使用NodePort類型的服務時,請求會直接轉發給實際的Pod而不用轉發給Service的Cluster IP(kube-proxy工作在iptables模式),具體實現方法可以在搜索引擎上搜“NodePort類型Service的工作原理”。
Ingress
前面介紹的內容都圍繞Service,主要解決網絡層的問題,Ingress的出現主要是解決應用層的問題。Ingress實際上充當一個反向代理的角色,和Nginx的功能很類似。Kubernetes中廣泛使用的Nginx Ingress其本質就是一個Nginx服務。Ingress依賴LoadBalancer類型的Service,因為它自己沒有暴露集群內服務到外部的能力。這里以Nginx Ingress為例,介紹它的工作原理,其他類型的Ingress可以參考其官方文檔介紹。
Nginx Ingress主要包含兩個部分:Ingress Controller和Nginx,Controller通過Watch的方式訪問API服務,從中采集它感興趣的資源更新,例如Ingress資源,然后操作Nginx,修改配置文件nginx.conf,更新證書、重啟Nginx等。它就像是一個Nginx的管理者,工程師發送指令到集群,Controller從API服務器接收到工程師發送的指令,然后操作Nginx。大體工作流程就是這樣。
上圖中有一個“Public Endpoint”組件,它可以通過LoadBalancer類型的Service來實現,下面yaml片段來自阿里云上真實的nginx-ingress服務(IP地址和端口做了脫敏操作):
......
spec:
clusterIP: 172.14.13.67
externalTrafficPolicy: Cluster
ports:
- name: http
nodePort: 31800
port: 80
protocol: TCP
targetPort: 80
- name: https
nodePort: 31700
port: 443
protocol: TCP
targetPort: 443
selector:
app: ingress-nginx
sessionAffinity: None
type: LoadBalancer
status:
loadBalancer:
ingress:
- ip: 47.215.177.38
集群部署Ingress資源后,進入集群流量的第一站就是Nginx Ingress中的Nginx服務,由它做HTTP層的負載均衡,還有TLS終結等工作。
總結
文章對NodePort和LoadBalancer類型的Service做了簡單介紹,在測試環境中如果需要快速將服務從集群內暴露出來,可以使用NodePort類型的Service,生產環境,如果使用了阿里云或騰訊云可以使用LoadBalancer類型的Service并配合Ingress,如果沒有也可以使用NodePort類型的Service并配置Haproxy等來實現負載均衡。