与容器服务 ACK 发行版的深度对话最终弹:如何通过 open-local 玩转容器本地存储
記者: 各位阿里巴巴云原生的讀者朋友們大家好,又跟大家見面了。今天是我們的老朋友『阿里云容器服務 ACK 發行版』最后一次做客探究身世之謎系列專欄,在之前的訪談中,它為我們帶來了精彩的講解,感興趣的朋友們歡迎回顧。我們了解到,從去年 12 月上線至今,容器服務 ACK 發行版受到了大家的關注與支持,也取得了不錯的下載量,對此您有什么看法嗎?
阿里云容器服務 ACK 發行版(簡稱ACK Distro): 是的,上線三個月以來有幸獲得 400+的下載量,也通過不同途徑與大家交流技術,感謝大家的關注,希望你們獲得更好的容器服務體驗。
記者: 好的,那讓我們進入正題吧~之前了解到 sealer 可以幫助您快速構建&部署,hybridnet 可以助力構建混合云統一網絡平面,那么今天為我們介紹的是哪位多才多藝的小伙伴呢?
ACK Distro: 我們都知道,云原生背景下有狀態應用需要借助一套存儲方案進行數據持久化保存。本地存儲相比分布式存儲,在成本、易用性、可維護性、IO 性能上都更勝一籌,所以今天給大家講解的就是——阿里巴巴開源的本地存儲管理系統 open-local,以及我是如何借助它玩轉容器本地存儲。先給大家交代一下 open-local 誕生的契機吧,雖然剛才提到本地存儲相較于分布式存儲的優勢,但本地存儲作為目前低成本交付 Kubernetes 集群,是依然存在許多問題的:
? Kubernetes 缺失存儲資源的感知能力: 本地存儲作為一種“非標”資源,在 Kubernetes 中的支持遠低于標準資源(cpu、內存等)。使用本地存儲需要一定的人力成本,如通過為節點打標來限制 Pod 調度、人工管理不同機型的磁盤、人工通過 Hostpath 方式掛載指定磁盤到容器等;同時還有一些私有化軟件現場交付問題,如綁定了錯誤的宿主機路徑使得故障無法及時發現,這些都嚴重影響了 Kubernetes 交付效率以及應用運行時的穩定性;
? 本地存儲空間隔離能力缺失: 應用掛載不適當的宿主機目錄(如掛載到宿主機根路徑)導致宿主機故障,如因應用數據寫滿磁盤導致容器運行時無響應、觸發 Pod 驅逐、Pod 之間 IO 相互影響等問題;
? Kubernetes 對有狀態應用使用本地存儲支持不足: 通過 Hostpath 無法做到節點保持,使得 Pod 漂移后應用數據丟失;使用半自動靜態 Local PV 可保證節點保持,但是無法實現全自動,仍需要人為參與(如創建文件夾路徑,為節點打標等);無法使用一些高級存儲能力(例如快照)。
而 open-local 可以最大程度上避免這些問題,讓大家獲得更好的體驗,在 Kubernetes 上使用本地存儲就像使用集中式存儲一樣簡單。
open-local 的架構組成
記者: 您可以進一步為我們講解下 open-local 的架構組成部分嗎?
ACK Distro: 當然,open-local 一共包含四個組件:
1. scheduler-extender: 作為 kube-scheduler 的擴展組件,通過 Extender 方式實現,擴展了原生調度器對本地存儲資源的感知,以實現對包括磁盤容量、多盤感知、磁盤介質(ssd or hdd)等信息的調度決策,做到存儲資源的混合調度;
2. csi-plugin: 符合 CSI(Container Storage Interface) 標準的本地磁盤管理能力,包含創建/刪除/擴容存儲卷、創建/刪除快照、暴露存儲卷 metrics 等能力;
3. agent: 運行在集群中的每個節點,根據配置清單初始化存儲設備,并通過上報集群中本地存儲設備信息以供 scheduler-extender 決策調度;
4. controller: 獲取集群存儲初始化配置,并向運行在各個節點的 agent 下發詳細的資源配置清單。
同時 open-local 包含兩個 CRD:
它的架構圖可以參照下面:
open-local 的使用場景
記者: 那么什么樣的需求場景下大家會用到 open-local 呢?
ACK Distro: 我總結了以下幾個使用案例,大家可以根據自己的情況對號入座。
如何在 ACK Distro 中使用 open-local
記者: 接下來又到老問題了,open-local 的優勢怎么在您身上體現呢?或者您怎樣使用 open-local 可以達到最佳實踐呢?
ACK Distro: 我分類別為大家講解吧~
1.初始化設置
首先確保環境中已經安裝 lvm 工具,在安裝部署我時會默認安裝 open-local,編輯NodeLocalStorageInitConfig 資源,進行存儲初始化配置。
# kubectl edit nlsc open-local使用 open-local 要求環境中有 VG(VolumeGroup),若您的環境中已存在 VG 且有剩余空間,則可以配置在白名單中;若環境中沒有 VG,您需要提供一個塊設備名稱供 open-local 創建 VG。
apiVersion: csi.aliyun.com/v1alpha1 kind: NodeLocalStorageInitConfig metadata:name: open-local spec:globalConfig: # 全局默認節點配置,初始化創建 NodeLocalStorage 時會填充到其 Spec 中listConfig:vgs:include: # VolumeGroup 白名單,支持正則表達式- open-local-pool-[0-9]+- your-vg-name # 若環境中已有 VG,可以寫入白名單由 open-local 納管resourceToBeInited:vgs:- devices:- /dev/vdc # 若環境中沒有 VG,用戶需提供一個塊設備name: open-local-pool-0 # 將塊設備 /dev/vdc 初始化為名叫 open-local-pool-0 的 VGNodeLocalStorageInitConfig 資源編輯完畢后,controller 和 agent 會更新所有節點的 NodeLocalStorage 資源。
2.存儲卷動態供應
open-local 默認在集群中部署了一些存儲類模板,我以 open-local-lvm、open-local-lvm-xfs 和 open-local-lvm-io-throttling 舉例:
# kubectl get sc NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE open-local-lvm local.csi.aliyun.com Delete WaitForFirstConsumer true 8d open-local-lvm-xfs local.csi.aliyun.com Delete WaitForFirstConsumer true 6h56m open-local-lvm-io-throttling local.csi.aliyun.com Delete WaitForFirstConsumer true創建一個 Statefulset,該 Statefulset 使用 open-local-lvm 存儲類模板。此時創建的存儲卷文件系統為 ext4。若用戶指定 open-local-lvm-xfs 存儲模板,則存儲卷文件系統為 xfs。
# kubectl apply -f https://raw.githubusercontent.com/alibaba/open-local/main/example/lvm/sts-nginx.yaml檢查 Pod/PVC/PV 狀態,可看到存儲卷創建成功:
# kubectl get pod NAME READY STATUS RESTARTS AGE nginx-lvm-0 1/1 Running 0 3m5s # kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE html-nginx-lvm-0 Bound local-52f1bab4-d39b-4cde-abad-6c5963b47761 5Gi RWO open-local-lvm 104s # kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS AGE local-52f1bab4-d39b-4cde-abad-6c5963b47761 5Gi RWO Delete Bound default/html-nginx-lvm-0 open-local-lvm 2m4s kubectl describe pvc html-nginx-lvm-03.存儲卷擴容
編輯對應 PVC 的 spec.resources.requests.storage 字段,將 PVC 聲明的存儲大小從 5Gi 擴容到 20Gi。
# kubectl patch pvc html-nginx-lvm-0 -p '{"spec":{"resources":{"requests":{"storage":"20Gi"}}}}'檢查 PVC/PV 狀態:
# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE html-nginx-lvm-0 Bound local-52f1bab4-d39b-4cde-abad-6c5963b47761 20Gi RWO open-local-lvm 7h4m # kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE local-52f1bab4-d39b-4cde-abad-6c5963b47761 20Gi RWO Delete Bound default/html-nginx-lvm-0 open-local-lvm 7h4m4.存儲卷快照
open-local 有如下快照類:
# kubectl get volumesnapshotclass NAME DRIVER DELETIONPOLICY AGE open-local-lvm local.csi.aliyun.com Delete 20m創建 VolumeSnapshot 資源:
# kubectl apply -f https://raw.githubusercontent.com/alibaba/open-local/main/example/lvm/snapshot.yaml volumesnapshot.snapshot.storage.k8s.io/new-snapshot-test created # kubectl get volumesnapshot NAME READYTOUSE SOURCEPVC SOURCESNAPSHOTCONTENT RESTORESIZE SNAPSHOTCLASS SNAPSHOTCONTENT CREATIONTIME AGE new-snapshot-test true html-nginx-lvm-0 1863 open-local-lvm snapcontent-815def28-8979-408e-86de-1e408033de65 19s 19s # kubectl get volumesnapshotcontent NAME READYTOUSE RESTORESIZE DELETIONPOLICY DRIVER VOLUMESNAPSHOTCLASS VOLUMESNAPSHOT AGE snapcontent-815def28-8979-408e-86de-1e408033de65 true 1863 Delete local.csi.aliyun.com open-local-lvm new-snapshot-test 48s創建一個新 Pod,該 Pod 對應的存儲卷數據與之前應用快照點時刻的數據一致:
# kubectl apply -f https://raw.githubusercontent.com/alibaba/open-local/main/example/lvm/sts-nginx-snap.yaml service/nginx-lvm-snap created statefulset.apps/nginx-lvm-snap created # kubectl get po -l app=nginx-lvm-snap NAME READY STATUS RESTARTS AGE nginx-lvm-snap-0 1/1 Running 0 46s # kubectl get pvc -l app=nginx-lvm-snap NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE html-nginx-lvm-snap-0 Bound local-1c69455d-c50b-422d-a5c0-2eb5c7d0d21b 4Gi RWO open-local-lvm 2m11s5.原生塊設備
open-local 支持創建的存儲卷將以塊設備形式掛載在容器中(本例中塊設備在容器 /dev/sdd 路徑):
# kubectl apply -f https://raw.githubusercontent.com/alibaba/open-local/main/example/lvm/sts-block.yaml檢查 Pod/PVC/PV 狀態:
# kubectl get pod NAME READY STATUS RESTARTS AGE nginx-lvm-block-0 1/1 Running 0 25s # kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE html-nginx-lvm-block-0 Bound local-b048c19a-fe0b-455d-9f25-b23fdef03d8c 5Gi RWO open-local-lvm 36s # kubectl describe pvc html-nginx-lvm-block-0 Name: html-nginx-lvm-block-0 Namespace: default StorageClass: open-local-lvm ... Access Modes: RWO VolumeMode: Block # 以塊設備形式掛載入容器 Mounted By: nginx-lvm-block-0 ...6.IO 限流
open-local 支持為 PV 設置 IO 限流,支持 IO 限流的存儲類模板如下: apiVersion: storage.k8s.io/v1 kind: StorageClass metadata:name: open-local-lvm-io-throttling provisioner: local.csi.aliyun.com parameters:csi.storage.k8s.io/fstype: ext4volumeType: "LVM"bps: "1048576" # 讀寫吞吐量限制在 1024KiB/s 上下iops: "1024" # IOPS 限制在 1024 上下 reclaimPolicy: Delete volumeBindingMode: WaitForFirstConsumer allowVolumeExpansion: true創建一個 Statefulset,該 Statefulset 使用 open-local-lvm-io-throttling 存儲類模板。
# kubectl apply -f https://raw.githubusercontent.com/alibaba/open-local/main/example/lvm/sts-io-throttling.yamlPod 處于 Running 狀態后,進入 Pod 容器中:
# kubectl exec -it test-io-throttling-0 sh此時存儲卷是以原生塊設備掛載在 /dev/sdd 上,執行 fio 命令:
# fio -name=test -filename=/dev/sdd -ioengine=psync -direct=1 -iodepth=1 -thread -bs=16k -rw=readwrite -numjobs=32 -size=1G -runtime=60 -time_based -group_reporting結果如下所示,可見讀寫吞吐量限制在 1024KiB/s 上下:
...... Run status group 0 (all jobs):READ: bw=1024KiB/s (1049kB/s), 1024KiB/s-1024KiB/s (1049kB/s-1049kB/s), io=60.4MiB (63.3MB), run=60406-60406msecWRITE: bw=993KiB/s (1017kB/s), 993KiB/s-993KiB/s (1017kB/s-1017kB/s), io=58.6MiB (61.4MB), run=60406-60406msec Disk stats (read/write):dm-1: ios=3869/3749, merge=0/0, ticks=4848/17833, in_queue=22681, util=6.68%, aggrios=3112/3221, aggrmerge=774/631, aggrticks=3921/13598, aggrin_queue=17396, aggrutil=6.75%vdb: ios=3112/3221, merge=774/631, ticks=3921/13598, in_queue=17396, util=6.75%7.臨時卷
open-local 支持為 Pod 創建臨時卷,其中臨時卷生命周期與 Pod 一致,即 Pod 刪除后臨時卷也隨之刪除。此處可理解為 open-local 版本的 emptydir。
# kubectl apply -f ./example/lvm/ephemeral.yaml其結果如下:
# kubectl describe po file-server Name: file-server Namespace: default ...... Containers:file-server:......Mounts:/srv from webroot (rw)/var/run/secrets/kubernetes.io/serviceaccount from default-token-dns4c (ro) Volumes:webroot: # 此為 CSI 臨時卷Type: CSI (a Container Storage Interface (CSI) volume source)Driver: local.csi.aliyun.comFSType:ReadOnly: falseVolumeAttributes: size=2GivgName=open-local-pool-0default-token-dns4c:Type: Secret (a volume populated by a Secret)SecretName: default-token-dns4cOptional: false8.監控大盤
open-local 自帶了監控大盤,用戶可通過 Grafana 查看集群本地存儲信息,包含存儲設備和存儲卷信息。如下圖所示:
ACK Distro:總而言之,借助 open-local ,在運維方面可減少人力成本,提高集群運行時的穩定性;功能方面,將本地存儲的優勢最大化,使用戶不僅能體驗到本地盤的高性能,同時各種高級存儲特性豐富了應用場景,讓廣大開發者體驗云原生帶來的紅利,實現應用上云尤其是有狀態應用云原生部署關鍵一步。
記者: 感謝 ACK Distro 的精彩講解,這三次的做客讓我們對它和它的小伙伴都有了更深入的了解,也希望訪談內容能為正在閱讀文章的您提供一些幫助。
ACK Distro: 是的,我和項目組成員在 GitHub 社區和社群歡迎大家的“騷擾”!
相關鏈接
[1]open-local 開源倉庫地址:
https://github.com/alibaba/open-local
[2]ACK Distro 官網:
https://www.aliyun.com/product/aliware/ackdistro
[3]ACK Distro 官方 GitHub:
https://github.com/AliyunContainerService/ackdistro
[4]讓創新觸手可及,阿里云容器服務 ACK 發行版開放免費下載:https://mp.weixin.qq.com/s/Lc2afj91sykHMDLUKA_0bw
[5]第一彈深度訪談:
https://mp.weixin.qq.com/s/wB7AS52vEA_VeRegUyrVkA
[6]第二彈深度訪談:
https://mp.weixin.qq.com/s/O095yS5xPtawkh55rvitTg
總結
以上是生活随笔為你收集整理的与容器服务 ACK 发行版的深度对话最终弹:如何通过 open-local 玩转容器本地存储的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中国科协发布 2021 开源创新榜,阿里
- 下一篇: AHPA:开启 Kubernetes 弹