RabbitMQ 是一個用 Erlang 編寫的訊息代理,可讓您組織一個跨多個節點進行完整資料複製的故障轉移集群,其中每個節點都可以服務讀寫請求。 在生產運行中擁有許多 Kubernetes 集群,我們支援大量 RabbitMQ 安裝,並且面臨著在不停機的情況下將資料從一個集群遷移到另一個集群的需要。
我們至少在兩種情況下需要此操作:
- 將資料從不在 Kubernetes 中的 RabbitMQ 叢集傳輸到一個新的-已經「kubernetized」(即在 K8s pod 中運行)的叢集。
- 將 Kubernetes 內的 RabbitMQ 從一個命名空間遷移到另一個命名空間(例如,如果電路由命名空間分隔,則將基礎設施從一個電路轉移到另一個電路)。
本文中提出的方法主要針對以下情況(但完全不限於此):存在舊的 RabbitMQ 叢集(例如,3 個節點),該叢集要麼已位於 K8s 中,要麼位於某些舊伺服器上。 託管在 Kubernetes 上的應用程式(已經存在或將來)可以使用它:
……我們面臨著將其遷移到 Kubernetes 中的新生產環境的任務。
首先,將描述遷移本身的一般方法,然後將描述其實現的技術細節。
遷移演算法
任何操作之前的第一個初步階段是檢查舊 RabbitMQ 安裝中是否啟用了高可用性模式(ha-mode: all
:
下一步是在 Kubernetes Pod 中建立一個新的 RabbitMQ 叢集(例如,在我們的範例中,由 3 個節點組成,但它們的數量可能不同)。
之後,我們合併新舊 RabbitMQ 集群,獲得單一集群(6 個節點):
啟動新舊RabbitMQ集群之間的資料同步過程。 一旦叢集中所有節點之間的所有資料同步,我們就可以切換應用程式以使用新叢集:
經過這些操作後,就足以從 RabbitMQ 叢集中刪除舊節點,移動可以認為完成了:
我們在生產中多次使用了這個方案。 然而,為了我們自己的方便,我們在一個專門的系統中實現了它,該系統在多個 Kubernetes 叢集之間分發標準 RMQ 配置 (對於那些好奇的人:我們正在談論
讓我們在實踐中嘗試一下
需求
細節很簡單:
- Kubernetes 叢集(minikube 也可以);
- RabbitMQ 叢集(可部署在裸機上,並根據官方 Helm 圖表製作成 Kubernetes 中的常規叢集)。
對於下面的範例,我將 RMQ 部署到 Kubernetes 並呼叫它 rmq-old
.
展位準備
1.下載Helm圖表並進行一些編輯:
helm fetch --untar stable/rabbitmq-ha
為了方便,我們設定了密碼, ErlangCookie
並進行政治 ha-all
以便預設情況下佇列在 RMQ 叢集的所有節點之間同步:
rabbitmqPassword: guest
rabbitmqErlangCookie: mae9joopaol7aiVu3eechei2waiGa2we
definitions:
policies: |-
{
"name": "ha-all",
"pattern": ".*",
"vhost": "/",
"definition": {
"ha-mode": "all",
"ha-sync-mode": "automatic",
"ha-sync-batch-size": 81920
}
}
2. 安裝圖表:
helm install . --name rmq-old --namespace rmq-old
3. 前往 RabbitMQ 管理面板,建立一個新佇列並新增幾個訊息。 需要它們,以便遷移後我們可以確保所有資料都保留並且我們沒有丟失任何內容:
測試平台已準備就緒:我們有「舊」RabbitMQ,其中包含需要傳輸的資料。
遷移 RabbitMQ 集群
1. 首先,我們將新的 RabbitMQ 部署在 朋友 命名空間與 相同的 ErlangCookie
和用戶的密碼。 為此,我們將執行上述操作,將安裝 RMQ 的最終命令變更為以下內容:
helm install . --name rmq-new --namespace rmq-new
2. 現在您需要將新叢集與舊叢集合併。 為此,請轉到每個 Pod 新 RabbitMQ 並執行指令:
export OLD_RMQ=rabbit@rmq-old-rabbitmq-ha-0.rmq-old-rabbitmq-ha-discovery.rmq-old.svc.cluster.local &&
rabbitmqctl stop_app &&
rabbitmqctl join_cluster $OLD_RMQ &&
rabbitmqctl start_app
在一個變量中 OLD_RMQ
找到其中一個節點的位址 舊的 RMQ 叢集。
這些命令將停止當前節點 新 RMQ 集群,將其附加到舊集群並再次啟動。
3. 6個節點的RMQ叢集準備就緒:
您必須等待訊息在所有節點之間同步。 不難猜測,訊息同步時間取決於叢集部署的硬體容量以及訊息數量。 在所描述的場景中,只有 10 個訊息,因此資料是即時同步的,但如果訊息數量足夠多,同步可能會持續幾個小時。
所以,同步狀態:
這裡 +5
表示訊息已在 更多的 在 5 個節點上(字段中指示的除外) Node
)。 這樣,同步就成功了。
4. 剩下的就是將應用程式中的RMQ位址切換到新叢集(這裡的具體操作取決於您所使用的技術堆疊和其他應用程式的具體情況),之後您就可以告別舊叢集了。
對於最後一次操作(即已經 後 將應用程式切換到新叢集)轉到每個節點 舊的 集群並執行命令:
rabbitmqctl stop_app
rabbitmqctl reset
叢集「忘記」舊節點:您可以刪除舊 RMQ,此時移動將完成。
注意:如果您使用帶有憑證的 RMQ,則不會發生根本性變化 - 移動過程將完全相同。
發現
當我們需要遷移 RabbitMQ 或只是移動到新叢集時,所描述的方案幾乎適用於所有情況。
在我們的例子中,只出現過一次困難,即從許多地方訪問 RMQ,並且我們沒有機會將 RMQ 地址更改為新的地址。 然後我們在同一個命名空間中使用相同的標籤啟動了一個新的RMQ,這樣它就會落入現有的服務和Ingress 下,並且在啟動pod 時我們手動操作標籤,在開始時將其刪除,這樣請求就不會落在清空RMQ,並在訊息同步後將其加回。
當將 RabbitMQ 更新到具有更改配置的新版本時,我們使用了相同的策略 - 一切都像時脈一樣工作。
聚苯乙烯
作為本資料的邏輯延續,我們正在準備有關 MongoDB(從硬體伺服器遷移到 Kubernetes)和 MySQL(我們如何在 Kubernetes 內準備此 DBMS)的文章。 它們將在未來幾個月內發布。
聚苯硫醚
另請閱讀我們的博客:
來源: www.habr.com