![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5yMwYjM4YTZzczN4QWN2ImZyYzX2MTOzcTM2EzLchDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
什麼是 Headless Service?
部署 Service時,可以設定三種不同的
ServiceTypes
以指定所需的 Service 類型:
- ClusterIP:僅在叢集内部 ip 位址上公開 Service,這也是預設的
。ServiceType
- NodePort:允許通過節點上的靜态端口公開 Service。
- LoadBalancer:允許使用雲提供商的外部負載均衡器公開 Service 。
為避免請求在單個 IP 位址後面進行負載均衡,當不需要單個 IP 位址時,我們可以通過指定 Cluster IP(
spec.clusterIP
)的值為
"None"
來建立 Headless Service。Kubernetes 不會為該 Service 配置設定任何 IP 位址。這種 Service 就稱為 Headless Services。
DNS 解析和 Headless Service
部署 Service 時,Kubernetes 會為其配置設定一個 DNS 名稱。叢集中的其他元件可以使用此名稱與 DNS 和上遊 Pod 通信。DNS 名稱遵循以下命名約定:
在 IP 位址上使用可讀名稱後,其他元件就不需要配置設定給 Service 實際 IP 位址。
使用正确的 Pod 選擇(selector)配置 Headless Service 時,Kubernetes 将為上遊標明的 Pod 建立正确端點記錄和 DNS 配置。
對于将連接配接到 Headless Service 的每個已連接配接 Pod,也會配置 A 或 AAAA 記錄。這樣就可以對 Headless Service 執行 DNS 查詢,以解析所連接配接 Pod 的所有 IP 位址。
如何實踐?
假設存在以下問題:Kubernetes 叢集中運作着一組有狀态的三個 MongoDB Pod。這三個 Pod 共同構成一個 MongoDB 副本集,這是一個高度可用的資料集。
為了能夠将控制台應用程式連接配接到 MongoDB 副本集,我們使用 MongoDB C# 驅動程式,同時需要顯式定義三個 Pod 的位址。
我們用 Headless Service 解決這個問題。假定 MongoDb Pod 都帶有
app=mongodb
标簽,該标簽可以在 Headless Service 中用于選擇 Pod。
我們定義的 Headless Service 資源如下所示:
通過将
clusterIp
設定為
"none"
,我們告訴 Kubernetes 将此 Service 視為 Headless Service。由于我們定義了名稱和命名空間,是以可以推斷出 DNS 名稱。我們在叢集内部使用
mongodb-headless-service.infrastructure.svc.cluster.local
或
mongodb-headless-service.infrastructure
作為位址與 Service 進行通信。
接下來讓我們來執行 DNS 查詢,以檢索連接配接 Pod 的 IP 位址。
Dns.GetHostAddresses
方法位于
System.Net
命名空間中,可幫助我們執行該 DNS 查詢并傳回 IP 位址數組。它需要一個主機名或 IP 位址。最後,我們可以使用 MongoDB 建立連接配接字元串(connection string)。
代碼如下:
通過該解決方案,我們可以動态建立連接配接字元串,其主要優點是,在必須擴充資料庫叢集時,我們不必手動更改連接配接字元串。
注意:MongoDB 确實通過 DNS 實作了類似的服務發現過程,隻需定義 Headless Service 的 DNS 名稱即可,這樣我們就不必自己生成連接配接字元串。