Longhorn 微服務化存儲初探

一、Longhorn 安裝

1.1、準備工作

Longhorn 官方推薦的最小配置如下,如果數據並不算太重要可適當縮減和調整,具體請自行斟酌:

本次安裝測試環境如下:

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 插件;以下爲簡要說明:

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-provisionercsi-snapshotterlonghorn-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 僅在以下情況做自動處理:

非這幾種情況外,如還原到更小容量的 Snapshot,可能需要手動調整文件系統,具體請參考 Filesystem expansion 章節文檔。

四、總結

總體來說目前 Longhorn 是一個比較清量級的存儲解決方案,微服務化使其更加可靠,同時官方文檔完善社區響應也比較迅速;最主要的是 Longhorn 採用的技術方案不會過於複雜,通過文檔以及閱讀源碼至少可以比較快速的瞭解其背後實現,而反觀一些其他大型存儲要麼文檔不全,要麼實現技術複雜,普通用戶很難窺視其核心;綜合來說在小型存儲選擇上比較推薦 Longhorn,至於穩定性麼,很不負責的說我也不知道,畢竟我也是新手,備份還沒折騰呢…

原文鏈接:https://mritd.com/2021/03/06/longhorn-storage-test/

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/05o3zUbxWOzKp8xhvtAL7Q