k8s入门篇-持久化存储管理
一、Volumes

二、Volumes的类型
2.1 ConfigMap
ConfigMap卷也可以作为volume使用,存储在ConfigMap中的数据可以通过ConfigMap类型的卷挂载到Pod中,然后使用该ConfigMap中的数据。引用ConfigMap对象时,只需要在volume中引用ConfigMap的名称即可,同时也可以自定义ConfigMap的挂载路径。
例如,将名称为log-config的ConfigMap挂载到Pod的/etc/config目录下,挂载的文件名称为path指定的值,当前为log_level:
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为{}即可:
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进行数据共享
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字符串:
[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是容器间共享。
[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时区:
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服务。
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:
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
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
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
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
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:
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来测试
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创建和挂载失败原因



浙公网安备 33010602011771号