一个大规模的 K8s 集群里很可能有成千上万个 PVC,运维人员必须得事先创建出成千上万个 PV,而随着新的 PVC 被提交,运维人员不得不继续添加新的 PV,否则新的 Pod 就会因为 PVC 绑定不到 PV 而失败。在实际操作中,这几乎没办法靠人工做到。
所以 K8s 提供了一套可以自动创建 PV 的机制,即:Dynamic Provisioning。
相比之下前面人工管理 PV 的方式就叫作 Static Provisioning。
Dynamic Provisioning 机制工作的核心在于一个名叫 StorageClass 的 API 对象。
而 StorageClass 对象的作用就是创建 PV 的模板。
StorageClass 对象会定义如下两个部分内容:
- PV 的属性。比如,存储类型、Volume 的大小等等。
- 创建这种 PV 需要用到的存储插件。比如,Ceph 等等。
有了这两个信息后,K8s 就能根据用户提交的 PVC,找到一个对应的 StorageClass 。然后调用该 StorageClass 声明的存储插件,创建出需要的 PV。
假如我们的 Volume 的类型是 GCE 的 Persistent Disk 的话,运维人员就需要定义一个如下所示的 StorageClass:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: block-service
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-ssd
provisioner 字段的值是:kubernetes.io/gce-pd,是 K8s 内置的 GCE PD 存储插件的名字。
parameters 字段是 PV 的参数。type=pd-ssd,指的是这个 PV 的类型是“SSD 格式的 GCE 远程磁盘”。
有了 StorageClass 的 YAML 文件之后,运维人员就可以在 K8s 里创建这个 StorageClass 了:
$ kubectl create -f sc.yaml
这时候,作为应用开发者,我们只需要在 PVC 里指定要使用的 StorageClass 名字即可:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: claim1
spec:
accessModes:
- ReadWriteOnce
storageClassName: block-service
resources:
requests:
storage: 30Gi
storageClassName 字段用于指定该 PVC 所要使用的 StorageClass 的名字是:block-service。
以 Google Cloud 为例。
通过 kubectl create 创建上述 PVC 对象之后,K8s 就会调用 Google Cloud 的 API,创建出一块 SSD 格式的 Persistent Disk。再使用这个 Persistent Disk 的信息,自动创建出一个对应的 PV 对象。
$ kubectl create -f pvc.yaml
可以看到,创建的 PVC 会绑定一个 K8s 自动创建的 PV:
$ kubectl describe pvc claim1
Name: claim1
Namespace: default
StorageClass: block-service
Status: Bound
Volume: pvc-e5578707-c626-11e6-baf6-08002729a32b
Labels: <none>
Capacity: 30Gi
Access Modes: RWO
No Events.
查看这个自动创建的 PV 的属性,它跟 PVC 里声明的存储的属性是一致的,如下所示:
$ kubectl describe pv pvc-e5578707-c626-11e6-baf6-08002729a32b
Name: pvc-e5578707-c626-11e6-baf6-08002729a32b
Labels: <none>
StorageClass: block-service
Status: Bound
Claim: default/claim1
Reclaim Policy: Delete
Access Modes: RWO
Capacity: 30Gi
...
No events.
这个自动创建出来的 PV 的 StorageClass 字段的值,也是 block-service。这是因为,K8s 只会将 StorageClass 相同的 PVC 和 PV 绑定起来。
有了 Dynamic Provisioning 机制,运维人员只需要在 K8s 集群里创建出数量有限的 StorageClass 对象就可以了。这就好比运维人员在集群里创建出了各样的 PV 模板。当开发人员提交了包含 StorageClass 字段的 PVC 后,K8s 就会根据这个 StorageClass 创建出对应的 PV。