我們經常遇到 Apache Cassandra 資料庫以及在基於 Kubernetes 的基礎架構中操作它的需求。 在本資料中,我們將分享將 Cassandra 遷移到 K8s 的必要步驟、標準和現有解決方案(包括營運商概述)的願景。
“誰能統治女人,誰就能統治國家”
卡桑德拉是誰? 它是一個分散式儲存系統,旨在管理大量數據,同時確保高可用性,無單點故障。 這個專案幾乎不需要長篇大論的介紹,因此我將只給出與特定文章上下文相關的 Cassandra 的主要功能:
- Cassandra 是用 Java 寫的。
- Cassandra 拓樸包括幾個等級:
- 節 - 一個已部署的 Cassandra 實例;
- Rack 是一組 Cassandra 實例,透過某種特徵聯合起來,位於同一個資料中心;
- 資料中心 - 位於一個資料中心的所有 Cassandra 實例組的集合;
- 集群是所有資料中心的集合。
- Cassandra 使用 IP 位址來識別節點。
- 為了加速寫入和讀取操作,Cassandra 將一些資料儲存在 RAM 中。
現在 - 實際可能遷移到 Kubernetes。
轉讓清單
談到Cassandra向Kubernetes的遷移,我們希望透過遷移,管理起來會更方便。 為此需要什麼,什麼會對此有幫助?
1. 資料存儲
正如已經澄清的那樣,Cassanda 將部分資料儲存在 RAM 中 - 記憶體表。 但資料的另一部分以以下形式儲存到磁碟: SS表。 一個實體被加入到此數據中 提交日誌 — 所有交易的記錄,也儲存到磁碟上。
在 Cassandra 中編寫事務圖
在 Kubernetes 中,我們可以使用 PersistentVolume 來儲存資料。 由於經過驗證的機制,在 Kubernetes 中處理資料每年都變得更加容易。
我們將為每個 Cassandra pod 分配我們自己的 PersistentVolume
值得注意的是,Cassandra 本身就意味著資料複製,為此提供了內建機制。 因此,如果您要從大量節點建立 Cassandra 集群,則無需使用 Ceph 或 GlusterFS 等分散式系統進行資料儲存。 在這種情況下,使用以下方法將資料儲存在主機磁碟上是合乎邏輯的: hostPath
.
另一個問題是您是否想為每個功能分支的開發人員創建一個單獨的環境。 在這種情況下,正確的方法是建立一個 Cassandra 節點並將資料儲存在分散式儲存中,即提到的 Ceph 和 GlusterFS 將是您的選擇。 那麼開發人員就能確保即使其中一個 Kubernetes 叢集節點遺失,他也不會遺失測試資料。
2. 監控
在 Kubernetes 中實現監控幾乎毫無爭議的選擇是 Prometheus (我們在
Grafana for Cassandra 中圖表的外觀範例
我們為自己選擇第一個,因為:
- JMX Exporter 正在不斷成長和發展,而 Cassandra Exporter 卻一直未能獲得足夠的社區支持。 Cassandra Exporter 仍然不支援大多數版本的 Cassandra。
- 您可以透過新增標誌將其作為 javaagent 運行
-javaagent:<plugin-dir-name>/cassandra-exporter.jar=--listen=:9180
. - 有一個適合他的
足夠的儀表板 ,與 Cassandra Exporter 不相容。
3. 選擇 Kubernetes 原語
根據上面的 Cassandra 叢集結構,我們嘗試將其中描述的所有內容翻譯成 Kubernetes 術語:
- Cassandra 節點 → Pod
- Cassandra Rack → StatefulSet
- Cassandra 資料中心 → StatefulSets 的池
- 卡桑德拉集群 → ???
事實證明,缺少一些額外的實體來立即管理整個 Cassandra 叢集。 但如果有些東西不存在,我們可以創造它! Kubernetes 有一個為此目的定義自己的資源的機制 -
聲明日誌和警報的附加資源
但自訂資源本身並沒有什麼意義:畢竟它需要 調節器。 您可能需要尋求協助
4. pod 的識別
在上一段中,我們一致認為 XNUMX 個 Cassandra 節點相當於 Kubernetes 中的 XNUMX 個 Pod。 但 Pod 的 IP 位址每次都會不同。 而Cassandra中節點的識別是基於IP位址的…事實證明,每次移除一個pod後,Cassandra叢集都會新增一個新的節點。
有出路,但不只是一條:
- 我們可以透過主機識別碼(唯一標識 Cassandra 實例的 UUID)或 IP 位址來保存記錄,並將其全部儲存在某些結構/表中。 此方法有兩個主要缺點:
- 如果兩個節點同時失敗,則存在競爭條件發生的風險。 崛起後,Cassandra節點會同時從表中請求IP位址,競爭相同資源。
- 如果 Cassandra 節點遺失了數據,我們將無法再識別它。
- 第二個解決方案看起來像是一個小技巧,但儘管如此:我們可以為每個 Cassandra 節點建立一個帶有 ClusterIP 的服務。 此實現的問題:
- 如果 Cassandra 叢集中有很多節點,我們必須建立很多服務。
- ClusterIP 功能是透過 iptables 實現的。 如果 Cassandra 叢集有許多(1000 個…甚至 100 個?)節點,這可能會成為問題。 雖然
基於IPVS的均衡 可以解決這個問題。
- 第三種解決方案是透過啟用以下設置,為 Cassandra 節點使用節點網絡,而不是專用的 Pod 網絡
hostNetwork: true
。 此方法有一定的限制:- 更換單位。 新節點必須與前一個節點具有相同的IP位址(在AWS、GCP等雲中這幾乎是不可能做到的);
- 使用叢集節點網絡,我們開始爭奪網路資源。 因此,在一個叢集節點上放置多個具有 Cassandra 的 Pod 將會出現問題。
5. 備份
我們希望按計劃保存單一 Cassandra 節點資料的完整版本。 Kubernetes 提供了一個方便的功能
讓我提醒您,Cassandra 將一些資料儲存在記憶體中。 要進行完整備份,您需要記憶體中的資料(記憶體表)移動到磁碟(SS表)。 此時,Cassandra 節點停止接受連接,從叢集中完全關閉。
此後,備份將被刪除(快照)並且該方案被保存(鍵空間)。 然後事實證明,僅僅備份並不能給我們帶來任何東西:我們需要保存 Cassandra 節點負責的資料標識符 - 這些是特殊的令牌。
分配令牌以確定 Cassandra 節點負責哪些數據
在 Kubernetes 中從 Google 取得 Cassandra 備份的範例腳本可以在以下位置找到:
set -eu
if [[ -z "$1" ]]; then
info "Please provide a keyspace"
exit 1
fi
KEYSPACE="$1"
result=$(nodetool snapshot "${KEYSPACE}")
if [[ $? -ne 0 ]]; then
echo "Error while making snapshot"
exit 1
fi
timestamp=$(echo "$result" | awk '/Snapshot directory: / { print $3 }')
mkdir -p /tmp/backup
for path in $(find "/var/lib/cassandra/data/${KEYSPACE}" -name $timestamp); do
table=$(echo "${path}" | awk -F "[/-]" '{print $7}')
mkdir /tmp/backup/$table
mv $path /tmp/backup/$table
done
tar -zcf /tmp/backup.tar.gz -C /tmp/backup .
nodetool clearsnapshot "${KEYSPACE}"
用於從一個 Cassandra 節點進行備份的 bash 腳本範例
Kubernetes 中 Cassandra 的現成解決方案
目前在 Kubernetes 中部署 Cassandra 所使用的是什麼?其中哪一個最適合給定的要求?
1.基於StatefulSet或Helm圖表的解決方案
使用基本的 StatefulSets 函數來運行 Cassandra 叢集是一個不錯的選擇。 使用 Helm 圖表和 Go 模板,您可以為使用者提供靈活的介面來部署 Cassandra。
這通常工作正常......直到發生意外情況,例如節點故障。 標準 Kubernetes 工具根本無法考慮上述所有功能。 此外,這種方法對於更複雜用途的擴展程度非常有限:節點更換、備份、復原、監控等。
代表:
兩個圖表都一樣好,但都存在上述問題。
2、基於Kubernetes Operator的解決方案
這些選項更有趣,因為它們為管理叢集提供了充足的機會。 對於設計 Cassandra 操作符,就像任何其他資料庫一樣,一個好的模式看起來像 Sidecar <-> Controller <-> CRD:
精心設計的 Cassandra 運算子中的節點管理方案
讓我們看看現有的運營商。
1.來自 instaclustr 的 Cassandra 運算符
-
GitHub上 - 準備狀態:阿爾法
- 許可證:Apache 2.0
- 實作語言:Java
這確實是一個非常有前途且正在積極開發的項目,來自一家提供託管 Cassandra 部署的公司。 如上所述,它使用透過 HTTP 接受命令的 sidecar 容器。 它是用 Java 編寫的,有時缺乏 client-go 庫的更高級功能。 此外,營運商不支援一個資料中心使用不同的機架。
但該操作員具有諸如支援監控、使用 CRD 進行高階叢集管理,甚至提供備份文件等優勢。
2.Jetstack 的導航器
-
GitHub上 - 準備狀態:阿爾法
- 許可證:Apache 2.0
- 實作於:Golang
旨在部署資料庫即服務的聲明。 目前支援兩種資料庫:Elasticsearch 和 Cassandra。 它有一些有趣的解決方案,例如透過 RBAC 進行資料庫存取控制(為此它有自己獨立的 navigator-apiserver)。 這是一個有趣的項目,值得仔細研究,但最後一次提交是在一年半前,這顯然降低了它的潛力。
3. Cassandra 運算符,作者:vgkowski
-
GitHub上 - 準備狀態:阿爾法
- 許可證:Apache 2.0
- 實作於:Golang
他們並沒有「認真」地考慮它,因為最後一次提交到儲存庫已經是一年多前了。 Operator 開發被放棄:據報導支持的 Kubernetes 最新版本是 1.9。
4. Rook 的 Cassandra 運算符
-
GitHub上 - 準備狀態:阿爾法
- 許可證:Apache 2.0
- 實作於:Golang
營運商的發展進展沒有我們希望的那麼快。 它具有用於叢集管理的深思熟慮的 CRD 結構,解決了使用 ClusterIP 服務識別節點的問題(相同的「hack」)…但目前僅此而已。 目前沒有開箱即用的監控或備份(順便說一句,我們是為了監控
注意:我們在一個專案中使用了這個運算符,並進行了一些小的修改。 在整個運行期間(運行約 4 個月),操作員的工作沒有發現任何問題。
5.來自Orange的CassKop
-
GitHub上 - 準備狀態:阿爾法
- 許可證:Apache 2.0
- 實作於:Golang
名單上最年輕的操作員:第一次提交於 23 年 2019 月 XNUMX 日進行。 現在它的武器庫中已經包含了我們清單中的大量功能,更多詳細資訊可以在專案儲存庫中找到。 該operator是在流行的operator-sdk的基礎上建構的。 支援開箱即用的監控。 與其他操作符的主要區別在於使用
發現
將 Cassandra 移植到 Kubernetes 的方法和可能選項的數量不言而喻:這個主題很受歡迎。
在此階段,您可以嘗試上述任何一種方法,但後果自負:沒有開發人員保證其解決方案在生產環境中 100% 運作。 但許多產品看起來已經有望在開發平台中嘗試使用。
我想以後船上這個女人一定會派上用場的!
聚苯乙烯
另請閱讀我們的博客:
- «
MongoDB 無縫遷移到 Kubernetes “; - «
RabbitMQ 無縫遷移到 Kubernetes “; - «
數據庫和 Kubernetes(概述和視頻報告) “; - «
K8s 提示與技巧:加快大型資料庫的引導速度 “。
來源: www.habr.com