在Kubernetes中,Service是用於將運行在一組Pod上的應用程式公開為網路服務的抽象概念。Service不但為這組Pod提供統一的DNS名稱,還讓Pod之間實現了負載平衡。本文介紹Kubernetes Service的原理、注意事項,以及Service類型選型建議。
基本概念
Service類型
名稱 | 描述 | 適用情境 | 計費說明 |
預設的服務類型。ClusterIP分配給服務的是一個只能在叢集內部訪問的虛擬IP。 | 只需要在叢集內部進行服務間的通訊,不需要將服務暴露給叢集外部。 例如,叢集中部署的前端應用Pod需要訪問同一叢集中部署的後端資料庫,後端資料庫可以作為ClusterIP運行。 | 不計費。 | |
NodePort會在叢集中的節點上開放連接埠,從而允許從叢集外部通過 | 需要臨時或低流量的應用時,需要從外網暴露一個連接埠。 例如,在測試環境中,當您部署調試一個Web應用服務時,可以使用NodePort運行。相較於LoadBalancer模式,不提供跨節點負載平衡能力,流量只會發送到一個節點並很容易達到資源瓶頸。 | 不計費。若需要實現公網訪問,需要為節點綁定EIP。關於EIP的計費說明,請參見計費概述。 | |
LoadBalancer類型基於NodePort增加了一個外部負載平衡器,使外部流量能夠平滑地分發到叢集中的多個Pod上。Service會自動提供一個外部IP,用戶端可通過此IP訪問服務。該服務既支援在OSI模型的第四層(傳輸層)處理TCP/UDP類型的流量,也可以擴充至第七層(應用程式層),進行HTTP/HTTPS流量管理。 | 在公用雲上運行應用且需要提供一個穩定的、易於管理的對外入口。 例如,生產環境中需要從互連網訪問的公用服務,需要承受大量的外部流量並保證高可用性,例如Web應用、API服務等。 | Server Load Balancer執行個體將產生費用請參見 | |
ExternalName | ExternalName類型的Service會在叢集中將一個內部服務名稱映射到一個外部網域名稱。這種映射使得叢集內的Pod可以通過Service Name來訪問外部網域名稱。 | 叢集需要訪問暴露在公用網域名稱下的服務。 例如,當您的應用Pod需要訪問外部的資料庫網域名稱時,可以使用ExternalName將網域名稱映射到叢集內部的Service Name上,使得叢集內部可以直接通過Service Name進行訪問。 | 不計費。 |
Headless Service | Headless Service指沒有虛擬IP的服務。訪問後端Pod時,服務的DNS查詢會直接返回Pod的IP地址清單,而不是單一的服務IP。Headless Service可以直接發現並串連到特定的Pod。 | 應用需要直接與後端的具體Pod進行通訊(而不是通過一個代理或負載平衡器)。 例如,當您部署了有狀態應用ClickHouse資料庫服務,可以使用Headless Service,使得應用Pod可以直接存取每個ClickHouse Pod,並且均衡地讀取資料或針對性地寫入資料,提升資料處理的效率。 | 不計費。 |
Service原理
ClusterIP
建立與分配
當您在ACK叢集中建立一個ClusterIP類型的Service時,叢集控制面會從預定義的Service網段為該Service分配一個虛擬IP地址,這個地址被稱為ClusterIP。ClusterIP只能在叢集內訪問,與後端Pod的IP地址網段是隔離的。
流量轉寄
在叢集內訪問ClusterIP時,該流量會被kube-proxy捕獲。kube-proxy使用iptables(或者使用IPVS)規則,使用輪詢調度的方式將流量轉寄到Service後端的一個Pod中。
服務發現
建立ClusterIP時,CoreDNS服務中會註冊一個對應的DNS記錄。該DNS記錄允許在叢集內部通過服務的名字來解析和訪問服務,格式為
服務名.命名空間.svc.cluster.local:連接埠
,例如nginx.default.svc.cluster.local:80
Pod標籤和端點跟蹤
每個Service都由一組標籤選取器(Label Selector)定義,決定哪些Pod屬於該Service的後端。
叢集控制面會即時監控Pod的變動。當匹配Service標籤選取器的Pod發生添加、更新或刪除等操作時,控制面將更新Endpoint。
NodePort
建立與分配
當建立NodePort類型的Service時,除了產生一個ClusterIP來允許內部通訊之外,叢集還會為此Service在節點上開放一個連接埠,稱為NodePort。此連接埠是在指定的連接埠範圍(預設是30000-32767)中自動選擇的。您也可以手動指定特定的連接埠。
流量轉寄
kube-proxy組件負責在每個節點上監聽NodePort連接埠。當一個外部請求到達任意節點的NodePort時,kube-proxy負責將這個流量路由到對應的ClusterIP上,然後通過ClusterIP進一步路由到後端Pod中。
外部存取
通過節點的IP地址加上靜態連接埠(NodePort)來訪問,格式為
<NodeIP>:<NodePort>
,作為外部的訪問地址。
LoadBalancer
建立與分配
當建立一個
LoadBalancer
類型的Service且未指定具體的負載平衡器時,叢集控制面會自動與負載平衡服務進行互動,建立負載平衡器執行個體用於處理該Service的流量。更多資訊,請參見通過使用已有負載平衡的服務暴露應用和通過使用自動建立負載平衡的服務公開應用。流量轉寄
當外部流量到達Server Load Balancer執行個體的外部IP時,Server Load Balancer執行個體會根據負載平衡策略將流量路由到節點上的連接埠,每個節點上的kube-proxy組件接收到流量後,基於iptables或IPVS規則將流量重新導向到後端Pod。
配置路由和健全狀態檢查
負載平衡器自動設定監聽Service YAML聲明的連接埠,並將流量轉寄到叢集中符合選取器條件的Pod上。同時,負載平衡器會配置健全狀態檢查機制,以確保流量只路由到健康的Pod。
外部流量策略Local和Cluster介紹
在叢集中,當服務類型為LoadBalancer或NodePort時,您才可以設定外部流量策略externalTrafficPolicy
,來控制從外部網路到服務的流量路由。此策略有兩種模式:Local和Cluster。不同網路外掛程式的外部流量策略功能不同。以下介紹Terway-Eniip和Flannel網路外掛程式的外部流量策略功能對比。
登入Container Service管理主控台,在叢集列表頁面單擊目的地組群的名稱,在基本資料頁簽下叢集資訊地區可以查看叢集的網路模式。
Flannel網路外掛程式
Flannel網路外掛程式下,流量經由節點的NodePort轉寄到Pod中。
Local:流量只轉寄給原生Pod,即流量僅在同一個節點的Pod中進行轉寄。
Cluster: 流量可以轉寄到叢集中其他節點上的Pod。
Local和Cluster兩種外部流量策略詳細的區別如下所示。
類別 | Local | Cluster |
負載平衡後端掛載行為 | 僅Pod所在的節點會掛載到負載平衡後端。 | 所有叢集內的節點都將掛載到負載平衡的後端。 |
負載平衡配額 | 負載平衡配額消耗較少。關於負載平衡配額的詳細介紹,請參見配額限制。 | 叢集內所有節點都掛載到負載平衡後端,會大量消耗負載平衡配額。關於負載平衡配額的詳細介紹,請參見配額限制。 |
訪問負載平衡地址 | 僅Pod所在節點可以訪問負載平衡地址。 | 叢集內任意節點均可訪問負載平衡地址。 |
Pod負載平衡 | 預設Pod之間負載不均衡。 如果您想要實現Pod之間負載平衡,需要指定策略為wrr,即為Service添加Annotation | 預設Pod之間負載平衡。 |
保留來源IP | 支援。 | 不支援。 |
會話保持 | 支援。 | 不支援。 |
適用情境 | 對需要保留用戶端原始IP地址的應用程式,例如基於原始IP地址的日誌記錄。 | 當需要保證服務的高可用性,並且對源IP儲存不敏感時,例如大型Web應用叢集。 |
Terway-Eniip網路外掛程式
Terway-Eniip網路外掛程式下,無論是Local還是Cluster,流量直接轉寄到Pod中。
Local和Cluster兩種外部流量策略詳細的區別如下表所示。
比較項 | Local | Cluster |
負載平衡後端掛載行為 | Pod直接掛載到負載平衡後端。 | |
負載平衡配額 | 僅掛載業務Pod,負載平衡配額消耗較少。關於負載平衡配額的詳細介紹,請參見配額限制。 | |
訪問負載平衡地址 | 僅Pod所在節點可以訪問負載平衡地址。 | 叢集內任意節點均可訪問負載平衡地址。 |
Pod負載平衡 | 預設Pod之間負載平衡。 | |
保留來源IP | 支援。 | |
會話保持 | 支援。 |
注意事項
在使用Service的負載平衡功能之前,建議您瞭解相關注意事項。詳細資料,請參見Service的負載平衡配置注意事項。