记者: 各位阿里巴巴云原生的读者朋友们咱们好,又跟咱们见面了。今日是咱们的老朋友『阿里云容器服务 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:

  1. NodeLocalStorage:open-local 经过 NodeLocalStorage 资源上报每个节点上的存储设备信息,该资源由 controller 创立,由每个节点的 agent 组件更新其 status。该 CRD 属于大局范围的资源。
  2. NodeLocalStorageInitConfig:open-local controller 可经过 NodeLocalStorageInitConfig 资源创立每个 NodeLocalStorage 资源。NodeLocalStorageInitConfig 资源中包括大局默许节点装备和特定节点装备,若节点的 node label 满足表达式则运用特定节点装备,不然运用默许装备。

它的架构图能够参照下面:

与容器服务 ACK 发行版的深度对话最终弹:如何通过 open-local 玩转容器本地存储

open-local 的运用场景

记者: 那么什么样的需求场景下咱们会用到 open-local 呢?

ACK Distro: 我总结了以下几个运用案例,咱们能够依据自己的状况对号入座。

  1. 运用期望数据卷具有容量阻隔才能,防止呈现诸如日志打满体系盘的状况;
  2. 运用需求大量本地存储并依靠节点坚持,如 Hbase、etcd、ZooKeeper、ElasticSearch 等;
  3. 集群本地磁盘数量很多,期望经过调度器完成有状况运用的自动化布置;
  4. 经过存储快照才能为数据库类运用备份瞬时数据等。

如安在 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 的 VG

NodeLocalStorageInitConfig 资源修改完毕后,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-0

3.存储卷扩容

修改对应 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            7h4m

4.存储卷快照

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   2m11s

5.原生块设备

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: ext4
  volumeType: "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.yaml

Pod 处于 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-60406msec
  WRITE: 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.com
    FSType:
    ReadOnly:          false
    VolumeAttributes:      size=2Gi
                           vgName=open-local-pool-0
  default-token-dns4c:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-dns4c
    Optional:    false

8.监控大盘

open-local 自带了监控大盘,用户可经过 Grafana 检查集群本地存储信息,包括存储设备和存储卷信息。如下图所示:

ACK Distro:总而言之,凭借 open-local ,在运维方面可减少人力成本,进步集群运行时的稳定性;功能方面,将本地存储的优势最大化,运用户不仅能体会到本地盘的高性能,一起各种高档存储特性丰厚了运用场景,让广阔开发者体会云原生带来的盈利,完成运用上云尤其是有状况运用云原生布置要害一步。

记者: 感谢 ACK Distro 的精彩解说,这三次的做客让咱们对它和它的小伙伴都有了更深化的了解,也期望访谈内容能为正在阅读文章的您供给一些协助。

ACK Distro: 是的,我和项目组成员在 GitHub 社区和社群欢迎咱们的“骚扰”!

相关链接

[1]open-local 开源库房地址: github.com/alibaba/ope… [2]ACK Distro 官网: www.aliyun.com/product/ali… [3]ACK Distro 官方 GitHub: github.com/AliyunConta… [4]让创新触手可及,阿里云容器服务 ACK 发行版敞开免费下载:mp.weixin.qq.com/s/Lc2afj91s… [5]第一弹深度访谈: mp.weixin.qq.com/s/wB7AS52vE… [6]第二弹深度访谈: mp.weixin.qq.com/s/O095yS5xP…