1. 程式人生 > >對映外部服務_Kubernetes中文社群

對映外部服務_Kubernetes中文社群

大多數 Kubernetes 使用者都有可能用到叢集外部的服務。例如,您可能使用 Twillio API 傳送簡訊,或使用 Google Cloud Vision API 進行影象分析。

如果位於不同環境中的應用連線相同的外部端點,並且您不打算將外部服務引入 Kubernetes 叢集,那麼在程式碼中直接使用外部服務端點是完全可以的。然而,很多時候情況並非如此。

資料庫就是一個很好的例子。雖然一些雲原生資料庫(如 Cloud Firestore 或 Cloud Spanner)對所有訪問均使用一個端點,但大多數資料庫對不同例項都有單獨的端點。

說到這裡,您可能會認為,就查詢端點而言,ConfigMap 是個不錯的解決方案。只需將端點地址儲存在 ConfigMap 中,並將其作為環境變數用於程式碼中。此解決方案的確有效,但也存在一些缺點。您需要修改部署以包含 ConfigMap 並編寫額外的程式碼以從環境變數中讀取。但最重要的是,如果端點地址發生變化,您可能需要重啟所有正在執行的容器以獲取更新後的端點地址。

在本集的 “Kubernetes 最佳實踐” 中,我們會學習如何將 Kubernetes 內建服務發現機制運用於叢集外部執行的服務,像使用叢集內的服務一樣使用外部服務!通過這種方式,您可以在開發環境和生產環境中實現相同的功能,如果您最終將服務移入叢集內,則不需要更改任何程式碼。

場景 1:具有 IP 地址的叢集外資料庫

其中一個常見場景是在叢集外部託管自己的資料庫,例如在 Google 計算引擎例項中。如果您在 Kubernetes 內部和外部分別執行一些服務,或者需要在 Kubernetes 允許的基礎上獲得更多定製或控制,通常可採用上述這種方式。

希望未來某個時候您可以將所有服務都移入叢集內,但在此之前將是“內外混用”的狀態。幸運的是,您可以使用靜態 Kubernetes 服務來緩解上述痛點。

在本例中,我使用 Cloud Launcher 建立了一個 MongoDB 伺服器。由於此伺服器在與 Kubernetes 叢集相同的網路(或 VPC)中建立,因此可以使用高效能的內部 IP 地址訪問。在 Google Cloud 中,這是預設設定,因此無需進行任何特殊配置。

現在我們有了 IP 地址,那麼第一步就是建立服務:

kind: Service

apiVersion: v1

metadata:

name: mongo

Spec:

type: ClusterIP

ports:

– port: 27017

targetPort: 27017

您可能會注意到此服務沒有 Pod 選擇器。此操作將建立一個服務,但它不知道往哪裡傳送流量。這樣一來,您可以手動建立一個將從此服務接收流量的 Endpoints 物件。

kind: Endpoints

apiVersion: v1

metadata:

name: mongo

subsets:

– addresses:

– ip: 10.240.0.4

ports:

– port: 27017

您可以看到 Endpoints 手動定義了資料庫的 IP 地址,並且使用的名稱與服務名稱相同。Kubernetes 將 Endpoints 中定義的所有 IP 地址視為與常規 Kubernetes Pod 一樣。現在您可以用一個簡單的連線字串訪問資料庫:

mongodb://mongo

> 根本不需要在程式碼中使用 IP 地址!如果以後 IP 地址發生變化,您可以為端點更新 IP 地址,而應用無需進行任何更改。

場景 2:具有 URI 的遠端託管資料庫

如果您使用的是來自第三方的託管資料庫服務,它們可能會為您提供可用於連線的統一資源識別符號 (URI)。如果它們為您提供 IP 地址,則可以使用場景 1 中的方法。

在本例中,我在 mLab 上託管了兩個 MongoDB 資料庫。一個是我的開發資料庫,另一個是生產資料庫。

這些資料庫的連線字串如下所示:

mongodb://<dbuser>:<dbpassword>@ds149763.mlab.com:49763/devmongodb://<dbuser>:<dbpassword>@ds145868.mlab.com:45868/prodmLab

為您提供了動態 URI 和動態埠,您可以看到兩者都不同。我們來使用 Kubernetes 基於這些差異建立一個抽象層。在本例中,我們將連線開發資料庫。

您可以建立一個 “ExternalName” Kubernetes 服務,此服務為您提供將流量重定向到外部服務的靜態 Kubernetes 服務。此服務在核心級別執行簡單的 CNAME 重定向,因此對效能的影響非常小。

服務的 YAML 如下所示:

kind: Service

apiVersion: v1

metadata:

name: mongo

spec:

type: ExternalName

externalName: ds149763.mlab.com

現在,您可以使用更簡化的連線字串:

mongodb://<dbuser>:<dbpassword>@mongo:<port>/dev

由於 “ExternalName” 使用 CNAME 重定向,因此無法執行埠重對映。對於使用靜態埠的服務來說,這可能不成問題,然而本例中使用的是動態埠。mLab 免費版為您提供了動態埠號,並且不允許更改。這意味著您需要對開發和生產資料庫使用其他連線字串。

但如果您可以獲取 IP 地址,就可以執行埠重對映,關於此內容,我將在下一部分進行介紹。

場景 3:具有 URI 和埠重對映功能的遠端託管資料庫

CNAME 重定向對於每個環境均使用相同埠的服務非常有效,但如果每個環境的不同端點使用不同的埠,CNAME 重定向就略顯不足。幸運的是我們可以使用一些基本工具來解決這個問題。

第一步是從 URI 獲取 IP 地址。

對 URI 執行 nslookup、hostname 或 ping 命令即可獲取資料庫的 IP 地址。

您現在可以建立一個重新對映 mLab 埠的服務,併為此 IP 地址建立端點。

kind: Service

apiVersion: v1

metadata:

name: mongo

spec:

ports:

– port: 27017

targetPort: 49763

kind: Endpoints

apiVersion: v1

metadata:

name: mongo

subsets:

– addresses:

– ip: 35.188.8.12

ports:

– port: 49763

注:URI 可以使用 DNS 在多個 IP 地址之間進行負載平衡,因此,如果 IP 地址發生變化,這個方法可能會有風險!如果您通過上述命令獲取多個 IP 地址,則可以將所有這些地址都包含在 Endpoints YAML 中,並且 Kubernetes 會在所有 IP 地址之間進行流量的負載平衡。

通過這種方式,您無需指定埠即可連線到遠端資料庫。Kubernetes 服務重對映埠的過程完全透明!

mongodb://<dbuser>:<dbpassword>@mongo/dev

結論

將外部服務對映到內部服務可讓您未來靈活地將這些服務納入叢集,同時最大限度地減少重構工作。即使您今天不打算將服務加入叢集,以後可能也會這樣做!而且,這樣一來,您可以更輕鬆地管理和了解組織所使用的外部服務。

如果外部服務具有有效域名,並且您不需要重新對映埠,那麼使用 “ExternalName” 服務型別將外部服務對映到內部服務十分簡便、快捷。如果您沒有域名或需要執行埠重對映,只需將 IP 地址新增到端點並使用即可。

來源:谷歌開發者