Longhorn 微服務化存儲初探
一、Longhorn 安裝
1.1、準備工作
Longhorn 官方推薦的最小配置如下,如果數據並不算太重要可適當縮減和調整,具體請自行斟酌:
-
3 Nodes
-
4 vCPUs per Node
-
4 GiB per Node
-
SSD/NVMe or similar performance block device on the node for storage(We don’t recommend using spinning disks with Longhorn, due to low IOPS.)
本次安裝測試環境如下:
-
Ubuntu 20.04(8c16g)
-
Disk 200g
-
Kubernetes 1.20.4(kubeadm)
-
Longhorn 1.1.0
1.2、安裝 Longhorn(Helm)
安裝 Longhorn 推薦使用 Helm,因爲在卸載時 kubectl 無法直接使用 delete 卸載,需要進行其他清理工作;helm 安裝命令如下:
# add Longhorn repo
helm repo add longhorn https://charts.longhorn.io
# update
helm repo update
# create namespace
kubectl create namespace longhorn-system
# install
helm install longhorn longhorn/longhorn --namespace longhorn-system --values longhorn-values.yamlCopy
其中 longhorn-values.yaml
請從 Charts 倉庫 下載,本文僅修改了以下兩項:
defaultSettings:
# 默認存儲目錄(默認爲 /var/lib/longhorn)
defaultDataPath: "/data/longhorn"
# 默認副本數量
defaultReplicaCount: 2Copy
安裝完成後 Pod 運行情況如下所示:
此後可通過集羣 Ingress 或者 NodePort 等方式暴露 service longhorn-frontend
的 80 端口來訪問 Longhorn UI;注意,Ingress 等負載均衡其如果採用 HTTPS 訪問請確保向 Longhorn UI 傳遞了 X-Forwarded-Proto: https 頭,否則可能導致 Websocket 不安全鏈接以及跨域等問題,後果就是 UI 出現一些神奇的小問題 (我排查了好久…)。
1.3、卸載 Longhorn
如果在安裝過程中有任何操作錯誤,或想重新安裝驗證相關設置,可通過以下命令卸載 Longhorn:
# 卸載
helm uninstall longhorn -n longhorn-systemCopy
二、Longhorn 架構
2.1、Design
Longhorn 總體設計分爲兩層: 數據平面和控制平面;Longhorn Engine 是一個存儲控制器,對應數據平面;Longhorn Manager 對應控制平面。
2.1.1、Longhorn Manager
Longhorn Manager 使用 Operator 模式,作爲 Daemonset 運行在每個節點上;Longhorn Manager 負責接收 Longhorn UI 以及 Kubernetes Volume 插件的 API 調用,然後創建和管理 Volume;
Longhorn Manager 在與 kubernetes API 通信並創建 Longhorn Volume CRD(heml 安裝直接創建了相關 CRD,查看代碼後發現 Manager 裏面似乎也會判斷並創建一下),此後 Longhorn Manager watch 相關 CRD 資源和 Kubernetes 原生資源 (PV/PVC…),一但集羣內創建了 Longhorn Volume 則 Longhorn Manager 負責創建物理 Volume。
當 Longhorn Manager 創建 Volume 時,Longhorn Manager 首先會在 Volume 所在節點創建 Longhorn Engine 實例 (對比實際行爲後發現所謂的 “實例” 其實只是運行了一個 Linux 進程,並非創建 Pod),然後根據副本數量在所需放置副本的節點上創建對應的副本。
2.1.2、Longhorn Engine
Longhorn Engine 始終與其使用 Volume 的 Pod 在同一節點上,它跨存儲在多個節點上的多個副本同步複製卷;同時數據的多路徑保證 Longhorn Volume 的 HA,單個副本或者 Engine 出現問題不會影響到所有副本或 Pod 對 Volume 的訪問。
下圖中展示了 Longhorn 的 HA 架構,每個 Kubernetes Volume 將會對應一個 Longhorn Engine,每個 Engine 管理 Volume 的多個副本,Engine 與 副本實質都會是一個單獨的 Linux 進程運行:
注意: 圖中的 Engine 並非是單獨的一個 Pod,而是每一個 Volume 會對應一個 golang exec 出來的 Linux 進程。
2.2、CSI Plugin
CSI 部分不做過多介紹,具體參考 如何編寫 CSI 插件;以下爲簡要說明:
-
Kubernetes CSI 被抽象爲具體的 CSI 容器並通過 gRPC 調用目標 plugin
-
Longhorn CSI Plugin 負責接收標準 CSI 容器發起的 gRPC 調用
-
Longhorn CSI Plugin 將 Kubernetes CSI gRPC 調用轉換爲自己的 Longhorn API 調用,並將其轉發到 Longhorn Manager 控制平面
-
Longhorn 某些功能使用了 iSCSI,所以可能需要在節點上安裝 open-iscsi 或 iscsiadm
2.3、Longhorn UI
Longhorn UI 向外暴露一個 Dashboard,並用過 Longhorn API 與 Longhorn Manager 控制平面交互;Longhorn UI 在架構上類似於 Longhorn CSI Plugin 的替代者,只不過一個是通過 Web UI 轉化爲 Longhorn API,另一個是將 CSI gRPC 轉換爲 Longhorn API。
2.4、Replicas And Snapshots
在 Longhorn 微服務架構中,副本也作爲單獨的進程運行,其實質存儲文件採用 Linux 的稀釋文件方式;每個副本均包含 Longhorn Volume 的快照鏈,快照就像一個 Image 層,其中最舊的快照用作基礎層,而較新的快照位於頂層。如果數據會覆蓋舊快照中的數據,則僅將其包含在新快照中;整個快照鏈展示了數據的當前狀態。
在進行快照時,Longhorn 會創建差異磁盤 (differencing disk) 文件,每個差異磁盤文件被看作是一個快照,當 Longhorn 讀取文件時從上層開始依次查找,其示例圖如下:
爲了提高讀取性能,Longhorn 維護了一個讀取索引,該索引記錄了每個 4K 存儲塊中哪個差異磁盤包含有效數據;讀取索引會佔用一定的內存,每個 4K 塊佔用一個字節,字節大小的讀取索引意味着每個卷最多可以拍攝 254 個快照,在大約 1TB 的卷中讀取索引大約會消耗 256MB 的內存。
2.5、Backups and Secondary Storage
由於數據大小、網絡延遲等限制,跨區域同步複製無法做到很高的時效性,所以 Longhorn 提供了稱之爲 Secondary Storage 的備份方案;Secondary Storage 依賴外部的 NFS、S3 等存儲設施,一旦在 Longhorn 中配置了 Backup Storage,Longhorn 將會通過卷的指定版本快照完成備份;** 備份過程中 Longhorn 將會抹平快照信息,這意味着快照歷史變更將會丟失,相同的原始卷備份是增量的,通過不斷的應用差異磁盤文件完成;爲了避免海量小文件帶來的性能瓶頸,Longhorn 採用 2MB 分塊進行備份,任何邊界內 4k 塊變動都會觸發 2MB 塊的備份行爲;Longhorn 的備份功能爲跨集羣、跨區域提供完善的災難恢復機制。**Longhorn 備份機制如下圖所示:
2.6、Longhorn Pods
上面的大部分其實來源於對官方文檔 Architecture and Concepts 的翻譯;在翻譯以及閱讀文檔過程中,通過對比文檔與實際行爲,還有閱讀源碼發現了一些細微差異,這裏着重介紹一下這些 Pod 都是怎麼回事:
2.6.1、longhorn-manager
longhorn-manager 與文檔描述一致,其通過 Helm 安裝時直接以 Daemonset 方式 Create 出來,然後 longhorn-manager 開啓 HTTP API(9500) 等待其他組件請求;同時 longhorn-manager 還會使用 Operator 模式監聽各種資源,包括不限於 Longhorn CRD 以及集羣的 PV(C) 等資源,然後作出對應的響應。
2.6.2、longhorn-driver-deployer
Helm 安裝時創建了 longhorn-driver-deployer Deployment,longhorn-driver-deployer 實際上也是 longhorn-manager 鏡像啓動,只不過啓動後會溝通 longhorn-manager HTTP API,然後創建所有 CSI 相關容器,包括 csi-provisioner
、csi-snapshotter
、longhorn-csi-plugin
等。
2.6.3、instance-manager-e
上面所說的每個 Engine 對應一個 Linux 進程其實就是通過這個 Pod 完成的,instance-manager-e 由 longhorn-manager 創建,創建完成後 instance-manager-e 監聽 gRPC 8500 端口,其只要職責就是接收 gRPC 請求,並啓動 Engine 進程;從上面我們 Engine 介紹可以得知 Engine 與 Volume 綁定,所以理論上集羣內 Volume 被創建時有某個 “東西” 創建了 CRD engines.longhorn.io,然後又有人 watch 了 engines.longhorn.io 並通知 instance-manager-e 啓動 Engine 進程;這裏不負責任的推測是 longhorn-manager 乾的,但是沒看代碼不敢說死…
同理 instance-manager-r
是負責啓動副本的 Linux 進程的,工作原理與 instance-manager-e
相同,通過簡單的查看代碼 (IDE 沒打開… 哈哈哈) 推測,instance-manager-e/-r
應該是 longhorn-manager Operator 下的產物,其維護了一個自己的 “Daemonset”,但是 kubectl 是看不到的。
2.6.4、longhorn-ui
longhorn-ui 很簡單,就是個 UI 界面,然後 HTTP API 溝通 longhorn-manager,這裏不再做過多說明。
三、Longhorn 使用
3.1、常規使用
默認情況下 Helm 安裝完成後會自動創建 StorageClass,如果集羣中只有 Longhorn 作爲存儲,那麼 Longhorn 的 StorageClass 將作爲默認 StorageClass。關於 StorageClass、PV、PVC 如果使用這裏不做過多描述,請參考官方 Example 文檔;
** 需要注意的是 Longhorn 作爲塊存儲僅支持 ReadWriteOnce 模式,如果想支持 ReadWriteMany 模式,則需要在節點安裝 nfs-common,Longhorn 將會自動創建 share-manager 容器然後通過 NFSV4 共享這個 Volume 從而實現 ReadWriteMany;** 具體請參考 Support for ReadWriteMany (RWX) workloads。
3.2、添加刪除磁盤
如果出現磁盤損壞重建或者添加刪除磁盤,請直接訪問 UI 界面,通過下拉菜單操作即可;在操作前請將節點調整到維護模式並驅逐副本,具體請參考 Evicting Replicas on Disabled Disks or Nodes。
需要注意的是添加新磁盤時,磁盤掛載的軟連接路徑不能工作,請使用原始掛載路徑或通過 mount --bind 命令設置新路徑。
3.3、創建快照及回滾
當創建好 Volume 以後可以用過 Longhorn UI 在線對 Volume 創建快照,** 但是回滾快照過程需要 Workload(Pod) 離線,同時 Volume 必須以維護模式 reattach 到某一個 Host 節點上,然後在 Longhorn UI 進行調整;** 以下爲快照創建回滾測試:
test.pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: longhorn-simple-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn
resources:
requests:
storage: 1GiCopy
test.po.yaml
apiVersion: v1
kind: Pod
metadata:
name: longhorn-simple-pod
namespace: default
spec:
restartPolicy: Always
containers:
- name: volume-test
image: nginx:stable-alpine
imagePullPolicy: IfNotPresent
livenessProbe:
exec:
command:
- ls
- /data/lost+found
initialDelaySeconds: 5
periodSeconds: 5
volumeMounts:
- name: volv
mountPath: /data
ports:
- containerPort: 80
volumes:
- name: volv
persistentVolumeClaim:
claimName: longhorn-simple-pvcCopy
3.3.1、創建快照
首先創建相關資源:
kubectl create -f test.pvc.yaml
kubectl create -f test.po.yamlCopy
創建完成後在 Longhorn UI 中可以看到剛剛創建出的 Volume:
點擊 Name 鏈接進入到 Volume 詳情,然後點擊 Take Snapshot
按鈕即可拍攝快照;有些情況下 UI 響應緩慢可能導致 Take Snapshot 按鈕變灰,刷新兩次即可恢復。
快照在回滾後仍然可以進行交叉創建
3.3.2、回滾快照
回滾快照時必須停止 Pod:
# 停止
kubectl delete -f test.po.yamlCopy
然後重新將 Volume Attach 到宿主機:
注意要開啓維護模式
稍等片刻等待所有副本 “Running” 然後 Revert 即可
回滾完成後,需要 Detach Volume,以便供重新創建的 Pod 使用
3.3.3、定時快照
除了手動創建快照之外,Longhorn 還支持定時對 Volume 進行快照處理;要使用定時任務,請進入 Volume 詳情頁面,在 Recurring Snapshot and Backup Schedule
選項卡下新增定時任務即可:
如果不想爲內核 Volume 都手動設置自動快照,可以用過調整 StorageClass 來實現爲每個自動創建的 PV 進行自動快照,具體請閱讀 Set up Recurring Jobs using a StorageClass 文檔。
3.4、Volume 擴容
Longhorn 支持對 Volume 進行擴容,擴容方式和回滾快照類似,都需要 Deacth Volume 並開啓維護模式。
首先停止 Workload
➜ ~ kubectl exec -it longhorn-simple-pod -- df -h
Filesystem Size Used Available Use% Mounted on
overlay 199.9G 4.7G 195.2G 2% /
tmpfs 64.0M 0 64.0M 0% /dev
tmpfs 7.8G 0 7.8G 0% /sys/fs/cgroup
/dev/longhorn/pvc-1c9e23f4-af29-4a48-9560-87983267b8d3
975.9M 2.5M 957.4M 0% /data
/dev/sda4 60.0G 7.7G 52.2G 13% /etc/hosts
/dev/sda4 60.0G 7.7G 52.2G 13% /dev/termination-log
/dev/sdc1 199.9G 4.7G 195.2G 2% /etc/hostname
/dev/sdc1 199.9G 4.7G 195.2G 2% /etc/resolv.conf
shm 64.0M 0 64.0M 0% /dev/shm
tmpfs 7.8G 12.0K 7.8G 0% /run/secrets/kubernetes.io/serviceaccount
tmpfs 7.8G 0 7.8G 0% /proc/acpi
tmpfs 64.0M 0 64.0M 0% /proc/kcore
tmpfs 64.0M 0 64.0M 0% /proc/keys
tmpfs 64.0M 0 64.0M 0% /proc/timer_list
tmpfs 64.0M 0 64.0M 0% /proc/sched_debug
tmpfs 7.8G 0 7.8G 0% /proc/scsi
tmpfs 7.8G 0 7.8G 0% /sys/firmware
➜ ~ kubectl delete -f test.po.yaml
pod "longhorn-simple-pod" deletedCopy
然後直接使用 kubectl 編輯 PVC,調整 spec.resources.requests.storage
保存後可以從 Longhorn UI 中看到 Volume 在自動 resize
重新創建 Workload 可以看到 Volume 已經擴容成功
➜ ~ kubectl create -f test.po.yaml
pod/longhorn-simple-pod created
➜ ~ kubectl exec -it longhorn-simple-pod -- df -h
Filesystem Size Used Available Use% Mounted on
overlay 199.9G 6.9G 193.0G 3% /
tmpfs 64.0M 0 64.0M 0% /dev
tmpfs 7.8G 0 7.8G 0% /sys/fs/cgroup
/dev/longhorn/pvc-1c9e23f4-af29-4a48-9560-87983267b8d3
4.9G 4.0M 4.9G 0% /data
/dev/sda4 60.0G 7.6G 52.4G 13% /etc/hosts
/dev/sda4 60.0G 7.6G 52.4G 13% /dev/termination-log
/dev/sdc1 199.9G 6.9G 193.0G 3% /etc/hostname
/dev/sdc1 199.9G 6.9G 193.0G 3% /etc/resolv.conf
shm 64.0M 0 64.0M 0% /dev/shm
tmpfs 7.8G 12.0K 7.8G 0% /run/secrets/kubernetes.io/serviceaccount
tmpfs 7.8G 0 7.8G 0% /proc/acpi
tmpfs 64.0M 0 64.0M 0% /proc/kcore
tmpfs 64.0M 0 64.0M 0% /proc/keys
tmpfs 64.0M 0 64.0M 0% /proc/timer_list
tmpfs 64.0M 0 64.0M 0% /proc/sched_debug
tmpfs 7.8G 0 7.8G 0% /proc/scsi
tmpfs 7.8G 0 7.8G 0% /sys/firmwareCopy
Volume 擴展過程中 Longhorn 會自動處理文件系統相關調整,但是並不是百分百會處理,一般 Longhorn 僅在以下情況做自動處理:
-
擴展後大小大約當前大小 (進行擴容)
-
Longhorn Volume 中存在一個 Linux 文件系統
-
Longhorn Volume 中的 Linux 文件系統爲 ext4 或 xfs
-
Longhorn Volume 使用
block device
作爲 frontend
非這幾種情況外,如還原到更小容量的 Snapshot,可能需要手動調整文件系統,具體請參考 Filesystem expansion 章節文檔。
四、總結
總體來說目前 Longhorn 是一個比較清量級的存儲解決方案,微服務化使其更加可靠,同時官方文檔完善社區響應也比較迅速;最主要的是 Longhorn 採用的技術方案不會過於複雜,通過文檔以及閱讀源碼至少可以比較快速的瞭解其背後實現,而反觀一些其他大型存儲要麼文檔不全,要麼實現技術複雜,普通用戶很難窺視其核心;綜合來說在小型存儲選擇上比較推薦 Longhorn,至於穩定性麼,很不負責的說我也不知道,畢竟我也是新手,備份還沒折騰呢…
原文鏈接:https://mritd.com/2021/03/06/longhorn-storage-test/
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/05o3zUbxWOzKp8xhvtAL7Q