StorageClass
上面介绍的PV和PVC模式是需要运维人员先创建好PV,然后开发人员定义好PVC进行一对一的Bond,但是如果PVC请求成千上万,那么就需要创建成千上万的PV,对于运维人员来说维护成本很高,Kubernetes提供一种自动创建PV的机制,叫StorageClass,它的作用就是创建PV的模板。
具体来说,StorageClass会定义一下两部分:
- PV的属性 ,比如存储的大小、类型等;
- 创建这种PV需要使用到的存储插件,比如Ceph等;
有了这两部分信息,Kubernetes就能够根据用户提交的PVC,找到对应的StorageClass,然后Kubernetes就会调用 StorageClass声明的存储插件,创建出需要的PV。
这里我们以NFS为例,要使用NFS,我们就需要一个nfs-client的自动装载程序,我们称之为Provisioner,这个程序会使用我们已经配置好的NFS服务器自动创建持久卷,也就是自动帮我们创建PV。
说明:
- 自动创建的PV会以${namespace}-${pvcName}-${pvName}的目录格式放到NFS服务器上;
- 如果这个PV被回收,则会以archieved-${namespace}-${pvcName}-${pvName}这样的格式存放到NFS服务器上;
详细可以参考:https://github.com/kubernetes-incubator/external-storage/tree/master/nfs-client
在部署之前,首先得确保有可用得NFS服务器,这里默认已经有可用得NFS服务器了。
1、创建ServiceAccount,为nfs-client授权。
nfs-client-sa.yaml --- apiVersion: v1 kind: ServiceAccount metadata: name: nfs-client-provisioner --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: nfs-client-provisioner-clusterrole rules: - apiGroups: [""] resources: ["persistentvolumes"] verbs: ["get", "list", "watch", "create", "delete"] - apiGroups: [""] resources: ["persistentvolumeclaims"] verbs: ["get", "list", "watch", "update"] - apiGroups: ["storage.k8s.io"] resources: ["storageclasses"] verbs: ["get", "list", "watch"] - apiGroups: [""] resources: ["events"] verbs: ["list", "watch", "create", "update", "patch"] - apiGroups: [""] resources: ["endpoints"] verbs: ["create", "delete", "get", "list", "watch", "patch", "update"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: nfs-client-provisioner-clusterrolebinding subjects: - kind: ServiceAccount name: nfs-client-provisioner namespace: default roleRef: kind: ClusterRole name: nfs-client-provisioner-clusterrole apiGroup: rbac.authorization.k8s.io
通过上面得配置,设置nfs-client对PV,PVC,StorageClass等得规则。接下来我们创建这个YAML文件:
[root@master storageclass]# kubectl apply -f nfs-client-sa.yaml serviceaccount/nfs-client-provisioner created clusterrole.rbac.authorization.k8s.io/nfs-client-provisioner-clusterrole created clusterrolebinding.rbac.authorization.k8s.io/nfs-client-provisioner-clusterrolebinding created
2、创建nfs-client
使用Deployment来创建nfs-client,配置如下:
nfs-client.yaml --- apiVersion: apps/v1 kind: Deployment metadata: name: nfs-client-prosioner spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app: nfs-client-prosioner template: metadata: labels: app: nfs-client-prosioner spec: serviceAccountName: nfs-client-provisioner containers: - name: nfs-client-prosioner image: registry.cn-hangzhou.aliyuncs.com/rookieops/nfs-client-provisioner:v0.1 imagePullPolicy: IfNotPresent volumeMounts: - name: nfs-client-root mountPath: /data/pv env: - name: PROVISIONER_NAME value: rookieops/nfs - name: NFS_SERVER value: 192.168.0.177 - name: NFS_PATH value: /data/k8s volumes: - name: nfs-client-root nfs: server: 192.168.0.177 path: /data/k8s
然后创建这个YAML文件。
[root@master storageclass]# kubectl apply -f nfs-client.yaml
deployment.extensions/nfs-client-prosioner created
查看其状态:
[root@master storageclass]# kubectl get pod NAME READY STATUS RESTARTS AGE nfs-client-prosioner-66c9bb7f88-q2qm4 1/1 Running 0 52m
3、上面得创建完成后就可以创建StorageClass了。
nfs-client-storageclass.yaml
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: nfs-client-storageclass provisioner: rookieops/nfs
注意provisioner必须和上面得Deployment的YAML文件中PROVISIONER_NAME的值保持一致。
创建这个YAML文件:
[root@master storageclass]# kubectl apply -f nfs-client-storageclass.yaml storageclass.storage.k8s.io/nfs-client-storageclass created [root@master storageclass]# kubectl get storageclass NAME PROVISIONER AGE nfs-client-storageclass fuseim.pri/ifs 15s
4、创建PVC
test-nfs-pvc.yaml
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: test-nfs-pvc2 annotations: volume.beta.kubernetes.io/storage-class: "nfs-client-storageclass" spec: accessModes: - ReadWriteMany resources: requests: storage: 1Mi
annotations的作用是在PVC里声明一个StorageClass对象的标识。
创建这个YAML文件,观察其状态:
[root@master storageclass]# kubectl apply -f test-pvc.yaml persistentvolumeclaim/test-nfs-pvc created [root@master storageclass]# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE test-nfs-pvc Bound pvc-e5b8765b-1d7b-4529-860f-bbe34e0b4109 1Mi RWX nfs-client-storageclass 2m16s
我们看到该PVC自动申请到空间,其STORAGECLASS就是我们创建的nfs-client-storageclass。
5、创建一个Pod,进行测试
test-pod.yaml
apiVersion: v1 kind: Pod metadata: name: test-storageclass-pod spec: containers: - name: busybox image: busybox:latest imagePullPolicy: IfNotPresent command: - "/bin/sh" - "-c" args: - "sleep 3600" volumeMounts: - name: nfs-pvc mountPath: /mnt restartPolicy: Never volumes: - name: nfs-pvc persistentVolumeClaim: claimName: test-nfs-pvc2
然后查看NFS服务器上是否生成对应的目录:
[root@master k8s]# ll total 0 drwxrwxrwx 2 root root 6 Oct 29 17:21 default-test-nfs-pvc2-pvc-91671ba7-8da8-4611-8bd5-3673f63d15cb
我们可以看到生成了对应的目录,格式和我们上面说的一致。现在进Pod向该目录下写一个文件,然后查看NFS服务器上是否存在该文件:
[root@master storageclass]# kubectl exec -it test-storageclass-pod -- /bin/sh / # cd /mnt/ /mnt # echo "hello,I am NFS Server!" > test /mnt # ls test [root@master default-test-nfs-pvc2-pvc-91671ba7-8da8-4611-8bd5-3673f63d15cb]# ls test [root@master default-test-nfs-pvc2-pvc-91671ba7-8da8-4611-8bd5-3673f63d15cb]# cat test hello,I am NFS Server!
我们发现NFS服务器上存在,说明我们验证成功。
另外我们可以看到我们这里是手动创建的一个 PVC 对象,在实际工作中,使用 StorageClass 更多的是 StatefulSet 类型的服务,StatefulSet 类型的服务我们也可以通过一个 volumeClaimTemplates 属性来直接使用 StorageClass,如下:(test-statefulset-nfs.yaml)
apiVersion: apps/v1beta1 kind: StatefulSet metadata: name: nfs-web spec: serviceName: "nginx" replicas: 2 template: metadata: labels: app: nfs-web spec: terminationGracePeriodSeconds: 10 containers: - name: nginx image: nginx:1.7.9 imagePullPolicy: IfNotPresent ports: - containerPort: 80 name: web volumeMounts: - name: www mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: www annotations: volume.beta.kubernetes.io/storage-class: nfs-client-storageclass spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 1Gi
可以看到volumeClaimTemplates就是我们上面的PVC模板。然后我们创建这个文件:
[root@master storageclass]# kubectl apply -f test-statefulset.yaml statefulset.apps/nfs-web created [root@master storageclass]# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE www-nfs-web-0 Bound pvc-5df69dbe-8b54-45dd-acd0-769c0c9ee1b8 1Gi RWO nfs-client-storageclass 7s www-nfs-web-1 Bound pvc-0e83fef9-ec16-4e02-8482-7e04b7c81c92 1Gi RWO nfs-client-storageclass 3s
可以看到会自动生成两个PVC。
在NFS服务器上也可以看到正常创建了目录:
[root@master k8s]# ll total 0 drwxrwxrwx 2 root root 18 Oct 29 17:29 default-test-nfs-pvc2-pvc-91671ba7-8da8-4611-8bd5-3673f63d15cb drwxrwxrwx 2 root root 6 Oct 29 17:34 default-www-nfs-web-0-pvc-5df69dbe-8b54-45dd-acd0-769c0c9ee1b8 drwxrwxrwx 2 root root 6 Oct 29 17:34 default-www-nfs-web-1-pvc-0e83fef9-ec16-4e02-8482-7e04b7c81c92