侵权投诉

评估K8s可用的最常见的存储解决方案

存储加速器 ? 2021-01-03 10:37 ? 次阅读

如果你正在运行K8s,其中最大的难题之一是如何为k8s集群选择正确的存储技术,你可能会考虑使用通过动态预配置的块存储。实际上,这很大程度上取决于您要运行的工作负载的类型。本篇文章的目标主要是评估K8s可用的最常见的存储解决方案,并进行基本性能测试

目前CNCF的存储格局和解决方案已经更新,它已从2019年的30个解决方案增长到目前的45个解决方案,还进行了公共云集成的管理扩展,例如AWS EBS,Google永久磁盘或Azure磁盘存储。一些新解决方案像Alluxio一样,更侧重于分布式文件系统或对象存储。

本文的目标是采用K8s可用的最常见的存储解决方案,并准备基本的性能比较。文章使用以下后端在Azure AKS上执行所有测试:

  • AKS native storage class — Azure native premium

  • AWS cloud volume mapped into instance — Azure hostPath with attached Azure managed disk

  • OpenEBS with cStor backend

  • OpenEBS MayaStor

  • Portworx

  • Gluster managed by Heketi

  • Ceph managed by Rook

  • Longhorn

相比于19年的存储方案,GlusterFS Heketi在性能结果上排名倒数第二,它的改进为零,并且大多数情况下是一个沉寂的项目(Heketi作为REST协调器而不是GlusterFS本身)。如果查看它们的官方GitHub,您会发现他们近乎将其置于维护模式,并且云本地存储功能没有任何更新。

另外根据GIGAOM 2020报告, PortWorx仍然是K8s的顶级商业存储解决方案。但是,从性能的角度来看,版本2.0和2.5之间的发行说明中并没有重大的技术或体系结构更改。最好的开源存储,是通过Rook精心策划的CEPH,他发布了2个新版本,并推出了一个新的CEPH版本,称为Octopus。Octopus对缓存机制进行了一些优化,并使用了更现代的内核接口。今年唯一的主要体系结构更改发生在OpenEBS中,它引入了一个称为MayaStor的新后端。这个后端看起来非常有前途。这些k8s常用的解决方案性能到底怎么样了?我们一起来看下。

本机Azure存储

之所以选择该存储类,是为了获得所有测试的基准。此存储类应提供最佳性能。Azure动态创建托管磁盘,并将其映射到具有k8s作为Pod卷的VM。

81534c9c-4655-11eb-8b86-12bb97331649.png

无需使用任何特殊功能。当您配置新的AKS群集时,将自动预定义2个存储类,分别称为“默认”和“高级托管”。高级类对卷使用基于SSD的高性能和低延迟磁盘。

优点

  • AKS上的默认设置无需执行任何操作。

缺点

  • 故障转移情况下非常慢,有时需要将近10分钟才能将卷重新连接到其他节点上的Pod。

$ kubectl get storageclassesNAME                PROVISIONER                AGEdefault (default)   kubernetes.io/azure-disk   8mmanaged-premium     kubernetes.io/azure-disk   8m
$ kubectl get pvcNAME              STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS      AGEdbench-pv-claim   Bound     pvc-e7bd34a4-1dbd-11e9-8726-ae508476e8ad   1000Gi     RWO            managed-premium   10s
$ kubectl get poNAME           READY     STATUS              RESTARTS   AGEdbench-w7nqf0/1ContainerCreating029s

OpenEBS

OpenEBS代表了新的容器附加存储(CAS)概念,其中是单个基于微服务的存储控制器和多个基于微服务的存储副本。它与Portworx一起属于云本机存储类别。

81d4be9e-4655-11eb-8b86-12bb97331649.png

它是完全开源的,目前提供2个后端,分别是Jiva和cStor。我从Jiva开始,然后切换到cStor。cStor进行了一些改进,因为控制器及其副本部署在单个名称空间(安装openebs的名称空间)中,或者它使用原始磁盘而不是格式化分区。每个k8s卷都有其自己的存储控制器,该存储可以在节点上可用存储容量的允许范围内进行扩展。

如何在AKS上获取它?在AKS上安装其实非常容易。

1.我必须连接到所有k8s节点的控制台并安装iSCSI,因为它使用iSCSI协议在Pod和存储控制器与k8s节点之间进行连接。

apt-get updateapt install -y open-iscsi

2.然后,我将单个YAML定义应用于我的k8s集群

kubectl apply -f https://openebs.github.io/charts/openebs-operator-0.8.0.yaml

3.下一步,OpenEBS控制器在底层节点发现了我所有的磁盘。但是我必须手动确定附加的AWS托管磁盘。

kubectl get diskNAME                                      AGEdisk-184d99015253054c48c4aa3f17d137b1     5mdisk-2f6bced7ba9b2be230ca5138fd0b07f1     5mdisk-806d3e77dd2e38f188fdaf9c46020bdc     5m

4.然后,将这些磁盘添加到标准StorageClass引用的自定义k8s资源StoragePoolClaim中。

---apiVersion: storage.k8s.io/v1kind: StorageClassmetadata:  name: openebs-custom  annotations:    openebs.io/cas-type: cstor    cas.openebs.io/config: |      - name: StoragePoolClaim        value: "cstor-disk"provisioner: openebs.io/provisioner-iscsi---apiVersion: openebs.io/v1alpha1kind: StoragePoolClaimmetadata:  name: cstor-diskspec:  name: cstor-disk  type: disk  maxPools: 3  poolSpec:    poolType: striped  disks:    diskList:    - disk-2f6bced7ba9b2be230ca5138fd0b07f1    - disk-806d3e77dd2e38f188fdaf9c46020bdc    - disk-184d99015253054c48c4aa3f17d137b1

完成这些步骤后,我便能够通过k8s PVC动态配置新卷。

优点

  • 开源的

  • Maya在资源使用可视化方面做得很好。您可以轻松地在k8s集群中部署多个服务,并轻松设置监视和日志记录以收集集群的所有重要方面。这是调试的理想工具。

  • 总的来说,CAS概念–我非常喜欢容器存储背后的想法,并且我相信会有未来。

  • OpenEBS背后的社区—我能够在几分钟内解决任何问题。Slack上的团队非常有帮助。

缺点

  • 不成熟-OpenEBS是一个相当新的项目,尚未达到稳定版本。核心团队仍在进行后端优化,这将在接下来的几个月中显著提高性能。

  • Kubelet和存储控制器之间的iSCSI连接由k8s服务实现,这在某些覆盖网络CNI插件(例如Tungsten Fabric)中可能是一个问题。

  • 需要在Kubernetes节点上安装其他软件(iSCSI),这使其在托管Kubernetes集群的情况下不切实际。

注意:OpenEBS团队在文档中调整了相关的测试用例场景

https://github.com/kmova/openebs/tree/fio-perf-tests/k8s/demo/dbench

Portworx

唯一的不开源的存储解决方案。但是,它免费提供3个节点试用版。

82288704-4655-11eb-8b86-12bb97331649.png

如何在AKS上安装它?在AKS上安装也非常容易。我使用了可在其网站上找到的Kubernetes spec生成器。

1.首选,我选择了Portworx托管的etcd来简化设置,并填充了k8s 1.11.4版本。

2.我必须将数据网络接口修改为azure0,因为我使用的是具有高级联网功能的Azure cni。否则,Portworx将使用来自docker bridge的IP地址而不是VM接口。

3.最后一步,网站生成器向我提供了渲染的k8s YAML清单以应用于我的集群。

4.引导后,我在每个k8s节点上运行了Portworx Pod

root@aks-agentpool-20273348-0:~# kubectl get pods -o wide -n kube-system -l name=portworxNAME             READY     STATUS    RESTARTS   AGE       IP          NODE                       NOMINATED NODEportworx-g9csq   1/1       Running   0          14m       10.0.1.66   aks-agentpool-20273348-2   <none>portworx-nt2lq   1/1       Running   0          14m       10.0.1.4    aks-agentpool-20273348-0   <none>portworx-wcjnx   1/1       Running   0          14m       10.0.1.35   aks-agentpool-20273348-1   <none>

我创建了具有高优先级和3个副本的Storage Class,然后可以配置k8s pvc。

优点

  • 易于部署-具有详细配置的网站配置器。

  • AKS集群的配置器,不需要任何其他步骤,如ceph或glusterfs。

  • 云原生存储,它可以在硬件集群和公共云上运行。

  • 存储感知的服务等级(COS)和应用感知的I/O调整

缺点

  • 闭源,专有供应商解决方案。

GlusterFS Heketi

GlusterFS是众所周知的开源存储解决方案。它沿用Ceph,这是RedHat支持的传统开源存储之一。Heketi是用于GlusterFS的RESTful卷管理接口。它提供了一种释放动态配置的GlusterFS卷功能的便捷方法。如果没有此访问权限,则必须手动创建GlusterFS卷并将其映射到k8s pv。

8296ef46-4655-11eb-8b86-12bb97331649.png

如何在AKS上安装它?我使用了默认的Heketi快速入门指南。

  1. 首先,我基于示例一创建了一个拓扑文件,其中包含磁盘和主机名。

https://github.com/gluster/gluster-kubernetes/blob/master/deploy/topology.json.sample

2.由于Heketi主要是在基于RHEL的操作系统上开发和测试的,因此我在使用Ubuntu主机的AKS上遇到了一个问题,该内核路径错误。这是解决此问题的PR。

https://github.com/gluster/gluster-kubernetes/pull/557
+++ b/deploy/kube-templates/glusterfs-daemonset.yaml@@ -67,7 +67,7 @@ spec:           mountPath: "/etc/ssl"           readOnly: true         - name: kernel-modules-          mountPath: "/usr/lib/modules"+          mountPath: "/lib/modules"           readOnly: true         securityContext:           capabilities: {}@@ -131,4 +131,4 @@ spec:           path: "/etc/ssl"       - name: kernel-modules         hostPath:-          path: "/usr/lib/modules"+          path: "/lib/modules"

3.我遇到的AKS的另一个问题是非空磁盘,因此我使用了擦拭来清理glusterfs的磁盘。该磁盘以前没有用于其他任何用途。

wipefs -a /dev/sdc/dev/sdc: 8 bytes were erased at offset 0x00000218 (LVM2_member): 4c 56 4d 32 20 30 30 31

4.最后一步,我运行命令gk-deploy -g -t topology.json,该命令在由heketi控制器控制的每个节点上部署了glusterfs pod。

root@aks-agentpool-20273348-0:~# kubectl get po -o wideNAME                     READY   STATUS    RESTARTS IP        NODE                       NOMINATED NODEglusterfs-fgc8f          1/1     Running   0       10.0.1.35  aks-agentpool-20273348-1glusterfs-g8ht6          1/1     Running   0       10.0.1.4   aks-agentpool-20273348-0glusterfs-wpzzp          1/1     Running   0       10.0.1.66  aks-agentpool-20273348-2heketi-86f98754c-n8qfb   1/1     Running   0       10.0.1.69  aks-agentpool-20273348-2

然后,我面临着动态配置的问题。Heketi restURL对k8s控制平面不可用。我尝试了kube dns记录,pod IP和svc IP。两者都不起作用。因此,我不得不通过Heketi CLI手动创建卷。

root@aks-agentpool-20273348-0:~# export HEKETI_CLI_SERVER=http://10.0.1.69:8080root@aks-agentpool-20273348-0:~# heketi-cli volume create --size=10 --persistent-volume --persistent-volume-endpoint=heketi-storage-endpoints | kubectl create -f -persistentvolume/glusterfs-efb3b155 created
root@aks-agentpool-20273348-0:~# kubectl get pvNAME                 CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM     STORAGECLASS   REASON    AGEglusterfs-efb3b155   10Gi       RWX            Retain           Available                                      19s

然后,必须为我的dbench工具将现有的PV映射到PVC。

kind: PersistentVolumeClaimapiVersion: v1metadata:  name: glusterfs-efb3b155spec:  accessModes:    - ReadWriteMany  storageClassName: ""  resources:    requests:      storage: 10Gi  volumeName: glusterfs-efb3b155
kubectl get pvcNAME                 STATUS    VOLUME               CAPACITY   ACCESS MODES   STORAGECLASS   AGEglusterfs-efb3b155   Bound     glusterfs-efb3b155   10Gi       RWX                           36m

从k8s上的Heketi Gluster安装获得更多输出。

gluster volume info vol_efb3b15529aa9aba889d7900f0ce9849
Volume Name: vol_efb3b15529aa9aba889d7900f0ce9849Type: ReplicateVolume ID: 96fde36b-e389-4dbe-887b-baae32789436Status: StartedSnapshot Count: 0Number of Bricks: 1 x 3 = 3Transport-type: tcpBricks:Brick1: 10.0.1.66:/var/lib/heketi/mounts/vg_5413895eade683e1ca035760c1e0ffd0/brick_cd7c419bc4f4ff38bbc100c6d7b93605/brickBrick2: 10.0.1.35:/var/lib/heketi/mounts/vg_3277c6764dbce56b5a01426088901f6d/brick_6cbd74e9bed4758110c67cfe4d4edb53/brickBrick3: 10.0.1.4:/var/lib/heketi/mounts/vg_29d6152eeafc57a707bef56f091afe44/brick_4856d63b721d794e7a4cbb4a6f048d96/brickOptions Reconfigured:transport.address-family: inetnfs.disable: onperformance.client-io-threads: off
kubectl get svcNAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGEheketi                     ClusterIP   192.168.101.75           8080/TCP   5hheketi-storage-endpoints   ClusterIP   192.168.103.66           1/TCP      5h
root@aks-agentpool-20273348-0:~# kubectl get endpointsNAME                       ENDPOINTS                            AGEheketi                     10.0.1.69:8080                       5hheketi-storage-endpoints   10.0.1.35:1,10.0.1.4:1,10.0.1.66:1   5hkubernetes                 172.31.22.152:443                    1droot@aks-agentpool-20273348-0:~# kubectl get endpoints heketi-storage-endpoints -o yamlapiVersion: v1kind: Endpointsmetadata:  creationTimestamp: 2019-01-29T15:14:28Z  name: heketi-storage-endpoints  namespace: default  resourceVersion: "142212"  selfLink: /api/v1/namespaces/default/endpoints/heketi-storage-endpoints  uid: 91f802eb-23d8-11e9-bfcb-a23b1ec87092subsets:- addresses:  - ip: 10.0.1.35  - ip: 10.0.1.4  - ip: 10.0.1.66  ports:  - port: 1    protocol: TCP

优点

  • 成熟的存储解决方案

  • 比Ceph更轻

缺点

  • Heketi不是为公共管理的k8设计的。它与HW群集配合使用,安装更容易。

  • 并非真正为“结构化数据”设计的,如SQL数据库。但是,您可以使用Gluster备份和还原数据库。

Ceph Rook

OpenStack私有云常见和Ceph进行搭配。它始终需要设计特定的硬件配置,根据数据类型生成pg组,配置日志SSD分区(在bluestore之前)并定义Crush Map。因此,当我第一次听说在3节点k8s集群中使用Ceph时,我不敢相信它实际上可以工作。但是,Rook编排工具给我留下了深刻的印象,该工具为我完成了所有痛苦的步骤,并且与k8s编排一起提供了一种非常简单的方法来处理整个存储集群的安装。

82f1800a-4655-11eb-8b86-12bb97331649.png

如何在AKS上安装它?在默认安装中,Rook不需要任何特殊步骤,并且如果您不希望使用高级配置,它会非常平滑。

1.我使用了Ceph快速入门指南

https://github.com/rook/rook/blob/master/Documentation/ceph-quickstart.md#ceph-storage-quickstart

2.我必须配置特定于AKS的FLEXVOLUME_DIR_PATH,因为它们使用/etc/kubernetes/volumeplugins/ 而不是默认的Ubuntu /usr/libexec。没有此更改,kubelet无法安装pvc 。

diff --git a/cluster/examples/kubernetes/ceph/operator.yaml b/cluster/examples/kubernetes/ceph/operator.yamlindex 73cde2e..33f45c8 100755--- a/cluster/examples/kubernetes/ceph/operator.yaml+++ b/cluster/examples/kubernetes/ceph/operator.yaml@@ -431,8 +431,8 @@ spec:         # - name: AGENT_MOUNT_SECURITY_MODE         #   value: "Any"         # Set the path where the Rook agent can find the flex volumes-        # - name: FLEXVOLUME_DIR_PATH-        #  value: ""+        - name: FLEXVOLUME_DIR_PATH+          value: "/etc/kubernetes/volumeplugins"         # Set the path where kernel modules can be found         # - name: LIB_MODULES_DIR_PATH         #  value: ""

3.然后,我必须指定要在deviceFilter中使用的设备。我的附加磁盘始终位于/dev/sdc上

diff --git a/cluster/examples/kubernetes/ceph/cluster.yaml b/cluster/examples/kubernetes/ceph/cluster.yamlindex 48cfeeb..0c91c48 100755--- a/cluster/examples/kubernetes/ceph/cluster.yaml+++ b/cluster/examples/kubernetes/ceph/cluster.yaml@@ -227,7 +227,7 @@ spec:   storage: # cluster level storage configuration and selection     useAllNodes: true     useAllDevices: false-    deviceFilter:+    deviceFilter: "^sdc"     location:     config:

4.安装后,我使用以下配置创建了Ceph块池和存储类

apiVersion: ceph.rook.io/v1kind: CephBlockPoolmetadata:  name: replicapool  namespace: rook-cephspec:  failureDomain: host  replicated:    size: 3---apiVersion: storage.k8s.io/v1kind: StorageClassmetadata:   name: rook-ceph-blockprovisioner: ceph.rook.io/blockparameters:  blockPool: replicapool  clusterNamespace: rook-ceph  fstype: xfsreclaimPolicy: Retain

5。最后,我通过以下部署工具检查状态:https://github.com/rook/rook/blob/master/Documentation/ceph-toolbox.md

ceph status  cluster:    id:     bee70a10-dce1-4725-9285-b9ec5d0c3a5e    health: HEALTH_OK
  services:    mon: 3 daemons, quorum c,b,a    mgr: a(active)    osd: 3 osds: 3 up, 3 in
  data:    pools:   0 pools, 0 pgs    objects: 0  objects, 0 B    usage:   3.0 GiB used, 3.0 TiB / 3.0 TiB avail    pgs:
[root@aks-agentpool-27654233-0 /]#[root@aks-agentpool-27654233-0 /]#[root@aks-agentpool-27654233-0 /]# ceph osd status+----+--------------------------+-------+-------+--------+---------+--------+---------+-----------+| id |           host           |  used | avail | wr ops | wr data | rd ops | rd data |   state   |+----+--------------------------+-------+-------+--------+---------+--------+---------+-----------+| 0  | aks-agentpool-27654233-0 | 1025M | 1021G |    0   |     0   |    0   |     0   | exists,up || 1  | aks-agentpool-27654233-1 | 1025M | 1021G |    0   |     0   |    0   |     0   | exists,up || 2  | aks-agentpool-27654233-2 | 1025M | 1021G |    0   |     0   |    0   |     0   | exists,up |+----+--------------------------+-------+-------+--------+---------+--------+---------+-----------+

优点

  • 在大型生产环境中运行的强大存储

  • Rook使生命周期管理变得更加简单。

缺点

  • 复杂且更重,甚至不适合在公共云中运行。最好只在配置正确的硬件群集上运行。

    Longhorn

Longhorn是Rancher开发的用于K8s的云原生分布式块存储。它主要是为微服务用例设计的。它为每个块设备卷创建一个专用的存储控制器,并跨存储在多个节点上的多个副本同步复制该卷。Longhorn在附加了卷的节点上创建了Longhorn Engine,并在复制了卷的节点上创建了副本。与其他存储方案类似,整个控制平面正常运行,而数据平面由K8s编排。它是完全开源的。有趣的是,OpenEBS Jiva后端实际上是基于Longhorn的,或者至少最初是基于Longhorn的。主要区别在于Longhorn使用TCMU Linux驱动程序,而OpenEBS Jiva使用的是gotgt。

8355ae9a-4655-11eb-8b86-12bb97331649.jpg

如何在AKS上获取它?当然也可以轻松安装到AKS,只需要运行一个命令,它将所有组件安装到我的AKS集群中

$ kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/master/deploy/longhorn.yaml
$ kubectl -n longhorn-system get poNAME                                        READY   STATUS    RESTARTS   AGEcsi-attacher-7965bb8b59-c4g2c               1/1     Running   0          116scsi-attacher-7965bb8b59-jqk9t               1/1     Running   0          116scsi-attacher-7965bb8b59-qrxl6               1/1     Running   0          116scsi-provisioner-5896666d9b-9lss2            1/1     Running   0          115scsi-provisioner-5896666d9b-v7wwd            1/1     Running   0          115scsi-provisioner-5896666d9b-vsq6v            1/1     Running   0          115scsi-resizer-98674fffd-27wgb                 1/1     Running   0          115scsi-resizer-98674fffd-q6scx                 1/1     Running   0          115scsi-resizer-98674fffd-rr7qc                 1/1     Running   0          115sengine-image-ei-ee18f965-5npvk              1/1     Running   0          2m44sengine-image-ei-ee18f965-9lp7w              1/1     Running   0          2m44sengine-image-ei-ee18f965-h7b4x              1/1     Running   0          2m44sinstance-manager-e-27146777                 1/1     Running   0          2m42sinstance-manager-e-58362831                 1/1     Running   0          2m40sinstance-manager-e-6043871c                 1/1     Running   0          2m43sinstance-manager-r-5cdb90bf                 1/1     Running   0          2m40sinstance-manager-r-cb47162a                 1/1     Running   0          2m41sinstance-manager-r-edd5778b                 1/1     Running   0          2m42slonghorn-csi-plugin-7xzw9                   2/2     Running   0          115slonghorn-csi-plugin-m8cp4                   2/2     Running   0          115slonghorn-csi-plugin-wzgp8                   2/2     Running   0          115slonghorn-driver-deployer-699db744fd-8j6q6   1/1     Running   0          3m8slonghorn-manager-c5647                      1/1     Running   1          3m10slonghorn-manager-dlsmc                      1/1     Running   0          3m10slonghorn-manager-jrnfx                      1/1     Running   1          3m10slonghorn-ui-64bd57fb9d-qjmsl                1/1     Running   0          3m9s

2.将带有ext4文件系统的/dev/sdc1挂载到/var/lib/longhorn,这是卷存储的默认路径。最好在Longhorn安装之前将磁盘安装到那里。

83b2503c-4655-11eb-8b86-12bb97331649.png

Longhorn中节点磁盘配置的屏幕截图

3.最后一步是创建一个具有3个副本定义的默认存储类。

# kubectl create -f https://raw.githubusercontent.com/longhorn/longhorn/master/examples/storageclass.yaml
kind: StorageClassapiVersion: storage.k8s.io/v1metadata:  name: longhornprovisioner: driver.longhorn.ioallowVolumeExpansion: trueparameters:  numberOfReplicas: "3"  staleReplicaTimeout: "2880" # 48 hours in minutes  fromBackup: ""

优点

  • 开源的

  • 云原生存储,它可以在硬件集群和公共云上运行。

  • 易于部署,它只需要一个命令,并且“开箱即用”。

  • 自动卷备份/还原到S3

缺点

  • 它使用标准文件系统(ext4或xfs)到/var/lib/longhorn的挂载点。每个卷就像一个磁盘文件。它可以随着许多控制器副本进行扩展,从而带来额外的网络开销。类似于我为OpenEBS Jiva描述的内容。

  • 卷的挂载有时会花费很长时间(几分钟),并且会显示最终从中恢复的错误。

OpenEBS MayaStor

上文有介绍OpenEBS使用cStor的方案,其性能结果确实很差。但是一年半后的时间,OpenEBS团队引入了一个名为MayStor的新后端。

这是用Rust编写的云原生声明性数据平面,由2个组件组成:

  • 以CSI概念和数据平面实现的控制平面。与以前的后端相比,主要区别在于利用NVMe而不是NVMe-oF,这有望为存储敏感型工作负载提供更好的IOPS和延迟价值。

  • 这种存储设计的另一个优点是,它在主机用户空间中完全用尽了内核,并消除了由不同Linux发行版中可用的各种内核引起的差异。它根本不依赖于内核进行访问。下面的链接中,详细介绍了MayStor的设计说明。

https://blog.mayadata.io/openebs/mayastor-crossing-the-chasm-to-nvmf-infinity-and-beyond

如何在AKS上获取它?在AKS上进行安装也非常简单,我遵循了他们的快速入门指南

  1. 我必须在AKS群集中的每个节点上用512个数字配置2MB的大页面。

echo 512 | sudo tee /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

但是我决定通过下面的k8s daemonset强制执行它们,而不是通过ssh进入我的每个实例。

apiVersion: apps/v1kind: DaemonSetmetadata:  name: hugepages-ensure  namespace: mayastor  labels:    app: hugepages-ensurespec:  selector:    matchLabels:      name: hugepages-ensure  updateStrategy:    type: OnDelete  template:    metadata:      name: hugepages-ensure      labels:        name: hugepages-ensure        app: hugepages-ensure    spec:      containers:      - name: shell        image: busybox:latest        imagePullPolicy: IfNotPresent        command:          - /bin/sh        args:          - -c          - "while true; do echo 512 | tee /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages;grep HugePages /proc/meminfo; sleep 6000; done"        volumeMounts:          - mountPath: /host-root            name: host-root        securityContext:          privileged: true      dnsPolicy: ClusterFirstWithHostNet      hostNetwork: true      volumes:        - name: host-root          hostPath:            path: /

2.我必须标记我的存储节点VM。

kubectl label node aks-agentpool-13651304-0 openebs.io/engine=mayastornode/aks-agentpool-13651304-0 labeledkubectl label node aks-agentpool-13651304-1 openebs.io/engine=mayastornode/aks-agentpool-13651304-1 labeledkubectl label node aks-agentpool-13651304-2 openebs.io/engine=mayastornode/aks-agentpool-13651304-2 labeled

3.然后,我应用了MayaStor存储库中指定的所有清单。

https://github.com/openebs/Mayastor/tree/develop/deploy
kubectl create -f nats-deployment.yamlkubectl create -f csi-daemonset.yamlkubectl create -f mayastorpoolcrd.yamlkubectl create -f moac-rbac.yamlkubectl create -f moac-deployment.yamlkubectl create -f mayastor-daemonset.yaml
kubectl get po -n mayastorNAME                     READY   STATUS    RESTARTS   AGEhugepages-ensure-5dr26   1/1     Running   0          47hhugepages-ensure-tpth6   1/1     Running   0          47hhugepages-ensure-z9mmh   1/1     Running   0          47hmayastor-csi-7rf2l       2/2     Running   0          47hmayastor-csi-hbqlb       2/2     Running   0          47hmayastor-csi-jdw7k       2/2     Running   0          47hmayastor-g9gnl           1/1     Running   7          47hmayastor-j7j4q           1/1     Running   4          47hmayastor-kws9r           1/1     Running   4          47hmoac-7d487fd5b5-hfvhq    3/3     Running   0          41hnats-b4cbb6c96-8drv4     1/1     Running   0          47h

4.当所有内容都在运行时,您可以开始创建用于卷置备的存储池。在我的情况下,我创建了3个存储池,每个节点有一个磁盘。

cat <apiVersion: openebs.io/v1alpha1kind: MayastorPoolmetadata:  name: pool-on-node-1  namespace: mayastorspec:  disks:  - /dev/sdc  node: aks-agentpool-13651304-1EOF
kubectl -n mayastor get MayastorPoolNAME             NODE                       STATE    AGEpool-on-node-0   aks-agentpool-13651304-0   online   40hpool-on-node-1   aks-agentpool-13651304-1   online   46hpool-on-node-2   aks-agentpool-13651304-2   online   46h

5.在继续进行StorageClass定义之前,检查每个存储池的状态很重要。状态必须可见。

kubectl -n mayastor describe msp pool-on-node-1Name:         pool-on-node-1Namespace:    mayastorLabels:       API Version:  openebs.io/v1alpha1Kind:         MayastorPoolMetadata:  Creation Timestamp:  2020-08-19T0852Z  Generation:          1  Resource Version:    45513  Self Link:           /apis/openebs.io/v1alpha1/namespaces/mayastor/mayastorpools/pool-on-node-1  UID:                 5330a0be-bebe-445a-9285-856511e318dcSpec:  Disks:    /dev/sdc  Node:  aks-agentpool-13651304-1Status:  Capacity:  1098433691648  Disks:    aio:///dev/sdc  Reason:  State:   online  Used:    1073741824Events:    

6.该过程的最后一步是StorageClass定义,在其中,我配置了3个副本以具有与之前的存储解决方案相同的测试环境。

cat <kind: StorageClassapiVersion: storage.k8s.io/v1metadata:  name: mayastorparameters:  repl: '3'  protocol: 'iscsi'provisioner: io.openebs.csi-mayastorEOF

完成这些步骤后,我便能够通过K8s PVC动态预配新卷。

优点

  • 具有强大社区支持的开源

  • 云原生存储,它可以在硬件集群和公共云上运行。

  • 与仅具有一个队列的SCSI相比,NVMe的使用旨在实现高度并行性,并且可以具有64K队列。

  • 它使用NVMe-oF作为传输方式,可以在各种传输方式(nvmf,uring,pcie)上工作,并且完全在用户空间(目标用户和发起者)中完成。在用户空间中运行可以避免进行大量的系统调用,避免后期崩溃/崩溃等。而且它与内核无关,因此跨云或物理环境的linux类型之间没有区别。

缺点

  • 早期版本-OpenEBS MayaStor的版本为0.3,因此它仍然存在一些限制和稳定性问题。但是,它们走在正确的轨道上,并且在几个月后,它可能是在K8中存储的首选。

  • 需要在Kubernetes节点上支持2MB的大页面。但是,与1GB的大页面相比,几乎在所有物理或虚拟环境中都可用。

性能测试结果

重要说明:单个存储性能测试的结果无法单独评估,但必须将测量结果相互比较。这里多种执行比较测试的方法是相对比较简单的。

为了进行验证,我使用了与Azure AKS 3节点群集和每个实例均附有1TB高级SSD托管磁盘的完全相同的实验室。

为了运行测试,我决定使用称为Dbench的负载测试器。这是Pod的K8s部署清单,在其中运行FIO,这是带有8个测试用例的Flexible IO Tester。在Docker映像的入口点中指定了测试:

  • 随机读写带宽

  • 随机读写IOPS

  • 读写延迟

  • 顺序读/写

  • 混合读/写IOPS

首先,我运行了Azure PVC测试以获得与去年进行比较的基准。结果几乎相同,因此我们可以假设条件保持不变,并且使用相同的存储版本将获得相同的数量。可从https://gist.github.com/pupapaik/76c5b7f124dbb69080840f01bf71f924获得来自2019年所有测试的更新的完整测试输出以及新的MayStor和Longhorn测试

随机读写带宽

随机读取测试表明,GlusterFS,Ceph和Portworx的读取性能比Azure本地磁盘上的主机路径好几倍。OpenEBS和Longhorn的性能几乎是本地磁盘的两倍。原因是读取缓存。对于OpenEBS,写入速度最快,但是Longhorn和GlusterFS的值也几乎与本地磁盘相同。

83f92c5a-4655-11eb-8b86-12bb97331649.png

843dc644-4655-11eb-8b86-12bb97331649.png

随机读写IOPS

Portworx和OpenEBS在随机IOPS测试中表现出最好的结果。这次,OpenEBS在写入方面的IOPS比本地Azure PVC更好,这在技术上几乎是不可能的。它很可能与在测试用例运行的不同时间处的Azure存储负载有关。

848acc50-4655-11eb-8b86-12bb97331649.png

84d47328-4655-11eb-8b86-12bb97331649.png

读写延迟

延迟读取获胜者与上次相同。LongHorn和OpenEBS几乎是PortWorx的两倍。这仍然不错,因为本机Azure pvc比大多数其他经过测试的存储要慢。但是,在OpenEBS和Longhorn上写入期间的延迟更好。GlusterFS仍然比其他存储要好。

85132a32-4655-11eb-8b86-12bb97331649.png

8574de3a-4655-11eb-8b86-12bb97331649.png

顺序读/写

顺序读/写测试显示的结果与随机测试相似,但是Ceph的读性能比GlusterFS高2倍。写入结果几乎都处于同一水平,OpenEBS和Longhorn达到了相同的水平。

85c0e802-4655-11eb-8b86-12bb97331649.png

862ab3e0-4655-11eb-8b86-12bb97331649.png

混合读/写IOPS

最后一个测试用例验证了混合读写IOPS,在读写方面,OpenEBS交付的速度几乎是PortWorx或Longhorn的两倍。

897613d2-4655-11eb-8b86-12bb97331649.png

89cd2ec4-4655-11eb-8b86-12bb97331649.png

结论

该文章验证了一个开放源代码项目在一年内可以有多大的变化!作为演示,让我们看一下在完全相同的环境下,OpenEBS cStor和OpenEBS MayaStor的IOPS的比较。

8a03a8f0-4655-11eb-8b86-12bb97331649.png

OpenEBS cStor和MayaStor之间的混合读写IOPS比较

在选择存储空间时,请仅将结果作为标准之一,不要仅根据文章做出最终判断。我们可以从上述的测试中得出以下结论:

  • Portworx和OpenEBS是AKS上最快的容器存储。

  • 围绕NVMe的稳健设计,OpenEBS似乎已成为最好的开源容器存储选项之一。

  • 对于硬件集群,Ceph是最好的开源后端存储。对于公共云而言,操作过于复杂,最终与默认的云存储类相比并没有增加太多价值。

  • 对于简单的块存储用例,Longhorn绝对是有效的选择,它与OpenEBS Jiva后端非常相似。

当然,以上只是评测容器存储选项的一种方法。存储评测应该还包括缩放和稳定性等。后期将密切关注CNCF存储领域中其他正在发展的项目,并从性能测试和扩展中带来跟多有趣的更新。

参考链接

1.https://medium.com/volterra-io/kubernetes-storage-performance-comparison-9e993cb27271

2.https://medium.com/volterra-io/kubernetes-storage-performance-comparison-v2-2020-updated-1c0b69f0dcf4

责任编辑:xj

原文标题:K8s最常见的存储解决方案之性能评测

文章出处:【微信公众号:存储社区】欢迎添加关注!文章转载请注明出处。


原文标题:K8s最常见的存储解决方案之性能评测

文章出处:【微信号:TopStorage,微信公众号:存储加速器】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
分享:

评论

相关推荐

分布式锁三个属性和两大类

“分布式锁”这个问题快被说烂了,奈何笔者实在没有找到一个满意的答案,故记录自己寻找答案、总结的过程。....
的头像 数据分析与开发 发表于 10-22 17:30 ? 266次 阅读

探究超大Transformer语言模型的分布式训练框架

NVIDIA Megatron 是一个基于 PyTorch 的框架,用于训练基于 Transform....
的头像 NVIDIA英伟达企业解决方案 发表于 10-20 09:25 ? 358次 阅读

Redis分布式锁的常用实现方式

今天我们聊聊分布式锁。 1. 分布式锁是什么? 我们的手机有锁、车有锁、家门有锁、贵重物品会锁进保险....
的头像 数据分析与开发 发表于 10-15 09:38 ? 167次 阅读

Redis分布式锁有什么特性

今天我们聊聊分布式锁。 1. 分布式锁是什么? 我们的手机有锁、车有锁、家门有锁、贵重物品会锁进保险....
的头像 Linux爱好者 发表于 10-12 16:42 ? 253次 阅读

分布式软总线让阿里巴巴商家玩转多设备直播

一、引言 距离HarmonyOS 2正式发布已经过去三个多月了,最新数据显示已有超过1.2亿台设备升级到了HarmonyOS 2操作系统。然...
发表于 10-12 16:00 ? 477次 阅读
分布式软总线让阿里巴巴商家玩转多设备直播

超大Transformer语言模型的分布式训练框架

NVIDIA Megatron 是一个基于 PyTorch 的框架,用于训练基于 Transform....
的头像 NVIDIA英伟达企业解决方案 发表于 10-11 16:46 ? 192次 阅读
超大Transformer语言模型的分布式训练框架

如何通过分布式架构驱动下一代电动汽车系统

电动汽车 (EV) 和混合动力电动汽车 (HEV) 正在不断演进,其中的电子设备同样也在发生变化。在....
的头像 德州仪器 发表于 10-11 10:06 ? 804次 阅读
如何通过分布式架构驱动下一代电动汽车系统

iphone13promax价格1tb多少钱

  iphone13promax价格1tb官网售价12999元起,这是苹果13机型中最贵的一款机型,....
的头像 lhl545545 发表于 09-27 10:14 ? 5669次 阅读

HarmonyOS教程—基于分布式数据接口,实现多种设备上一致的数据访问体验

1. 如何使用分布式数据库       介绍分布式数据服务(Distributed Data Service,DDS) 为应用程序提...
发表于 09-26 11:40 ? 606次 阅读
HarmonyOS教程—基于分布式数据接口,实现多种设备上一致的数据访问体验

STM32F407的FLASH为什么只能按扇区擦除

STM32F407的FLASH为什么只能按扇区擦除? 怎样使用STM32F407内部扇区储存数据? ...
发表于 09-24 12:04 ? 0次 阅读

如何去实现一种分布式计算技术

分布式计算技术是什么? 如何去实现一种分布式计算技术? ...
发表于 09-24 07:52 ? 0次 阅读

【木棉花】学习笔记--页面间跳转

前言大家好,我又回来啦。这一星期的学习时间又到了。那我们在前几个星期讲的都是harmonyOS里的分布式能力,可能学起来会相对较...
发表于 09-15 14:43 ? 420次 阅读

HarmonyOS教程—分布式亲子早教系统

1. 项目介绍      远程教育,多屏协同是智慧教育的一个重要场景。本篇Codelab通过一个亲子早教系统,完成了...
发表于 09-14 11:06 ? 606次 阅读

HarmonyOS教程—基于分布式能力和IDL跨进程通信,实现视频跨设备播放、控制

1. 介绍      此篇Codelab文档是基于实现一个简易播放器的高阶篇。在已实现视频播放功能的基础上,实现分布...
发表于 09-13 11:49 ? 606次 阅读

HarmonyOS教程一基于分布式调度的能力,实现远程FA的启动

1. 介绍      开发者在应用中集成分布式调度能力,通过调用指定能力的分布式接口,实现跨设备能力调度。根据...
发表于 09-10 10:07 ? 707次 阅读

HarmonyOS教程一分布式语音照相机

1. 项目介绍       生活中我们经常会遇到这样的例子:张三和李四外出旅游,他们俩需要相互拍照片,张三在远...
发表于 09-10 09:53 ? 846次 阅读

HarmonyOS教程—基于跨设备迁移和分布式文件能力,实现邮件的跨设备编辑和附件的调用

1. 介绍       当前,在不同的设备上迁移一个任务的操作通常十分复杂,比如路上在手机里写了一半的邮件,回...
发表于 09-09 10:03 ? 303次 阅读

软总线是什么 剖析鸿蒙软总线超详细教程

软总线是什么?分布式软总线是手机、平板、智能穿戴、智慧屏、车机等分布式设备的通信基座,为设备之间的互....
的头像 华为麒麟 发表于 08-27 11:13 ? 2654次 阅读
软总线是什么 剖析鸿蒙软总线超详细教程

基于HarmonyOS的分镜头App开发技术详解

《分镜头App》的创作灵感来源于殷冬的日常观察,他发现平常人们在自拍时,往往会用前置摄像头,由于像素....
的头像 HarmonyOS开发者 发表于 08-26 17:59 ? 675次 阅读
基于HarmonyOS的分镜头App开发技术详解

Pegasus智能家居开发套件_2021

Pegasus智能家居开发套件指南
发表于 08-18 15:39 ? 39次 阅读

Taurus AI Camera开发套件_2021

TaurusAICamera开发套件指南
发表于 08-18 13:32 ? 20次 阅读

Neptune开发套件_2021

Neptune开发套件指南
发表于 08-18 13:32 ? 11次 阅读

飞机线缆分布式检测线束测试仪方案综述

飞机线缆分布式检测线束测试仪方案综述
发表于 08-17 10:51 ? 76次 阅读

鸿蒙软总线的简单使用

软总线是什么? 分布式软总线是手机、平板、智能穿戴、智慧屏、车机等分布式设备的通信基座,为....
的头像 HiHope社区 发表于 08-16 10:47 ? 295次 阅读
鸿蒙软总线的简单使用

为什么需要分布式锁 基于Zookeeper锁安全吗

这篇文章我想和你聊一聊,关于 Redis 分布式锁的「安全性」问题。 Redis 分布式锁的话题,很....
的头像 上海磐启微电子有限公司 发表于 08-10 18:06 ? 3145次 阅读

鸿蒙分布式怎么理解

HarmonyOS系统的使命和目标是将不同的设备串联,成为设备的“万能语言”,让一个系统连接起所有上....
的头像 汽车玩家 发表于 07-08 14:47 ? 760次 阅读

鸿蒙系统底层架构 鸿蒙系统分布式架构

鸿蒙系统是一款面向未来、面向全场景的分布式操作系统,鸿蒙系统开创性地提出了基于同一套系统能力、适配多....
的头像 如意 发表于 07-08 14:35 ? 2033次 阅读

鸿蒙系统有啥用 鸿蒙分布式系统的好处

鸿蒙系统2.0已正式上线,也有许多用户使用鸿蒙系统一段时间了,那么我们接下来盘点下鸿蒙系统有啥用,有....
的头像 如意 发表于 07-06 17:10 ? 1410次 阅读

你们知道计算机是如何识别你写的代码的吗?

学习编程其实就是学高级语言,即那些为人类设计的计算机语言。 但是,计算机不理解高级语言,必须通过编译....
的头像 strongerHuang 发表于 07-06 10:03 ? 969次 阅读

基于CAN总线的水下航行器分布式控制系统

基于CAN总线的水下航行器分布式控制系统
发表于 07-01 16:53 ? 113次 阅读

基于多STM32和CAN总线的分布式电动护理床控制

基于多STM32和CAN总线的分布式电动护理床控制
发表于 06-30 15:15 ? 119次 阅读

基于联盟链的建筑行业标准管理系统设计方案

基于联盟链的建筑行业标准管理系统设计方案
发表于 06-30 10:51 ? 92次 阅读

吸波材料在储存中要注意哪些问题

对于吸波材料,大部门的人有所了解,但是对于吸波材料在储存过程中要注意的那些事项,您可能有所不知,吸波....
发表于 06-28 16:03 ? 125次 阅读

智能电网的弹性调控平台任务调度研究

智能电网的弹性调控平台任务调度研究
发表于 06-27 16:21 ? 103次 阅读

Google Brain和DeepMind联手发布可以分布式训练模型的框架

【导读】AI模型进入大数据时代,单机早已不能满足训练模型的要求,最近Google Brain和Dee....
的头像 中科院长春光机所 发表于 06-26 15:42 ? 739次 阅读
Google Brain和DeepMind联手发布可以分布式训练模型的框架

揭秘Google和Facebook不用Docker的原因

写作本文的起因是我想让修改后的分布式 PyTorch 程序能更快的在 Facebook 的集群上启动....
的头像 Linux爱好者 发表于 06-26 15:37 ? 533次 阅读

基于分布式传感的实时三维重建系统

基于分布式传感的实时三维重建系统
发表于 06-25 11:25 ? 106次 阅读

OpenHarmony软总线设计理念

分布式软总线旨在为OpenHarmony系统提供跨进程或跨设备的通信能力,主要包含软总线和进程间通信....
的头像 独爱72H 发表于 06-24 10:56 ? 561次 阅读

基于观测器的多智能体有限时间包含控制问题

基于观测器的多智能体有限时间包含控制问题
发表于 06-23 15:14 ? 79次 阅读

基于Simulink的电子对抗分布式仿真系统

基于Simulink的电子对抗分布式仿真系统
发表于 06-22 15:47 ? 111次 阅读

基于改进二进制粒子群算法的配电网故障检测

基于改进二进制粒子群算法的配电网故障检测
发表于 06-22 11:55 ? 108次 阅读

openharmony开源方案的亮点是什么

OpenHarmony是自主研发、不兼容安卓的全领域下一代开源操做系统。
的头像 独爱72H 发表于 06-22 11:46 ? 487次 阅读

基于分布式光纤测温的结冰风洞喷雾耙温度场

基于分布式光纤测温的结冰风洞喷雾耙温度场
发表于 06-22 10:44 ? 100次 阅读

高效快速的分布式水军群检测算法

为在电子商务水军群组检测中快速处理真实环境中的大规模用户数据,提出一种分布式水军群组检测算法。设计基....
发表于 06-21 16:14 ? 114次 阅读

异构环境下的多DAG任务调度算法综述

异构环境下的多DAG任务调度算法综述
发表于 06-21 15:15 ? 76次 阅读

基于分布式仿真系统的实时通讯架构

基于分布式仿真系统的实时通讯架构
发表于 06-19 14:55 ? 119次 阅读

基于机器学习的HBase数据库配置参数优化

Hbase是一个分布式数据库管理系统,对于需要快速随机访冋大量数据的应用程序,它正变得越来越流行。但....
发表于 06-17 15:08 ? 71次 阅读

基于判断聚合模型的数据挖掘分类算法

随着互联网的发展和云计算技术的广泛应用,许多数据存储在不同的服务器上,分布式数据挖掘技术应运而生。智....
发表于 06-17 14:57 ? 97次 阅读

面向云服务的分布式消息系统动态负载均衡策略

针对云服务下分布式消息系统存在的节点间负载倾斜问题,提岀基于副本角色的动态负载均衡策略,并将算法应用....
发表于 06-17 10:35 ? 158次 阅读

基于KingSCADA的分布式运动控制监测系统

基于KingSCADA的分布式运动控制监测系统
发表于 06-16 10:49 ? 127次 阅读

切换拓扑条件下的多无人机系统分布式控制器

针对切换拓扑条件下的多无人机系统编队包含控制问题,基于一致性算法设计了分布式控制器,通过变量代换将领....
发表于 06-15 14:48 ? 93次 阅读

分布式存储系统的局部修复码分析

局部修复码应用于分布式存储系统中,其码字的任意位发生错误都可通过读取该码字其他若干位予以修复。根据该....
发表于 06-11 16:33 ? 98次 阅读

一种分布式认知无线电网络资源分配算法

为在不完美频谱检测环境下对资源进行优化分配,提出一种分布式认知无线电网络资源分配算法。根据叶斯理论给....
发表于 06-11 11:25 ? 103次 阅读

基于簇的分布式IPv6地址配置方案

为实现无线传感器网络(WSN)与IPv6互联网的全P通信,提出一种全 IP WSN地址配置方案。将W....
发表于 06-11 11:21 ? 129次 阅读

模型驱动的分布式卫星终端用户行为仿真

针对天地一体化网络中用户数量多、并发通信高和时变性的特点,基于多尺度虚拟化技术,提出一种模型驱动的分....
发表于 06-11 11:09 ? 83次 阅读

鸿蒙系统有什么特别之处?

6月2号话华为发布会正式发布鸿蒙操作系统,华为官方对鸿蒙操作系统做了很全面的介绍,小编这里就对此次发....
的头像 ss 发表于 06-07 09:55 ? 46016次 阅读

多小区分布式阵列系统的AP协作方法研究

在多小区分布式阵列系统中,用户与接入节点(AP)间的距离对频谱效率具有重要影响,边缘用户可以通过不同....
发表于 06-04 14:08 ? 94次 阅读

二阶多智体系统的自适应参数一致性算法

目前二阶多智能体系统尚未明确给出自适应参数的确定方法,且系统的收敛速度较慢。为在实际应用中预测飞行器....
发表于 06-04 11:53 ? 104次 阅读

分布式存储系统中的纠删码容错方法综述

HRC码是一种具有存储效率高、计算复杂度低等优点的纠删码,但其存在编解码计算开销大、实现较为复杂等不....
发表于 06-04 11:27 ? 96次 阅读

鸿蒙系统有什么特别之处 鸿蒙系统的特点是什么

根据王成录介绍,华为鸿蒙OS诞生的目标就是希望用一套系统来解决所有的IoT硬件设备的问题。
的头像 独爱72H 发表于 06-03 11:52 ? 7929次 阅读
综合在线 日韩欧美 中文字幕_综合在线 日韩欧美 中文字幕精品视频 <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <文本链> <文本链> <文本链> <文本链> <文本链> <文本链>