暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

kubernetes中用NFS做后端存储支不支持PVC扩容?

乔克的好奇心 2020-02-07
2189
↑ 点击上方“乔边故事”关注我们


在虚拟机时代,我们经常会收到给磁盘扩容的需求,一般我们就是添加一块磁盘,然后做LVM扩容操作,那在容器时代,我们可以给PVC扩容吗?

之前发了持久化存储相关的知识--PV和PVCStorageClass,本文来给你介绍一下用NFS做后端存储能不能扩容的问题,当然在生产上没有哪个愿意用NFS做后端存储......

你首先需要准备好NFS存储

首先我们介绍一下pv和pvc模式,也就是纯手动创建的模式。
(1)、首先我们创建一个PV的YAML文件(pv2.yaml)

  1. apiVersion: v1

  2. kind: PersistentVolume

  3. metadata:

  4. name: my-pv02

  5. labels:

  6. storage: pv

  7. spec:

  8. accessModes:

  9. - ReadWriteOnce

  10. capacity:

  11. storage: 500Mi

  12. persistentVolumeReclaimPolicy: Recycle

  13. nfs:

  14. path: /data/k8s

  15. server: 10.1.10.128

创建pv

  1. # kubectl apply -f pv2.yaml

  2. persistentvolume/my-pv02 created

  3. # kubectl get pv

  4. NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE 30s

  5. my-pv02 500Mi RWO Recycle Bound default/pvc-test 30s

(2)、创建PVC(pvc.yaml),我们这里创建一个比较小的pvc,如下

  1. apiVersion: v1

  2. kind: PersistentVolumeClaim

  3. metadata:

  4. name: pvc-test

  5. spec:

  6. accessModes:

  7. - ReadWriteOnce

  8. resources:

  9. requests:

  10. storage: 500Mi

然后创建pvc

  1. # kubectl apply -f pvc.yaml

  2. # kubectl get pvc

  3. NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE

  4. pvc-test Bound my-pv02 500Mi RWO 58s

我们其实可以看到,我在pvc里定义的是500Mi,它会自动匹配刚好合适的PV。
这时候如果我们修改my-pv02的YAML文件,如下:

  1. apiVersion: v1

  2. kind: PersistentVolume

  3. metadata:

  4. name: my-pv02

  5. labels:

  6. storage: pv

  7. spec:

  8. accessModes:

  9. - ReadWriteOnce

  10. capacity:

  11. storage: 2Gi

  12. persistentVolumeReclaimPolicy: Recycle

  13. nfs:

  14. path: /data/k8s

  15. server: 10.1.10.128

然后我们尝试创建这个PV,如下:

  1. # kubectl apply -f pv2.yaml

  2. persistentvolume/my-pv02 configured

  3. # kubectl get pv

  4. NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE

  5. my-pv02 2Gi RWO Recycle Bound default/pvc-test 116m

  6. # kubectl get pvc

  7. NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE

  8. pvc-test Bound my-pv02 500Mi RWO 116m

我们看到我们my-pv02的CAPACITY变成了2Gi,我们的pvc还是500Mi,那么我们能不能对PVC进行扩容呢?我尝试的修改了pvc的配置文件,如下:

  1. apiVersion: v1

  2. kind: PersistentVolumeClaim

  3. metadata:

  4. name: pvc-test

  5. spec:

  6. accessModes:

  7. - ReadWriteOnce

  8. resources:

  9. requests:

  10. storage: 1Gi

然后我们执行这个配置文件

  1. ]# kubectl apply -f pvc.yaml

  2. Error from server (Forbidden): error when applying patch:

  3. {"metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"v1\",\"kind\":\"PersistentVolumeClaim\",\"metadata\":{\"annotations\":{},\"name\":\"pvc-test\",\"namespace\":\"default\"},\"spec\":{\"accessModes\":[\"ReadWriteOnce\"],\"resources\":{\"requests\":{\"storage\":\"1Gi\"}}}}\n"}},"spec":{"resources":{"requests":{"storage":"1Gi"}}}}

  4. to:

  5. Resource: "/v1, Resource=persistentvolumeclaims", GroupVersionKind: "/v1, Kind=PersistentVolumeClaim"

  6. Name: "pvc-test", Namespace: "default"

  7. Object: &{map["apiVersion":"v1" "kind":"PersistentVolumeClaim" "metadata":map["annotations":map["kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"v1\",\"kind\":\"PersistentVolumeClaim\",\"metadata\":{\"annotations\":{},\"name\":\"pvc-test\",\"namespace\":\"default\"},\"spec\":{\"accessModes\":[\"ReadWriteOnce\"],\"resources\":{\"requests\":{\"storage\":\"500Mi\"}}}}\n" "pv.kubernetes.io/bind-completed":"yes" "pv.kubernetes.io/bound-by-controller":"yes"] "creationTimestamp":"2019-12-24T10:46:05Z" "finalizers":["kubernetes.io/pvc-protection"] "name":"pvc-test" "namespace":"default" "resourceVersion":"15059" "selfLink":"/api/v1/namespaces/default/persistentvolumeclaims/pvc-test" "uid":"6a905af6-5e44-4940-ba87-e56f6e99df24"] "spec":map["accessModes":["ReadWriteOnce"] "resources":map["requests":map["storage":"500Mi"]] "volumeMode":"Filesystem" "volumeName":"my-pv02"] "status":map["accessModes":["ReadWriteOnce"] "capacity":map["storage":"500Mi"] "phase":"Bound"]]}

  8. for: "pvc.yaml": persistentvolumeclaims "pvc-test" is forbidden: only dynamically provisioned pvc can be resized and the storageclass that provisions the pvc must support resize

我们发现报错了,错误信息如下:

  1. persistentvolumeclaims "pvc-test" is forbidden: only dynamically provisioned pvc can be resized and the storageclass that provisions the pvc must support resize

它的意思就是说只有动态供应的pvc可以调整大小,供应pvc的存储类必须支持调整大小。也就是说我们手动创建PV,PVC模式是不支持调整大小的。

我们现在来验证一下用storageclass创建的PVC。
(1)、因为我们使用nfs作为后端存储,所以我们需要先创建一个nfs-client,YAML文件如下:

  1. ---

  2. apiVersion: v1

  3. kind: ServiceAccount

  4. metadata:

  5. name: nfs-client-provisioner


  6. ---

  7. apiVersion: rbac.authorization.k8s.io/v1

  8. kind: ClusterRole

  9. metadata:

  10. name: nfs-client-provisioner-clusterrole

  11. rules:

  12. - apiGroups: [""]

  13. resources: ["persistentvolumes"]

  14. verbs: ["get", "list", "watch", "create", "delete"]

  15. - apiGroups: [""]

  16. resources: ["persistentvolumeclaims"]

  17. verbs: ["get", "list", "watch", "update"]

  18. - apiGroups: ["storage.k8s.io"]

  19. resources: ["storageclasses"]

  20. verbs: ["get", "list", "watch"]

  21. - apiGroups: [""]

  22. resources: ["events"]

  23. verbs: ["list", "watch", "create", "update", "patch"]

  24. - apiGroups: [""]

  25. resources: ["endpoints"]

  26. verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]


  27. ---

  28. apiVersion: rbac.authorization.k8s.io/v1

  29. kind: ClusterRoleBinding

  30. metadata:

  31. name: nfs-client-provisioner-clusterrolebinding

  32. subjects:

  33. - kind: ServiceAccount

  34. name: nfs-client-provisioner

  35. namespace: default

  36. roleRef:

  37. kind: ClusterRole

  38. name: nfs-client-provisioner-clusterrole

  39. apiGroup: rbac.authorization.k8s.io

  40. ---

  41. apiVersion: extensions/v1beta1

  42. kind: Deployment

  43. metadata:

  44. name: nfs-client-prosioner

  45. spec:

  46. replicas: 1

  47. strategy:

  48. type: Recreate

  49. template:

  50. metadata:

  51. labels:

  52. app: nfs-client-prosioner

  53. spec:

  54. serviceAccountName: nfs-client-provisioner

  55. containers:

  56. - name: nfs-client-prosioner

  57. image: registry.cn-hangzhou.aliyuncs.com/rookieops/nfs-client-provisioner:v0.1

  58. imagePullPolicy: IfNotPresent

  59. volumeMounts:

  60. - name: nfs-client-root

  61. mountPath: /data/pv

  62. env:

  63. - name: PROVISIONER_NAME

  64. value: rookieops/nfs

  65. - name: NFS_SERVER

  66. value: 10.1.10.128

  67. - name: NFS_PATH

  68. value: /data/k8s

  69. volumes:

  70. - name: nfs-client-root

  71. nfs:

  72. server: 10.1.10.128

  73. path: /data/k8s

创建YAML文件

  1. # kubectl apply -f !$

  2. kubectl apply -f nfs-client.yaml

  3. serviceaccount/nfs-client-provisioner created

  4. clusterrole.rbac.authorization.k8s.io/nfs-client-provisioner-clusterrole created

  5. clusterrolebinding.rbac.authorization.k8s.io/nfs-client-provisioner-clusterrolebinding created

  6. deployment.extensions/nfs-client-prosioner created

  7. # kubectl get pod

  8. NAME READY STATUS RESTARTS AGE

  9. nfs-client-prosioner-56f44c675b-t2ml9 1/1 Running 0 6s

(1)我们创建一个普通的StorageClass(storageclass.yaml)

  1. apiVersion: storage.k8s.io/v1

  2. kind: StorageClass

  3. metadata:

  4. name: nfs-client-storageclass

  5. provisioner: rookieops/nfs

创建这个YAML文件

  1. # kubectl apply -f storageclass.yaml

  2. storageclass.storage.k8s.io/nfs-client-storageclass created

  3. # kubectl get storageclasses.storage.k8s.io

  4. NAME PROVISIONER AGE

  5. nfs-client-storageclass rookieops/nfs 34s

创建一个PVC(storageclass-pvc.yaml)

  1. apiVersion: v1

  2. kind: PersistentVolumeClaim

  3. metadata:

  4. name: test-nfs-pvc2

  5. annotations:

  6. volume.beta.kubernetes.io/storage-class: "nfs-client-storageclass"

  7. spec:

  8. accessModes:

  9. - ReadWriteMany

  10. resources:

  11. requests:

  12. storage: 1Mi

创建这个YAML文件

  1. # kubectl apply -f storageclass-pvc.yaml

  2. persistentvolumeclaim/test-nfs-pvc2 created

  3. # kubectl get pvc

  4. NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE

  5. pvc-test Bound my-pv02 500Mi RWO 26d

  6. test-nfs-pvc2 Bound pvc-9dd9c608-6875-4609-829c-c92920aaa783 1Mi RWX nfs-client-storageclass 21s

我们看到已经Bound了,我们现在直接修改pvc(storageclass-pvc.yaml)

  1. apiVersion: v1

  2. kind: PersistentVolumeClaim

  3. metadata:

  4. name: test-nfs-pvc2

  5. annotations:

  6. volume.beta.kubernetes.io/storage-class: "nfs-client-storageclass"

  7. spec:

  8. accessModes:

  9. - ReadWriteMany

  10. resources:

  11. requests:

  12. storage: 100Mi

然后我们执行这个YAML文件

  1. # kubectl apply -f storageclass-pvc.yaml

  2. Error from server (Forbidden): error when applying patch:

  3. {"metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"v1\",\"kind\":\"PersistentVolumeClaim\",\"metadata\":{\"annotations\":{\"volume.beta.kubernetes.io/storage-class\":\"nfs-client-storageclass\"},\"name\":\"test-nfs-pvc2\",\"namespace\":\"default\"},\"spec\":{\"accessModes\":[\"ReadWriteMany\"],\"resources\":{\"requests\":{\"storage\":\"100Mi\"}}}}\n"}},"spec":{"resources":{"requests":{"storage":"100Mi"}}}}

  4. to:

  5. Resource: "/v1, Resource=persistentvolumeclaims", GroupVersionKind: "/v1, Kind=PersistentVolumeClaim"

  6. Name: "test-nfs-pvc2", Namespace: "default"

  7. Object: &{map["apiVersion":"v1" "kind":"PersistentVolumeClaim" "metadata":map["annotations":map["kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"v1\",\"kind\":\"PersistentVolumeClaim\",\"metadata\":{\"annotations\":{\"volume.beta.kubernetes.io/storage-class\":\"nfs-client-storageclass\"},\"name\":\"test-nfs-pvc2\",\"namespace\":\"default\"},\"spec\":{\"accessModes\":[\"ReadWriteMany\"],\"resources\":{\"requests\":{\"storage\":\"1Mi\"}}}}\n" "pv.kubernetes.io/bind-completed":"yes" "pv.kubernetes.io/bound-by-controller":"yes" "volume.beta.kubernetes.io/storage-class":"nfs-client-storageclass" "volume.beta.kubernetes.io/storage-provisioner":"rookieops/nfs"] "creationTimestamp":"2020-01-20T06:04:20Z" "finalizers":["kubernetes.io/pvc-protection"] "name":"test-nfs-pvc2" "namespace":"default" "resourceVersion":"29483" "selfLink":"/api/v1/namespaces/default/persistentvolumeclaims/test-nfs-pvc2" "uid":"9dd9c608-6875-4609-829c-c92920aaa783"] "spec":map["accessModes":["ReadWriteMany"] "resources":map["requests":map["storage":"1Mi"]] "volumeMode":"Filesystem" "volumeName":"pvc-9dd9c608-6875-4609-829c-c92920aaa783"] "status":map["accessModes":["ReadWriteMany"] "capacity":map["storage":"1Mi"] "phase":"Bound"]]}

  8. for: "storageclass-pvc.yaml": persistentvolumeclaims "test-nfs-pvc2" is forbidden: only dynamically provisioned pvc can be resized and the storageclass that provisions the pvc must support resize

发现报与上面一样的错,这是因为要支持动态扩容需要满足两个条件:

  • 后端底层存储支持卷扩展(后端存储保证足够资源)

  • 需要在StorageClass对象中设置allowVolumeExpansion为true

我们由于是测试,申请的资源比较少,我们直接对StorageClass对象进行修改(storageclass.yaml),如下:

  1. apiVersion: storage.k8s.io/v1

  2. kind: StorageClass

  3. metadata:

  4. name: nfs-client-storageclass

  5. provisioner: rookieops/nfs

  6. allowVolumeExpansion: true

然后我们重新申明一下

  1. # kubectl apply -f storageclass.yaml

  2. storageclass.storage.k8s.io/nfs-client-storageclass configured

我们再次创建前面的storageclass-pvc.yaml文件

  1. # kubectl apply -f storageclass-pvc.yaml

  2. persistentvolumeclaim/test-nfs-pvc2 configured

我们发现这次没有报错,我们查看一下这个PVC

  1. # kubectl get pvc

  2. NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE

  3. pvc-test Bound my-pv02 500Mi RWO 26d

  4. test-nfs-pvc2 Bound pvc-9dd9c608-6875-4609-829c-c92920aaa783 1Mi RWX nfs-client-storageclass 14m

我们一看,发现并没有扩展成功,这是为什么呢?我们describe一下这个pvc,发现如下提示:

  1. # kubectl describe pvc test-nfs-pvc2

  2. ...

  3. Warning ExternalExpanding 7m43s volume_expand

  4. Ignoring the PVC: didn't find a plugin capable of expanding the volume; waiting for an external controller to process this PVC.

报错信息为:没有找到可扩展的插件。
我上官方网站一看,原来人家已经说的很清楚了:Although the feature is enabled by default, a cluster admin must opt-in to allow users to resize their volumes. Kubernetes v1.11 ships with volume expansion support for the following in-tree volume plugins: AWS-EBS, GCE-PD, Azure Disk, Azure File, Glusterfs, Cinder, Portworx, and Ceph RBD.

我们的NFS并不被支持(用NFS做后端存储的小伙伴注意了哈)。



-----------------------

公众号:乔边故事(ID:qiaobiangushi)

知乎: 乔边故事

头条号:乔边故事

只要脸皮够厚,整个世界都将被你踩在脚下。

-----------------------

扫码二维码关注公众号,不定期维护优质内容,技术干货!


温馨提示

如果你喜欢本文,请分享到朋友圈,想要获得更多信息,请关注我。




文章转载自乔克的好奇心,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论