天天看點

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 出現一些神奇的小問題(我排查了好久…)。

Longhorn 微服務化存儲初探

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 程序運作:

Longhorn 微服務化存儲初探

注意: 圖中的 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 微服務化存儲初探

為了提高讀取性能,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 備份機制如下圖所示:

Longhorn 微服務化存儲初探

2.6、Longhorn Pods

上面的大部分其實來源于對官方文檔 Architecture and Concepts 的翻譯;在翻譯以及閱讀文檔過程中,通過對比文檔與實際行為,還有閱讀源碼發現了一些細微差異,這裡着重介紹一下這些 Pod 都是怎麼回事:

Longhorn 微服務化存儲初探

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 幹的,但是沒看代碼不敢說死…

Longhorn 微服務化存儲初探

同理

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。

Longhorn 微服務化存儲初探

需要注意的是添加新磁盤時,磁盤挂載的軟連接配接路徑不能工作,請使用原始挂載路徑或通過 mount --bind 指令設定新路徑。

Longhorn 微服務化存儲初探

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:

Longhorn 微服務化存儲初探

點選 Name 連結進入到 Volume 詳情,然後點選

Take Snapshot

按鈕即可拍攝快照;有些情況下 UI 響應緩慢可能導緻 Take Snapshot 按鈕變灰,重新整理兩次即可恢複。

Longhorn 微服務化存儲初探

快照在復原後仍然可以進行交叉建立

Longhorn 微服務化存儲初探

3.3.2、復原快照

復原快照時必須停止 Pod:

# 停止
kubectl delete -f test.po.yamlCopy
           

複制

然後重新将 Volume Attach 到主控端:

Longhorn 微服務化存儲初探

注意要開啟維護模式

Longhorn 微服務化存儲初探

稍等片刻等待所有副本 “Running” 然後 Revert 即可

Longhorn 微服務化存儲初探

復原完成後,需要 Detach Volume,以便供重新建立的 Pod 使用

Longhorn 微服務化存儲初探

3.3.3、定時快照

除了手動建立快照之外,Longhorn 還支援定時對 Volume 進行快照處理;要使用定時任務,請進入 Volume 詳情頁面,在

Recurring Snapshot and Backup Schedule

頁籤下新增定時任務即可:

Longhorn 微服務化存儲初探

如果不想為核心 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 微服務化存儲初探

儲存後可以從 Longhorn UI 中看到 Volume 在自動 resize

Longhorn 微服務化存儲初探

重新建立 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/

文章轉載自k8s技術圈。點選這裡閱讀原文了解更多。