云原生 Kubernetes 分布式存儲平臺 Longhorn 初體驗
前面我們學(xué)習(xí)了本地存儲、NFS共享存儲,除了這些存儲類型之外,還有一個塊存儲,同樣為 Kubernetes 提供塊存儲的方案有很多,比如 Ceph RBD,今天我們?yōu)榇蠹医榻B的是 Rancher 開源的一款 Kubernetes 的云原生分布式塊存儲方案 - Longhorn,Longhorn 是一個輕量級且功能強(qiáng)大的云原生 Kubernetes 分布式存儲平臺,可以在任意基礎(chǔ)設(shè)施上運(yùn)行,Longhorn 還可以與 Rancher 結(jié)合使用,將幫助你在 Kubernetes 環(huán)境中輕松、快速和可靠地部署高可用性持久化塊存儲。
使用 Longhorn,可以:
使用 Longhorn 卷作為 Kubernetes 集群中分布式有狀態(tài)應(yīng)用程序的持久存儲 將你的塊存儲分區(qū)為 Longhorn 卷,以便你可以在有或沒有云提供商的情況下使用 Kubernetes 卷 跨多個節(jié)點(diǎn)和數(shù)據(jù)中心復(fù)制塊存儲以提高可用性 將備份數(shù)據(jù)存儲在 NFS 或 AWS S3 等外部存儲中 創(chuàng)建跨集群災(zāi)難恢復(fù)卷,以便可以從第二個 Kubernetes 集群中的備份中快速恢復(fù)主 Kubernetes 集群中的數(shù)據(jù) 調(diào)度一個卷的快照,并將備份調(diào)度到 NFS 或 S3 兼容的二級存儲 從備份還原卷 不中斷持久卷的情況下升級 Longhorn
Longhorn 還帶有獨(dú)立的 UI,可以使用 Helm、kubectl 或 Rancher 應(yīng)用程序目錄進(jìn)行安裝。
架構(gòu)
Longhorn 為每個卷創(chuàng)建一個專用的存儲控制器,并在多個節(jié)點(diǎn)上存儲的多個副本之間同步復(fù)制該卷。Longhorn 在整體上分為兩層:數(shù)據(jù)平面和控制平面,Longhorn Engine 是存儲控制器,對應(yīng)數(shù)據(jù)平面,Longhorn Manager 對應(yīng)控制平面。
Longhorn Manager 會以 DaemonSet 的形式在 Longhorn 集群中的每個節(jié)點(diǎn)上運(yùn)行,它負(fù)責(zé)在 Kubernetes 集群中創(chuàng)建和管理卷,并處理來自 UI 或 Kubernetes 卷插件的 API 調(diào)用,它是遵循 Kubernetes 控制器模式。
Longhorn Manager 通過與 Kubernetes APIServer 通信來創(chuàng)建新的 Longhorn volume CRD,然后 Longhorn Manager 會一直 Watch APIServer 的響應(yīng),當(dāng)它看到發(fā)現(xiàn)創(chuàng)建了一個新的 Longhorn volume CRD 時,Longhorn Manager 就會去創(chuàng)建一個新的對應(yīng)卷。當(dāng) Longhorn Manager 被要求創(chuàng)建一個卷時,它會在卷所連接的節(jié)點(diǎn)上創(chuàng)建一個 Longhorn Engine 實例,并在每個將放置副本的節(jié)點(diǎn)上創(chuàng)建一個副本,副本應(yīng)放置在不同的主機(jī)上以確保最大可用性。副本的多條數(shù)據(jù)路徑確保了 Longhorn 卷的高可用性,即使某個副本或引擎出現(xiàn)問題,也不會影響所有副本或 Pod 對卷的訪問。
Longhorn Engine 始終與使用 Longhorn 卷的 Pod 在同一節(jié)點(diǎn)中運(yùn)行,它在存儲在多個節(jié)點(diǎn)上的多個副本之間同步復(fù)制卷。
如下圖所示,描述了 Longhorn 卷、Longhorn Engine、副本實例和磁盤之間的讀/寫數(shù)據(jù)流:

上圖中有3個 Longhorn 卷實例 每個卷都有一個專用控制器,稱為 Longhorn Engine,并作為 Linux 進(jìn)程運(yùn)行 每個 Longhorn 卷有兩個副本,每個副本也是一個 Linux 進(jìn)程 圖中的箭頭表示卷、控制器實例、副本實例和磁盤之間的讀/寫數(shù)據(jù)流 通過為每個卷創(chuàng)建單獨(dú)的 Longhorn Engine,如果一個控制器發(fā)生故障,其他卷的功能不會受到影響
注意: 圖中的 Engine 并非是單獨(dú)的一個 Pod,而是每一個 Volume 會對應(yīng)一個 golang exec 出來的 Linux 進(jìn)程
在 Longhorn 中,每個 Engine 只需要服務(wù)一個卷,簡化了存儲控制器的設(shè)計,由于控制器軟件的故障域與單個卷隔離,因此控制器崩潰只會影響一個卷。由于 Longhorn Engine 足夠簡單和輕便,因此我們可以創(chuàng)建多達(dá) 100000 個獨(dú)立的 Engine,Kubernetes 去調(diào)度這些獨(dú)立的 Engine,從一組共享的磁盤中提取資源,并與 Longhorn 合作形成一個彈性的分布式塊存儲系統(tǒng)。
因為每個卷都有自己的控制器,所以每個卷的控制器和副本實例也可以升級,而不會導(dǎo)致 IO 操作明顯中斷。Longhorn 可以創(chuàng)建一個長時間運(yùn)行的 job 任務(wù)來協(xié)調(diào)所有卷的升級,而不會中斷系統(tǒng)的運(yùn)行。
Longhorn 是通過 CSI 驅(qū)動在 Kubernetes 中管理的,CSI 驅(qū)動通過調(diào)用 Longhorn 來創(chuàng)建卷,為 Kubernetes 工作負(fù)載創(chuàng)建持久性數(shù)據(jù),CSI 插件可以讓我們創(chuàng)建、刪除、附加、分離、掛載卷,并對卷進(jìn)行快照操作,Kubernetes 集群內(nèi)部使用 CSI 接口與Longhorn CSI 驅(qū)動進(jìn)行通信,而 Longhorn CSI 驅(qū)動是通過使用 Longhorn API 與 Longhorn Manager 進(jìn)行通信。
此外 Longhorn 還提供一個 UI 界面程序,通過 Longhorn API 與 Longhorn Manager 進(jìn)行交互,通過 Longhorn UI 可以管理快照、備份、節(jié)點(diǎn)和磁盤等,此外,集群工作節(jié)點(diǎn)的空間使用情況還可以通過 Longhorn UI 查看。
安裝
要在 Kubernetes 集群上安裝 Longhorn,需要集群的每個節(jié)點(diǎn)都必須滿足以下要求:
與 Kubernetes 兼容的容器運(yùn)行時(Docker v1.13+、containerd v1.3.7+ 等) Kubernetes v1.18+ 安裝 open-iscsi,并且iscsid守護(hù)程序在所有節(jié)點(diǎn)上運(yùn)行,這是必要的,因為 Longhorn 依賴主機(jī)上的iscsiadm為 Kubernetes 提供持久卷RWX 支持需要每個節(jié)點(diǎn)上都安裝 NFSv4 客戶端 宿主機(jī)文件系統(tǒng)支持 file extents功能來存儲數(shù)據(jù),目前我們支持:ext4 與 XFSbash、curl、findmnt、grep、awk、blkid、lsblk 等工具必須安裝 Mount propagation必須啟用,它允許將一個容器掛載的卷與同一 pod 中的其他容器共享,甚至可以與同一節(jié)點(diǎn)上的其他 pod 共享
Longhorn workloads 必須能夠以 root 身份運(yùn)行才能正確部署和操作 Longhorn。
依賴
為了驗證這些環(huán)境要求,Longhorn 官方提供了一個腳本來幫助我們進(jìn)行檢查,執(zhí)行該腳本需要在本地安裝 jq 工具,執(zhí)行下面的命令即可運(yùn)行腳本:
??curl?-sSfL?https://raw.githubusercontent.com/longhorn/longhorn/v1.2.3/scripts/environment_check.sh?|?bash
daemonset.apps/longhorn-environment-check?created
waiting?for?pods?to?become?ready?(0/2)
waiting?for?pods?to?become?ready?(0/2)
all?pods?ready?(2/2)
??MountPropagation?is?enabled!
cleaning?up...
daemonset.apps?"longhorn-environment-check"?deleted
clean?up?complete
如果沒有檢查通過會給出相關(guān)的提示信息。
要安裝 open-iscsi,可以直接使用下面的命令即可:
#?apt-get?install?open-iscsi??#?Debian?和?Ubuntu?系統(tǒng)命令
??yum?install?-y?iscsi-initiator-utils
Longhorn 官方還為我們還提供了一個 iscsi 安裝程序,可以更輕松地自動安裝 open-iscsi:
??kubectl?apply?-f?https://raw.githubusercontent.com/longhorn/longhorn/v1.2.3/deploy/prerequisite/longhorn-iscsi-installation.yaml
部署完成后,運(yùn)行以下命令來檢查安裝程序的 pod 狀態(tài):
??kubectl?get?pod?|?grep?longhorn-iscsi-installation
longhorn-iscsi-installation-49hd7???1/1?????Running???0??????????21m
longhorn-iscsi-installation-pzb7r???1/1?????Running???0??????????39m
也可以通過以下命令查看日志,查看安裝結(jié)果:
??kubectl?logs?longhorn-iscsi-installation-pzb7r?-c?iscsi-installation
...
Installed:
??iscsi-initiator-utils.x86_64?0:6.2.0.874-7.amzn2
Dependency?Installed:
??iscsi-initiator-utils-iscsiuio.x86_64?0:6.2.0.874-7.amzn2
Complete!
Created?symlink?from?/etc/systemd/system/multi-user.target.wants/iscsid.service?to?/usr/lib/systemd/system/iscsid.service.
iscsi?install?successfully
同樣要安裝 NFSv4 客戶端,可以直接使用下面的命令一鍵安裝:
#?apt-get?install?nfs-common??#??Debian?和?Ubuntu?系統(tǒng)命令
??yum?install?nfs-utils
同樣 Longhorn 官方也提供了一個 nfs 客戶端安裝程序,可以更輕松地自動安裝 nfs-client:
??kubectl?apply?-f?https://raw.githubusercontent.com/longhorn/longhorn/v1.2.3/deploy/prerequisite/longhorn-nfs-installation.yaml
部署完成后,運(yùn)行以下命令來檢查安裝程序的 pod 狀態(tài):
??kubectl?get?pod?|?grep?longhorn-nfs-installation
NAME??????????????????????????????????READY???STATUS????RESTARTS???AGE
longhorn-nfs-installation-t2v9v???1/1?????Running???0??????????143m
longhorn-nfs-installation-7nphm???1/1?????Running???0??????????143m
也可以通過以下命令查看日志,查看安裝結(jié)果:
??kubectl?logs?longhorn-nfs-installation-t2v9v?-c?nfs-installation
...
nfs?install?successfully
相關(guān)依賴環(huán)境準(zhǔn)備好過后就可以開始安裝 Longhorn 了。
部署
官方支持使用 Rancher Catalog 應(yīng)用、kubectl 與 helm 三種方式來進(jìn)行安裝,同樣這里我們選擇使用 helm 進(jìn)行安裝。
首先添加 longhorn 的 chart 倉庫:
??helm?repo?add?longhorn?https://charts.longhorn.io
??helm?repo?update
然后可以根據(jù)自己的實際場景定制 values 文件,可以通過下面的命令獲取默認(rèn)的 values 文件:
??curl?-Lo?values.yaml?https://raw.githubusercontent.com/longhorn/charts/master/charts/longhorn/values.yaml
然后可以修改 values 文件中的配置,longhorn 推薦單獨(dú)掛盤作為存儲使用,這里作為測試直接使用默認(rèn)的 /var/lib/longhorn 目錄。
如下所示默認(rèn)配置的示例片段:
defaultSettings:
??backupTarget:?s3://backupbucket@us-east-1/backupstore
??backupTargetCredentialSecret:?minio-secret
??createDefaultDiskLabeledNodes:?true
??defaultDataPath:?/var/lib/longhorn-example/
??replicaSoftAntiAffinity:?false
??storageOverProvisioningPercentage:?600
??storageMinimalAvailablePercentage:?15
??upgradeChecker:?false
??defaultReplicaCount:?2
??defaultDataLocality:?disabled
??guaranteedEngineCPU:
??defaultLonghornStaticStorageClass:?longhorn-static-example
??backupstorePollInterval:?500
??taintToleration:?key1=value1:NoSchedule;?key2:NoExecute
??systemManagedComponentsNodeSelector:?"label-key1:label-value1"
??priority-class:?high-priority
??autoSalvage:?false
??disableSchedulingOnCordonedNode:?false
??replicaZoneSoftAntiAffinity:?false
??volumeAttachmentRecoveryPolicy:?never
??nodeDownPodDeletionPolicy:?do-nothing
??mkfsExt4Parameters:?-O?^64bit,^metadata_csum
??guaranteed-engine-manager-cpu:?15
??guaranteed-replica-manager-cpu:?15
ingress:??#?開啟ingress
??enabled:?true
??ingressClassName:?nginx??#?配置?ingressclass
??host:?longhorn.k8s.local
??annotations:?#?添加annotations
????nginx.ingress.kubernetes.io/proxy-body-size:?10000m
enablePSP:?false
然后執(zhí)行下面的命令一鍵安裝 Longhorn:
??helm?upgrade?--install?longhorn?longhorn/longhorn?--namespace?longhorn-system?--create-namespace?-f?values.yaml
NAME:?longhorn
LAST?DEPLOYED:?Sun?Feb?20?16:14:05?2022
NAMESPACE:?longhorn-system
STATUS:?deployed
REVISION:?1
TEST?SUITE:?None
NOTES:
Longhorn?is?now?installed?on?the?cluster!
Please?wait?a?few?minutes?for?other?Longhorn?components?such?as?CSI?deployments,?Engine?Images,?and?Instance?Managers?to?be?initialized.
Visit?our?documentation?at?https://longhorn.io/docs/
部署后可以查看 Pod 的運(yùn)行狀態(tài)來確保安裝正確:
??kubectl?get?pods?-n?longhorn-system
NAME????????????????????????????????????????READY???STATUS????RESTARTS???AGE
csi-attacher-5f46994f7-fqntq????????????????1/1?????Running???0??????????33s
csi-attacher-5f46994f7-ltxg8????????????????1/1?????Running???0??????????36m
csi-attacher-5f46994f7-vw75d????????????????1/1?????Running???0??????????36m
csi-provisioner-6ccbfbf86f-bvc99????????????1/1?????Running???0??????????33s
csi-provisioner-6ccbfbf86f-k46hn????????????1/1?????Running???0??????????36m
csi-provisioner-6ccbfbf86f-lxm8h????????????1/1?????Running???0??????????36m
csi-resizer-6dd8bd4c97-52gmm????????????????1/1?????Running???0??????????35m
csi-resizer-6dd8bd4c97-9btj6????????????????1/1?????Running???0??????????3s
csi-resizer-6dd8bd4c97-fdjmp????????????????1/1?????Running???0??????????35m
csi-snapshotter-86f65d8bc-5mjk2?????????????1/1?????Running???0??????????33s
csi-snapshotter-86f65d8bc-5rrfs?????????????1/1?????Running???0??????????35m
csi-snapshotter-86f65d8bc-bg6nv?????????????1/1?????Running???0??????????35m
engine-image-ei-fa2dfbf0-jrb2d??????????????1/1?????Running???0??????????36m
engine-image-ei-fa2dfbf0-m5799??????????????1/1?????Running???0??????????36m
instance-manager-e-051171e6?????????????????1/1?????Running???0??????????36m
instance-manager-e-db94b4b7?????????????????1/1?????Running???0??????????24m
instance-manager-r-dd84ad5c?????????????????1/1?????Running???0??????????36m
instance-manager-r-f5eefb8a?????????????????1/1?????Running???0??????????24m
longhorn-csi-plugin-mljt2???????????????????2/2?????Running???0??????????35m
longhorn-csi-plugin-rfzcj???????????????????2/2?????Running???0??????????24m
longhorn-driver-deployer-6db849975f-dh4p4???1/1?????Running???0??????????58m
longhorn-manager-bxks6??????????????????????1/1?????Running???0??????????24m
longhorn-manager-tj58k??????????????????????1/1?????Running???0??????????2m50s
longhorn-ui-6f547c964-k56xr?????????????????1/1?????Running???0??????????58m
由于上面安裝的時候我們添加了 Ingress 支持,所以可以通過配置的域名去訪問 Longhorn UI:
??kubectl?get?ingress??-n?longhorn-system
NAME???????????????CLASS???HOSTS????????????????ADDRESS?????????PORTS???AGE
longhorn-ingress???nginx???longhorn.k8s.local???192.168.31.31???80??????4m11s
這里我們使用的 ingress-nginx 這個控制器,安裝完成后在瀏覽器中直接訪問 http://longhorn.k8s.local 即可:

Longhorn UI 界面中展示了當(dāng)前存儲系統(tǒng)的狀態(tài),也可以在頁面中進(jìn)行其他相關(guān)配置。
此外還會創(chuàng)建一個默認(rèn)的 StorageClass 對象:
??kubectl?get?sc?longhorn
NAME?????????????????PROVISIONER??????????RECLAIMPOLICY???VOLUMEBINDINGMODE???ALLOWVOLUMEEXPANSION???AGE
longhorn?(default)???driver.longhorn.io???Delete??????????Immediate???????????true???????????????????91m
??kubectl?get?sc?longhorn?-o?yaml
allowVolumeExpansion:?true
apiVersion:?storage.k8s.io/v1
kind:?StorageClass
metadata:
??annotations:
????......
????storageclass.kubernetes.io/is-default-class:?"true"
??creationTimestamp:?"2022-02-20T09:32:51Z"
??......
??name:?longhorn
??resourceVersion:?"4524911"
??uid:?6066e858-e7ab-4dab-95db-7ff829e6e01b
parameters:
??fromBackup:?""
??fsType:?ext4
??numberOfReplicas:?"3"
??staleReplicaTimeout:?"30"
provisioner:?driver.longhorn.io
reclaimPolicy:?Delete
volumeBindingMode:?Immediate
測試
下面我們來測試使用 longhorn 提供一個存儲卷,由于提供了默認(rèn)的 StorageClass,所以直接創(chuàng)建 PVC 即可,創(chuàng)建一個如下所示的 PVC:
apiVersion:?v1
kind:?PersistentVolumeClaim
metadata:
??name:?mysql-pvc
spec:
??storageClassName:?longhorn
??accessModes:
????-?ReadWriteOnce
??resources:
????requests:
??????storage:?1Gi
然后部署一個 mysql 應(yīng)用來使用上面的 PVC 進(jìn)行數(shù)據(jù)持久化:
apiVersion:?apps/v1
kind:?Deployment
metadata:
??name:?mysql
spec:
??selector:
????matchLabels:
??????app:?mysql
??strategy:
????type:?Recreate
??template:
????metadata:
??????labels:
????????app:?mysql
????spec:
??????containers:
??????-?image:?mysql:5.6
????????name:?mysql
????????env:
????????-?name:?MYSQL_ROOT_PASSWORD
??????????value:?password
????????ports:
????????-?containerPort:?3306
??????????name:?mysql
????????volumeMounts:
????????-?name:?data
??????????mountPath:?/var/lib/mysql
??????volumes:
??????-?name:?data
????????persistentVolumeClaim:
??????????claimName:?mysql-pvc
直接創(chuàng)建上面的資源對象:
??kubectl?get?pvc?mysql-pvc
NAME????????STATUS???VOLUME?????????????????????????????????????CAPACITY???ACCESS?MODES???STORAGECLASS???AGE
mysql-pvc???Bound????pvc-ec17a7e4-7bb4-4456-9380-353db3ed4307???1Gi????????RWO????????????longhorn???????8s
??kubectl?get?pods
NAME?????????????????????READY???STATUS????RESTARTS??????AGE
mysql-6879698bd4-r8cxz???1/1?????Running???0?????????????3m10s
??kubectl?exec?-it?mysql-6879698bd4-r8cxz?--?mysql?-uroot?-ppassword
Warning:?Using?a?password?on?the?command?line?interface?can?be?insecure.
Welcome?to?the?MySQL?monitor.??Commands?end?with?;?or?\g.
Your?MySQL?connection?id?is?1
Server?version:?5.6.51?MySQL?Community?Server?(GPL)
Copyright?(c)?2000,?2021,?Oracle?and/or?its?affiliates.?All?rights?reserved.
Oracle?is?a?registered?trademark?of?Oracle?Corporation?and/or?its
affiliates.?Other?names?may?be?trademarks?of?their?respective
owners.
Type?'help;'?or?'\h'?for?help.?Type?'\c'?to?clear?the?current?input?statement.
mysql>?create?database?longhorn;
Query?OK,?1?row?affected?(0.01?sec)
mysql>
應(yīng)用啟動成功后我們可以去節(jié)點(diǎn)上查看數(shù)據(jù)來驗證是否成功:
??ls?/var/lib/longhorn/
engine-binaries??longhorn-disk.cfg??replicas
??ls?/var/lib/longhorn/replicas/
pvc-ec17a7e4-7bb4-4456-9380-353db3ed4307-c40376c5
??ls?/var/lib/longhorn/replicas/pvc-ec17a7e4-7bb4-4456-9380-353db3ed4307-c40376c5
revision.counter??volume-head-000.img??volume-head-000.img.meta??volume.meta
需要注意的是 longhorn 是分布式塊存儲,與分布式文件系統(tǒng)不同,不能超過 pv 設(shè)置的存儲大小(上例中為1G)。我們在數(shù)據(jù)庫中創(chuàng)建了一個名為 longhorn 的數(shù)據(jù)庫,然后我們重建 Pod 再次查看數(shù)據(jù)是否依然存在:
??kubectl?get?pods
NAME?????????????????????READY???STATUS????RESTARTS??????AGE
mysql-6879698bd4-s8tfv???1/1?????Running???0?????????????6s
???kubectl?exec?-it?mysql-6879698bd4-s8tfv?--?mysql?-uroot?-ppassword
Warning:?Using?a?password?on?the?command?line?interface?can?be?insecure.
Welcome?to?the?MySQL?monitor.??Commands?end?with?;?or?\g.
Your?MySQL?connection?id?is?1
Server?version:?5.6.51?MySQL?Community?Server?(GPL)
Copyright?(c)?2000,?2021,?Oracle?and/or?its?affiliates.?All?rights?reserved.
Oracle?is?a?registered?trademark?of?Oracle?Corporation?and/or?its
affiliates.?Other?names?may?be?trademarks?of?their?respective
owners.
Type?'help;'?or?'\h'?for?help.?Type?'\c'?to?clear?the?current?input?statement.
mysql>?show?databases;
+---------------------+
|?Database????????????|
+---------------------+
|?information_schema??|
|?longhorn????????????|
|?#mysql50#lost+found?|
|?mysql???????????????|
|?performance_schema??|
+---------------------+
5?rows?in?set?(0.00?sec)
mysql>
可以看到前面創(chuàng)建的數(shù)據(jù)庫依然存在,證明我們的數(shù)據(jù)持久化成功了。在 Longhorn UI 界面中也可以看到數(shù)據(jù)卷的信息:

關(guān)于 Longhorn 的高級特性請關(guān)注后續(xù)文章。
原文鏈接:https://kube100.com/d/6-longhorn
