1. StorageClass简介StorageClass 为管理员提供了描述存储 “类” 的方法。 不同的类型可能会映射到不同的服务质量等级或备份策略,或是由集群管理员制定的任意策略。 Kubernetes 本身并不清楚各种类代表的什么。这个类的概念在其他存储系统中有时被称为 “配置文件”。
参考文档:
2. 安装配置StorageClass概述要使用 StorageClass,我们就得安装对应的自动配置程序,比如存储后端使用的是 nfs-server,那么我们就需要使用到一个 nfs-client 的自动配置程序,我们也叫它 Provisioner,这个程序使用我们已经配置好的 nfs 服务器,来自动创建持久卷,也就是自动帮我们创建 PV。
参考文档:
3. 安装NFS参考文档《Linux中安装NFS》 ,在存储节点安装nfs-server,K8S所有节点安装nfs-client。
nfs-server安装完成后,对外服务路径为:
1 192.168.56.101:/data/nfs
4. 特别注意配置好 nfs-server 后,可以直接用它的IP来配置 nfs-client-provisioner 。 但是,更好的办法是给 nfs-server 配置一个主机名,用主机名来配置 nfs-client-provisioner 。 使用主机名的好处是如果 nfs-server 需要迁移,IP 发生了变更,那么不会影响到 nfs-client-provisioner,也就不会影响到 storageclass。
参考文档:
5. 安装nfs-provisioner1、编写sa spec,nfs-client-sa.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 apiVersion: v1 kind: ServiceAccount metadata: name: nfs-client-provisioner --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: nfs-client-provisioner-runner 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" ] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: run-nfs-client-provisioner subjects: - kind: ServiceAccount name: nfs-client-provisioner namespace: default roleRef: kind: ClusterRole name: nfs-client-provisioner-runner apiGroup: rbac.authorization.k8s.io
2、编写nfs-client-provisioner的deployment spec,nfs-client.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 kind: Deployment apiVersion: apps/v1 metadata: name: nfs-client-provisioner spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app: nfs-client-provisioner template: metadata: labels: app: nfs-client-provisioner spec: serviceAccountName: nfs-client-provisioner containers: - name: nfs-client-provisioner image: registry.cn-beijing.aliyuncs.com/mydlq/nfs-subdir-external-provisioner:v4.0.0 volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes env: - name: PROVISIONER_NAME value: fuseim.pri/ifs - name: NFS_SERVER value: 192.168 .56 .101 - name: NFS_PATH value: /data/nfs volumes: - name: nfs-client-root nfs: server: 192.168 .56 .101 path: /data/nfs
3、编写sc spec,nfs-client-sc.yaml
1 2 3 4 5 6 7 apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: nfs-storage annotations: "storageclass.kubernetes.io/is-default-class": "true" provisioner: fuseim.pri/ifs
这里的fuseim.pri/ifs
是deployment中定义的 PROVISIONER_NAME
变量
4、创建资源对象
1 2 3 kubectl apply -f nfs-client-sa.yaml kubectl apply -f nfs-client.yaml kubectl apply -f nfs-client-sc.yaml
5、查看pod状态
1 kubectl describe pods nfs-client-provisioner-7975f9b954-7fw5l
报错:
1 2 3 4 Output: mount: wrong fs type, bad option, bad superblock on 192.168.56.101:/data/nfs missing codepage or helper program, or other error (for several filesystems (e.g. nfs, cifs) you might need a /sbin/mount.<type> helper program)
这是因为nfs-client-provider依赖宿主机上的/sbin/mount.<type>
,所以所有的节点都需要安装nfs和rpcbind。详情参考nfs挂载报错误wrong fs type, bad option, bad superblock
6. 安装nfs-provisioner简化版1、添加chart repo
1 helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
2、获取chart
1 2 3 4 helm search repo nfs-subdir-external-provisioner/nfs-subdir-external-provisioner -l helm pull nfs-subdir-external-provisioner/nfs-subdir-external-provisioner --version 4.0.18 tar -xzvf nfs-subdir-external-provisioner-4.0.18.tgz vim nfs-subdir-external-provisioner/values.yaml
3、执行安装
1 2 3 4 5 helm install nfs-provisioner ./nfs-subdir-external-provisioner \ --set nfs.server=192.168.56.101 \ --set nfs.path=/data/nfs \ --set image.repository=registry.cn-beijing.aliyuncs.com/mydlq/nfs-subdir-external-provisioner \ --set image.tag=v4.0.0
参考文档:github - kubernetes-sigs/nfs-subdir-external-provisioner
7. 设置默认StorageClass如果没有设置默认的storageclass,可以参考改变默认 StorageClass ,设置nfs-storage
为默认storageclass
1 kubectl patch storageclass nfs-storage -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
8. 启用selflink1.20.x之后的k8s版本,selflink已经弃用了。 而quay.io/external_storage/nfs-client-provisioner:latest
的实现基于selflink,因此在使用时会报错。
解决办法:apiserver添加启动参数--feature-gates=RemoveSelfLink=false
。 详情参考文档《K8S中安装KubeSphere》
如果是k8s1.24.x以上的版本,是不支持修改启动参数RemoveSelfLink的,否则api-server无法启动。 解决办法:替换nfs-client-provisioner的镜像版本为新版本(上文中已经替换)。
9. 使用StorageClass参考文档配置 Pod 以使用 PersistentVolume 作为存储
9.1. 创建 PersistentVolumeClaim1、定义pvc.yaml
1 2 3 4 5 6 7 8 9 10 11 apiVersion: v1 kind: PersistentVolumeClaim metadata: name: busybox-pv-claim spec: storageClassName: nfs-storage accessModes: - ReadWriteOnce resources: requests: storage: 3Gi
2、创建pvc
1 2 3 kubectl apply -f pvc.yaml kubectl get pvc kubectl get pv
注意:nfs-privisioner提供的存储,在申请时是可以超过真实存储容量的。比如NFS的真实存储只有10GB,我们申请的PVC是100GB或者1000GB,也可以申请成功,当PVC绑定给Pod后,能够创建出对应PV。
9.2. 创建Pod1、定义pod.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 apiVersion: v1 kind: Pod metadata: creationTimestamp: null labels: run: busybox name: busybox spec: containers: - command: - sleep - "3000" image: busybox:1.25 name: busybox resources: {} volumeMounts: - mountPath: "/data" name: busybox-pv-storage volumes: - name: busybox-pv-storage persistentVolumeClaim: claimName: busybox-pv-claim dnsPolicy: ClusterFirst restartPolicy: Never status: {}
2、创建pod
1 2 3 4 kubectl apply -f pod.yaml kubectl get pods kubectl get pvc kubectl get pv
3、验证挂载
1 2 3 4 kubectl exec -it busybox /bin/sh df -hls /datatouch /data/test.txt
然后,登录到nfs-server的主机192.168.56.101,查看写入结果。
9.3. volumeClaimTemplates对于statefulset,需要使用volumeClaimTemplates来声明使用storageclass,详情参考StatefulSet
10. 安装配置多个StorageClass如果k8s集群中的存储全部使用同一个nfs-server,那么这个nfs-server的网络压力会很大。 为了分担单个nfs-server的压力,我们可以在多个主机上安装配置nfs-server,然后在k8s中软件部署时规划好哪些软件使用哪个nfs-server。
假设现在我们在192.168.56.102主机上也安装好了nfs-server,下面我们在k8s集群中添加它的配置。
1、再创建一个nfs-client-provisioner,sa不用变
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 kind: Deployment apiVersion: apps/v1 metadata: name: nfs-client-provisioner-102 spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app: nfs-client-provisioner-102 template: metadata: labels: app: nfs-client-provisioner-102 spec: serviceAccountName: nfs-client-provisioner containers: - name: nfs-client-provisioner image: quay.io/external_storage/nfs-client-provisioner:latest volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes env: - name: PROVISIONER_NAME value: fuseim.pri/ifs-102 - name: NFS_SERVER value: 192.168 .56 .102 - name: NFS_PATH value: /data/nfs volumes: - name: nfs-client-root nfs: server: 192.168 .56 .102 path: /data/nfs
2、再创建一个storageclass
1 2 3 4 5 apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: nfs-storage-102 provisioner: fuseim.pri/ifs-102
3、使用192.168.56.102存储数据 当我们使用nfs-storage-102
这个storageclass时,就能够存储数据到 192.168.56.102 这台主机上了。