当前位置: 代码网 > 服务器>服务器>云虚拟主机 > k8s如何使用NFS作为StorageClass提供动态存储

k8s如何使用NFS作为StorageClass提供动态存储

2024年10月28日 云虚拟主机 我要评论
一、概要本文主要以下几方面介绍k8s中的storageclass:什么是storageclass为什么要引入storageclassstorageclass实现方式定义storageclass(nfs

一、概要

本文主要以下几方面介绍k8s中的storageclass:

  • 什么是storageclass
  • 为什么要引入storageclass
  • storageclass实现方式
  • 定义storageclass(nfs)
  • 关于storageclass回收策略对数据的影响
  • 设置默认的storageclass

二、什么是storageclass

存储类,在k8s集群中创建用于动态pv的管理,可以链接至不同的后端存储,比如ceph、glusterfs、nfs等。之后对存储的请求可以指向storageclass,然后storageclass会自动的创建、删除pv。

每个 storageclass 都包含provisioner、parameters和reclaimpolicy字段, 这些字段会在 storageclass 需要动态制备 persistentvolume 以满足 persistentvolumeclaim (pvc) 时使用到。

storageclass可以定义以下属性:

  • volumebindingmode:指定持久卷绑定模式,可以是"immediate"或"waitforfirstconsumer"。"immediate"表示持久卷将立即绑定到声明的请求,而"waitforfirstconsumer"表示持久卷将等待第一个消费者使用它之前才进行绑定
  • provisioner:指定用于创建持久卷的存储提供商。不同的存储提供商可能具有不同的实现和配置要求
  • parameters:存储提供商特定的参数,用于配置持久卷的创建和属性。例如,可以指定存储容量、存储类别、访问模式等
  • reclaimpolicy:指定在释放持久卷时应如何处理底层存储资源。可以选择"retain"(保留)、"delete"(删除)或"recycle"(回收)
  • mountoptions:通过storageclass动态创建的pv可以使用mountoptions指定挂载参数。如果指定的卷插件不支持指定的挂载选项,就不会被创建成功,因此在设置时需要进行确认。
  • allowvolumeexpansion:是否允许对pv进行扩容,需要后端存储支持,一般不推荐进行缩容

注意:

  • storageclass 对象的命名很重要,用户使用这个命名来请求生成一个特定的类。
  • 当创建 storageclass 对象时,管理员设置 storageclass 对象的命名和其他参数,一旦创建了对象就不能再对其更新。

三、为什么要引入storageclass

虽然使用pv和pvc能屏蔽一些存储使用上的细节,降低了存储使用的复杂度,但是也会有另一个问题无法解决。当公司kubernetes集群很多,并且使用它们的技术人员过多时,对于pv的创建是一个很耗时、耗力的工作,并且达到一定规模后,过多的pv将难以维护。所以就需要某种机制用于自动管理pv的生命周期,比如创建、删除、自动扩容等,于是kubernetes就设计了一个名为storageclass(缩写为sc,没有命名空间隔离性)的东西,通过它可以动态管理集群中的pv,这样kubernetes管理员就无须浪费大量的时间在pv的管理中。

在kubernetes中,管理员可以只创建storageclass“链接”到后端不同的存储,比如ceph、glusterfs、openstack的cinder、其他公有云提供的存储等,之后有存储需求的技术人员,创建一个pvc指向对应的storageclass即可,storageclass会自动创建pv供pod使用,也可以使用statefulset的volumeclaimtemplate自动分别为每个pod申请一个pvc。

四、storageclass实现方式

storageclass的实现方式取决于kubernetes集群所使用的存储插件和存储提供商。不同的存储插件和提供商可能有不同的实现细节和配置要求。

针对不同厂商的存储管理,k8s编写相应的代码。而不同厂商为了适配k8s,都会提供一个驱动(csi或者fiex volume)安装到k8s集群中,然后storageclass只需要配置该驱动即可,驱动器会代替storageclass管理存储。

每个 storageclass 都有一个制备器(provisioner),用来决定使用哪个卷插件制备 pv。 该字段必须指定。

五、定义storageclass(nfs)

下面演示一个基本的storageclass配置,使用nfs作为后端存储,nfs类型的sc只建议在测试环境使用,因为nfs存在性能瓶颈及单点故障问题,生产环境推荐使用分布式存储。

1.环境准备

主机ip用途版本安装方式备注
10.3.248.136k8s-masterv1.24.4二进制安装了nfs-until
10.3.248.143k8s-node01v1.24.4二进制安装了nfs-until
10.3.248.144k8s-node02v1.24.4二进制安装了nfs-until
10.3.248.134nfs-server

2.创建nfs的sa及rbac

vim nfs-rbac.yaml

apiversion: v1
kind: serviceaccount
metadata:
  name: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: default        #根据实际环境设定namespace,下面类同
---
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: ["create", "update", "patch"]
---
kind: clusterrolebinding
apiversion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-client-provisioner
subjects:
  - kind: serviceaccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: default
roleref:
  kind: clusterrole
  name: nfs-client-provisioner-runner
  apigroup: rbac.authorization.k8s.io
---
kind: role
apiversion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
    # replace with namespace where provisioner is deployed
  namespace: default
rules:
  - apigroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: rolebinding
apiversion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
subjects:
  - kind: serviceaccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: default
roleref:
  kind: role
  name: leader-locking-nfs-client-provisioner
  apigroup: rbac.authorization.k8s.io

创建

kubectl apply -f nfs-rbac.yaml

3.创建nfs资源的stroageclass

vim nfs-storageclass.yaml

apiversion: storage.k8s.io/v1
kind: storageclass
metadata:
  name: managed-nfs-storage
provisioner: test-nfs-storage #这里的名称要和provisioner配置文件中的环境变量provisioner_name保持一致
parameters:
#  archiveondelete: "false"
#    archiveondelete: "true"

创建

kubectl apply -f nfs-storageclass.yaml

4.创建nfs provisioner

vim nfs-provisioner.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 #与rbac文件中的namespace保持一致
spec:
  replicas: 1
  selector:
    matchlabels:
      app: nfs-client-provisioner
  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-hangzhou.aliyuncs.com/k8s_study_rfb/nfs-subdir-external-provisioner:v4.0.0
          volumemounts:
            - name: nfs-client-root
              mountpath: /persistentvolumes
          env:
            - name: provisioner_name
              value: test-nfs-storage  #provisioner名称,请确保该名称与 nfs-storageclass.yaml文件中的provisioner名称保持一致
            - name: nfs_server
              value: 10.3.248.134   #nfs server ip地址
            - name: nfs_path
              value: "/data/k8s"    #nfs挂载卷
      volumes:
        - name: nfs-client-root
          nfs:
            server: 10.3.248.134  #nfs server ip地址
            path: "/data/k8s"     #nfs 挂载卷

创建

kubectl apply -f nfs-provisioner.yaml

5.查看状态

# kubectl get sc 
name                  provisioner        reclaimpolicy   volumebindingmode   allowvolumeexpansion   age
managed-nfs-storage   test-nfs-storage   retain          immediate           false                  13d

6.创建测试pod验证

创建pvc链接至nfs的的storgeclass

vim pvc-claim.yaml

kind: persistentvolumeclaim
apiversion: v1
metadata:
  name: test-claim
  annotations:
    #与nfs-storageclass.yaml metadata.name保持一致
    volume.beta.kubernetes.io/storage-class: "managed-nfs-storage" 
spec:
  storageclassname: "managed-nfs-storage"
  accessmodes:
    - readwritemany
    #- readwriteonce
  resources:
    requests:
      storage: 1gi

创建并查看pvc:要确保状态为bound,如果为pending,肯定是有问题 ,需要进一步检查原因

# kubectl apply -f pvc-claim.yaml
# kubectl get pvc 
name         status   volume                                     capacity   access modes   storageclass          age
test-claim   bound    pvc-ae9942dc-73ea-4cea-ab1b-f26baf0b61f9   1gi        rwx            managed-nfs-storage   4m20s

创建pod

apiversion: apps/v1
kind: deployment
metadata:
  name: nginx-deployment-pvc
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchlabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: 10.3.248.134:10080/k8s/nginx:1.25.2
        ports:
        - containerport: 80
        volumemounts: 
        - mountpath: /usr/share/nginx/html
          name: nfs-pvc-claim
      volumes: 
        - name: nfs-pvc-claim   # name of volume
          persistentvolumeclaim: 
            claimname: test-claim  # name of pvc 

创建

kubectl apply -f pvc-nginx.yaml

进入pod创建一个文件

# kubectl get pod 
name                                      ready   status    restarts   age
nfs-client-provisioner-5d5f87db5b-v5r2r   1/1     running   0          3d23h
nginx-deployment-pvc-7774b9d564-rnwl2     1/1     running   0          3m2s
# kubectl exec -it nginx-deployment-pvc-7774b9d564-rnwl2 -- bash 
root@nginx-deployment-pvc-7774b9d564-rnwl2:/# cd /usr/share/nginx/html/
root@nginx-deployment-pvc-7774b9d564-rnwl2:/usr/share/nginx/html# echo "hello nfs storgeclass" >index.html
root@nginx-deployment-pvc-7774b9d564-rnwl2:/usr/share/nginx/html# 
exit

访问nginx的pod

# kubectl get pod -owide 
name                                      ready   status    restarts   age     ip               node      nominated node   readiness gates
nfs-client-provisioner-5d5f87db5b-v5r2r   1/1     running   0          3d23h   172.16.178.203   mongodb   <none>           <none>
nginx-deployment-pvc-7774b9d564-rnwl2     1/1     running   0          5m46s   172.16.178.212   mongodb   <none>           <none>
# curl 172.16.178.212
hello nfs storgeclass

删除pod再次访问

# kubectl delete pod nginx-deployment-pvc-7774b9d564-rnwl2
pod "nginx-deployment-pvc-7774b9d564-rnwl2" deleted
# kubectl get pod -owide 
name                                      ready   status    restarts   age   ip               node         nominated node   readiness gates
nfs-client-provisioner-5d5f87db5b-v5r2r   1/1     running   0          4d    172.16.178.203   mongodb      <none>           <none>
nginx-deployment-pvc-7774b9d564-2gmfk     1/1     running   0          26s   172.28.82.243    k8s-master   <none>           <none>
# curl 172.28.82.243
hello nfs storgeclass

此时我们可以发现进入pod创建的文件已经持久化存储了,即使删除了pod文件不会丢失。

六、关于storageclass回收策略对数据的影响

1.第一种配置

   archiveondelete: "false"  
   reclaimpolicy: delete   #默认没有配置,默认值为delete

测试结果

  • 1.pod删除重建后数据依然存在,旧pod名称及数据依然保留给新pod使用
  • 2.sc删除重建后数据依然存在,旧pod名称及数据依然保留给新pod使用
  • 3.删除pvc后,pv被删除且nfs server对应数据被删除

2.第二种配置

   archiveondelete: "false"  
   reclaimpolicy: retain  

测试结果

  • 1.pod删除重建后数据依然存在,旧pod名称及数据依然保留给新pod使用
  • 2.sc删除重建后数据依然存在,旧pod名称及数据依然保留给新pod使用
  • 3.删除pvc后,pv不会别删除,且状态由bound变为released,nfs server对应数据被保留
  • 4.重建sc后,新建pvc会绑定新的pv,旧数据可以通过拷贝到新的pv中

3.第三种配置

   archiveondelete: "ture"  
   reclaimpolicy: retain  

测试结果

  • 1.pod删除重建后数据依然存在,旧pod名称及数据依然保留给新pod使用
  • 2.sc删除重建后数据依然存在,旧pod名称及数据依然保留给新pod使用
  • 3.删除pvc后,pv不会别删除,且状态由bound变为released,nfs server对应数据被保留
  • 4.重建sc后,新建pvc会绑定新的pv,旧数据可以通过拷贝到新的pv中

4第四种配置

  archiveondelete: "ture"  
  reclaimpolicy: delete 

测试结果

  • 1.pod删除重建后数据依然存在,旧pod名称及数据依然保留给新pod使用
  • 2.sc删除重建后数据依然存在,旧pod名称及数据依然保留给新pod使用
  • 3.删除pvc后,pv不会别删除,且状态由bound变为released,nfs server对应数据被保留
  • 4.重建sc后,新建pvc会绑定新的pv,旧数据可以通过拷贝到新的pv中

总结:除以第一种配置外,其他三种配置在pv/pvc被删除后数据依然保留

七、设置默认的storageclass

官网地址改变默认 storageclass | kubernetes

kubectl patch命令

kubectl patch storageclass standard -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"false"}}}'

这里的standard是你选择的 storageclass 的名字。

注意:最多只能有一个 storageclass 能够被标记为默认。 如果它们中有两个或多个被标记为默认,kubernetes 将忽略这个注解, 也就是它将表现为没有默认 storageclass。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com