kubernetes高性能存储-piraeus简介

piraeus简介

Piraeus 是面向 Kubernetes 的高性能、高可用性、简单、安全且与云无关的云原生存储解决方案,号称性能和稳定性都优于 Ceph/OpenEBS/Longhorn 等项目。Piraeus 对应的商业产品为LINSTOR 。

众所周知,本地存储具有高性能的优势,但它将应用程序绑定到特定节点,从而使应用程序难以调度,如果该节点或本地卷遇到故障并变得不可访问,则该容器也将变得不可访问。有了piraeus的加持,使高性能的本地存储同时具备高可用的能力,在kubernetes集群中运行数据库、大数据等对性能要求高的有状态应用不再令人望而生畏。

Piraeus 项目成长路径:

  • 2019 年 5 月由浦发银行、DaoCloud 道客联合奥地利 LINBIT 公司共同孵化,致力于为 Kubernetes
    的本地持久卷实现全局管理,动态分配,高可用,和压缩备份等企业级功能。
  • 2020 年 7 月在 KuberCon China 被首次分享。
  • 2021 年 1 月通过 CNCF TOC 投票入选云原生计算基金会(CNCF)Sandbox 项目。
  • 2021 年 5 月注册成为LF/CNCF 资产,并在 2021 年7 月世界人工智能大会上正式宣布被 CNCF 接纳为沙盒项目。

官方网站:https://piraeus.io/
项目地址:https://github.com/piraeusdatastore/piraeus

Piraeus核心技术为基于操作系统内核的DRBD数据块复制技术来实现本地卷可高用。
kubernetes高性能存储-piraeus简介_第1张图片

Piraeus 项目能够具备高可用,高性能,丰富的企业级存储特性,有以下原因:

  • 复用成熟的 Linux 内核 Distributed Replicated Block Device (分布式复制块,简称 DRBD) 数据技术,没有新写的数据层
  • 邀请 DRBD 作者 Phil Reisner 亲自督导
  • 控制流和数据流完全分离
  • 100% 开源, Apache 开源许可,支持商业开发
  • DaoCloud 道客 和 LINBIT 合作提供企业级技术支持
  • 性能和稳定性都优于 Ceph/OpenEBS/Longhorn等项目

Piraeus 与其他存储对比

Piraeus vs. 专业NAS

特点 Piraeus NAS
动态分配
数据隔离 块级别 无 (都在一个母路径下)
OLTP数据库小IO性能
本地数据访问
易用性 K8S集群内即插即用 购买专业NAS设备
成本
延展度 高(和k8s节点数匹配)

Piraeus vs. 本地盘

特点 Piraeus 本地盘
动态分配
数据多节点高可用 单点故障
数据远程访问
数据隔离 块级别 无 (都在一个母路径下)
安全性 差(暴露OS路径给租户)
容量管理
超量分配(thin)
快照克隆
压缩去冗

和同类别项目对比

存储技术 数据技术 数据同步技术 开源 商业许可
Piraeus LVM, Zvol Linux 内核原生 DRBD 技术 开源 自主掌控 和代码作者合作
Longhorn Sparse file 自研未知 开源 属于 Rancher
Rook(ceph) Sparse file Ceph 开源 属于 Redhat
Portworx Btrfs 商业自研 纯商业 属于 PureStorage

Piraeus 案例

博客链接:https://piraeus.io/site/blog/

传统的大数据平台是一种保存大量数据并对其进行流式计算的基础设施。典型的大数据平台包括Hadoop、Spark、Flume、Flink、Kafka等组件。这些组件的容器化和编排催生了云原生大数据平台。

在研究了Cloudera CDP等主流大数据平台,充分了解采用云原生工作流程的优势和挑战后,浦发银行认识到存储技术是云原生大数据平台建设成功的关键。为此,浦发银行与合作伙伴合作开展云原生存储项目Piraeus Datastore的研究和实验,最终浦发银行的工程师采用了Piraeus云原生存储,并将其应用到大数据生产中。

Piraeus 数据卷是块设备,使用 ext4 或 xfs 文件系统本地安装。Piraeus Kubernetes-CSI 驱动程序和 DRBD Transport 远程挂载技术使容器能够从集群中的任何节点访问数据卷。Piraeus多副本卷采用DRBD同步复制技术,在保证高可用性的同时,提供堪比本地磁盘的高吞吐量和低延迟。

在成功使用 Piraeus 支持节点管理器后,还配置了 MySQL 容器来挂载 Piraeus 副本卷,这也取得了非常令人满意的结果。

kubernetes高性能存储-piraeus简介_第2张图片

piraeus-operator部署

项目地址:https://github.com/piraeusdatastore/piraeus-operator

准备1至多个kubernetes节点,这里以3个节点为例,测试场景下节点无需挂盘等额外任何操作。

root@node1:~# kubectl get nodes -o wide
NAME    STATUS   ROLES           AGE    VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
node1   Ready    control-plane   7d4h   v1.26.7   192.168.72.30   <none>        Ubuntu 22.04.2 LTS   5.15.0-78-generic   containerd://1.6.22
node2   Ready    control-plane   7d4h   v1.26.7   192.168.72.31   <none>        Ubuntu 22.04.2 LTS   5.15.0-78-generic   containerd://1.6.22
node3   Ready    control-plane   7d4h   v1.26.7   192.168.72.32   <none>        Ubuntu 22.04.2 LTS   5.15.0-78-generic   containerd://1.6.22

所有节点配置内核参数

echo fs.inotify.max_user_instances=8192 | tee -a /etc/sysctl.conf && sudo sysctl -p

下载helm chart

wget https://github.com/piraeusdatastore/piraeus-operator/archive/refs/tags/v2.1.1.tar.gz
tar -zxvf v2.1.1.tar.gz
cd piraeus-operator-2.1.1/charts/

使用helm安装piraeus-operator

helm upgrade --install piraeus-operator ./piraeus \
--create-namespace -n piraeus-datastore \
--set installCRDs=true

查看部署的pods

root@node1:~# kubectl -n piraeus-datastore get pods 
NAME                                                    READY   STATUS        RESTARTS   AGE
piraeus-datastore-controller-manager-6f6b8f48c4-st7zb   2/2     Running       0          14m

部署Piraeus数据存储

创建storage cluster

$ kubectl apply -f - <apiVersion: piraeus.io/v1
kind: LinstorCluster
metadata:
  name: linstorcluster
spec: {}
EOF

查看部署的pods

root@node1:~# kubectl -n piraeus-datastore get pods 
NAME                                                   READY   STATUS    RESTARTS   AGE
ha-controller-bmz2w                                    1/1     Running   0          66s
ha-controller-rn54t                                    1/1     Running   0          66s
ha-controller-x6sh9                                    1/1     Running   0          66s
linstor-controller-97cd7495c-rqgzd                     1/1     Running   0          67s
linstor-csi-controller-7f85967cd9-8dq7t                7/7     Running   0          67s
linstor-csi-node-dxpc4                                 3/3     Running   0          67s
linstor-csi-node-p9f62                                 3/3     Running   0          67s
linstor-csi-node-q8dwv                                 3/3     Running   0          67s
node1                                                  2/2     Running   0          59s
node2                                                  2/2     Running   0          66s
node3                                                  2/2     Running   0          65s
piraeus-operator-controller-manager-6f8974c495-fk5ql   2/2     Running   0          2m2s

使用linstor客户端检查已部署的 LINSTOR集群的状态:

root@node1:~# kubectl -n piraeus-datastore exec deploy/linstor-controller -- linstor node list
+--------------------------------------------------------+
| Node  | NodeType  | Addresses                 | State  |
|========================================================|
| node1 | SATELLITE | 100.64.0.82:3366 (PLAIN)  | Online |
| node2 | SATELLITE | 100.64.1.173:3366 (PLAIN) | Online |
| node3 | SATELLITE | 100.64.2.178:3366 (PLAIN) | Online |
+--------------------------------------------------------+

配置存储

我们尚未为卷配置任何存储位置。这可以通过创建LinstorSatelliteConfiguration新资源来完成 。

查看支持的存储池类型:

kubectl explain linstorsatelliteconfigurations.spec.storagePools

支持的存储池类型如下

  • filePool 配置基于文件系统的存储池,为每个卷分配一个常规文件
  • fileThinPool 配置基于文件系统的存储池,为每个卷分配稀疏文件
  • lvmPool 将LVM卷组配置为存储池
  • lvmThinPool 将LVM精简池配置为存储池。

我们将在每个节点上创建一个fileThinPool type 的存储池。我们选择fileThinPool它是因为它不需要在主机上进行进一步配置,直接使用根磁盘路径,无需额外准备磁盘。

$ kubectl apply -f - <apiVersion: piraeus.io/v1
kind: LinstorSatelliteConfiguration
metadata:
  name: storage-pool
spec:
  storagePools:
    - name: pool1
      fileThinPool:
        directory: /var/lib/piraeus-datastore/pool1
EOF

这将导致一些 Pod 被重新创建。发生这种情况时linstor node list会暂时显示节点离线,再等一会儿,节点又会出现Online。一旦节点再次连接,我们就可以验证存储池是否已配置:

root@node1:~# kubectl -n piraeus-datastore exec deploy/linstor-controller -- linstor storage-pool list
+------------------------------------------------------------------------------------------------------------------------------------------------+
| StoragePool          | Node  | Driver    | PoolName                         | FreeCapacity | TotalCapacity | CanSnapshots | State | SharedName |
|================================================================================================================================================|
| DfltDisklessStorPool | node1 | DISKLESS  |                                  |              |               | False        | Ok    |            |
| DfltDisklessStorPool | node2 | DISKLESS  |                                  |              |               | False        | Ok    |            |
| DfltDisklessStorPool | node3 | DISKLESS  |                                  |              |               | False        | Ok    |            |
| pool1                | node1 | FILE_THIN | /var/lib/piraeus-datastore/pool1 |    23.17 GiB |     96.90 GiB | True         | Ok    |            |
| pool1                | node2 | FILE_THIN | /var/lib/piraeus-datastore/pool1 |    72.38 GiB |     96.90 GiB | True         | Ok    |            |
| pool1                | node3 | FILE_THIN | /var/lib/piraeus-datastore/pool1 |    70.57 GiB |     96.90 GiB | True         | Ok    |            |
+------------------------------------------------------------------------------------------------------------------------------------------------+

使用Piraeus Datastore

支持的所有参数:https://linbit.com/drbd-user-guide/linstor-guide-1_0-en/#s-kubernetes-sc-parameters

我们现在已经成功部署和配置了 Piraeus 数据存储,并准备 PersistentVolume在 Kubernetes 中创建我们的第一个数据存储。

首先,我们将为我们的卷设置一个新的StorageClass。在StorageClass 中,我们指定上面的存储池:

$ kubectl apply -f - <apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: piraeus-storage
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: linstor.csi.linbit.com
allowVolumeExpansion: true
volumeBindingMode: WaitForFirstConsumer
parameters:
  linstor.csi.linbit.com/placementCount: "2"
  linstor.csi.linbit.com/storagePool: pool1
  csi.storage.k8s.io/fstype: xfs
EOF

参数说明:

  • placementCount: 支持1/2/3副本,默认为1
  • fstype:支持ext4和xfs,默认为ext4

查看创建的storageclass

root@node1:~# kubectl get sc
NAME                        PROVISIONER              RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
piraeus-storage (default)   linstor.csi.linbit.com   Delete          WaitForFirstConsumer   true                   16s

接下来,我们将创建一个PersistentVolumeClaim,从新创建的StorageClass 中请求 1G 的存储空间。

$ kubectl apply -f - <apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data-volume
spec:
  storageClassName: piraeus-storage
  resources:
    requests:
      storage: 1Gi
  accessModes:
    - ReadWriteOnce
EOF

当我们检查创建的 PersistentVolumeClaim 时,我们可以看到它仍然处于Pending状态。

$ kubectl get persistentvolumeclaim
NAME          STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS      AGE
data-volume   Pending                                      piraeus-storage   14s

首先需要创建一个“消费者”,在本例中只是一个Pod. 对于我们的消费者,我们将为一个简单的 Web 服务器创建一个部署,从我们的卷中提供文件。

$ kubectl apply -f - <apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: web-server
  template:
    metadata:
      labels:
        app.kubernetes.io/name: web-server
    spec:
      containers:
        - name: web-server
          image: nginx
          volumeMounts:
            - mountPath: /usr/share/nginx/html
              name: data
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: data-volume
EOF

短暂等待后,Pod 已完成Running,我们的PersistentVolumeClaim现在已完成Bound

$ kubectl wait pod --for=condition=Ready -l app.kubernetes.io/name=web-server
pod/web-server-84867b5449-hgdzx condition met

$ kubectl get persistentvolumeclaim
NAME          STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS      AGE
data-volume   Bound    pvc-9e1149e7-33db-47a7-8fc6-172514422143   1Gi        RWO            piraeus-storage   1m

检查正在运行的容器,我们看到该卷已安装在我们预期的位置:

$ kubectl exec deploy/web-server -- df -h /usr/share/nginx/html
Filesystem      Size  Used Avail Use% Mounted on
/dev/drbd1000   973M   24K  906M   1% /usr/share/nginx/html

查看客户端linstor,我们可以看到该卷已在 LINSTOR 中列出并由InUsePod 标记为。经过短暂的等待,可以看到 LINSTOR 将卷放在两个节点上,当一个节点故障后,pod会调度到第二个节点并挂载卷:

root@node1:~# kubectl -n piraeus-datastore exec deploy/linstor-controller -- linstor resource list-volumes
+---------------------------------------------------------------------------------------------------------------------------------------------+
| Node  | Resource                                 | StoragePool          | VolNr | MinorNr | DeviceName    | Allocated | InUse  |      State |
|=============================================================================================================================================|
| node1 | pvc-62bdaf29-188f-4e88-9c04-db7b7f6cca95 | DfltDisklessStorPool |     0 |    1000 | /dev/drbd1000 |           | Unused | TieBreaker |
| node2 | pvc-62bdaf29-188f-4e88-9c04-db7b7f6cca95 | pool1                |     0 |    1000 | /dev/drbd1000 | 10.58 MiB | InUse  |   UpToDate |
| node3 | pvc-62bdaf29-188f-4e88-9c04-db7b7f6cca95 | pool1                |     0 |    1000 | /dev/drbd1000 |  2.39 MiB | Unused |   UpToDate |
+---------------------------------------------------------------------------------------------------------------------------------------------+

我们现在已经成功设置了 Piraeus 数据存储,并使用它在 Kubernetes 集群中配置持久卷。

kubectl-linstor安装

kubectl-linstor是一个通过 kubectl 命令行执行 LINSTOR 命令的插件。要使用 kubectl linstor 需要使用Piraeus Operator。

wget https://github.com/piraeusdatastore/kubectl-linstor/releases/download/v0.2.1/kubectl-linstor-v0.2.1-linux-amd64.tar.gz
tar -zxvf kubectl-linstor-v0.2.1-linux-amd64.tar.gz kubectl-linstor
mv kubectl-linstor /usr/local/bin/
chmod +x /usr/local/bin/kubectl-linstor

查看节点

root@node1:~# kubectl linstor node list
╭────────────────────────────────────────────────────────╮
┊ Node  ┊ NodeType  ┊ Addresses                 ┊ State  ┊
╞════════════════════════════════════════════════════════╡
┊ node1 ┊ SATELLITE ┊ 100.64.0.83:3366 (PLAIN)  ┊ Online ┊
┊ node2 ┊ SATELLITE ┊ 100.64.1.175:3366 (PLAIN) ┊ Online ┊
┊ node3 ┊ SATELLITE ┊ 100.64.2.179:3366 (PLAIN) ┊ Online ┊
╰────────────────────────────────────────────────────────╯

查看存储池

root@node1:~# kubectl linstor storage-pool list
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
┊ StoragePool          ┊ Node  ┊ Driver    ┊ PoolName                         ┊ FreeCapacity ┊ TotalCapacity ┊ CanSnapshots ┊ State ┊ SharedName ┊
╞════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╡
┊ DfltDisklessStorPool ┊ node1 ┊ DISKLESS  ┊                                  ┊              ┊               ┊ False        ┊ Ok    ┊            ┊
┊ DfltDisklessStorPool ┊ node2 ┊ DISKLESS  ┊                                  ┊              ┊               ┊ False        ┊ Ok    ┊            ┊
┊ DfltDisklessStorPool ┊ node3 ┊ DISKLESS  ┊                                  ┊              ┊               ┊ False        ┊ Ok    ┊            ┊
┊ pool1                ┊ node1 ┊ FILE_THIN ┊ /var/lib/piraeus-datastore/pool1 ┊    23.14 GiB ┊     96.90 GiB ┊ True         ┊ Ok    ┊            ┊
┊ pool1                ┊ node2 ┊ FILE_THIN ┊ /var/lib/piraeus-datastore/pool1 ┊    72.24 GiB ┊     96.90 GiB ┊ True         ┊ Ok    ┊            ┊
┊ pool1                ┊ node3 ┊ FILE_THIN ┊ /var/lib/piraeus-datastore/pool1 ┊    70.45 GiB ┊     96.90 GiB ┊ True         ┊ Ok    ┊            ┊
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

你可能感兴趣的:(kubernetes,storage,kubernetes,容器,云原生)