一、StorageClass持久化存储介绍¶
k8s支持两种资源的供应模式:静态模式(Static)和动态模式(Dynamic)。
- 1、静态模式:集群管理员手工创建PV,在定义PV时需要将后端存储的特性进行设置。
- 2、动态模式:集群管理员无需手工创建PV,而是通过StorageClass的设置对后端存储进行描述,标记为某种类型。此时要求PVC对存储的类型进行声明,系统将自动完成PV的创建及与PVC 的绑定。
1.1 PV的回收策略(persistentVolumeReclaimPolicy)¶
| 策略 | 解释 |
|---|---|
| 保持 (Retain) | 删除PV后后端存储上的数据仍然存在,如需彻底删除则需要手动删除后端存储volume; |
| 删除 (Delete) | 删除被PVC释放的PV和后端存储volume; |
| 回收(Recycle) | 保留PV,但清空PV上的数据 |
说明:回收(Recycle)这种策略已经被淘汰了,不建议使用。
1.2 PV的状态¶
| 状态 | 解释 |
|---|---|
| Available | 可用 |
| Bound | 已经成功和PVC进行了绑定 |
| Released | PVC解绑但还未执行回收策略。 |
| Failed | 发生错误 |
StorageClass依赖一个自动配置程序,比如我们的后端存储是nfs,那么就需要一个nfs- client的自动配置程序,也称为Provisione,StorageClass也是靠这个Provisione自动配 置程序来实现自动创建PV持久卷;
自动创建 的PV以 {namespace}-${pvcname}-${pvname} 进行命名到服务器上创建相应的目录
当pv被回收 后会以 archieved-${namespace}-${pvcname}-${pvname} 格式存在服务器上
storageclass自动创建的pv命名规则:pvc-${PVC_UID}
二、StorageClass应用场景¶
- statefulset控制器下每个pod都需要使用单独的pvc
- 动态创建PVC(企业中最常用的存储方式)
2.1 原理(NFS为例)¶
首先管理员想storageClass声明我需要一个PVC-test的存储,这时storageclass就去找自动配置程序也就是nfs-client-provisioner,由nfs-client-provisioner去创建一个PV,并将PV的数据存储在对应的nfs设备上,然后再从PV中分出一个PVC-test,最后挂载到Pod上实现持久化存储;
2.2 NFS部署¶
额外开一台虚拟机,搭建NFS服务。假设NFS服务器IP地址为10.0.0.61(这里选择和集群共用节点),共享目录为/data/nfs
1、每台机器安装NFS客户端
$ yum install nfs-utils -y
2、在k8s-node01(10.0.0.61)启动nfs
[root@k8s-node01 ~]# systemctl start nfs-server
3、在k8s-node01(10.0.0.61)查看nfs支持的版本
[root@k8s-node01 ~]# cat /proc/fs/nfsd/versions
-2 +3 +4 +4.1 +4.2
4、在k8s-node01(10.0.0.61)上创建一个共享目录
[root@k8s-node01 ~]# mkdir -p /data/nfs
5、在k8s-node01(10.0.0.61)编辑授权文件,这里网段根据自己主机来定,我这里网段是10.0.0.0/24
[root@k8s-node01 ~]# vim /etc/exports
/data/nfs/ 10.0.0.0/24(rw,sync,no_subtree_check,no_root_squash)
6、在k8s-node01(10.0.0.61)配置生效
[root@k8s-node01 ~]# exportfs -r
7、在k8s-node01(10.0.0.61)重新加载NFS
[root@k8s-node01 ~]# systemctl reload nfs-server
8、在每台主机上查看是否可以成功挂载
$ showmount -e 10.0.0.61
Export list for 10.0.0.61:
/data/nfs 10.0.0.0/24
2.3 storageclass存储资源清单文件¶
1、创建sc并进行测试
(1)下载源码
[root@master01 1]# git clone https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner
(2)修改命名空间为kube-system并创建rbac授权
[root@master01 1]# cd nfs-subdir-external-provisioner/deploy
[root@master01 deploy]# sed -i 's/namespace: default/namespace: kube-system/' rbac.yaml
[root@master01 deploy]# kubectl apply -f rbac.yaml
查看创建情况
[root@master01 deploy]# k get sa -n kube-system | grep nfs
nfs-client-provisioner 1 44s
(3)修改并应用deployment.yaml
修改命名空间为kube-system
[root@master01 1]# cd nfs-subdir-external-provisioner/deploy
[root@master01 deploy]# sed -i 's/namespace: default/namespace: kube-system/' deployment.yaml
修改nfs服务器地址、nfs共享目录和镜像地址
[root@master01 1]# cd nfs-subdir-external-provisioner/deploy
[root@master01 deploy]# vim deployment.yaml
#修改内容
##修改第24行内容,替换镜像地址
24 image: registry.cn-hangzhou.aliyuncs.com/abroad_images/nfs-subdir-external-prov isioner:v4.0.2
##修改第32行内容
32 value: 10.0.0.61
##修改第34行内容
34 value: /data/nfs
##修改第38行内容
38 server: 10.0.0.61
##修改第39行内容
39 path: /data/nfs

应用deployment.yaml
[root@master01 1]# cd nfs-subdir-external-provisioner/deploy
[root@master01 deploy]# k apply -f deployment.yaml
验证查看
[root@master01 deploy]# k get deploy -n kube-system | grep nfs
nfs-client-provisioner 1/1 1 1 16m
(4)创建SC
[root@master01 1]# cd nfs-subdir-external-provisioner/deploy
[root@master01 deploy]# k apply -f class.yaml
验证查看
[root@master01 deploy]# k get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
nfs-client k8s-sigs.io/nfs-subdir-external-provisioner Delete Immediate false 3m30s
(5)创建PVC
[root@master01 1]# vim test-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: test-pvc
spec:
storageClassName: nfs-client
accessModes:
- ReadWriteMany
resources:
requests:
storage: 500Mi
应用
[root@master01 1]# k apply -f test-pvc.yaml
(6)查看pv和pvc的状态
[root@master01 1]# kg pv,pvc
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/pvc-cd2da257-6c6a-4056-a3a7-526ba69be000 500Mi RWX Delete Bound default/test-pvc nfs-client 3m56s
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/test-pvc Bound pvc-cd2da257-6c6a-4056-a3a7-526ba69be000 500Mi RWX nfs-client 3m56s
2、使用deployment资源引用创建的PVC资源
# 编写yaml文件
[root@master01 1]# vim nginx-deploy-pvc.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-pv
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx-pv
image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.21.6
volumeMounts:
- name: nginx-data
mountPath: /usr/share/nginx
volumes:
- name: nginx-data
persistentVolumeClaim:
claimName: test-pvc #指定如上pvc
readOnly: false
# 创建资源
[root@master01 1]# kaf nginx-deploy-pvc.yaml
# 进入容器产生数据
[root@master01 1]# kubectl exec -it nginx-pv-6f9b79cd9d-msmxf /bin/bash
root@nginx-pv-6f9b79cd9d-msmxf:/# cd /usr/share/nginx/
root@nginx-pv-6f9b79cd9d-msmxf:/usr/share/nginx# for i in {1..10};do echo "this is web${i}" >> index.html; sleep 1;done
# 在NFS机器上查看是否有数据产生
[root@node01 ~]# cat /data/nfs/default-test-pvc-pvc-cd2da257-6c6a-4056-a3a7-526ba69be000/index.html
this is web1
this is web2
this is web3
this is web4
this is web5
this is web6
this is web7
this is web8
this is web9
this is web10
# 环境复原
[root@master01 1]# k delete -f nginx-deploy-pvc.yaml
3、使用StatefulSet控制器引入StorageClass
需求:使用statfulset部署nginx,每个pod使用不同的pvc存储数据
# 定义yaml文件
[root@master01 1]# vim nginx-statfuleset-pvc.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nginx-storage-stat
spec:
replicas: 3
serviceName: "nginx"
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.21.6
volumeMounts:
- name: nginx-storage-test-pvc
mountPath: /usr/share/nginx/html
volumeClaimTemplates: #在statfulset.spec下定义pvc模板,里面的配置参数和pvc的一致
- metadata: #定义元数据
name: nginx-storage-test-pvc #pvc的名称,要与volumeMounts中的名称一致
spec: #定义属性
storageClassName: nfs-client #指定使用哪个storageclass
accessModes: #访问模式为多主机可读写
- ReadWriteMany
resources: #分配的资源大小
requests:
storage: 1Gi
# 应用
[root@master01 1]# kaf nginx-statfuleset-pvc.yaml
# 查看,观察到已为每个Pod分配了pvc
[root@master01 1]# kgp | grep nginx-storage-stat
nginx-storage-stat-0 2/2 Running 0 34s
nginx-storage-stat-1 2/2 Running 0 28s
nginx-storage-stat-2 2/2 Running 0 24s
[root@master01 1]# kg pvc |grep nginx-storage-test
nginx-storage-test-pvc-nginx-storage-stat-0 Bound pvc-098095ba-8116-4036-a84d-610bd105c309 1Gi RWX nfs-client 97s
nginx-storage-test-pvc-nginx-storage-stat-1 Bound pvc-6f6b6b54-f339-43bd-bf12-c8ae91b642ed 1Gi RWX nfs-client 91s
nginx-storage-test-pvc-nginx-storage-stat-2 Bound pvc-c70d6988-f88a-4eab-91e1-2660e8326191 1Gi RWX nfs-client 87s
# 在每个pod上写入数据验证持久化
[root@master01 1]# kubectl exec -it nginx-storage-stat-0 bash
root@nginx-storage-stat-0:/# echo nginx00000000000 > /usr/share/nginx/html/nginx-storage-stat-0
root@nginx-storage-stat-0:/# exit
exit
[root@master01 1]# kubectl exec -it nginx-storage-stat-1 bash
root@nginx-storage-stat-1:/# echo nginx11111111111 > /usr/share/nginx/html/nginx-storage-stat-1
root@nginx-storage-stat-1:/# exit
exit
[root@master01 1]# kubectl exec -it nginx-storage-stat-2 bash
root@nginx-storage-stat-2:/# echo nginx22222222222 > /usr/share/nginx/html/nginx-storage-stat-2
root@nginx-storage-stat-2:/# exit
# 验证,在nfs机器上查看数据是否写入,观察到数据已成功写入
[root@node01 ~]# cat /data/nfs/default-nginx-storage-test-pvc-nginx-storage-stat-0-pvc-098095ba-8116-4036-a84d-610bd105c309/nginx-storage-stat-0
nginx00000000000
[root@node01 ~]# cat /data/nfs/default-nginx-storage-test-pvc-nginx-storage-stat-1-pvc-6f6b6b54-f339-43bd-bf12-c8ae91b642ed/nginx-storage-stat-1
nginx11111111111
[root@node01 ~]# cat /data/nfs/default-nginx-storage-test-pvc-nginx-storage-stat-2-pvc-c70d6988-f88a-4eab-91e1-2660e8326191/nginx-storage-stat-2
nginx22222222222
# 删除sts资源
[root@master01 1]# k delete -f nginx-statfuleset-pvc.yaml
# 重新应用并验证,观察到数据仍然存在
[root@master01 1]# kaf nginx-statfuleset-pvc.yaml
[root@master01 1]# kubectl exec -it nginx-storage-stat-0 -- cat /usr/share/nginx/html/nginx-storage-stat-0
nginx00000000000
[root@master01 1]# kubectl exec -it nginx-storage-stat-1 -- cat /usr/share/nginx/html/nginx-storage-stat-1
nginx11111111111
[root@master01 1]# kubectl exec -it nginx-storage-stat-2 -- cat /usr/share/nginx/html/nginx-storage-stat-2
nginx22222222222
# 环境复原
[root@master01 1]# k delete -f nginx-statfuleset-pvc.yaml
总结:
- statefulset创建的pvc,即使删除statefulset控制器、PVC是不会删除的;
- 下次重建statefulset控制器,重新使用StorageClass创建pvc,数据依旧是存在的;