使用本地 SSD


本页面简要介绍 Kubernetes 的本地 SSD 支持,以及如何将本地 SSD 与 Google Kubernetes Engine (GKE) 搭配使用。

概览

本地 SSD 为集群中的每个节点提供高性能临时存储设备。与标准磁盘相比,本地 SSD 具有更高的吞吐量和更短的延迟时间。本地 SSD 适用于提供本地缓存和处理的工作负载。

您可以在集群的机器类型限制和项目的配额范围内创建具有本地 SSD 的节点池。

  • 写入本地 SSD 的数据为临时数据,在删除、修复、升级节点或节点遇到不可恢复的错误时,这些数据不会继续留存。

  • 本地 SSD 仅挂接到一个节点,而节点本身就是临时性的。您可以随时将工作负载调度到其他节点上。

如需详细了解本地固态硬盘的好处和局限性,例如性能和每种机器类型允许的固态硬盘数量,请参阅 Compute Engine 文档中的本地固态硬盘

创建具有本地 SSD 的集群

您可以通过 Google Cloud Console 或 gcloud 命令行工具创建集群或更新集群以使用本地 SSD。

控制台

您可以通过 Cloud Console 中的 GKE 菜单创建具有本地 SSD 的集群或节点池。

如需创建默认池使用本地 SSD 的集群,请执行以下操作:

  1. 转到 Cloud Console 中的 Google Kubernetes Engine 页面:

    转到 Google Kubernetes Engine

  2. 点击 创建

  3. 根据需要配置集群。

  4. 在导航窗格的节点池下,点击默认池 (default-pool)。

  5. 节点数字段中,输入 2

  6. 在导航窗格的默认池 (default-pool) 下,点击节点

  7. 输入每个节点所需的本地 SSD 磁盘绝对数量。

  8. 点击创建

要在现有集群中创建具有本地 SSD 磁盘的节点池,请执行以下步骤:

  1. 转到 Cloud Console 中的 Google Kubernetes Engine 页面:

    转到 Google Kubernetes Engine

  2. 在集群列表中,点击您要修改的集群的名称。

  3. 点击 添加节点池

  4. 节点数字段中,输入 1

  5. 在导航窗格中,点击节点

  6. 输入每个节点所需的本地 SSD 磁盘绝对数量。

  7. 点击创建

gcloud

如需使用 gcloud 创建具有本地 SSD 的集群或节点池,请指定 --local-ssd count 标志。--local-ssd-count 指定要为每个节点创建的本地 SSD 数量。数量上限因机器类型和地区而异。 创建节点时,本地 SSD 会自动格式化并装载到节点文件系统的装载点处(例如,第一个磁盘装载到 /mnt/disks/ssd0,第二个磁盘装载到 /mnt/disks/ssd1,依此类推)。

要创建默认池使用本地 SSD 磁盘的集群,请运行以下命令:

gcloud container clusters create CLUSTER_NAME \
  --num-nodes 2 \
  --local-ssd-count NUMBER_OF_DISKS \
  --machine-type MACHINE_TYPE

如需在现有集群中创建具有本地 SSD 磁盘的节点池,请运行以下命令:

gcloud container node-pools create POOL_NAME \
  --cluster CLUSTER_NAME \
  --num-nodes 1 \
  --local-ssd-count NUMBER_OF_DISKS \
  --machine-type MACHINE_TYPE

请替换以下内容:

  • CLUSTER_NAME:集群的名称。
  • POOL_NAME:新节点池的名称。
  • NUMBER_OF_DISKS:每个节点上预配的本地固态硬盘的数量。
  • MACHINE_TYPE:要使用的机器类型,因为本地固态硬盘不能与默认的 e2-medium 类型搭配使用

使用本地 SSD 上的临时存储设备创建节点池

从 1.18 开始,GKE 节点池可以配置为使用本地 SSD 作为临时存储设备。

要使用本地 SSD 上的临时存储设备创建节点池,请运行以下命令:

gcloud beta container node-pools create POOL_NAME \
    --ephemeral-storage local-ssd-count=NUMBER_OF_DISKS \
    --machine-type MACHINE_TYPE

请替换以下内容:

  • POOL_NAME:新节点池的名称。
  • NUMBER_OF_DISKS:每个节点上预配的本地固态硬盘的数量。 在节点设置期间,这些固态硬盘会合并为一个逻辑卷。磁盘的最大数量因机器类型和区域而异
  • MACHINE_TYPE:要使用的机器类型,因为本地固态硬盘不能与默认的 e2-medium 类型搭配使用。

在节点池中创建的节点包含一个 cloud.google.com/gke-ephemeral-storage-local-ssd 标签。您可以通过运行以下命令来验证标签:

kubectl describe node NODE_NAME

为 Windows Server 集群设置本地 SSD 格式

将本地 SSD 与运行 Windows 节点池的集群配合使用时,需要先登录到节点并设置磁盘格式,然后才能使用。以下示例使用 NTFS 文件系统设置本地 SSD 磁盘格式。您还可以在磁盘下创建目录。在此示例中,目录位于磁盘 D 下。

PS C:\> Get-Disk | Where partitionstyle -eq 'raw' | Initialize-Disk -PartitionStyle MBR -PassThru | New-Partition -AssignDriveLetter -UseMaximumSize | Format-Volume -FileSystem ntfs -Confirm:$false
PS C:\> mkdir D:\test-ss

使用本地 SSD

以下部分介绍如何将本地 SSD 与 GKE 结合使用。

您可以使用以下某种方法访问本地 SSD:

  • 使用 hostpath,建议将它们用于:

    • 使用 DaemonSet 的工作负载。
    • 使用专用节点池的工作负载。必须在 DaemonSet 所有实例的相同路径上访问所有本地 SSD。
  • 使用 local PersistentVolumes,建议将其用于:

    • 使用 StatefulSet 和 volumeClaimTemplate 的工作负载。
    • 共享节点池的工作负载。每个本地固态硬盘可以通过 PersistentVolumeClaim 保留,并且特定主机路径不直接在 Pod 规范中编码。
    • 需要同一本地 SSD 的数据引力的 Pod。Pod 始终与其本地 PersistentVolume 安排在同一节点上。
  • 使用临时存储设备作为 emptyDir(已在 GKE 1.18 及更高版本中推出 Beta 版),建议用于:

    • 需要高性能临时暂存空间的应用。

    此功能将节点池配置为在本地 SSD 上装载节点临时存储空间。使用 emptyDir 的 Pod 以透明方式使用本地 SSD;但是,该节点池上的所有节点上的所有 Pod 也是如此。某些 Pod 无法使用本地 SSD emptyDir 卷,而其他 Pod 无法使用传统 emptyDir。对于不应使用传统 emptyDir 卷的工作负载,请将这些工作负载安排到其他节点池中。

hostPath 卷用法示例

以下示例展示了如何在 Windows 和 Linux 中使用 hostPath 卷。

Linux

如果您创建了具有三个本地 SSD 的节点池,则主机操作系统会将这些磁盘分别装载到 /mnt/disks/ssd0/mnt/disks/ssd1/mnt/disks/ssd2。您的 Kubernetes 容器使用对象配置文件中定义的 hostPath 参数来访问磁盘。

以下示例 Pod 配置文件引用了本地 SSD /mnt/disks/ssd0

apiVersion: v1
kind: Pod
metadata:
  name: "test-ssd"
spec:
  containers:
  - name: "shell"
    image: "ubuntu:14.04"
    command: ["/bin/sh", "-c"]
    args: ["echo 'hello world' > /test-ssd/test.txt && sleep 1 && cat /test-ssd/test.txt"]
    volumeMounts:
    - mountPath: "/test-ssd/"
      name: "test-ssd"
  volumes:
  - name: "test-ssd"
    hostPath:
      path: "/mnt/disks/ssd0"
  nodeSelector:
    cloud.google.com/gke-local-ssd: "true"

Windows

apiVersion: v1
kind: Pod
metadata:
  name: "test-ssd"
spec:
  containers:
  - name: "test"
    image: "mcr.microsoft.com/windows/servercore/iis"
    volumeMounts:
    - mountPath: "/test-ssd/"
      name: "test-ssd"
  volumes:
  - name: "test-ssd"
    hostPath:
      path: "d:\\test-ssd"
  nodeSelector:
    cloud.google.com/gke-local-ssd: "true"
    kubernetes.io/os: windows

本地 PersistentVolume 用法示例

本地 SSD 可指定为 PersistentVolume

如需从本地 SSD 创建 PersistentVolume,您既可以手动创建 PersistentVolume,也可以运行本地卷静态预配工具。

限制

  • 本地 PersistentVolume 目前不支持集群自动扩缩动态预配

  • 升级 GKE 集群或修复节点会删除 Compute Engine 实例,同时也会删除本地 SSD 上的所有数据。

  • 请勿针对使用本地 SSD 来存储持久性数据的集群或节点池启用节点自动升级节点自动修复。您必须先备份应用数据,然后将数据还原到新的集群或节点池。请注意,使用发布版本时,不能停用自动升级和自动修复。不建议将本地 PersistentVolume 用于发布版本中的集群。

  • 当删除、升级、修复或缩减节点时,系统不会自动清理本地 PersistentVolume 对象。我们建议您定期扫描并删除与已删除节点关联的过时本地 PersistentVolume 对象。

手动创建 PersistentVolume

您可以为集群中每个节点上的每个本地 SSD 手动创建 PersistentVolume。

请使用 PersistentVolume 对象中的 nodeAffinity 字段来引用特定节点上的本地 SSD。例如,以下 Linux 示例是装载到 gke-test-cluster-default-pool-926ddf80-f166 节点上 /mnt/disks/ssd0 子目录中的本地 SSD 的 PersistentVolume 规范:

Linux

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"

Windows

apiVersion: v1
kind: PersistentVolume
metadata:
  name: ssd-local-pv
spec:
  capacity:
    storage: 375Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  local:
    path: "d:\\test-ssd"
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - gke-gke-cluster-windows-dds-2263bc7c-wq6m
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: ssd-local-claim
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: local-storage
  resources:
    requests:
      storage: 37Gi

您现在可以创建一个 Pod 来访问该磁盘。如需确保将 Pod 正确调度到 Windows Server 节点上,您必须在 Pod 规范中添加节点选择器:

apiVersion: v1
kind: Pod
metadata:
  name: "test-ssd"
spec:
  containers:
  - name: "test"
    image: "mcr.microsoft.com/windows/servercore/iis"
    volumeMounts:
    - mountPath: "/test-ssd/"
      name: "test-ssd"
  volumes:
  - name: "test-ssd"
    persistentVolumeClaim:
      claimName: ssd-local-claim
  nodeSelector:
    cloud.google.com/gke-local-ssd: "true"
  tolerations:
  - key: "node.kubernetes.io/os"
    value: "windows"
    operator: "Equal"
    effect: "NoSchedule"

如果删除 PersistentVolume,您需要手动清空磁盘中的数据。

运行本地卷静态预配工具

您可以使用本地卷静态预配工具自动为本地 SSD 创建 PersistentVolume。预配工具是一个 DaemonSet,用于管理每个节点上的本地 SSD、为它们创建和删除 PersistentVolume 以及在释放 PersistentVolume 时清除本地 SSD 上的数据。

要运行本地卷静态预配程序,请执行以下操作:

  1. sig-storage-local-static-provisioner 代码库下载 gke.yaml 规范,并根据需要修改该规范的 namespace 字段。

    规范包括:

    • 预配工具的 ServiceAccount
    • 拥有以下权限的 ClusterRole 和 ClusterRoleBinding:
      • 创建和删除 PersistentVolume 对象
      • 获取 Node 对象
    • 具有适用于 GKE 的预配程序设置的 ConfigMap
    • 用于运行预配工具的 DaemonSet
  2. 部署预配工具:

    kubectl apply -f gke.yaml
    

预配工具成功运行后,它将为集群中的每个本地 SSD 创建一个 PersistentVolume 对象。

启用延迟的卷绑定

为了提升调度性能,建议您同时创建一个具有 volumeBindingMode: WaitForFirstConsumer 的 StorageClass。这会将 PersistentVolumeClaim 绑定延迟到 Pod 调度阶段,以便从可运行 Pod 的适当节点中选择本地固态硬盘。在为可运行的 Pod 选择节点时,此增强的调度行为不仅考虑了 Pod CPU 和内存请求、节点亲和性、Pod 亲和性和反亲和性以及多个 PersistentVolumeClaim 请求,还考虑了哪些节点具有可用的本地固态硬盘。

此示例使用延迟的卷绑定模式:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: "local-scsi"
provisioner: "kubernetes.io/no-provisioner"
volumeBindingMode: "WaitForFirstConsumer"

如果将集群用于 Windows Server 节点池,您应该创建一个 StorageClass,因为默认 StorageClass 使用仅适用于 Linux 容器的 ext4 作为文件系统类型。

以下 YAML 文件使用将 NTFS 用作文件存储类型的 Compute Engine 永久性磁盘。您可以在操作 Windows 集群时使用此 StorageClass。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: storageclass-name
parameters:
  type: pd-standard
  fstype: NTFS
provisioner: kubernetes.io/gce-pd
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer

如需创建具有延迟绑定的 StorageClass,请将 YAML 清单保存到本地文件,并使用以下命令将其应用到集群:

kubectl apply -f filename

使用临时存储设备作为 emptyDir 卷的示例

GKE 节点池可以配置为使用本地 SSD 作为临时存储设备,包括 emptyDir 卷。

以下是使用 emptyDircloud.google.com/gke-ephemeral-storage-local-ssd 节点选择器的 Pod 的示例 YAML 文件。您可以为 Deployment 或 StatefulSet 应用类似的技术。

apiVersion: v1
kind: Pod
metadata:
  name: POD_NAME
spec:
  containers:
    - name: CONTAINER_NAME
      image: "k8s.gcr.io/pause"
      resources:
        requests:
          ephemeral-storage: "200Gi"
      volumeMounts:
        - mountPath: /cache
          name: scratch-volume
  nodeSelector:
    cloud.google.com/gke-ephemeral-storage-local-ssd: "true"
  volumes:
    - name: scratch-volume
      emptyDir: {}

后续步骤