6.1 持久化存储: PV 和 PVC 的设计与实现原理

Volume Controller

  • PersistentVolumeController 绑定 PVC 与 PV

持久化 Volume:

image.png

  • 持久化 Volume 依赖远程存储服务

将宿主机目录持久化

  1. 第一阶段

kubelet 默认为 Volume 创建的目录是一个宿主机上的路径:

  1. /var/lib/kubelet/pods/<Pod ID>/volumes/kubernetes.io~<Volume Type>/<Volume Name>

根据 Volume 类型再进行下一步:

  • 如果是远程块存储 (如 GCE), 那么 kuberlet 就调用 Google Cloud 的 API, 将 Persistent Disk 挂载到宿主机上
  • 相当于执行:
$ gcloud compute instances attach-disk <虚拟机名字> --disk <远程磁盘名字>
  1. 第二阶段

kubelet 格式化这个磁盘, 然后挂载到宿主机的挂载点上.

  • 相当于执行:

image.png

挂载不是 mount 命令吗?

如果使用 NFS, 那么只有第二阶段:

image.png

  • 第一阶段依靠 AttachDetachController
  • 第二阶段依靠 VolumeManagerReconciler

StorageClass

自动创建 PV 机制: Dynamic Provisioning

  • 人工管理 PV: Static Provisioning

StorageClass 是API 对象, 作用是创建 PV 的模板:

  • PV 属性, 存储类型, Volume 大小等
  • 存储插件, 如 Ceph

Kubernetes 根据用户提交的PVC找到一个对应的StorageClass。然后’Kubemetes就会调用该StorageClass声明的存储插件’创建出需要的PV°

StorageClass 定义:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
    name: block-service
provisioner: kubernetes.io/gce-pd
parameters:
    type: pd-ssd

使用 Rook 存储服务:

image.png

在 PVC 中指定要使用的 StorageClass:

image.png
image.png

小结

image.png

image.png

6.2 深入理解本地持久化数据卷

Local PV, 适用场景有限.

难点一: 如何抽象本地磁盘为 PV

  • 一个磁盘一个 PV

难点二: 如何保证 Pod 正确被调度到 Local PV 所在节点

  • 调度器需要知道所有节点于 Local PV 的对应关系
    • VolumeBindingChecker

image.png

  • 如果 Pod 想要使用 这个 PV, 就必须在 node-1 上运行

创建 PVC 使用的 StorageClass:

  • no-provisioner: Local PV 不支持 Dynamic Provisioning
  • WaitForFirstConsumer: 延迟绑定, 避免 PV 与具体磁盘在调度 Pod 之前绑定, 防止亲和性冲突

image.png

定义一个 PVC:

image.png

定义 Pod:

image.png

删除 PV 流程步骤:

image.png

Static Provisioner: 自动创建/删除 PV