前言
容器磁盘上的文件的生命周期是短暂的,这就使得在容器中运行重要应用时会出现一些问题。首先,当容器崩溃时,kubelet 会重启它,但是容器中的文件将丢失——容器以干净的状态(镜像最初的状态)重新启动。其次,在Pod中同时运行多个容器时,这些容器之间通常需要共享文件。Kubernetes 中的Volume抽象就很好的解决了这些问题。Pod中的容器通过Pause容器共享Volume。
1.emptyDir(主要用于容器内部共享数据)
容器内部共享存储卷,k8s系统中,是一个pod当中的多个容器共享一个存储目录。
emptyDir卷可以使pod当中的容器在这个存储卷上读取和写入
emptyDir是不能挂载到节点的,随着pod的生命周期结束
kubectl create deployment nginx --image=nginx:1.22 --replicas=3 --dry-run=client -o yaml > /opt/test1.yamlvim test1.yamlapiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginx1name: nginx1
spec:replicas: 1selector:matchLabels:app: nginx1template:metadata:labels:app: nginx1spec:containers:- image: nginx:1.22name: nginx1volumeMounts:- name: htmlmountPath: /usr/share/nginx/html- image: nginx:1.22name: nginx2volumeMounts:- name: htmlmountPath: /datacommand: ["/bin/bash","-c","while true; do echo $(date) >> /data/index.html; sleep 2; done"]volumes:- name: htmlemptyDir: {}kubectl exec -it nginx1-6b677dd6bc-4rnkc -c nginx2 bash
2.hostPath
将容器内的挂载点,和节点上的目录进行挂载,hostPath可以实现数据持久化。node节点被销毁,那么数据也会丢失
污点设置为:
NoExecute:节点上的pod会被驱逐,文件数据不在?
pod被驱逐,并不是node节点被销毁,所有数据还保留在节点上。
pod被驱逐(基于控制器创建的)会在其他重新部署,由会在其他节点生成一个新的存储卷。数据依然可以持久化
hostPath模拟展示
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginx1name: nginx1
spec:replicas: 3selector:matchLabels:app: nginx1template:metadata:labels:app: nginx1spec:containers:- image: nginx:1.22name: nginx1volumeMounts:- name: htmlmountPath: /usr/share/nginx/html- image: nginx:1.22name: nginx2volumeMounts:- name: htmlmountPath: /datacommand: ["/bin/bash","-c","while true; do echo $(date) >> /data/index.html; sleep 2; done"]volumes:- name: htmlhostPath:path: /opt/testtype: DirectoryOrCreate
-c 进入不同容器内的信息
logs -c 查看不同容器输出的日志
3.NFS共享存储
所有的pod内的目录都和节点上的nfs共享目录形成数据卷,所有的数据文件都保存在共享目录当中。
使用nfs服务将共享存储设备空间挂载到容器中,可实现持久化数据存储,且Pod能实现跨节点共享数据 。
node02
先把共享目录创建出来
mkdir /data/volumes
chmod 777 volumes/
vim /etc/exports/data/volumes 20.0.0.0/24(rw,no_root_squash)
wqsystemctl restart rpcbind
systemctl restart nfs
showmount -emaster01
showmount -e 20.0.0.64vim test1.yamlspec:containers:- image: nginx:1.22name: nginx1volumeMounts:- name: htmlmountPath: /usr/share/nginx/html- image: nginx:1.22 name: nginx2volumeMounts: - name: htmlmountPath: /data command: ["/bin/bash","-c","while true; do echo $(date) >> /data/index.html; sleep 2; done"]volumes:- name: htmlnfs:path: /data/volumesserver: 20.0.0.64wqkubectl apply -f test1.yamlnode02
touch 123 456 789去master01
kubectl exec -it nginx1-
cd /usr/share/html
exitvolumes:- name: htmlnfs:path: /data/volumesserver: node02 / 20.0.0.63
server可以是共享目录的ip地址,也可以是主机名。主机名要做映射
PVC和PV的静态存储卷
pv:全称Persistent Volume 持久化存储卷,描述和定义一个存储卷,pv是由我们运维人员来定义。
pvc:persistent Volume Claim是持久化存储的请求。
pvc-------> pv --------NFS
pvc实际上是用来描述或者声明我希望使用什么样的pv来进行存储。
pvc-pv是一一对应的关系(描述,存储(大小))
pv和pvc都是虚拟化的概念,是k8s的抽象的虚拟的存储资源。
pvc和pv之间静态请求,一旦成百个pvc怎么办?-----使用动态pvc
PV是集群中的资源。 PVC是对这些资源的请求,也是对资源的索引检查。
PVC和PV的创建和销毁过程
pv和pvc之间是有生命周期管理:
1.Provisioning(配置)----pvc请求request-----检索(找一个合适的pv)-----pvc和pv(binding 绑定)----使用---pod被删除---pvreleasing(释放)---recycling(回收)
●Provisioning,即 PV 的创建,可以直接创建 PV(静态方式),也可以使用 StorageClass 动态创建
●Binding,将 PV 分配给 PVC
●Using,Pod 通过 PVC 使用该 Volume,并可以通过准入控制StorageProtection(1.9及以前版本为PVCProtection) 阻止删除正在使用的 PVC
●Releasing,Pod 释放 Volume 并删除 PVC
●Reclaiming,回收 PV,可以保留 PV 以便下次使用,也可以直接从云存储中删除
根据这 5 个阶段,PV 的状态有以下 4 种:
●Available(可用):表示可用状态,还未被任何 PVC 绑定
●Bound(已绑定):表示 PV 已经绑定到 PVC
●Released(已释放):表示 PVC 被删掉,但是资源尚未被集群回收
●Failed(失败):表示该 PV 的自动回收失败
读写方式:
ReadWriteOnce:RWO,配置文件里面是全称,存储pv是可读可写,但是只能被单个pod挂载。
ReadOnlyMany:ROX,存储的pv可以以只读的方式被多个pod挂载。
ReadWriteMany:RWX存储可以支持读写的方式被多个pod共享。
nfs:可以支持三种读写和挂载方式
SCSI
ISCSI:不支持 RWX
hostPath:只支持RWO,其他都不支持。
lsscsi可以查看当前设备的所有设备
iscsiadm -m session -P 3
iscsiadm:查看服务器是否有iscsi设备
-m session:指定操作的会话模块,管理iscsi会话
-P 3:显示详细信息的级别。级别就是3.显示详细信息。
回收策略
集群回收pv资源的方式:
Retain(默认策略):保留,pod和挂载点的数据不会被删除
Recycle:回收,pv上的数据会被删除。挂载点的数据也被删除
Delete:删除,解绑时,自动删除pv上的数据。(本地硬盘无法使用,AWS,EBS,GCE)支持的动态卷可以使用,pv不再可用(云平台自己处理)
补充:当pod运行之后,通过pvc请求到了pv,除非pod被销毁,否则无法删除pvc
vim /etc/exports
/data/v1 20.0.0.0/24(rw,no_root_squash)
/data/v2 20.0.0.0/24(rw,no_root_squash)
/data/v3 20.0.0.0/24(rw,no_root_squash)
/data/v4 20.0.0.0/24(rw,no_root_squash)
/data/v5 20.0.0.0/24(rw,no_root_squash)
wqexportfs -arv
showmount -e
各个节点都查看一下vim pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:name: pv001labels:name: pv001
spec:nfs:path: /data/v1server: 20.0.0.64accessModes: ["ReadWriteMany","ReadWriteOnce"]capacity:storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv002labels:name: pv002
spec:nfs:path: /data/v2server: 20.0.0.64accessModes: ["ReadWriteOnce"]capacity:storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv003labels:name: pv003
spec:nfs:path: /data/v3server: 20.0.0.64accessModes: ["ReadWriteMany","ReadWriteOnce"]capacity:storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv004labels:name: pv004
spec:nfs:path: /data/v4server: 20.0.0.64accessModes: ["ReadWriteMany","ReadWriteOnce"]capacity:storage: 4Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv005labels:name: pv005
spec:nfs:path: /data/v5server: 20.0.0.64accessModes: ["ReadWriteMany","ReadWriteOnce","ReadOnlyMany"]capacity:storage: 5Giwqkubectl apply -f pv.yaml
kubectl get pvvim pvc.yamlapiVersion: v1
kind: PersistentVolumeClaim
metadata:name: mypvc
spec:accessModes: ["ReadWrtieMany"]
#pvc期望请求的pv的读写挂载类型是什么。resources:requests:storage: 2Gi
#pvc期望请求pv的存储大小是2G,期望的pv类型:readwritemany 大小是2G。
---
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginxname: nginx1
spec:replicas: 3selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- image: nginx:1.22name: nginx1volumeMounts:- name: htmlmountPath: /usr/share/nginx/htmlvolumes:- name: htmlpersistentVolumeClaim:claimName: mypvcwqkubectl apply -f test1.yaml
kubectl get pv
pvc---请求用哪个pv的存储-----pv和物理存储做映射(挂载)---物理设备提供存储卷
只有是Available才是可用被请求
同时,还可以对pv设置回收策略
模拟--一个pv匹配多个pod
vim pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:name: pv001labels:name: pv001
spec:nfs:path: /data/v1server: 20.0.0.63accessModes: ["ReadWriteMany","ReadWriteOnce"]capacity:storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv002labels:name: pv002
spec:nfs:path: /data/v2server: 20.0.0.63accessModes: ["ReadWriteOnce"]capacity:storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv003labels:name: pv003
spec:nfs:path: /data/v3server: 20.0.0.63accessModes: ["ReadWriteMany","ReadWriteOnce"]capacity:storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv004labels:name: pv004
spec:nfs:path: /data/v4server: 20.0.0.63accessModes: ["ReadWriteMany","ReadWriteOnce"]capacity:storage: 4Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv005labels:name: pv005
spec:nfs:path: /data/v5server: 20.0.0.63accessModes: ["ReadWriteMany","ReadWriteOnce","ReadOnlyMany"]capacity:storage: 5Givim pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: mypvc
spec:accessModes: ["ReadWriteMany"]resources:requests:storage: 2Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginxname: nginx-dir
spec:replicas: 3selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- image: nginx:1.22name: nginx1volumeMounts:- name: htmlmountPath: /usr/share/nginx/htmlvolumes:- name: htmlpersistentVolumeClaim:claimName: mypvc
---
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginx-2name: nginx-dir1
spec:replicas: 3selector:matchLabels:app: nginx-2template:metadata:labels:app: nginx-2spec:containers:- image: nginx:1.22name: nginx-2volumeMounts:- name: htmlmountPath: /usr/share/nginx/htmlvolumes:- name: htmlpersistentVolumeClaim:claimName: mypvc
总结:
k8s当中存储卷的模式:
emptyDir:容器内的存储卷,随着pod被销毁,也会被销毁,数据被保留
hostPath:和节点目录的存储卷,可以实现持久化存储。数据在每个节点上都有,不方便集中管理
nfs:共享目录存储卷,可以实现持久化,数据集中在一个目录,方便管理。
pv和pvc:
pvc请求---pv的存储资源--------硬盘空间(NFS)
因为NFS支持pvc的所有挂载方式和读写模式
hostPath:仅支持ReadWriteOnce方式。
pvc是以检索的方式找到匹配的pv资源,
检索挂载方式和读写模式:
检索pv能提供的存储资源的大小。谁合适选谁
资源保留三种方式:
保留:默认可以不写
回收:自动回收,节点上的数据会被删除
删除:pv会变成failed模式,不可用,数据也会被删除。