Kubernetes 最佳實踐:映射外部服務
文 / 開發技術推廣工程師 Sandeep Dinesh
大多數 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 地址添加到端點並使用即可。
更多 AI 相關閱讀:
·?通過安全瀏覽保護 WebView
·?通過視頻著色進行自監督跟蹤
·?通過機器學習讓醫療數據更好用
文章來源:https://blog.csdn.net/jILRvRTrc/article/details/81117261
Kubernetes 最佳實踐:映射外部服務