k8s入门篇-持久化存储管理
作者:@skyflask
转载本文请注明出处:https://www.cnblogs.com/skyflask/p/16823590.html
目录
一、Volumes
二、Volumes的类型
2.1 ConfigMap
2.2 emptyDir
2.3 hostPath
2.4 NFS
3 PV&PVC
3.1 PV&PVC概述
3.2 创建PV
3.3 PVC使用案例
3.4 PVC创建和挂载失败原因
一、Volumes
二、Volumes的类型
2.1 ConfigMap
ConfigMap卷也可以作为volume使用,存储在ConfigMap中的数据可以通过ConfigMap类型的卷挂载到Pod中,然后使用该ConfigMap中的数据。引用ConfigMap对象时,只需要在volume中引用ConfigMap的名称即可,同时也可以自定义ConfigMap的挂载路径。
例如,将名称为log-config的ConfigMap挂载到Pod的/etc/config目录下,挂载的文件名称为path指定的值,当前为log_level:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | apiVersion: v1 kind: Pod metadata: name: configmap-pod spec: containers: - name: test image: busybox volumeMounts: - name: config-vol mountPath: /etc/config volumes: - name: config-vol configMap: name: log-config items: - key: log_level path: log_level |
2.2 emptyDir
和上述volume不同的是,如果删除Pod,emptyDir卷中的数据也将被删除,一般emptyDir卷用于Pod中的不同Container共享数据。它可以被挂载到相同或不同的路径上。
默认情况下,emptyDir卷支持节点上的任何介质,可能是SSD、磁盘或网络存储,具体取决于自身的环境。可以将emptyDir.medium字段设置为Memory,让Kubernetes使用tmpfs(内存支持的文件系统),虽然tmpfs非常快,但是tmpfs在节点重启时,数据同样会被清除,并且设置的大小会被计入到Container的内存限制当中。
使用emptyDir卷的示例,直接指定emptyDir为{}即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | apiVersion: v1 kind: Pod metadata: name: test -pd spec: containers: - image: k8s.gcr.io /test-webserver name: test -container volumeMounts: - mountPath: /cache name: cache-volume volumes: - name: cache-volume emptyDir: {} |
案例:容器中使用emptyDir进行数据共享
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | apiVersion: apps /v1 kind: Deployment metadata: annotations: deployment.kubernetes.io /revision : "1" labels: app: nginx name: nginx-emptdir-deploy namespace: default spec: progressDeadlineSeconds: 600 replicas: 2 #副本数 revisionHistoryLimit: 10 # 历史记录保留的个数 selector: matchLabels: app: nginx-emptydir type : front strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type : RollingUpdate template: metadata: creationTimestamp: null labels: app: nginx-emptydir type : front spec: containers: - image: nginx:1.15.2 #第一个容器,挂载点/opt,类型是emptydir imagePullPolicy: IfNotPresent name: nginx terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /opt name: share-volume - image: nginx:1.15.2 #第二个容器,挂载点/mnt,类型是emptydir imagePullPolicy: IfNotPresent name: nginx2 command : - sh - -c - sleep 3600 terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /mnt name: share-volume dnsPolicy: ClusterFirst schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30 volumes: - name: share-volume emptyDir: {} |
挂载后,写入test字符串:
1 2 3 4 | [root@k8s-master01 ~ /k8s/volums ] # kubectl exec -it nginx-emptdir-deploy-7784c5bcf4-25v89 -c nginx -- cat /opt/test test [root@k8s-master01 ~ /k8s/volums ] # kubectl exec -it nginx-emptdir-deploy-7784c5bcf4-25v89 -c nginx2 -- cat /mnt/test test |
再次修改,可以看到两个容器内的内容都变了,说明emptydir是容器间共享。
1 2 3 4 5 6 7 8 9 10 | [root@k8s-master01 ~ /k8s/volums ] # kubectl exec -it nginx-emptdir-deploy-7784c5bcf4-25v89 -c nginx -- bash root@nginx-emptdir-deploy-7784c5bcf4-25v89:/ # echo "my name is nginx" /opt/test my name is nginx /opt/test root@nginx-emptdir-deploy-7784c5bcf4-25v89:/ # echo "my name is nginx" > /opt/test root@nginx-emptdir-deploy-7784c5bcf4-25v89:/ # exit exit [root@k8s-master01 ~ /k8s/volums ] # kubectl exec -it nginx-emptdir-deploy-7784c5bcf4-25v89 -c nginx2 -- cat /mnt/test my name is nginx [root@k8s-master01 ~ /k8s/volums ] # kubectl exec -it nginx-emptdir-deploy-7784c5bcf4-25v89 -c nginx -- cat /opt/test my name is nginx |
2.3 hostPath
通过挂载宿主机的目录或文件到容器里面,例如,我们将宿主机的时区文件挂载到pod,初始化pod时区:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | apiVersion: apps /v1 kind: Deployment metadata: annotations: deployment.kubernetes.io /revision : "1" labels: app: nginx name: nginx-hostpath-deploy namespace: default spec: progressDeadlineSeconds: 600 replicas: 2 #副本数 revisionHistoryLimit: 10 # 历史记录保留的个数 selector: matchLabels: app: nginx-hostpath type : front strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type : RollingUpdate template: metadata: creationTimestamp: null labels: app: nginx-hostpath type : front spec: containers: - image: nginx:1.15.2 imagePullPolicy: IfNotPresent name: nginx terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /opt name: share-volume - mountPath: /etc/localtime #将宿主机的时区挂载到pod name: timezone - image: nginx:1.15.2 imagePullPolicy: IfNotPresent name: nginx2 command : - sh - -c - sleep 3600 terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /mnt name: share-volume dnsPolicy: ClusterFirst schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30 volumes: - name: share-volume emptyDir: {} - name: timezone #设置hostpath hostPath: path: /etc/localtime type : File |
hostPath卷常用的type(类型)如下:
- type为空字符串:默认选项,意味着挂载hostPath卷之前不会执行任何检查。
- DirectoryOrCreate:如果给定的path不存在任何东西,那么将根据需要创建一个权限为0755的空目录,和Kubelet具有相同的组和权限。
- Directory:目录必须存在于给定的路径下。
- FileOrCreate:如果给定的路径不存储任何内容,则会根据需要创建一个空文件,权限设置为0644,和Kubelet具有相同的组和所有权。
- File:文件,必须存在于给定路径中。
- Socket:UNIX套接字,必须存在于给定路径中。
- CharDevice:字符设备,必须存在于给定路径中。
- BlockDevice:块设备,必须存在于给定路径中。
2.4 NFS
NFS卷也是一种网络文件系统,同时也可以作为动态存储,和GFS类似,删除Pod时,NFS中的数据不会被删除。NFS可以被多个写入同时挂载。
在其中一个节点安装nfs服务。
1 2 3 4 5 6 7 8 9 | yum install nfs-uitls -y systemctl nfs-server start systemctl start rpcbind systemctl start nfs systemctl enable rpcbind systemctl enable nfs cat /etc/exports /data1/nfs 10.10.2.0 /24 (rw, sync ,no_root_squash) |
在每个需求挂载nfs的机器上安装nfs客户端:yum install nfs-uitls -y
使用nfs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | apiVersion: apps /v1 kind: Deployment metadata: annotations: deployment.kubernetes.io /revision : "1" labels: app: nginx name: nginx-hostpath-deploy namespace: default spec: progressDeadlineSeconds: 600 replicas: 2 #副本数 revisionHistoryLimit: 10 # 历史记录保留的个数 selector: matchLabels: app: nginx-hostpath type : front strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type : RollingUpdate template: metadata: creationTimestamp: null labels: app: nginx-hostpath type : front spec: containers: - image: nginx:1.15.2 imagePullPolicy: IfNotPresent name: nginx terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - image: nginx:1.15.2 imagePullPolicy: IfNotPresent name: nginx2 command : - sh - -c - sleep 3600 terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /opt name: nfs-volume #挂载nfs卷 dnsPolicy: ClusterFirst schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30 volumes: - name: nfs-volume #定义nfs挂载卷 nfs: server: 10.10.2.129 path: /data1/nfs/nginx |
测试:
nfs上更新文件:
pod上查看文件:
缺点:nfs属于单点,没有保障,不建议生产环境上使用。
3 PV&PVC
3.1 PV&PVC概述
PersistentVolume(简称PV)是由管理员设置的存储,它同样是集群中的一类资源,PV是容量插件,如Volumes(卷),但其生命周期独立使用PV的任何Pod,PV的创建可使用NFS、iSCSI、GFS、CEPH等。
PersistentVolumeClaim(简称PVC)是用户对存储的请求,类似于Pod,Pod消耗节点资源,PVC消耗PV资源,Pod可以请求特定级别的资源(CPU和内存),PVC可以请求特定的大小和访问模式。例如,可以以一次读/写或只读多次的模式挂载。
虽然PVC允许用户使用抽象存储资源,但是用户可能需要具有不同性质的PV来解决不同的问题,比如使用SSD硬盘来提高性能。所以集群管理员需要能够提供各种PV,而不仅是大小和访问模式,并且无须让用户了解这些卷的实现方式,对于这些需求可以使用StorageClass资源实现。
目前PV的提供方式有两种:静态或动态。
静态PV由管理员提前创建,动态PV无需提前创建,只需指定PVC的StorageClasse即可。
(1)回收策略
当用户使用完卷时,可以从API中删除PVC对象,从而允许回收资源。回收策略会告诉PV如何处理该卷,目前卷可以保留、回收或删除。
- Retain:保留,该策略允许手动回收资源,当删除PVC时,PV仍然存在,volume被视为已释放,管理员可以手动回收卷。【静态PV推荐】
- Recycle:回收,如果volume插件支持,Recycle策略会对卷执行rm -rf清理该PV,并使其可用于下一个新的PVC,但是本策略已弃用,建议使用动态配置。【将会被废弃】
- Delete:删除,如果volume插件支持,删除PVC时会同时删除PV,动态卷默认为Delete。【动态PV推荐】
3.2 创建PV
在使用持久化时,需要先创建PV,然后再创建PVC,PVC会和匹配的PV进行绑定,然后Pod即可使用该存储。
3.2.1 创建一个基于NFS的PV
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | apiVersion: v1 kind: PersistentVolume metadata: name: pv0003 #PV名称 spec: capacity: storage: 5Gi volumeMode: Filesystem accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle storageClassName: slow mountOptions: - hard - nfsvers=4.1 nfs: path: /tmp server: 10.10.2.129 |
说明:
capacity:容量。需要后端存储支持才行,比如NFS就不支持。
accessModes:访问模式。包括以下3种:
- ReadWriteOnce:可以被单节点以读写模式挂载,命令行中可以被缩写为RWO。
- ReadOnlyMany:可以被多个节点以只读模式挂载,命令行中可以被缩写为ROX。
- ReadWriteMany:可以被多个节点以读写模式挂载,命令行中可以被缩写为RWX。
storageClassName:PV的类,一个特定类型的PV只能绑定到特定类别的PVC。【PV和PVC绑定关系的名称】
persistentVolumeReclaimPolicy:回收策略。
- Retain:保留,该策略允许手动回收资源,当删除PVC时,PV仍然存在,volume被视为已释放,管理员可以手动回收卷。【静态PV推荐】
- Recycle:回收,如果volume插件支持,Recycle策略会对卷执行rm -rf清理该PV,并使其可用于下一个新的PVC,但是本策略已弃用,建议使用动态配置。【将会被废弃】
- Delete:删除,如果volume插件支持,删除PVC时会同时删除PV,动态卷默认为Delete。【动态PV推荐】
mountOptions:非必须,新版本中已弃用。
nfs:NFS服务配置。包括以下两个选项:
- path:NFS上的目录
- server:NFS的IP地址
创建的PV会有以下几种状态:
- Available(可用),没有被PVC绑定的空间资源。
- Bound(已绑定),已经被PVC绑定。
- Released(已释放),PVC被删除,但是资源还未被重新使用。
- Failed(失败),自动回收失败。
3.2.2 创建一个hostpath的PV
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | kind: PersistentVolume apiVersion: v1 metadata: name: task-pv-volume labels: type : local spec: storageClassName: hostpath capacity: storage: 10Gi accessModes: - ReadWriteOnce hostPath: path: "/mnt/data" |
hostpath的PV一般在线上环境很少使用,除非是内网环境,将某台节点的目录共享给pod使用,此时,共享目录和pod必须绑定,也就是pod的调度只能绑定在本主机上,不能随便漂移。
3.3 PVC使用案例
我们通过一个案例来体验PV和PVC的使用。
3.3.1 定义一个PV
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | cat pv-nfs.yaml apiVersion: v1 kind: PersistentVolume metadata: name: pv-nfs spec: capacity: storage: 5Gi volumeMode: Filesystem accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle storageClassName: nfs-slow nfs: path: /data1/nfs server: 10.10.2.129 |
定义一个叫pv-nfs的pv,大小5GB,单节点读写权限,storageClassName是 nfs-slow。挂载在nfs的/data1/nfs下面。
3.3.2 定义一个PVC
1 2 3 4 5 6 7 8 9 10 11 12 13 | cat pvc-nfs.yaml kind: PersistentVolumeClaim apiVersion: v1 metadata: name: task-pvc-claim spec: storageClassName: nfs-slow accessModes: - ReadWriteOnce resources: requests: storage: 3Gi |
PVC的名称是task-pvc-claim,同样,storageClassName是 nfs-slow,单点读写权限,大小3GB。注意:storageClassName和读写权限必须一样,大小必须小于等于PV,这样才会满足。
3.3.3 定义deployment使用pvc
定义deploy:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | cat dp-nfs.yaml apiVersion: apps /v1 kind: Deployment metadata: labels: app: nginx-pvc name: nginx-pvc- test namespace: default spec: replicas: 2 revisionHistoryLimit: 10 selector: matchLabels: app: nginx-pvc strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 0 type : RollingUpdate template: metadata: creationTimestamp: null labels: app: nginx-pvc spec: volumes: #使用pvc - name: task-pv-storage persistentVolumeClaim: claimName: task-pvc-claim containers: - env : - name: TZ value: Asia /Shanghai - name: LANG value: C.UTF-8 image: nginx imagePullPolicy: IfNotPresent name: nginx volumeMounts: #将PV的内容挂载到容器 - mountPath: "/usr/share/nginx/html" name: task-pv-storage |
定义svc来测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | cat nginx-svc.yaml apiVersion: v1 kind: Service metadata: annotations: labels: app: nginx-pvc name: nginx-pvc-svc namespace: default spec: ports: - name: web #service端口的名称 port: 80 #service自己的端口 protocol: TCP #后端协议 targetPort: 80 #后端应用的端口 sessionAffinity: None selector: app: nginx-pvc type : NodePort status: loadBalancer: {} |
3.4 PVC创建和挂载失败原因
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
2019-10-25 Zabbix实战-简易教程--中间件kafka监控
2019-10-25 Zabbix实战-简易教程--中间件ZooKeeper监控
2019-10-25 Zabbix实战-简易教程--中间件RabbitMQ监控