Categories
程式開發

如何在 Kubernetes 上運行數據庫服務?


導讀: Kubernetes 已經成為了集群調度領域最炙手可熱的開源項目之一。用Kubernetes 來部署和管理Web 應用、移動後端和API 服務等相對容易,因為這些應用通常都是無狀態應用,通過基本的Kubernetes API 就能運行,可以在沒有其他知識的情況下進行擴展並從故障中恢復。但要是用 Kubernetes 來運行有狀態應用呢?比如數據庫、緩存和監控系統。這就為我們帶來了不小的挑戰。因為這些系統需要應用領域的知識才能正確擴展、升級和重新配置,從而防止數據丟失或不可用。 Leonid Mirsky 為我們闡述瞭如何在 Kubernetes 部署和管理有狀態應用,本文以在 Kubernetes 上運行數據庫為例講解。

你在網上所能找到的許多 Kubernetes 示例,大都集中於運行無狀態應用。

通常,這些都是標準的 NodeJS Express 應用或用 Flask 編寫的基於 Python 的 API。

現在,在 Kubernetes 上運行這些類型的應用相對比較容易了。你擁有大規模管理和運營它們所需的一切:滾動部署、入口控制器、終止超時控制,等等。

但是,如果運行一個有狀態應用,它偶爾需要在磁盤上寫入數據,並確保這些數據在容器重啟之間,或容器重新調度到另一個節點時仍然保持不變,又該如何做呢?

這就是事情沒有那麼簡單的地方。幸運的是,Kubernetes 及其充滿活力的社區,為如何運行這些有狀態的工作負載提供了許多選擇。

我們將更深入研究這些選擇,但你可能會問以下這些問題……

為何在 Kubernetes 上部署有狀態應用比較困難?

我們能不能在 Pod 模板上附加一個卷?這難道還不夠嗎?從理論上講,你的應用現在就可以寫入磁盤,但如果容器重啟或移動到另一個節點的話,那麼這個卷將會被重新附加到容器的新位置。

對於簡單的案例來說,確實如此。但是對於 Elasticsearch、etcd、Consul 等服務來說,情況就要復雜得多了。

這些服務有一些常規 Kubernetes 部署控制器無法滿足的要求。

例如,你可能需要為每個 Pod 提供可預測的 DNS 名稱,以便使初始集群形成更加容易。或者,你部署的系統,可能需要確保 Pod 將按某種預定義的順序來啟動容器。

此外,你還可能希望為每個 Pod 創建並附加單獨的捲,這些卷將在整個 Pod 的生命週期中與其綁定。對於常規 Pod,你只能附加一個卷,這個卷將在同一部署創建的所有 Pod 之間共享。

我們也沒有提到如何操作數據庫。你還需要確保制定一個計劃,確定何時以及如何執行備份,或者在發生錯誤時如何執行恢復 / 故障轉移。

運行有狀態應用的可用選項

以下是一些關於如何在 Kubernetes 上部署數據庫的幾個選項。

1. StatefulSet

StatefulSet,是一個內置的控制器(譯者註:原稱 PetSet,首次出現在 Kubernetes 1.4,後在 1.5 更名為 StatefulSet),本質上類似於 Kubernetes 的部署。

最終,它將基於你將指定的 Pod 模板創建和管理一組 Pod。

主要區別在於,它為底層應用提供了以下保證:

  • 每個 Pod 都有一個穩定、唯一的網絡標識符。
  • 每個 Pod 可能有一個穩定的、持久的存儲卷。
  • 部署、擴展或終止都將是有序而優雅地執行。

下面是一些使用 StatefulSet 的開源數據庫部署實現的示例:

  1. Kubernetes Elasticsearch Cluster,作者:Paulo Pires
  2. Consul on Kubernetes,作者:Kelsey Hightower

StatefulSet 是通用的,因此你可以使用它們來對數據庫的unique cluster formation或主 / 從架構進行建模。

然而,最終的結果將在操作方面有所欠缺。你將需要添加其他資源或自動化,以確保能夠執行定期備份或添加處理諸如故障轉移等邊緣情況的腳本。

最終,使用 StatefulSet 為更複雜的有狀態服務建模可能會有點笨拙的感覺,並且還不是 Kubernetes 原生的,而且,如上所述,它還將缺乏管理自動化。這就是 Operator 發揮作用之處:

StatefulSet 是 Kubernetes 提供的管理有狀態應用的負載管理控制器 API。在 Pod 管理的基礎上,保證 Pod 的順序和一致性。與 Deployment 一樣,StatefulSet 也是使用容器的 Spec 來創建 Pod,與之不同 StatefulSet 創建的 Pod 在生命週期中會保持持久的標記(例如 Pod Name)。簡單地說,StatefulSet 是一個給 Pod 提供唯一標誌的控制器,它可以保證部署和擴展的順序。

2. Operator

如果你決定在 Kubernetes 上運行數據的原因之一,是為了統一所有應用程序組件的管理,那麼 Operator 可能會提供你想要擁有的體驗!

與其將應用程序放入 StatefulSet 模型中,不如編寫(或者使用其他人的)自定義控制器。

作為用戶,這允許你使用 Kubectl CLI 來控制有狀態應用,將其作為本地 Kubernetes 資源。例如,如果你部署了 etcd Operator,那麼可以使用下面的 kubectl 命令檢查集群的備份狀態:

kubectl get EtcdBackup example-etcd-cluster

與 StatefulSet 相比,Operator 的主要優勢在於,它們添加了一個自動化層,該層對於其操作的有狀態應用是獨有的。你無需擔心如何在 Elasticsearch 集群中添加備份 cron,該集群使用 StatefulSet 實現。使用 Operator,你只需指定存儲此備份的存儲桶即可。

不幸的是,由於編寫新的 Operator 除了需要了解有狀態應用的細節之外,還需要了解 Kubernetes 及其 API,因此,目前可用的 Operator 並不多,而且現有的 Operator 仍然相對較新。

下面是一些 Operator 的示例,你可以自己測試概念:

  1. Prometheus operator,作者:CoreOS
  2. Elastic Search operator,作者:UPMC Enterprises

譯註: Operator 是 CoreOS 推出的旨在簡化複雜有狀態應用管理的框架,它是一個感知應用狀態的控制器,通過擴展 Kubernetes API 來自動創建、管理和配置應用實例。 Operator 基於 Third Party Resources (CRD)擴展了新的應用資源,並通過控制器來保證應用處於預期狀態。比如 etcd operator 通過下面的三個步驟模擬了管理 etcd 集群的行為:通過 Kubernetes API 觀察集群的當前狀態;分析當前狀態與期望狀態的差別;調用 etcd 集群管理 API 或 Kubernetes API 消除這些差別。

3. 其他

本節提到的定義較少,主要是為了說明對於特定的數據庫,比如我們稍後將看到的 PostgreSQL 示例,還有其他選項可以將它們作為 Docker 容器在 Kubernetes 上部署和管理。

有時,除了 StatefulSet 或專用的 Operator 實現之外,還有其他可用的選項。

例如,Stolon 是一個“PostgreSQL 高可用性的雲原生 PostgreSQL 管理器”,雖然我個人還沒有機會使用它,但看到過一些帖子中提到了 Stolon。

要在 Kubernetes 上部署 Stolon,可以使用提供的 StatefulSet 定義。但是,由於 Stolon 的功能,你不需要添加自己的集群管理自動化來控制 PostgreSQL 集群。 Stolon 為此提供了自己的 CLI

總結

下面是一棵快速決策樹,希望它能夠幫助你作出如何在 Kubernetes 上進行最佳部署和維護有狀態工作負載的決策:

1.你能自己維護數據庫嗎?

  • 如果不能,那就忘掉本文,付錢給別人,讓他幫你做這件事。

  • 如果能,那麼就繼續讀下去。

2.你是否已經在 Kubernetes 上運行了大部分應用程序?

  • 如果沒有,而是以與其他應用程序類似的方式部署數據庫。根據你的方便程度,組合使用物理服務器、雲實例或虛擬機。

  • 如果是,那麼請接著思考以下三個問題:
    1]. 你能為所選擇的數據庫找到成熟的 Operator 嗎?
    2]. 你能找到一個像 Stolon(上面提到的)這樣的獨立項目來使管理變得更容易嗎?
    3]. 你可以找到基於 StatefulSet 的部署嗎?它是否“生產準備就緒”?

當涉及到無狀態應用程序時,Kubernetes 是一個非常直觀的平台。然而,在處理類似數據庫的服務時,你需要更多考慮如何在 Kubernetes 上部署和管理它們。好消息和壞消息就是,都有幾個選項可供選擇。

作者介紹:

Leonid Mirsky,Opsfleet 的創始人,幫助初創企業將現有的基礎架構遷移到 Kubernetes。

原文鏈接:

https://opsfleet.com/running-database-services-on-kubernetes/