淘先锋技术网

首页 1 2 3 4 5 6 7

piraeus简介

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

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数据块复制技术来实现本地卷可高用。

在这里插入图片描述
Piraeus Datastore 在数据平面使用著名的 Distributed Replicated Block Device (以下简称 DRBD )开源技术。DRBD 是 Linux 里的块设备跨主机复制软件,由奥地利工程师 Philipp Reisner 于 2000 年创立。2009 年 Linus Torvalds 亲自审核 DRBD 技术,并将其整合到 Linux 内核中作为 Linux 的标准组件之一。

之后,DRBD 不断演进和完善,在企业级的关键业务中得到了广泛的应用和大量的验证,成为 Linux 开源社区里最成熟的块数据同步技术。2019 年 11 月 18 日,在美国圣地亚哥的 KubeCon 大会上,Piraeus Datastore 正式发布。

左四(Philipp Reisner)
在这里插入图片描述

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

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

在这里插入图片描述

Piraeus 与其他存储对比

Piraeus vs. 专业NAS

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

Piraeus vs. 本地盘

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

和同类别项目对比

存储技术数据技术数据同步技术开源商业许可
PiraeusLVM, ZvolLinux 内核原生 DRBD 技术开源自主掌控 和代码作者合作
LonghornSparse file自研未知开源属于 Rancher
Rook(ceph)Sparse fileCeph开源属于 Redhat
PortworxBtrfs商业自研纯商业属于 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 副本卷,这也取得了非常令人满意的结果。

在这里插入图片描述

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

所有节点配置内核参数

下载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 - <<EOF
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 - <<EOF
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 - <<EOF
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 - <<EOF
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 服务器创建一个部署,从我们的卷中提供文件。

注意:piraeus仅支持 strategy.type: Recreate策略。

$ kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: volume-logger
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: volume-logger
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app.kubernetes.io/name: volume-logger
    spec:
      terminationGracePeriodSeconds: 0
      containers:
        - name: volume-logger
          image: busybox
          args:
            - sh
            - -c
            - |
              echo "Hello from \$HOSTNAME, running on \$NODENAME, started at \$(date)" >> /volume/hello
              # We use this to keep the Pod running
              tail -f /dev/null
          env:
            - name: NODENAME
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
          volumeMounts:
            - mountPath: /volume
              name: data-volume
      volumes:
        - name: data-volume
          persistentVolumeClaim:
            claimName: data-volume
EOF

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

root@node1:~# kubectl wait pod --for=condition=Ready -l app.kubernetes.io/name=volume-logger
pod/volume-logger-cbcd897b7-tm8rr condition met

root@node1:~# kubectl get persistentvolumeclaim
NAME          STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS      AGE
data-volume   Bound    pvc-9599f79e-d825-4550-b044-5c577f1f0020   1Gi        RWO            piraeus-storage   112s

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-9599f79e-d825-4550-b044-5c577f1f0020 | pool1                |     0 |    1004 | /dev/drbd1004 | 32.91 MiB | InUse  |   UpToDate |
| node2 | pvc-9599f79e-d825-4550-b044-5c577f1f0020 | pool1                |     0 |    1004 | /dev/drbd1004 |   932 KiB | Unused |   UpToDate |
| node3 | pvc-9599f79e-d825-4550-b044-5c577f1f0020 | DfltDisklessStorPool |     0 |    1004 | /dev/drbd1004 |           | Unused | TieBreaker |
+---------------------------------------------------------------------------------------------------------------------------------------------+

通过在 Pod 中读取来检查我们的 Pod 是否实际记录了预期的信息:

root@node1:~# kubectl exec deploy/volume-logger -- cat /volume/hello
Hello from volume-logger-cbcd897b7-tm8rr, running on node1, started at Thu Aug 10 08:21:06 UTC 2023

测试复制

现在将验证将 Pod 移动到另一个节点时,我们仍然可以访问相同的数据。

为了测试这一点,将禁用 Pod 当前运行的节点上的调度。一旦我们触发重启,这就会迫使 Kubernetes 将 Pod 移动到另一个节点。在本示例中,Hello 消息告诉我们 Pod 是在 node1 上启动的,因此这是我们禁用的节点。将名称替换为您自己的节点名称。

root@node1:~# kubectl cordon node1
node/node1 cordoned

现在,以触发新的部署。由于禁用了node1节点调度,另一个节点将不得不接管 Pod。

root@node1:~# kubectl rollout restart deploy/volume-logger
deployment.apps/volume-logger restarted

root@node1:~# kubectl wait pod --for=condition=Ready -l app.kubernetes.io/name=volume-logger
pod/volume-logger-649f8df755-v5km9 condition met

root@node1:~# kubectl get pods -owide
NAME                             READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
volume-logger-649f8df755-v5km9   1/1     Running   0          45s   100.64.2.240   node3   <none>           <none>

正如预期的那样,Pod 现在在不同的节点上运行,在本例中是在node3.

现在,可以验证来自原始 pod 的消息是否仍然存在:

root@node1:~# kubectl exec deploy/volume-logger -- cat /volume/hello
Hello from volume-logger-cbcd897b7-tm8rr, running on node1, started at Thu Aug 10 08:21:06 UTC 2023
Hello from volume-logger-649f8df755-v5km9, running on node3, started at Thu Aug 10 08:26:56 UTC 2023

正如预期的那样,仍然可以看到来自 node1 的消息,以及来自 node2 上新 Pod 的消息。

还可以看到 LINSTOR 现在显示新节点上的InUse卷:

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-9599f79e-d825-4550-b044-5c577f1f0020 | pool1                |     0 |    1004 | /dev/drbd1004 | 32.91 MiB | Unused | UpToDate |
| node2 | pvc-9599f79e-d825-4550-b044-5c577f1f0020 | pool1                |     0 |    1004 | /dev/drbd1004 |   944 KiB | Unused | UpToDate |
| node3 | pvc-9599f79e-d825-4550-b044-5c577f1f0020 | DfltDisklessStorPool |     0 |    1004 | /dev/drbd1004 |           | InUse  | Diskless |
+-------------------------------------------------------------------------------------------------------------------------------------------+

现在已成功创建复制卷并验证数据是否可从多个节点访问。

重置启用节点,现在我们已经验证了复制工作,我们可以重置禁用的节点:

root@node1:~#  kubectl uncordon node1
node/node1 uncordoned

我们现在已经成功设置了 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    ┊            ┊
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯