k8s存储:卷、持久卷、存储类

  • emptyDir:临时数据卷
  • hostPath:节点数据卷
  • nfs:网络数据卷
  • PV:持久卷
    • 持久卷的类型
    • volumeMode:卷模式
    • accessModes:访问模式
    • Phase:状态阶段
    • Reclaim Policy:回收策略
  • PVC:持久卷申领
    • 示例:创建一个nfs类型的PV
  • StorageClass:存储类
    • Provisioner:存储类制备器
    • NFS StorageClass动态供给PV

容器中的文件是临时存储在磁盘上的,数据卷的引入主要是为了解决以下几个问题:

  • 当容器升级或者崩溃时,kubelet会重建容器,容器内原有的文件会丢失;
  • 一个Pod中运行的多个容器需要共享文件。

常用的数据卷(Volume)有:

  • 本地:例如hostPath、emptyDir;
  • 网络:例如NFS、Ceph、GlusterFS;
  • 公有云:例如AWS EBS;
  • k8s资源:例如configmap、secret。

emptyDir:临时数据卷

emptyDir卷是一种临时存储卷,与Pod的生命周期绑定。在Pod运行期间,emptyDir一直存在;如果Pod被删除了,emptyDir中的数据也会被永久删除。

:容器崩溃会导致Pod被删除,因此容器崩溃期间emptyDir中的数据是安全的。

emptyDir可以实现Pod中容器之间的数据共享。尽管Pod中的容器挂载emptyDir卷的路径可能不同,这些容器都可以读写emptyDir卷中相同的文件。

emptyDir的配置示例如下:

apiVersion: v1
kind: Pod
metadata:name: test-pod
spec:containers:- image: centosname: writercommand: ["bash","-c","for i in {1..100}; do echo $i >> /data/tmpfile; sleep 1; done"]volumeMounts:- mountPath: /dataname: data- image: centosname: readercommand: ["bash", "-c", "tail -f /data/tmpfile"]volumeMounts:- mountPath: /datavolumes:- name: dataemptyDir: {}

emptyDir挂在的容器目录位于Pod所在节点的以下路径:

/var/lib/kubelet/pods/${container_ID}/volumes/kubernetes.io~empty-dir

hostPath:节点数据卷

hostPath卷能将Pod所在宿主机节点文件系统上的文件或目录挂载到Pod中。具有相同配置(例如基于同一PodTemplate创建)的多个Pod,会由于节点上文件的不同,而在不同节点上有不同的行为。

:HostPath卷存在许多安全风险,最佳做法是尽可能避免使用HostPath。 当必须使用HostPath卷时,它的范围应仅限于所需的文件或目录,并以只读方式挂载。HostPath卷可能会暴露特权系统凭据(例如Kubelet)或特权API(例如容器运行时套接字),可用于容器逃逸或攻击集群的其他部分。

HostPath配置示例如下:

apiVersion: v1
kind: Pod
metadata:name: test-pod
spec:containers:- image: k8s.gcr.io/test-webservername: test-containervolumeMounts:- mountPath: /mydataname: test-volume1- mountPath: /mylogname: test-volume2volumes:- name: test-volume1hostPath:path: /data       # 宿主上目录位置type: Directory - name: test-volume2hostPath:path: /log        # 宿主上目录位置type: Directory

nfs:网络数据卷

提供对NFS挂载支持,可以自动将NFS共享路径挂载到Pod中。

搭建NFS文件共享服务器:

[root@k8s-node1 ~]# yum install nfs-utils -y
[root@k8s-node1 ~]# vi /etc/exports
/ifs/kubernetes *(rw,sync,no_root_squash)
[root@k8s-node1 ~]# mkdir -p /ifs/kubernetes
[root@k8s-node1 ~]# systemctl start nfs
[root@k8s-node1 ~]# systemctl enable nfs

所有Node节点上都要安装nfs-utils包。在其他节点挂载NFS路径:

[root@k8s-node2 ~]# yum install nfs-utils -y
[root@k8s-node2 ~]# mkdir -p /ifs/kubernetes
#手动挂载
[root@k8s-node2 ~]# mount -t nfs 192.168.136.120:/ifs/kubernetes /ifs/kubernetes
#开机自动挂载
[root@k8s-node2 ~]# echo '192.168.136.120:/ifs/kubernetes  /ifs/kubernetes  nfs4  defaults  0 0' >> /etc/fstab
[root@k8s-node2 ~]# mount -a
#移除挂载
[root@k8s-node2 ~]# umount -v /ifs/kubernetes/

将nginx网站程序根目录持久化到NFS存储,为多个Pod提供网站程序文件。

apiVersion: apps/v1
kind: Deployment
metadata:name: webserver
spec:selector:matchLabels:app: nginxreplicas: 3template:metadata:labels:app: nginxspec:containers:- name: nginximage: nginxvolumeMounts:- name: wwwrootmountPath: /usr/share/nginx/htmlvolumes:- name: wwwrootnfs:server: 192.168.136.120path: /ifs/kubernetes

PV:持久卷

持久卷(PersistentVolume, PV)是对存储资源创建和使用的抽象,使得存储可以作为集群中的资源被管理。

持久卷的类型

持久卷是通过插件的形式实现的。目前k8s支持的插件包括:

  • awsElasticBlockStore
  • azureDisk
  • cephfs
  • csi 容器存储接口
  • hostPath卷
  • iscsi(iSCSI存储)
  • local 节点上挂载的本地存储设备
  • nfs 网络文件系统存储
  • vsphereVolume(vSphere VMDK卷)

等等。

volumeMode:卷模式

k8s支持两种卷模式(volumeModes):Filesystem(文件系统)和Block(块存储)。volumeMode是一个可选的API参数。如果该参数被省略,默认的卷模式是Filesystem。

volumeMode属性设置为Filesystem的卷会被Pod挂载到某个目录。如果卷的存储来自某块设备而该设备目前为空,k8s会在第一次挂载卷之前在设备上创建文件系统。

也可以将volumeMode设置为Block,以便将卷作为原始块设备来使用。这类卷以块设备的方式交给Pod使用,其上没有任何文件系统,使用前需要格式化。

accessModes:访问模式

PV支持的访问模式(accessModes)有:

  • ReadWriteOnce(RWO):卷可以被一个节点以读写方式挂载。ReadWriteOnce访问模式也允许运行在同一节点上的多个 Pod 访问卷。

  • ReadOnlyMany(ROX):卷可以被多个节点以只读方式挂载。

  • ReadWriteMany(RWX):卷可以被多个节点以读写方式挂载。

  • ReadWriteOncePod:卷可以被单个Pod以读写方式挂载。
    如果想确保整个集群中只有一个Pod可以读取或写入该PVC, 要使用ReadWriteOncePod访问模式。这只支持CSI卷以及需要Kubernetes 1.22以上版本。

参考:https://kubernetes.io/blog/2021/09/13/read-write-once-pod-access-mode-alpha/

Phase:状态阶段

每个卷会处于以下阶段(Phase)之一:

  • Available(可用):卷是一个空闲资源,尚未绑定到任何申领;
  • Bound(已绑定):该卷已经绑定到某申领;
  • Released(已释放):所绑定的申领已被删除,但是资源尚未被集群回收;
  • Failed(失败):卷的自动回收操作失败。

Reclaim Policy:回收策略

目前的回收策略有:

  • Retain(手动回收):默认策略,保留数据,需要手动回收;
  • Recycle(回收):保留PV,但是会清除PV中的数据,相当于rm -rf /thevolume/*
  • Delete(删除):删除PV和数据,与PV相关联的后端存储同时被删除。诸如AWS EBS、GCE PD、Azure Disk或OpenStack Cinder卷这类关联存储资源也被删除。

PVC:持久卷申领

持久卷申领(PersistentVolumeClaim, PVC)是用户对集群中PV资源的请求。

Pod申请PVC作为卷来使用,k8s通过PVC查找绑定的PV,并在Pod中挂载。创建PVC之后,k8s控制平面将通过匹配访问模式accessModes和容量storage查找满足要求的PV。如果控制平面找到具有合适的PV,则会将PVC绑定到该PV上。

PVC和PV的一般匹配原则如下:

  • 首先,PV.spec.accessModes要与PVC.spec.accessModes相同;
  • 其次,PV.spec.capacity.storage不能小于PVC.spec.resources.requests.storage
  • 如果有多个PV满足以上要求,则优先选择容量最接近的PV;
  • 如果没有找到合适的PV,则容器和PVC会一直处于Pending状态。

PVC中的需求容量字段storage只能用于匹配PV,并不能起到资源限制作用。容器实际能够使用的容量大小取决于后端存储。也就是说,假设PVC中定义的资源需求为10G,PV后端使用的存储的剩余空间为100G,那么绑定该PV后,容器实际可以使用的存储大小也是100G。

示例:创建一个nfs类型的PV

首先确保所有Node节点操作系统已经挂载NFS。

容器应用中使用PVC来申请PV资源(my-pod-pvc.yaml):

---
apiVersion: v1
kind: Pod
metadata:name: my-pod
spec:containers:- name: webserverimage: nginxports:- containerPort: 80volumeMounts:- name: wwwrootmountPath: /usr/share/nginx/htmlvolumes:- name: wwwroot           #与volumeMounts.name保持一致persistentVolumeClaim:claimName: my-pvc---
apiVersion: v1
kind: PersistentVolumeClaim
metadata: name: my-pvc       #与claimName保持一致
spec:accessModes:       #访问模式- ReadWriteManyresources:requests:storage: 8Gi   #容量

查看Pods和PVC状态:

[root@k8s-master ~]# kubectl apply -f my-pod-pvc.yaml
[root@k8s-master ~]# kubectl get pods,pvc
NAME                             READY   STATUS    RESTARTS        AGE
pod/my-pod                       0/1     Pending   0               23sNAME                           STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/my-pvc   Pending                                                     23s

由于尚未创建PV,my-pod和my-pvc的STATUS都应该为Pending

接下来定义一个nfs类型的PV资源(my-pv.yaml):

apiVersion: v1
kind: PersistentVolume
metadata:name: my-pv
spec:capacity:storage: 10Gi       #容量accessModes:- ReadWriteMany     #访问模式nfs:path: /if/kubernetesserver: 192.168.136.120

查看Pods、PVC和PV状态:

[root@k8s-master ~]# kubectl apply -f my-pv.yaml#PV和PVC未绑定前
[root@k8s-master ~]# kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
my-pv   10Gi       RWX            Retain           Available                                   2m20s#PV和PVC绑定后
[root@k8s-master ~]# kubectl get pods,pvc,pv
NAME                             READY   STATUS    RESTARTS        AGE
pod/my-pod                       1/1     Running   0               3m8sNAME                           STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/my-pvc   Bound    my-pv    1Gi        RWX                           3m8sNAME                     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM            STORAGECLASS   REASON   AGE
persistentvolume/my-pv   10Gi       RWX            Retain           Bound    default/my-pvc                           3m2s

正常情况下,my-pvc和my-pv的STATUS都会变成Bound,Pods的状态也会变成Running。

进入容器测试一下:

[root@k8s-node1 ~]# ls /ifs/kubernetes/
a.txt  b.txt[root@k8s-master ~]# kubectl exec -it my-pod -- bash
root@my-pod:/# cd /usr/share/nginx/html
root@my-pod:/usr/share/nginx/html# ls
a.txt  b.txt
root@my-pod:/usr/share/nginx/html# echo '<p>Hello Nginx!</p>' > index.html
root@my-pod:/usr/share/nginx/html# ls
a.txt  b.txt  index.html

StorageClass:存储类

PV的供给有两种方式:静态供给和动态供给。像前面那样,集群管理员手动创建若干PV卷,供容器消费使用,即是静态供给的方式。静态供给的缺点是维护成本很高。

集群管理员也可以使用StorageClass实现PV资源的动态供给。每个StorageClass都包含provisioner、parameters和reclaimPolicy字段, 这些字段会在StorageClass需要动态分配PV时会使用到。

Provisioner:存储类制备器

每个存储类都有一个provisioner,用来决定使用哪个卷插件制备PV。

目前,NFS没有内部制备器,需要使用外部制备器插件来实现PV的动态供给。

官方内部支持的制备器参见:https://kubernetes.io/zh-cn/docs/concepts/storage/storage-classes/#provisioner
NFS外部制备器插件参考:https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner

NFS provisioner插件部署:

[root@k8s-master nfs-storageClass]# ls
class.yaml  deployment.yaml  rbac.yaml
#修改NFS服务器地址和共享文件路径
[root@k8s-master nfs-storageClass]# grep NFS deployment.yaml- name: NFS_SERVER- name: NFS_PATH#授权访问api-server
[root@k8s-master nfs-storageClass]# kubectl apply -f rbac.yaml
#部署nfs provisioner插件
[root@k8s-master nfs-storageClass]# kubectl apply -f deployment.yaml
#创建存储类
[root@k8s-master nfs-storageClass]# kubectl apply -f class.yaml#查看存储类
[root@k8s-master nfs-storageClass]# kubectl get sc
NAME                  PROVISIONER                                   RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
managed-nfs-storage   k8s-sigs.io/nfs-subdir-external-provisioner   Delete          Immediate           false                  2m3s

:部署配置文件下载地址为 https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner/tree/master/deploy

NFS StorageClass动态供给PV

修改前面的示例,使用nfs存储类来实现动态供给PV卷(pod-scnfs.yaml)。

---
apiVersion: v1
kind: Pod
metadata:name: pod-sc-nfs
spec:containers:- name: pod-sc-nfsimage: nginxports:- containerPort: 80volumeMounts:- name: sc-nfs-pvcmountPath: /usr/share/nginx/htmlvolumes:- name: sc-nfs-pvc           #与volumeMounts.name保持一致persistentVolumeClaim:claimName: test-nfs-scclaim---
apiVersion: v1
kind: PersistentVolumeClaim
metadata: name: test-nfs-scclaim       #与claimName保持一致
spec:storageClassName: "managed-nfs-storage"   #与部署nfs provisioner插件时class.yaml中metadata.name保持一致accessModes:       #访问模式- ReadWriteManyresources:requests:storage: 1Gi   #容量

无需手动创建PV,检查部署后状态:

[root@k8s-master ~]# kubectl apply -f pod-scnfs.yaml
[root@k8s-master ~]# kubectl get pods
NAME                                      READY   STATUS    RESTARTS        AGE
my-pod                                    1/1     Running   0               5h40m
nfs-client-provisioner-5d5775b9bb-5657c   1/1     Running   0               21m
pod-sc-nfs                                1/1     Running   0               24s
[root@k8s-master ~]#
[root@k8s-master ~]# kubectl get pvc,pv
NAME                                     STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
persistentvolumeclaim/my-pvc             Bound    my-pv                                      1Gi        RWX                                  5h41m
persistentvolumeclaim/test-nfs-scclaim   Bound    pvc-14c4221b-f3af-465c-b431-eddc1191a864   1Gi        RWX            managed-nfs-storage   33sNAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                      STORAGECLASS          REASON   AGE
persistentvolume/my-pv                                      1Gi        RWX            Retain           Bound    default/my-pvc                                            5h41m
persistentvolume/pvc-14c4221b-f3af-465c-b431-eddc1191a864   1Gi        RWX            Delete           Bound    default/test-nfs-scclaim   managed-nfs-storage            33s
[root@k8s-master ~]#

可以看到,动态分配的PV的STORAGECLASS一栏为managed-nfs-storage,回收策略为Delete

查看NFS Server上的共享文件路径:

[root@k8s-master ~]# kubectl exec -it pod-sc-nfs -- bash
root@pod-sc-nfs:/# df -Th
Filesystem                                                                                        Type     Size  Used Avail Use% Mounted on
...
192.168.136.120:/ifs/kubernetes/default-test-nfs-scclaim-pvc-14c4221b-f3af-465c-b431-eddc1191a864 nfs4      37G  3.7G   34G  10% /usr/share/nginx/html
...
root@pod-sc-nfs:/# cd /usr/share/nginx/html
root@pod-sc-nfs:/usr/share/nginx/html# ls
root@pod-sc-nfs:/usr/share/nginx/html# touch test-nfs-file-001
root@pod-sc-nfs:/usr/share/nginx/html# exit[root@k8s-node1 ~]# ll /ifs/kubernetes/
total 4
-rw-r--r--. 1 root root  0 Aug 12 23:26 a.txt
-rw-r--r--. 1 root root  0 Aug 12 23:29 b.txt
drwxrwxrwx. 2 root root  6 Aug 13 05:23 default-test-nfs-scclaim-pvc-14c4221b-f3af-465c-b431-eddc1191a864
-rw-r--r--. 1 root root 20 Aug 12 23:49 index.html
[root@k8s-node1 ~]# ls /ifs/kubernetes/default-test-nfs-scclaim-pvc-14c4221b-f3af-465c-b431-eddc1191a864/
test-nfs-file-001

测试Delete回收策略是否会生效:

[root@k8s-master ~]# kubectl delete -f pod-scnfs.yaml
pod "pod-sc-nfs" deleted
persistentvolumeclaim "test-nfs-scclaim" deleted#查看绑定的PV是否一并被删除
[root@k8s-master ~]# kubectl get pvc,pv,sc
NAME                           STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/my-pvc   Bound    my-pv    1Gi        RWX                           5h55mNAME                     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM            STORAGECLASS   REASON   AGE
persistentvolume/my-pv   1Gi        RWX            Retain           Bound    default/my-pvc                           5h55mNAME                                              PROVISIONER                                   RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
storageclass.storage.k8s.io/managed-nfs-storage   k8s-sigs.io/nfs-subdir-external-provisioner   Delete          Immediate           false                  36m#查看NFS Server上的共享文件路径是否同时被删除
[root@k8s-node1 ~]# ls /ifs/kubernetes/
a.txt  b.txt  index.html

如果想在删除PVC时,对PV中的数据进行归档,可以将nfs provisioner插件部署配置文件class.yaml中的参数

archiveOnDelete: "false"

修改为true后重新部署。这样NFS Server上共享文件路径中的数据就会留存一份归档。

References
【1】https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/
【2】https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/
【3】https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-persistent-volume-storage/
【4】https://kubernetes.io/zh-cn/docs/concepts/storage/storage-classes/

k8s存储:卷、持久卷、存储类相关推荐

  1. 多个containers 共用一个pvc_深入k8s:Kubernetes持久卷PV、PVC及源码分析

    推荐阅读:膜拜!阿里内部都在强推的K8S(kubernetes)学习指南,不能再详细了 从一个例子入手PV.PVC Kubernetes 项目引入了一组叫作 Persistent Volume Cla ...

  2. k8s存储之Volumes卷类型

    一.Volumes配置管理 (一)容器中的文件在磁盘上是临时存放的,这给容器中运行的特殊应用程序带来一些问题.首先,当容器崩溃时,kubelet 将重新启动容器,容器中的文件将会丢失,因为容器会以干净 ...

  3. mysql上k8s_通过搭建MySQL掌握k8s(Kubernetes)重要概念(上):网络与持久卷

    上一篇"通过实例快速掌握k8s(Kubernetes)核心概念"讲解了k8s的核心概念,有了核心概念整个骨架就完整了,应付无状态程序已经够了,但还不够丰满.应用程序分成两种,无状态 ...

  4. k8s service type_通过搭建MySQL掌握k8s(Kubernetes)重要概念(上):网络与持久卷...

    点击上方蓝色"Go语言中文网"关注我们,设个星标,每天学习 Go 语言 前一篇"通过实例快速掌握 k8s(Kubernetes)核心概念[1]"讲解了 k8s ...

  5. 通过搭建MySQL掌握k8s(Kubernetes)重要概念(上):网络与持久卷

    上一篇"通过实例快速掌握k8s(Kubernetes)核心概念"讲解了k8s的核心概念,有了核心概念整个骨架就完整了,应付无状态程序已经够了,但还不够丰满.应用程序分成两种,无状态 ...

  6. @kubernetes(k8s)数据持久化Volume存储卷(emptyDir、hostPath、NFS、StorageClass)

    文章目录 kubernetes(k8s)数据持久化Volume 一.数据持久化 1.Vlolume概述 2.数据卷的分类 3.常用的四种数据卷 4.Pod使用Volume步骤: 5. volume基本 ...

  7. Docker(二十一)--Docker k8s--Kubernetes存储--Volumes配置管理--持久卷--动态静态分配

    目录 1. 简介 2. NFS PV示例(静态分配) 2.1.保证环境的干净 2.2 创建所需资源 2.3 书写pv,pvc,pod文件并进行测试 2.3.1 创建pv 2.3.2 创建pvc和pod ...

  8. k8s--Kubernetes存储--Volumes配置管理--持久卷--动态静态分配

    文章目录 一.简介 二.NFS PV示例( 静态分配) 1.保证环境的干净 2.创建所需资源 3.书写pv,pvc,pod文件并进行测试 (1)创建静态pv (2)创建pvc (3)创建pod (4) ...

  9. 云原生周报 | K8s 树内存储向 CSI 卷迁移进展;百度混部技术解析;BFE 通过工信部开源成熟度评估

    业界要闻 1. BFE 开源项目通过工信部电子标准院开源项目成熟度评估 摘要:BFE(Beyond Front End) 是开源的现代化七层负载均衡系统,是 CNCF(云原生计算基金会)沙箱项目.BF ...

最新文章

  1. linux下的几种隐藏技术
  2. [渝粤教育] 南开大学 思辨式英文写作 参考 资料
  3. 逐步创建ASP.NET Core 2.2应用程序
  4. Java将hive数据导入到hdfs_sqoop数据导入到Hdfs 或者hive
  5. 2015年1月c语言程序设 第二版,2015年电大1253+C语言程序设计A(2010年1月)小抄参考.doc...
  6. 线性调频信号(chirp signal)
  7. mysql 内连接查询三表数据_数据库三表连接查询怎么做
  8. 国家测绘局制定的测绘与地理信息行业标准统计 (20110706)
  9. 冰点还原精灵V8.37.020系统还原软件
  10. cocos2d-x 音乐/音效设置
  11. menu在python中的意思_Python-Tkinter 组件之Menu
  12. win10主题更换_小白如何做到不更换硬件提升电脑性能做到不卡顿?
  13. CAD二次开发(c#)利用选择集获取标注尺寸
  14. mysql 8安装方法_Mysql8.0.17安装教程【推荐】
  15. Look Into Person数据集的错误!!
  16. 一位中科院自动化研究所博士的论文致谢:求学22载,计算机终成一生的事业与希望...
  17. c语言graphics调用gpg图片,求助:嵌入式c驱动程序,初始化gpg0和gpg9 为什么getpin时不是0...
  18. 令人闹心挠心的智商测试题
  19. 魅族搭载鸿蒙的机型,魅族宣布接入鸿蒙系统 魅族鸿蒙系统手机是哪些?
  20. vue-echarts画深度图

热门文章

  1. macOS Big Sur系统安装
  2. excel中基于两组数的拟合幂指关系,预测结果的函数
  3. 区块链如何打通征信行业的“任督二脉”?
  4. 平安金融壹账通测试技术周报(七十一期)
  5. 16个你不知道的Win8.1技巧
  6. Go语言 Google资深工程师深度讲解
  7. 在word文档中插入代码
  8. plt自定义主要刻度值和次要刻度值
  9. Latex学习笔记 (Ex2) 使用LaTeX画规则的树形图
  10. div-css计算器制作