# Kubernetes 中的 StorageClass 和动态卷供给

原文：[Dynamic Provisioning and Storage Classes in Kubernetes](hhttps://kubernetes.io/blog/2016/10/dynamic-provisioning-and-storage-in-kubernetes)

存储是容器运行环境的重要一环，Kubernetes 提供了一些用于存储管理的基础能力。动态卷供给是一个 Kubernetes 独有的功能，这一功能允许按需创建存储卷。在没有这种能力之前，集群管理员需要打电话给他们的云或者存储提供者来创建新的存储卷，成功以后再创建 `PersistentVolume` 对象，才能够在 Kubernetes 中使用。动态卷供给能力让管理员不必进行预先创建存储卷，而是随用户需求进行创建。这一特性在 1.2 版本中处于 α 阶段，在 [版本 1.4](http://blog.kubernetes.io/2016/09/kubernetes-1.4-making-it-easy-to-run-on-kuberentes-anywhere.html) 中提升为 β。这一版本提高了动态卷的弹性和可用性。

## 新特性

Alpha 版本的动态卷，一个集群同时只能允许单独的、被硬编码的提供者。也就是说，如果 Kubernetes 要提供动态卷的时候，即使集群中可以使用多个存储系统，Kubernetes 也只会使用同一个存储卷插件。存储提供者的选型是基于云环境类型决定的 —— AWS 的 EBS，Google Cloud 的 Persistent Disk 或者是 OpenStack 的 Cinder，以及 vSphere 的 vSphere Volume。另外只有容量参数可以配置。这就意味着，即使有其他参数可用，所有的动态卷除了尺寸大小，其他都是一样的。

> 因为只有容量是大家都有的吧。。。

虽说这一功能的 Alpha 版本实用性有限，这毕竟是迈出了一步，有助于确定今后的发展方向。

Kubernetes 1.4 中中加入了一个 [新的 API 对象](http://kubernetes.io/docs/user-guide/persistent-volumes/#storageclasses) `StorageClass`，可以定义多个 `StorageClass` 对象，并可以分别指定存储插件、设置参数，用于提供不同的存储卷。这样的设计让集群管理员能够在同一个集群内，定义和提供不同类型的、不同参数的卷（相同或者不同的存储系统）。这样的设计还确保了最终用户在无需了解太多的情况下，有能力选择不同的存储选项。

## 如何使用

下面是一个例子，管理员提供了两种存储，用户可以选择其中一个使用。细节可以查看 [手册](http://kubernetes.io/docs/user-guide/persistent-volumes/#storageclasses) 以及 [示例](https://github.com/kubernetes/kubernetes/tree/release-1.4/examples/experimental/persistent-volume-provisioning) 文档。

### 管理员配置

集群管理员定义并发布了两个 `StorageClass` 对象

~~~yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1beta1
metadata:
  name: slow
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-standard
~~~

> 这一段创建了一个名为 "slow" 的 `StorageClass`，用于提供标准的持久存储。

~~~yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1beta1
metadata:
  name: fast
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-ssd
~~~

> 这一段创建了一个名为 "fast" 的 `StorageClass`，用于提供类似 SSD 的持久存储。

### 用户请求

用户在 `PersistentVolumeClaim` 中可以包含一个 `StorageClass` 申请动态提供存储。这一任务需要使用 `volume.beta.kubernetes.io/storage-class` 注解来完成。这一注解的值必须符合管理员配置的 `StorageClass` 名称。

要选择 "fast" 存储类，用户需要创建如下的 PVC：

~~~json
 {
  "kind": "PersistentVolumeClaim",
  "apiVersion": "v1",
  "metadata": {
    "name": "claim1",
    "annotations": {
        "volume.beta.kubernetes.io/storage-class": "fast"
    }
  },
  "spec": {
    "accessModes": [
      "ReadWriteOnce"
    ],
    "resources": {
      "requests": {
        "storage": "30Gi"
      }
    }
  }
}
~~~

上述报文会提供一个等效于 SSD 的持久盘，当这个 PVC 被删除，这个卷也随之销毁。

### 缺省行为

所有的 PVC 都可以在不使用 `StorageClass` 注解的情况下，直接使用某个动态存储。把一个 `StorageClass` 对象标记为 "default" 就可以了。`StorageClass` 用注解 `storageclass.beta.kubernetes.io/is-default-class` 就可以成为缺省存储。

有了缺省的 `StorageClass`，用户创建 PVC 就不用 storage-class 的注解了，1.4 中新加入的 [DefaultStorageClass](https://github.com/kubernetes/kubernetes/pull/30900) 准入控制器会自动把这个标注指向缺省存储类。

### 我还能使用 Alpha 版本么？

Kubernetes 1.4 兼容 alpha 版本的动态卷特性，让用户能够平滑过渡到 beta 版本。用 `volume.alpha.kubernetes.io/storage-class` 注解来标注 alpha 版本。

在未来版本中将会弃用 Alpha 版本。

### 下一步？

动态卷功能会持续发展，下面是一些要点。

#### 标准云支持

如果 Kubernetes 集群部署在云服务商，我们 [考虑](https://github.com/kubernetes/kubernetes/pull/31617/files) 自动使用云的本地存储系统创建一个动态卷供给者。例如在 AWS 上的标准部署会得到一个 EBS 的动态卷供给，而 Google Cloud 的部署则会提供一个 GCE PD 动态卷供应者。我们还在讨论是否应该把这种卷作为缺省卷。
