首页 > 其他分享 >大白话说明白K8S的PV / PVC / StorageClass(理论+实践)

大白话说明白K8S的PV / PVC / StorageClass(理论+实践)

时间:2024-02-11 11:14:12浏览次数:27  
标签:PV 创建 PVC nfs StorageClass Pod K8S

本文主要通过大白话说明白PV、PVC的概念和原理,再说说StorageClass的作用,最后通过实践加深理解。

先来个一句话总结:PV、PVC是K8S用来做存储管理的资源对象,它们让存储资源的使用变得可控,从而保障系统的稳定性、可靠性。StorageClass则是为了减少人工的工作量而去自动化创建PV的组件。所有Pod使用存储只有一个原则:先规划后申请再使用

一、理论

1、PV概念

PV是对K8S存储资源的抽象,PV一般由运维人员创建和配置,供容器申请使用。

没有PV之前,服务器的磁盘没有分区的概念,有了PV之后,相当于通过PV对服务器的磁盘进行分区。

2、PVC概念

PVC 是Pod对存储资源的一个申请,主要包括存储空间申请、访问模式等。创建PV后,Pod就可以通过PVC向PV申请磁盘空间了。类似于某个应用程序向操作系统的D盘申请1G的使用空间。

PVC 创建成功之后,Pod 就可以以存储卷(Volume)的方式使用 PVC 的存储资源了。Pod 在使用 PVC 时必须与PVC在同一个Namespace下。

3、PV / PVC的关系

PV相当于对磁盘的分区,PVC相当于APP(应用程序)向某个分区申请多少空间。比如说安装WPS程序时,一般会告知我们安装它需要多少存储空间,让你选择在某个磁盘下安装。如果将来某个分区磁盘满了,也不会影响别的分区磁盘的使用。

一旦 PV 与PVC绑定,Pod就可以使用这个 PVC 了。如果在系统中没有满足 PVC 要求的 PV,PVC则一直处于 Pending 状态,直到系统里产生了一个合适的 PV。

4、StorageClass概念

K8S有两种存储资源的供应模式:静态模式和动态模式,资源供应的最终目的就是将适合的PV与PVC绑定:

  • 静态模式:管理员预先创建许多各种各样的PV,等待PVC申请使用。
  • 动态模式:管理员无须预先创建PV,而是通过StorageClass自动完成PV的创建以及与PVC的绑定。

StorageClass就是动态模式,根据PVC的需求动态创建合适的PV资源,从而实现存储卷的按需创建。

一般某个商业性的应用程序,会用到大量的Pod,如果每个Pod都需要使用存储资源,那么就需要人工时不时的去创建PV,这也是个麻烦事儿。解决方法就是使用动态模式:当Pod通过PVC申请存储资源时,直接通过StorageClass去动态的创建对应大小的PV,然后与PVC绑定,所以基本上PV → PVC是一对一的关系。

5、Provisioner概念

在创建 PVC 时需要指定 StorageClass,PVC 选择到对应的StorageClass后,与其关联的 Provisioner 组件来动态创建 PV 资源。

那Provisioner是个啥呢?其实就一个存储驱动,类似操作系统里的磁盘驱动。

StorageClass 资源对象的定义主要包括:名称、Provisioner、存储的相关参数配置、回收策略。StorageClass一旦被创建,则无法修改,只能删除重新创建。

PV和PVC的生命周期,包括4个阶段:资源供应(Provisioning)、资源绑定(Binding)、资源使用(Using)、资源回收(Reclaiming)。首先旧的有资源供应,说白了就是得有存储驱动,然后才能创建、绑定和使用、回收。

6、使用PV / PVC前后对比

6.1、通过描述对比

在没有使用PV、PVC之前,各个Pod都可以任意的向存储资源里(比如NFS)写数据,随便一个Pod都可以往磁盘上插一杠子,长期下去磁盘的管理会越来越混乱,然后导致数据使用超限,磁盘爆掉,最后导致磁盘上的所有应用全部挂掉。

为了解决这个问题,引入了PV、PVC的概念,达到限制Pod写入存储数据大小的目的,从而更好地保障了系统的可用性、稳定性。

有了PVC、PV之后,所有Pod使用存储资源,保持一个原则:先规划 → 后申请 → 再使用。

那你肯定有一个疑问,“StorageClass是自动化创建PV,跟原本的无序不可控是一样的效果啊,都可以随便占用存储资源啊”。

其实不然,使用StorageClass只是自动化了创建PV的流程,但依旧执行的是一个存储可控的流程。每个Pod使用多少存储空间是固定的,Pod没有办法超额使用存储空间,更不会影响到别的应用,要出故障也只是某个Pod自己出故障。

6.2、通过图片对比

没有使用PV、PVC之前的情况,如下面2张图:

有了PV、PVC之后的情况,如下图:

二、实践

在实践PV、PVC、StorageClass之前,需要读者朋友自行安装NFS服务器。文中演示的内容是通过yaml编排自动到NFS服务器起上创建PV。

1、Pod使用PV、PVC挂载存储卷

1.1、编排PV、PVC、Pod挂载PVC

文中演示的是:Pod的某个目录挂载到NFS的某个目录下。使用了nginx镜像,将html文件写在PV所在的NFS服务器上,最终可以看到利用PV / PVC 成功挂载上去了。

yaml文件如下:

# PV编排
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv1
  namespace: dev1
  labels:
    pv: nfs-pv1
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  # Recycle 删除PVC会同步删除PV | Retain 删除PVC不会同步删除PV
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /data/nfstest/share/pv1
    server: 10.20.1.20
    readOnly: false
---
# PVC 编排,通过selector查找PV,K8S里的资源查找都是通过selector查找label标签
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc1
  namespace: dev1
  labels:
    pv: nfs-pvc1
spec:
  resources:
    requests:
      storage: 100Mi
  accessModes:
    - ReadWriteOnce
  selector:
    matchLabels:
      pv: nfs-pv1
---
# Pod挂载PVC,这里为了测试,直接通过node节点的hostPort暴露服务
apiVersion: v1
kind: Pod
metadata:
  name: webapp
  namespace: dev1
  labels:
    app: webapp
spec:
  containers:
    - name: webapp
      image: nginx
      imagePullPolicy: IfNotPresent
      ports:
        - containerPort: 80
          hostPort: 8081
      volumeMounts:
        - name: workdir
          mountPath: /usr/share/nginx/html
  volumes:
    - name: workdir
      persistentVolumeClaim:
        claimName: nfs-pvc1

执行kubectl命令,查看实践效果如下:

然后查看pod的情况,发现pod一直处于创建中,如下:

于是查看pod的情况kubectl describe pod webapp -n dev1,发现如下异常信息:

是因为没有在NFS上创建此文件夹。到NFS创建此文件夹之后,重启Pod,一切正常了,然后找到Pod所在Node节点。通过http://nodeip:port访问,可以看到成功的界面:

[root@k8s-master pv-pvc-storageclass]# kubectl get pods -n dev1 -owide  | grep webapp
webapp                                                 1/1     Running            0          4m17s   10.21.69.214   k8s-worker-3   <none>           <none>

此时因为nginx下还没有html页面,所以看不到内容。此时到NFS服务器对应的目录/data/nfstest/share/pv1下增加index.html页面,然后刷新页面即可,界面如下:

也可以通过进入到Pod内部,查看验证是够挂载成功。

执行进入Pod的命令kubectl exec -it webapp -n dev1 -- /bin/sh,可以看到如下页面:

2、Pod使用StorageClass自动挂载存储卷

2.1、安装 Provisioner

文中选择通过helm的方式安装nfs-subdir-external-provisioner,这种方式相对简单。安装文档、安装过程见下文:

  • 安装文档

https://kubernetes.io/zh-cn/docs/concepts/storage/storage-classes/#nfs

https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner

  • 安装过程

通过以下3个步骤完成nfs-subdir-external-provisioner的安装。

  1. 安装helm,本文以mac为例
brew install heml
  1. 安装nfs-subdir-external-provisioner,执行以下2个命令:
$ helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
$ helm install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner -n kube-system \
    --set image.repository=dyrnq/nfs-subdir-external-provisioner \
    --set nfs.server=10.20.1.20 \
    --set nfs.path=/data/nfstest/nfs-storage

这里注意几个参数:

image.repository:修改了镜像的地址,默认用的国外镜像很有可能拉不下来

nfs.server:你的NFS服务器地址

nfs.path:存储目录

  1. 查看helm安装的结果:

执行命令:helm list -A,查看helm安装结果:

查看是否创建了对应的pod,如果没有修改镜像地址会一直拉取失败,如下图:

修改镜像地址后成功启动Pod,如下图:

2.2、使用StorageClass

文中演示的是:Pod利用StorageClass自动创建PV,同时在对应的存储目录上创建了文件,写入了数据。

yaml文件如下:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-storage-1
provisioner: cluster.local/nfs-subdir-external-provisioner
parameters:
  # 设置为"false"时删除PVC不会保留数据,"true"则保留数据
  archiveOnDelete: "false"
mountOptions:
  # 指定NFS版本,这个需要根据NFS Server版本号设置
  - nfsvers=4
---
# 创建PVC
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: nfs-storage-pvc-1
  namespace: dev1
spec:
  storageClassName: nfs-storage-1    #需要与上面创建的storageclass的名称一致
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Mi
---
kind: Pod
apiVersion: v1
metadata:
  name: nfs-storage-pod-1
  namespace: dev1
spec:
  containers:
    - name: nfs-storage-pod-1
      image: busybox
      command:
        - "/bin/sh"
      args:
        - "-c"
        - "touch /mnt/teststorage && echo 111 > /mnt/teststorage && exit 0 || exit 1"  ## 创建一个名称为"SUCCESS"的文件
      volumeMounts:
        - name: nfs-pvc
          mountPath: "/mnt"
  restartPolicy: "Never"
  volumes:
    - name: nfs-pvc
      persistentVolumeClaim:
        claimName: nfs-storage-pvc-1

执行kubectl命令后,可以看到如下效果:

可以看到如我们预料的那样,通过storageClass自动创建了PV,同时在NFS对应的存储目录上创建了文件,写入了数据。

至此,我们实践过程全部结束。

三、总结

本文主要讲解了PV、PVC、StorageClass的理论和实战。

一句话总结:PV、PVC是K8S用来做存储管理的资源对象,它们让存储资源的使用变得可控,从而保障系统的稳定性、可靠性。StorageClass则是为了减少人工的工作量而去自动化创建PV的组件。所有Pod使用存储只有一个原则:先规划后申请再使用

参考文献:《Kubernetes权威指南》

本篇完结!感谢你的阅读,欢迎点赞 关注 收藏 私信!!!

原文链接:http://www.mangod.top/articles/2023/09/12/1694516710285.htmlhttps://mp.weixin.qq.com/s/bxRdOavM2BZEovEnoZ6wZw

标签:PV,创建,PVC,nfs,StorageClass,Pod,K8S
From: https://www.cnblogs.com/mangod/p/18013247

相关文章

  • 5分钟搞懂K8S的污点和容忍度(理论+实战)
    本文主要快速讲解Kubernetes的污点和容忍度,一句话总结:如果Pod能容忍某个节点上的污点,那么Pod就可以调度到该节点。在K8S中,如果Pod能容忍某个节点上的污点,那么Pod就可以调度到该节点。如果不能容忍,那就无法调度到该节点。污点和容忍度就像谈恋爱的小情侣,你情我愿,女生知道男生的......
  • 10分钟搞懂K8S的亲和与反亲和调度
    本文主要快速讲解Kubernetes的亲和性调度和反亲和性调度,通过理论结合实际的方式,让理解更深刻。首先来个一句话总结:亲和性调度就像关系亲密的闺蜜,你去哪儿我也去哪儿。反亲和性调度就像赌气的两个孩子,赌气永远不在一起玩儿。更多解释和实战详见下文。花10分钟看到最后,你肯定会有......
  • 在k8S中,外部如何访问集群内的服务?
    在Kubernetes(k8s)中,要让外部客户端能够访问集群内的服务,通常有以下几种方式:NodePort:创建一个类型为NodePort的服务,这会在每个工作节点上开放一个特定端口(系统自动分配或用户指定的范围内的端口),并将流量转发到对应Service背后的Pod。外部客户端可以通过任意节点的IP地址和......
  • 在k8S中,Headless Service是什么?
    在Kubernetes(k8s)中,HeadlessService是一种特殊类型的Service,它不会被分配一个ClusterIP(集群内部的虚拟IP地址),而是直接将服务背后的PodIP地址暴露给客户端。当创建HeadlessService时,其spec.clusterIP字段设置为"None"。HeadlessService的主要特征和用途包括:DNS解析:Kuberne......
  • 在k8S中,Servic类型有哪些?
    在Kubernetes(k8s)中,Service是用于定义一组Pod的访问策略和机制的资源对象。以下是KubernetesService支持的主要类型:ClusterIP:这是默认的服务类型。创建一个仅集群内部可访问的虚拟IP地址(VIP)。应用程序只能通过内部集群DNS名称从集群内的其他Pod或服务访问这个Service。No......
  • 在k8S中,Service分发后端的策略是什么?
    在Kubernetes(k8s)中,Service可以使用多种策略来分发流量到后端Pod。以下是一些主要的分发策略:ClusterIP(默认策略):Service会获取一个仅集群内部可访问的虚拟IP(ClusterIP),kube-proxy组件根据Service定义的SessionAffinity(如启用)和负载均衡策略将请求转发到后端Pod池。R......
  • 在k8S中,自动扩容机制是什么?
    在Kubernetes(k8s)中,自动扩容机制主要用于根据资源使用情况动态调整Pod副本的数量,以确保服务的稳定性和高效性。主要实现这一功能的组件是HorizontalPodAutoscaler(HPA)。HorizontalPodAutoscaler工作原理如下:监控指标:HPA通过与KubernetesMetricsServer或者其他的自定......
  • 在k8S中,deployment升级策略是什么?
    在Kubernetes(k8s)中,Deployment的升级策略主要指的是在更新Pod副本以部署新的容器镜像或配置时所采用的方法。主要有两种内置的升级策略:滚动更新(RollingUpdate):这是Deployment默认使用的升级策略。在滚动更新中,Deployment控制器会按批次替换现有的Pod,每次只替换一部......
  • 在k8S中,DaemonSet类型的资源特性有哪些?
    Kubernetes(k8S)中的DaemonSet是一种控制器资源,它具有以下关键特性:每个节点运行一个实例:DaemonSet确保集群中的每个节点(满足特定条件的节点)上都运行一个Pod副本。这意味着无论何时创建或加入新的节点到集群中,DaemonSet都会自动为新节点调度和管理一个Pod。目标节点......
  • 在k8S中,初始化容器(init container)概念原理是什么?
    在Kubernetes(k8S)中,初始化容器(InitContainer)是一个特殊类型的容器,它会在应用程序容器启动之前运行。它的主要目的是执行一些必要的先决条件任务,这些任务必须在主应用容器开始服务前完成。初始化容器的概念原理如下:顺序执行:Pod中可以定义多个初始化容器,它们按照配置文件......