跳到主要内容
版本:3.11.0

在 GKE 和 EKS 上使用本地持久化存储卷

在 K8s 中,本地持久化存储卷(Local Persistent Volumes,Local PV)直接使用节点的本地磁盘目录存储容器数据。相比网络存储,Local PV 提供更高的 IOPS 和更低的读写延迟,适合数据密集型应用。本文介绍如何在 GKE(Google Kubernetes Engine)EKS(Amazon Elastic Kubernetes Service)中使用 Local PV 以及在使用 Local PV 过程中节点发生故障的处理方法。

虽然使用 Local PV 能提升性能,但是不同于网络存储,本地存储数据不会自动备份。如果节点因任何原因停止,本地存储上的所有数据可能会丢失。因此,使用 Local PV 时,需要在服务可用性、数据持久性和灵活性方面做出一定权衡取舍。

原理介绍

NebulaGraph Operator 实现了存储卷 Provisioner 接口。Provisioner 接口负责创建和删除 Persistent Volume 对象。通过存储卷 Provisioner,您可按需创建 Local PV。NebulaGraph Operator 根据集群配置文件中定义的 PVC 和 StorageClass,自动创建 PVC 并绑定到对应 Local PV 上。

当 Provisioner 接口创建 Local PV 时,Provisioner 控制器创建local类型的 PV,并且设置nodeAffinity字段,这样将使用local类型的 PV 的 Pod 被调度到特定节点上。当删除 Local PV 时,Provisioner 控制器移除local类型的 PV 对象,并清理节点上的存储资源。

前提条件

已安装 NebulaGraph Operator。详情参见安装 NebulaGraph Operator

操作步骤

以下示例所创建的资源均处于默认命名空间default中。

=== "GKE 上使用 Local PV"

  1. 创建具备本地 SSD 的节点池。
gcloud container node-pools create "pool-1" --cluster "gke-1" --region us-central1 --node-version "1.27.10-gke.1055000" --machine-type "n2-standard-2" --local-nvme-ssd-block count=2 --max-surge-upgrade 1 --max-unavailable-upgrade 0 --num-nodes 1 --enable-autoscaling --min-nodes 1 --max-nodes 2

关于创建具备本地 SSD 节点池的参数解释,请参见创建具备本地 SSD 的节点池

  1. 使用 DaemonSet 配置 RAID 并对磁盘进行格式化。

  2. 下载 gke-daemonset-raid-disks.yaml 文件。

  3. 部署 RAID 磁盘 DaemonSet。DaemonSet 会在所有本地 SSD 磁盘上设置 RAID 0 阵列,并将设备格式化为 ext4 文件系统。

kubectl apply -f gke-daemonset-raid-disks.yaml
  1. 部署 Local PV Provisioner。

  2. 下载 local-pv-provisioner.yaml 文件。

  3. 部署 Local PV Provisioner。

kubectl apply -f local-pv-provisioner.yaml
  1. 在集群配置文件中,通过spec.storaged.dataVolumeClaimsspec.metad.dataVolumeClaim定义的 PVC 和 StorageClass 来自动创建 Local PV。其中,StorageClass 需要配置成local-nvme。具体操作步骤,参见创建悦数图数据库集群
<ProductName />集群的部分配置
...
metad:
dataVolumeClaim:
resources:
requests:
storage: 2Gi
storageClassName: local-nvme
storaged:
dataVolumeClaims:
- resources:
requests:
storage: 2Gi
storageClassName: local-nvme
...
  1. 查看 PV 列表。
kubectl get pv

返回:

NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-01be9b75-9c50-4532-8695-08e11b489718 5Gi RWO Delete Bound default/storaged-data-nebula-storaged-0 local-nvme 3m35s
pvc-09de8eb1-1225-4025-b91b-fbc0bcce670f 5Gi RWO Delete Bound default/storaged-data-nebula-storaged-1 local-nvme 3m35s
pvc-4b2a9ffb-9000-4998-a7bb-edb825c872cb 5Gi RWO Delete Bound default/storaged-data-nebula-storaged-2 local-nvme 3m35s
...
  1. 查看 PV 的详细信息。
kubectl get pv pvc-01be9b75-9c50-4532-8695-08e11b489718 -o yaml

返回:

apiVersion: v1
kind: PersistentVolume
metadata:
annotations:
local.pv.provisioner/selected-node: gke-snap-test-snap-test-591403a8-xdfc
nebula-graph.io/pod-name: nebula-storaged-0
pv.kubernetes.io/provisioned-by: nebula-cloud.io/local-pv
creationTimestamp: "2024-03-05T06:12:32Z"
finalizers:
- kubernetes.io/pv-protection
labels:
app.kubernetes.io/cluster: nebula
app.kubernetes.io/component: storaged
app.kubernetes.io/managed-by: nebula-operator
app.kubernetes.io/name: nebula-graph
name: pvc-01be9b75-9c50-4532-8695-08e11b489718
resourceVersion: "9999469"
uid: ee28a4da-6026-49ac-819b-2075154b4724
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 5Gi
claimRef:
apiVersion: v1
kind: PersistentVolumeClaim
name: storaged-data-nebula-storaged-0
namespace: default
resourceVersion: "9996541"
uid: 01be9b75-9c50-4532-8695-08e11b489718
local:
fsType: ext4
path: /mnt/disks/raid0
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- gke-snap-test-snap-test-591403a8-xdfc
persistentVolumeReclaimPolicy: Delete
storageClassName: local-nvme
volumeMode: Filesystem
status:
phase: Bound

=== "EKS 上使用 Local PV"

  1. 创建具备 Instance Store 的节点池。
eksctl create nodegroup --instance-types m5ad.2xlarge --nodes 3 --cluster eks-1

关于创建的节点池的参数解释,请参见创建托管节点池

  1. 使用 DaemonSet 配置 RAID 并对磁盘进行格式化。

  2. 下载 eks-daemonset-raid-disks.yaml 文件。

  3. 根据步骤 1 中创建的节点类型,按需修改eks-daemonset-raid-disks.yaml文件中的nodeSelector.node.kubernetes.io/instance-type字段的值。

spec:
nodeSelector:
node.kubernetes.io/instance-type: "m5ad.2xlarge"
  1. 安装 nvme-cli。
  • Ubuntu 和 Debian 系统
    sudo apt-get update
    sudo apt-get install -y nvme-cli
  • CentOS 和 RHEL 系统
    sudo yum install -y nvme-cli
  1. 部署 RAID 磁盘 DaemonSet。DaemonSet 会在所有本地 SSD 磁盘上设置 RAID 0 阵列,并将设备格式化为 ext4 文件系统。
kubectl apply -f gke-daemonset-raid-disks.yaml
  1. 部署 Local PV Provisioner。

  2. 下载 local-pv-provisioner.yaml 文件。

  3. 部署 Local PV Provisioner。

kubectl apply -f local-pv-provisioner.yaml
  1. 在集群配置文件中,通过spec.storaged.dataVolumeClaimsspec.metad.dataVolumeClaim定义的 PVC 和 StorageClass 来自动创建 Local PV。其中,StorageClass 需要配置成local-nvme。具体操作步骤,参见创建悦数图数据库集群
<ProductName />集群的部分配置
metad:
dataVolumeClaim:
resources:
requests:
storage: 2Gi
storageClassName: local-nvme
storaged:
dataVolumeClaims:
- resources:
requests:
storage: 2Gi
storageClassName: local-nvme
  1. 查看 PV 列表。
kubectl get pv

返回:

NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-290c15cc-a302-4463-a591-84b7217a6cd2 5Gi RWO Delete Bound default/storaged-data-nebula-storaged-0 local-nvme 3m40s
pvc-fbb3167f-f556-4a16-ae0e-171aed0ac954 5Gi RWO Delete Bound default/storaged-data-nebula-storaged-1 local-nvme 3m40s
pvc-6c7cfe80-0134-4573-b93e-9b259c6fcd63 5Gi RWO Delete Bound default/storaged-data-nebula-storaged-2 local-nvme 3m40s
...
  1. 查看 PV 的详细信息。
kubectl get pv pvc-290c15cc-a302-4463-a591-84b7217a6cd2 -o yaml

返回:

apiVersion: v1
kind: PersistentVolume
metadata:
annotations:
local.pv.provisioner/selected-node: ip-192-168-77-60.ec2.internal
nebula-graph.io/pod-name: nebula-storaged-0
pv.kubernetes.io/provisioned-by: nebula-cloud.io/local-pv
creationTimestamp: "2024-03-04T07:51:32Z"
finalizers:
- kubernetes.io/pv-protection
labels:
app.kubernetes.io/cluster: nebula
app.kubernetes.io/component: storaged
app.kubernetes.io/managed-by: nebula-operator
app.kubernetes.io/name: nebula-graph
name: pvc-290c15cc-a302-4463-a591-84b7217a6cd2
resourceVersion: "7932689"
uid: 66c0a2d3-2914-43ad-93b5-6d84fb62acef
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 5Gi
claimRef:
apiVersion: v1
kind: PersistentVolumeClaim
name: storaged-data-nebula-storaged-0
namespace: default
resourceVersion: "7932688"
uid: 8ecb5d96-004b-4672-bac4-1355ae15eae4
local:
fsType: ext4
path: /mnt/disks/raid0
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- ip-192-168-77-60.ec2.internal
persistentVolumeReclaimPolicy: Delete
storageClassName: local-nvme
volumeMode: Filesystem
status:
phase: Bound

云上环境中 Local PV 的故障转移

使用网络存储(如 AWS EBS、Google Cloud Persistent Disk、Azure Disk Storage、Ceph、NFS 等)作为 PV,存储资源不依赖于任何特定节点,因此无论 Pod 被调度到哪个节点,都能挂载并使用此存储资源。然而,使用本地存储盘作为 PV 时,由于节点亲和性(NodeAffinity),存储资源只能被特定节点上的 Pod 使用。

悦数图数据库的 Storage 服务具备数据冗余能力,可以设置多个奇数分片副本。节点故障时,关联分片会自动迁移到健康节点。但是,使用 Local PV 的 Storage Pod 由于节点亲和性,不能在其他节点运行,必须等待节点恢复。若要在其他节点运行,需要解除 Pod 与 Local PV 的绑定。

针对使用 Local PV 过程中发生节点故障的情况,NebulaGraph Operator 支持结合云上环境的资源弹性伸缩能力进行自动故障转移操作。通过在集群的配置文件中设置spec.enableAutoFailovertrue,自动解除 Pod 与 Local PV 的绑定,从而使 Pod 能在其他节点上运行。

示例如下:

...
spec:
# 开启自动故障转移
enableAutoFailover: true
# Storage 服务为`OFFLINE`状态后等待自动故障转移的时间。
# 默认值 5 分钟。
# 如果 Storage 服务在此期间内恢复正常状态,不会触发故障转移。
failoverPeriod: "2m"
...