# StorageClass自动创建卷

之前提到的都是需要集群管理员**手动创建PV资源**的，这里将提供一种可以动态创建PV卷的方法，即利用StorageClass资源。

StorageClass中会指定置备程序，在使用PVC尝试申请PV卷时，该程序会自动创建PV卷，然后绑定至PVC。

使用StorageClass动态创建PV卷的步骤有三步：

1. 创建StorageClass，并且指定其置备程序（即创建哪种类型的存储技术的PV卷）；
2. 创建PVC，在PVC的`spec.storageClassName`中指定需要动态创建PV卷的StorageClass的名字；
3. 创建Pod，挂载PVC卷；

从上面的步骤中可以看到，省去了手动创建PV卷的功能，且StorageClass资源一次创建，可无数次使用。

{% hint style="info" %}
**Tips:** 可以在StorageClass中预创建PV资源，即在PV的`spec.storageClassName`指定其所属的StorageClass资源（通常不这么做，因为使用StorageClass就是为了动态创建PV，因此这样做没什么意义）。
{% endhint %}

下面展示完整的从StorageClass中申请PV资源的步骤：

![PV动态配置的完整图示](https://2906552408-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M6Ub8CloS5kJszh6xSR%2Fsync%2Fb4577baf6a67387eecdf807302e0a0485c16a455.png?generation=1588594616433460\&alt=media)

## 创建StorageClass

StorageClass在Kubernetes中也是一种资源，同样可以使用配置文件进行创建。

下面展示一个例子，创建一个名为`fast`的StorageClass资源，其用来创建hostPath类型的PV卷，因此其置备程序被指定为`k8s.io/minikube-hostpath`：

```yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: k8s.io/minikube-hostpath    # （必须）用于配置PV卷的置备程序
parameters:
  type: pd-ssd
```

## 创建PVC

在PVC中，需要指定`spec.storageClassName`从指定的StorageClass资源中动态申请PV资源：

1. 若`storageClassName`不指定，即没有写该字段，则从集群默认的StorageClass资源中分配PV卷；
2. 若`storageClassName=""`，则不从任何一个StorageClass中申请PV，而是尝试与预创建的不属于任何StorageClass的PV卷绑定（即PV的`spec.storageClassName=""`）；
3. 若`storageClassName=fast`，则从名为`fast`的StorageClass中申请PV卷；

下面展示一个例子，创建一个名为`mongodb-pvc`的PVC资源，该资源从名为`fast`的StorageClass中动态分配大小为`100Mi`，访问模式为`仅允许被一个Node读写`的PV资源：

```yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mongodb-pvc 
spec:
  resources:    # PVC请求的资源规格
    requests:
      storage: 100Mi
  accessModes:    # 卷的访问模式
    - ReadWriteOnce
  storageClassName: fast    # 请求从名为fast的StorageClass中动态分配PV资源
```

## 使用Pod挂载PVC资源

对于用户而言，无论是动态创建PV还是静态创建PV，他们都是无感的，因此只需要在Pod中挂载PVC，两步即可：

1. 定义卷：此处定义的是PVC资源，即在`spec.volumes.persistentVolumeClaim`中指定`claimName`为预先创建好的PVC资源的名字，即与PVC相关联；
2. 挂载卷：在Pod的`spec.container.volumeMounts`中指定挂载点和挂载卷名；

下面举一个例子，创建一个名为`mongodb`的Pod，其在内部的名为`mongodb`的容器的`/data/db`下挂载一个名为`mongodb-data`的PVC卷，该卷与名为`mongodb-pvc`的PVC资源关联：

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: mongodb 
spec:
  containers:
  - image: mongo
    name: mongodb
    volumeMounts:    # 定义挂载点
    - name: mongodb-data    # （必须）需要挂载的卷名
      mountPath: /data/db    # （必须）挂载至容器的文件系统中的路径
    ports:
    - containerPort: 27017
      protocol: TCP
  volumes:    # 定义卷
  - name: mongodb-data    # （必须）卷名
    persistentVolumeClaim:    # 定义一个PVC卷
      claimName: mongodb-pvc    # 与预先创建好的PVC资源名一致
```
