本页面介绍了如何在 Google Kubernetes Engine (GKE) 集群上预配本地 SSD 存储空间,以及如何配置工作负载以使用连接到集群中节点的本地 SSD 支持的原始块存储空间中的数据。
使用此本地固态硬盘选项可让您更好地控制底层存储空间,并为 Pod 构建自己的节点级缓存,从而为应用提供更好的性能。您还可以根据需要运行 DaemonSet 来配置 RAID 并对磁盘进行格式化,从而在本地固态硬盘磁盘上安装文件系统,以自定义此选项。
如需详细了解 GKE 上本地 SSD 对原始块访问的支持,请参阅本地 SSD 简介。
须知事项
在开始之前,请确保您已执行以下任务:
- 启用 Google Kubernetes Engine API。 启用 Google Kubernetes Engine API
- 如果您要使用 Google Cloud CLI 执行此任务,请安装并初始化 gcloud CLI。 如果您之前安装了 gcloud CLI,请运行
gcloud components update
以获取最新版本。
创建具有本地固态硬盘支持的原始块存储的集群或节点池
将 gcloud CLI 与 --local-nvme-ssd-block
选项搭配使用,以创建具有本地固态硬盘支持的原始块存储的集群。
您用于创建集群或节点池的 gcloud CLI 命令取决于您使用的机器类型所属的机器系列代。例如,N1 和 N2 机器类型分别属于第一代和第二代机器系列,而 C3 机器类型属于第三代机器系列。
创建具有本地 SSD 的集群
第 1 代或第 2 代
如果您使用第 1 代或第 2 代机器系列中的机器类型,则可以通过指定 --local-nvme-ssd-block count=NUMBER_OF_DISKS
选项来创建集群。此选项会指定要挂接到每个节点的本地固态硬盘磁盘的数量。数量上限因机器类型和区域而异。
要创建集群,请执行以下操作:
gcloud container clusters create CLUSTER_NAME \
--local-nvme-ssd-block count=NUMBER_OF_DISKS \
--machine-type=MACHINE_TYPE \
--release-channel CHANNEL_NAME
替换以下内容:
CLUSTER_NAME
:集群的名称。NUMBER_OF_DISKS
:每个节点上预配的本地固态硬盘的数量。磁盘的最大数量因机器类型和区域而异。MACHINE_TYPE
:要使用的第 1 代或第 2 代机器类型。此字段是必填字段,因为您不能将本地固态硬盘与默认的e2-medium
类型搭配使用。CHANNEL_NAME
:包含高于 1.25.3-gke.1800 的 GKE 版本的发布渠道。
第 3 代
如果您使用的是第 3 代机器系列中的机器类型,请使用 --local-nvme-ssd-block
选项(不带计数字段)创建集群。GKE 会根据虚拟机类型为您的集群自动预配本地固态硬盘容量。数量上限因机器类型和区域而异。
gcloud container clusters create CLUSTER_NAME \
--machine-type=MACHINE_TYPE \
--cluster-version CLUSTER_VERSION \
--local-nvme-ssd-block
替换以下内容:
CLUSTER_NAME
:集群的名称。MACHINE_TYPE
:要使用的第 3 代机器系列中的机器类型。CLUSTER_VERSION
:GKE 集群版本,支持在第 3 代机器系列中的机器类型上使用本地 SSD。
创建具有本地 SSD 的节点池
第 1 代或第 2 代
如需创建节点池以使用本地固态硬盘磁盘进行原始块访问,请运行以下命令:
gcloud container node-pools create POOL_NAME \
--cluster=CLUSTER_NAME \
--machine-type=MACHINE_TYPE \
--local-nvme-ssd-block count=NUMBER_OF_DISKS
替换以下内容:
POOL_NAME
:新节点池的名称。CLUSTER_NAME
:集群的名称。MACHINE_TYPE
:要使用的第 1 代或第 2 代机器类型。此字段是必填字段,因为本地 SSD 不能与默认的e2-medium
类型搭配使用。NUMBER_OF_DISKS
:每个节点上预配的本地固态硬盘的数量。磁盘的最大数量因机器类型和区域而异。
第 3 代
如果您使用的是第 3 代机器系列中的机器类型,请使用 --local-nvme-ssd-block
选项(不带计数字段)创建集群:
gcloud container node-pools create POOL_NAME \
--cluster=CLUSTER_NAME \
--machine-type=MACHINE_TYPE \
--node-version NODE_VERSION \
--local-nvme-ssd-block
替换以下内容:
POOL_NAME
:新节点池的名称。CLUSTER_NAME
:集群的名称。MACHINE_TYPE
:要使用的第 3 代机器类型中的机器类型。NODE_VERSION
:GKE 节点池版本,支持在第三代机器系列中的机器类型上使用本地 SSD。
在节点池中创建的节点包含一个 cloud.google.com/gke-local-nvme-ssd=true
标签。您可以通过运行以下命令来验证标签:
kubectl describe node NODE_NAME
对于挂接到节点池的每个本地 SSD,主机操作系统都会创建一个符号链接(用于访问序号文件夹下的磁盘),以及一个包含通用唯一标识符 (UUID) 的符号链接。例如,如果您使用 --local-nvme-ssd-block
选项创建具有三个本地 SSD 的节点池,则主机操作系统会为磁盘创建以下符号链接:
/dev/disk/by-id/google-local-ssd-block0
/dev/disk/by-id/google-local-ssd-block1
/dev/disk/by-id/google-local-ssd-block2
相应地,主机操作系统还会为磁盘创建以下具有 UUID 的符号链接:
/dev/disk/by-uuid/google-local-ssds-nvme-block/local-ssd-GENERATED_UUID1
/dev/disk/by-uuid/google-local-ssds-nvme-block/local-ssd-GENERATED_UUID2
/dev/disk/by-uuid/google-local-ssds-nvme-block/local-ssd-GENERATED_UUID3
这样就能确保可以使用唯一标识符访问磁盘。
访问本地固态硬盘卷
以下示例展示了如何访问本地 SSD 支持的原始块存储。
本地 PersistentVolume
可以使用 PersistentVolumes 将本地固态硬盘卷作为 Pod 装载。
如需从本地 SSD 创建 PersistentVolume,您既可以手动创建 PersistentVolume,也可以运行本地卷静态预配工具。
本地 PersistentVolume 的限制
升级 GKE 集群或修复节点会删除 Compute Engine 实例,同时也会删除本地 SSD 磁盘上的所有数据。
请勿针对使用本地 SSD 来存储持久性数据的集群或节点池启用节点自动升级或节点自动修复。您必须先备份应用数据,然后将数据还原到新的集群或节点池。
- 当删除、升级、修复或缩减节点时,系统不会自动清理本地 PersistentVolume 对象。我们建议您定期扫描并删除与已删除节点关联的过时本地 PersistentVolume 对象。
手动创建 PersistentVolume
您可以为集群中每个节点上的每个本地 SSD 手动创建 PersistentVolume。
请使用 PersistentVolume 对象中的 nodeAffinity
字段来引用特定节点上的本地 SSD。以下示例展示了运行 Linux 的节点上本地固态硬盘的 PersistentVolume 规范:
apiVersion: v1
kind: PersistentVolume
metadata:
name: "example-local-pv"
spec:
capacity:
storage: 375Gi
accessModes:
- "ReadWriteOnce"
persistentVolumeReclaimPolicy: "Retain"
storageClassName: "local-storage"
local:
path: "/mnt/disks/ssd0"
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: "kubernetes.io/hostname"
operator: "In"
values:
- "gke-test-cluster-default-pool-926ddf80-f166"
在此示例中,本地固态硬盘磁盘手动配置为 RAID 并格式化,然后装载到节点 gke-test-cluster-default-pool-926ddf80-f166
上的 /mnt/disks/ssd0
处。nodeAffinity 字段用于帮助将工作负载分配给手动配置为 RAID 的本地固态硬盘的节点。如果集群中只有一个节点,或者您为所有节点配置了 RAID,则无需 nodeAffinity 字段。
相应的 PersistenVolumeClaim 规范如下所示:
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: ssd-local-claim
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-storage
resources:
requests:
storage: 37Gi
如果删除 PersistentVolume,则必须手动清空磁盘中的数据。
运行本地卷静态预配工具
您可以使用本地卷静态预配工具自动为本地 SSD 创建 PersistentVolume。预配工具是一个 DaemonSet,用于管理每个节点上的本地固态硬盘磁盘、为它们创建和删除 PersistentVolume 以及在释放 PersistentVolume 时清除本地固态硬盘磁盘上的数据。
要运行本地卷静态预配程序,请执行以下操作:
使用 DaemonSet 配置 RAID 并对磁盘进行格式化:
- 下载
gke-daemonset-raid-disks.yaml
规范。 部署 RAID 磁盘 DaemonSet。DaemonSet 会在所有本地 SSD 磁盘上设置 RAID 0 阵列,并将设备格式化为
ext4
文件系统。kubectl create -f gke-daemonset-raid-disks.yaml
- 下载
下载
gke-nvme-ssd-block-raid.yaml
规范,并根据需要修改该规范的命名空间字段。规范包括以下资源:
- 预配工具的 ServiceAccount
- 拥有以下权限的 ClusterRole 和 ClusterRoleBinding:
- 创建和删除 PersistentVolume 对象
- 获取 Node 对象
- 具有适用于 GKE 的预配工具设置的 ConfigMap
- 用于运行预配工具的 DaemonSet
部署预配工具:
kubectl create -f gke-nvme-ssd-block-raid.yaml
预配工具成功运行后,它将为集群中的 RAID 本地固态硬盘设备创建一个 PersistentVolume 对象。
将以下 PersistentVolumeClaim 清单保存为
provisioner-pvc-example.yaml
:kind: PersistentVolumeClaim apiVersion: v1 metadata: name: PVC_NAME spec: accessModes: - ReadWriteOnce resources: requests: storage: 50Gi storageClassName: nvme-ssd-block
将
PVC_NAME
替换为您的 PersistentVolumeClaim 名称。创建 PersistentVolumeClaim:
kubectl create -f provisioner-pvc-example.yaml
将以下 Pod 清单另存为
provisioner-pod-example.yaml
:apiVersion: v1 kind: Pod metadata: name: POD_NAME spec: containers: - name: "shell" image: "ubuntu:14.04" command: ["/bin/sh", "-c"] args: ["echo 'hello world' > /cache/test.txt && sleep 1 && cat /cache/test.txt && sleep 3600"] volumeMounts: - mountPath: /cache name: local-ssd-storage volumes: - name: local-ssd-storage persistentVolumeClaim: claimName: PVC_NAME
将
POD_NAME
替换为您的 Pod 名称。创建 Pod:
kubectl create -f provisioner-pod-example.yaml
启用延迟的卷绑定
为了提升调度性能,我们还建议您使用 volumeBindingMode: WaitForFirstConsumer
创建 StorageClass。这会将 PersistentVolumeClaim 绑定延迟到 Pod 调度阶段,以便从可运行 Pod 的适当节点中选择本地固态硬盘。在为可运行的 Pod 选择节点时,此增强的调度行为不仅考虑了 Pod CPU 和内存请求、节点亲和性、Pod 亲和性和反亲和性以及多个 PersistentVolumeClaim 请求,还考虑了哪些节点具有可用的本地固态硬盘。
此示例使用延迟的卷绑定模式:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: "local-nvme"
provisioner: "kubernetes.io/no-provisioner"
volumeBindingMode: "WaitForFirstConsumer"
如需创建具有延迟绑定的 StorageClass,请将 YAML 清单保存到本地文件,并使用以下命令将其应用到集群:
kubectl apply -f filename
问题排查
如需了解问题排查说明,请参阅对 GKE 中的存储空间进行问题排查。