kubernetes StorageClass(NFS)
一. StorageClass 简介
在K8S环境,当pod需要存储空间时,StorageClass比PV更灵活和方便,每个 StorageClass 都包含 provisioner、parameters 和 reclaimPolicy 字段, 这些字段会在 StorageClass 需要动态分配 PersistentVolume 时会使用到。
StorageClass的属性
• Provisioner(存储分配器):用来决定使用哪个卷插件分配 PV,该字段必须指定。可以指 定内部分配器,也可以指定外部分配器。外部分配器的代码地址为: kubernetesincubator/external-storage,其中包括NFS和Ceph等。
• Reclaim Policy(回收策略):通过reclaimPolicy字段指定创建的Persistent Volume的回收 策略,回收策略包括:Delete 或者 Retain,没有指定默认为Delete。
二. 部署nfs-client
这里我们以NFS为例,要使用NFS,我们就需要一个nfs-client的自动装载程序,我们称之为Provisioner,这个程序会使用我们已经配置好的NFS服务器自动创建持久卷,也就是自动帮我们创建PV。
详细可以参考:https://github.com/kubernetes-retired/external-storage/blob/master/nfs-client/deploy/deployment.yaml
在部署之前,首先得确保有可用得NFS服务器,这里默认已经有可用得NFS服务器了。
- 创建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@baozexu 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
-
创建nfs-client
使用Deployment来创建nfs-client,配置如下:nfs-client.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: nfs-client-provisioner labels: app: nfs-client-provisioner # replace with namespace where provisioner is deployed namespace: default 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: easzlab/nfs-subdir-external-provisioner:v4.0.1 volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes env: - name: PROVISIONER_NAME value: rookieops/nfs - name: NFS_SERVER value: 2.16.128.1 - name: NFS_PATH value: /public volumes: - name: nfs-client-root nfs: server: 2.16.128.1 path: /public
然后创建这个yaml文件
[root@baozexu storageclass]# kubectl apply -f nfs-client.yaml deployment.extensions/nfs-client-prosioner created
查看其状态
[root@baozexu nfs]# kubectl get pods NAME READY STATUS RESTARTS AGE nfs-client-provisioner-6c59bb8b-k8hd8 1/1 Running 0 50m
- 上面创建完成后就可以创建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@baozexu nfs]# kubectl apply -f nfs-client-storageclass.yaml
storageclass.storage.k8s.io/nfs-client-storageclass created
[root@baozexu nfs]# kubectl get storageclasses.storage.k8s.io
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
nfs-client-storageclass rookieops/nfs Delete Immediate false 4h30m
注意:卷绑定模式
volumeBindingMode
字段控制了卷绑定和动态制备 应该发生在什么时候。
默认情况下,Immediate
模式表示一旦创建了 PersistentVolumeClaim 也就完成了卷绑定和动态制备。 对于由于拓扑限制而非集群所有节点可达的存储后端,PersistentVolume 会在不知道 Pod 调度要求的情况下绑定或者制备。
集群管理员可以通过指定 WaitForFirstConsumer
模式来解决此问题。 该模式将延迟 PersistentVolume 的绑定和制备,直到使用该 PersistentVolumeClaim 的 Pod 被创建。 PersistentVolume 会根据 Pod 调度约束指定的拓扑来选择或制备。这些包括但不限于 资源需求、 节点筛选器、 pod 亲和性和互斥性、 以及污点和容忍度。
- 创建pvc
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc1
spec:
storageClassName: nfs-client-storageclass
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
- 创建这个yaml文件,观察其状态:
[root@nfs baozexu]# kubectl apply -f test-pvc.yaml
persistentvolumeclaim/test-nfs-pvc created
[root@baozexu nfs]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc1 Bound pvc-33d2aa7f-e52f-4865-a05e-ebd53fbec914 1Gi RWX nfs-client-storageclass 120m
我们看到该PVC自动申请到空间,其STORAGECLASS就是我们创建的nfs-client-storageclass。
6. 创建一个pod,进行测试 pv-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: 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: pvc1
- 查看pv是否生成
[root@baozexu ~]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-33d2aa7f-e52f-4865-a05e-ebd53fbec914 1Gi RWX Delete Bound default/pvc1 nfs-client-storageclass 77m
- 然后查看nfs目录中是否有文件生成
[root@baozexu public]# ls
default-pvc1-pvc-33d2aa7f-e52f-4865-a05e-ebd53fbec914
我们可以看到生成了对应的目录,格式和我们上面说的一致。