StorageClass 存储类用于描述集群中可以提供的存储的类型。不同的存储类可能对应着不同的:
服务等级(quality-of-service level)
备份策略
集群管理员自定义的策略
Kubernetes 自身对存储类所代表的含义并无感知,由集群管理员自行约定。
每个 StorageClass 都包含 provisioner、parameters 和 reclaimPolicy 字段, 这些字段会在 StorageClass 需要动态分配 PersistentVolume 时会使用到。
StorageClass 对象的命名很重要,用户使用这个命名来请求生成一个特定的类。 当创建 StorageClass 对象时,管理员设置 StorageClass 对象的命名和其他参数,一旦创建了对象就不能再对其更新。
Kubernetes 本身支持的动态 PV 创建不包括 NFS,所以需要使用外部存储卷插件分配PV。
卷插件称为 Provisioner(存储分配器),NFS 使用的是 nfs-client,这个外部卷插件会使用已经配置好的 NFS 服务器自动创建 PV。 Provisioner:用于指定 Volume 插件的类型,包括内置插件(如 kubernetes.io/aws-ebs)和外部插件(如 external-storage 提供的 ceph.com/cephfs)。
这里新建一个/data/nfs/的文件夹,并挂载。
vim nfs-client-rbac.yaml
#创建 Service Account 账户,用来管理 NFS Provisioner 在 k8s 集群中运行的权限 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: # 绑定角色 ServiceAccount - kind: ServiceAccount name: nfs-client-provisioner namespace: default roleRef: kind: ClusterRole name: nfs-client-provisioner-clusterrole apiGroup: rbac.authorization.k8s.io
kubectl apply -f nfs-client-rbac.yaml
kubectl get serviceaccount -A|grep nfs kubectl get clusterrole -A|grep nfs kubectl get clusterrolebinding -A|grep nfs
由于 1.20 版本启用了 selfLink,所以 k8s 1.20+ 版本通过 nfs provisioner 动态生成pv会报错,解决方法如下
vim /etc/kubernetes/manifests/kube-apiserver.yaml - --feature-gates=RemoveSelfLink=false #添加这一行
# 重启apiserver,删除apiserver的pod,让他自动重建 kubectl delete pod kube-apiserver-master01 -n kube-system kubectl get pod --all-namespaces
有两个功能:一个是在 NFS 共享目录下创建挂载点(volume),另一个则是将 PV 与 NFS 的挂载点建立关联。
vim nfs-client-provisioner.yaml
kind: Deployment apiVersion: apps/v1 metadata: name: nfs-client-provisioner spec: replicas: 1 selector: matchLabels: app: nfs-client-provisioner strategy: type: Recreate template: metadata: labels: app: nfs-client-provisioner spec: serviceAccountName: nfs-client-provisioner #指定Service Account账户 containers: - name: nfs-client-provisioner image: quay.io/external_storage/nfs-client-provisioner:latest imagePullPolicy: IfNotPresent volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes env: - name: TZ value: Asia/Shanghai #容器时区 - name: PROVISIONER_NAME value: nfs-storage #配置provisioner的Name,确保该名称与StorageClass资源中的provisioner名称保持一致 - name: NFS_SERVER value: 192.168.102.130 #配置绑定的nfs服务器 - name: NFS_PATH value: /data/nfs #配置绑定的nfs服务器目录,挂载路径 volumes: #申明nfs数据卷 - name: nfs-client-root nfs: server: 192.168.102.130 #配置绑定的nfs服务器 path: /data/nfs
kubectl apply -f nfs-client-provisioner.yaml kubectl get pod --all-namespaces
查看 apiVersion 版本
kubectl api-resources
vim nfs-client-storageclass.yaml
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: nfs-client-storageclass provisioner: nfs-storage #这里的名称要和provisioner配置文件中的环境变量PROVISIONER_NAME保持一致 parameters: archiveOnDelete: "false" #false表示在删除PVC时不会对数据进行存档,即删除数据
kubectl apply -f nfs-client-storageclass.yaml kubectl get storageclasses
vim test-pvc-pod.yaml
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: test-nfs-pvc spec: accessModes: - ReadWriteOnce storageClassName: nfs-client-storageclass #关联StorageClass对象 resources: requests: storage: 2Gi
kubectl apply -f test-pvc-pod.yaml kubectl get pvc kubectl get pv
自动绑定
nfs服务器查看
cd /data/nfs ls -l
创建一个pod
vim pod.yaml
apiVersion: v1 kind: Pod metadata: name: task-pv-pod spec: volumes: - name: task-pv-storage persistentVolumeClaim: claimName: test-nfs-pvc containers: - name: task-pv-container image: nginx ports: - containerPort: 80 name: "http-server" env: - name: TZ value: Asia/Shanghai #容器时区 volumeMounts: - mountPath: "/usr/share/nginx/html" name: task-pv-storage #与PVC名称保持一致
kubectl apply -f pod.yaml kubectl get pod --all-namespaces
在 NFS 服务器中,添加一条数据。因为我们把 pod 的 /usr/share/nginx/html 目录挂载到了 pvc,所以在 /data/nfs 目录下面新增文件就相当于在 /usr/share/nginx/html 目录下新增文件。
cd /data/nfs/default-test-nfs-pvc-pvc-f83594bf-cd41-4056-9065-bd19a3871c43/ vim index.html cat index.html
访问
kubectl get pods -o wide curl 10.122.241.118