K8S 最佳實踐 對映外部服務

2021-09-19 22:23:22 字數 3949 閱讀 2806

大多數 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 中,這是預設設定,因此無需進行任何特殊配置。

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:

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

您可以建立乙個 「externalname」 kubernetes 服務,此服務為您提供將流量重定向到外部服務的靜態 kubernetes 服務。此服務在核心級別執行簡單的 cname 重定向,因此對效能的影響非常小。

服務的 yaml 如下所示:

kind: service

apiversion: v1

metadata:

name: mongo

spec:

type: externalname

externalname: ds149763.mlab.com

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

mongodb://:@mongo:/dev

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

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

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

第一步是從 uri 獲取 ip 位址。

對 uri 執行 nslookup、hostname 或 ping 命令即可獲取資料庫的 ip 位址。

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

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

mongodb://:@mongo/dev

結論

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

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

本文**中文社群-k8s 最佳實踐-對映外部服務

k8s最佳實踐

通過下面兩種方式可以減小構建映象大小 small base images 有些base映象有非常齊全的工具鏈,考慮考慮是否需要這些工具鏈,還是只需要精簡映象版映象並補充所需的工具 builder pattern 對於一些go c語言專案,使用docker提供的builder pattern,先構建乙...

k8s編排最佳實踐

不受任何控制器 deployment,replicasets,jobs 控制的pod稱之為裸pod foo service host foo service port 如果 中要訪問service,不要使用上述環境變數,最好使用service的dns名稱,上述環境變數只是為了解決有些老的系統無法使用...

新手篇 K8S配置最佳實踐

本文件旨在彙總和強調使用者指南 快速開始文件和示例中的最佳實踐。本文已上傳到 kubernetes handbook 中的第四章最佳實踐章節,本文僅作歸檔,更新以 kubernetes handbook 為準。通用配置建議 裸奔的pods vs replication controllers和 jo...