一、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

Day01-kubernetes基础架构解读-图12

应用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,数据依旧是存在的;