06_k8s数据持久化
06_k8s数据持久化
一句话用nfs共享存储数据卷就很好了----简单ez
前面完成了部署一个web服务,运行pod创建service创建,创建ingress对外提供域名的7层代理
下一就要关注应用部署后的数据存储问题,容器化如何管理,k8s化如何管理
1.什么是volume
- 容器内部数据存储,在容器生命周期比较短暂,伴随容器的销毁而删除,很不稳定,
- 并且在同一个pod下同时运行多个容器,经常需要再多个容器之间共享文件,
- 因此k8s抽象一个Volume存储卷来决绝这个问题
- volume属于pod的一部分,不能单独的创建,只能在pod中定义
- pod中的所有容器都可以访问volume,且是挂载后使用,可以挂载到容器的任何目录
- k8s的volume不仅仅支持集群内部资源类型,还支持第三方的存储。
Volume的生命周期与它挂载pod相同,但是volume里面的文件可能在volume消失后任然存在,这个取决于volume的类型
2.Volume类型
k8s的volume有非常多的类型,在实际使用中最多的类型
- emptyDir:一种简单的空目录,主要用于临时存储
- hostPath:将主机某个目录挂载到容器中
- ConfigMap,Secret 特殊类型,将kubernetes特定类型的队形挂载到POD
- persistentVolumeClaim:Kubernetes的持久化存储类型,详细介绍请参考PV、PVC和StorageClass中会详细介绍。
2.1EmptyDir类型
EmptyDir是最简单的一种Volume类型,根据名字相同就能看出,这个Volume挂载后就是一个空目录,应用程序可以里面读写文件emptyDir Volume的生命周期与Pod相同,Pod删除后Volume的数据也同时删除。
- pod内容器共享数据卷数据
- 存在pod生命周期,pod销毁,数据丢失
- pod内容器自动创建,数据不会丢失
[root@k8s-master-10 ~/test-volumes]#cat busybox-volume.yml
apiVersion: v1
kind: Pod
metadata:name: busybox-emptynamespace: yuchaoit
spec:containers:- image: busyboxname: test-busyboxvolumeMounts:- mountPath: /data/busybox/name: cache-busyboxcommand: ["/bin/sh","-c","while true;do echo $(date) >> /data/busybox/www.yuchaoit.cn.log;sleep 2;done"]volumes:- name: cache-busyboxemptyDir: {}
emptyDir实际是将Volume的内容写在Pod所在节点的磁盘上
创建资源
[root@k8s-master-10 ~/test-volumes]#kubectl create -f busybox-volume.yml [root@k8s-master-10 ~/test-volumes]#kubectl -n yuchaoit get po busybox-empty -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox-empty 1/1 Running 0 2m18s 10.2.1.48 k8s-node-11 <none> <none>
查看目标机器的volume情况
# 1. docker inspect查看容器挂载信息# 2. 查看宿主机挂载目录
[root@k8s-node-11 ~]#tail -f /var/lib/kubelet/pods/e631e809-d3e7-4bcf-8d13-3364a4e4add2/volumes/kubernetes.io~empty-dir/cache-busybox/*
Mon Sep 12 08:44:03 UTC 2022
Mon Sep 12 08:44:05 UTC 2022
Mon Sep 12 08:44:07 UTC 2022
Mon Sep 12 08:44:09 UTC 2022
Mon Sep 12 08:44:11 UTC 2022
Mon Sep 12 08:44:13 UTC 2022
Mon Sep 12 08:44:15 UTC 2022
Mon Sep 12 08:44:17 UTC 2022
Mon Sep 12 08:44:19 UTC 2022
干掉pod
[root@k8s-master-10 ~/test-volumes]#kubectl -n yuchaoit delete po busybox-empty
pod "busybox-empty" deleted查看Volume状态
随之也被清空了
小结
EmptyDir 与pod共存亡
2.2 HostPath类型
https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/
Container 中的文件在磁盘上是临时存放的,这给 Container 中运行的较重要的应用程序带来一些问题。
问题之一是当容器崩溃时文件丢失。 kubelet 会重新启动容器,但容器会以干净的状态重启。
第二个问题会在同一 Pod
中运行多个容器并共享文件时出现。 Kubernetes 卷(Volume) 这一抽象概念能够解决这两个问题。
阅读本文前建议你熟悉一下 Pod。
HostPath是一种持久化存储,emptyDir里面的内容会随着pod的删除而消失,但HostPath不会
对应的Pod删除,HostPath Volume里面的内容依然存在于节点目录,如果后续重新创建Pod并调度同一节点,挂载依旧可以督导pod以前的内容
HostPath存储的内容与节点相关,所以它不适合像数据库这类的应用,想象下如果数据库的Pod被调度到别的节点了,那读取的内容就完全不一样了。记住永远不要使用HostPath存储跨Pod的数据,一定要把HostPath的使用范围限制在读取节点文件上,这是因为Pod被重建后不确定会调度哪个节点上,写文件可能会导致前后不一致。
yaml
[root@k8s-master-10 ~/test-volumes]#cat busybox-volume.yml
apiVersion: v1
kind: Pod
metadata:name: busybox-hostpathnamespace: yuchaoit
spec:volumes:- name: hostpath-busyboxhostPath:path: /data/hostpath-busybox # 宿主机映射点type: DirectoryOrCreate # 目录不存在自动创建containers:- image: busyboxname: test-busyboxvolumeMounts: # 容器数据挂到Volume里- mountPath: /data/busybox/ # 容器内挂载点name: hostpath-busybox # 容器内挂载点,挂到哪个卷command: ["/bin/sh","-c","while true;do echo $(date) 超哥带你学k8s >> /data/busybox/www.yuchaoit.cn.log;sleep 2;done"]
创建结果
[root@k8s-master-10 ~/test-volumes]#kubectl -n yuchaoit get po busybox-hostpath -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox-hostpath 1/1 Running 0 42s 10.2.1.49 k8s-node-11 <none> <none>
查看宿主机日志挂载
3.NFS类型(常用要记)
https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/#nfs
很明显,这种不一致的数据持久化,必然是不可取的,我们可以采用共享式存储文件系统,NFS就是个代表。
nfs
卷能将 NFS (网络文件系统) 挂载到你的 Pod 中。
不像 emptyDir
那样会在删除 Pod 的同时也会被删除,nfs
卷的内容在删除 Pod 时会被保存,卷只是被卸载。 这意味着 nfs
卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。
注意: 在使用 NFS 卷之前,你必须运行自己的 NFS 服务器并将目标 share 导出备用。
# 变化的只有关于Volume设置参数
# 查看应该用什么字段
# [root@k8s-master-10 ~/test-volumes]#kubectl explain pod.spec.volumes.nfs
# 提前准备好一个NFS服务器即可。# yum install nfs-utils rpcbind -y# /nfsShare *(insecure,rw,sync,root_squash)
- 具体yaml
[root@k8s-master-10 ~/test-volumes]#cat busybox-volume.yml
apiVersion: v1
kind: Pod
metadata:name: nginx-volume-nfsnamespace: yuchaoit
spec:volumes:- name: nfs-datanfs:server: 10.0.0.11path: /nfsSharecontainers:- image: nginx:1.14.1name: nginx-volume-nfsports:- name: httpcontainerPort: 80volumeMounts: # 容器数据挂到Volume里- mountPath: /usr/share/nginx/html/ # 容器内挂载点name: nfs-data # 容器内挂载点,挂到哪个卷
创建pod查看nfs共享数据
[root@k8s-master-10 ~/test-volumes]#kubectl create -f nfs-volume.yml
pod/nginx-volume-nfs created
[root@k8s-master-10 ~/test-volumes]#
[root@k8s-master-10 ~/test-volumes]#kubectl -n yuchaoit get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-6f7886b6db-pvjd5 1/1 Running 0 6h 10.2.2.60 k8s-node-12 <none> <none>
nginx-deployment-6f7886b6db-xsj8n 1/1 Running 0 6h 10.2.1.47 k8s-node-11 <none> <none>
nginx-volume-nfs 1/1 Running 0 6s 10.2.1.50 k8s-node-11 <none> <none>
[root@k8s-master-10 ~/test-volumes]#
[root@k8s-master-10 ~/test-volumes]#curl 10.2.1.50
<meta charset=utf-8>666www.yuchaoit.cn
思考
这只是给pod单个的添加Volume字段,如果一组pod控制器需要使用nfs,该如何配置?
volume支持的种类众多(参考 https://kubernetes.io/docs/concepts/storage/volumes/#types-of-volumes )
每种对应不同的存储后端实现,因此为了屏蔽后端存储的细节,同时使得Pod在使用存储的时候更加简洁和规范,k8s引入了两个新的资源类型,PV和PVC。PersistentVolume(持久化卷),是对底层的存储的一种抽象,它和具体的底层的共享存储技术的实现方式有关,比如 Ceph、GlusterFS、NFS 等,都是通过插件机制完成与共享存储的对接。
如使用PV对接NFS存储。apiVersion: v1
kind: PersistentVolume
metadata:name: nfs-pv
spec:capacity: storage: 1GiaccessModes:- ReadWriteManypersistentVolumeReclaimPolicy: Retainnfs:path: /nfsShareserver: 10.0.0.11
4.pv(PersistentVolume)持久化数据卷
前面介绍的是针对pod资源设置Volume的三种玩法
EmptyDir,非持久化
hostPath,属于持久化,但只限在具体Node,只适合读的场景。
nfs,属于持久化。
如果要求pod在重新被调度后,依然能保留,使用之前读写后的数据,就必须用网络存储;
网络存储有很多主流的方案,块存储、文件存储、对象存储等。
开源技术
cephFS
GlusterFS
NFS生产环境下的公有云厂商提供的
-对象存储
-云硬盘
-弹性文件系统
PV是什么
PersistentVolume
PV描述的是持久化存储卷,主要定义的是一个持久化存储在宿主机上的目录,比如一个NFS的挂载目录。
PVC是什么
PersistentVolumeClaim
PVC描述的是Pod所希望使用的持久化存储的属性,比如,Volume存储的大小、可读写权限等等。
PVC绑定PV
nfs与mysql数据共享持久化
1.准备NFS
yum install nfs-utils -y
mkdir /nfs-volume/mysql/ -p
cat > /etc/exports <<'EOF'
/nfs-volume/mysql/ 10.0.0.0/24(rw,async,no_root_squash,no_all_squash)
EOFsystemctl restart nfs rpcbind
systemctl enable nfs rpcbindshowmount -e 127.0.0.1
2.node安装nfs套件
yum install nfs-utils -yshowmount -e 10.0.0.10
3.管理员准备NFS-PV
apiVersion: v1
kind: PersistentVolume
metadata:name: nfs-pv # pv资源名# namespace: yuchaoit
spec:capacity: storage: 10Gi # 存储10Gi资源accessModes:- ReadWriteMany # 多个节点可以读写PVpersistentVolumeReclaimPolicy: Retain # PV回收策略,保留数据,需要管理员手工删除nfs: # 对接存储类型path: /nfs-volume/mysql/server: 10.0.0.10
创建pv
[root@k8s-master-10 /all-k8s-yml]#kubectl create -f mysql-nfs-pv.yml
persistentvolume/nfs-pv created[root@k8s-master-10 /all-k8s-yml]#kubectl -n yuchaoit get pv -owide
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
nfs-pv 10Gi RWX Retain Available 9s Filesystem一个 PV 的生命周期中,可能会处于4中不同的阶段:Available(可用):表示可用状态,还未被任何 PVC 绑定
Bound(已绑定):表示 PV 已经被 PVC 绑定
Released(已释放):PVC 被删除,但是资源还未被集群重新声明
Failed(失败): 表示该 PV 的自动回收失败
pv资源字段解释
capacity,存储能力, 目前只支持存储空间的设置, 就是我们这里的 storage=1Gi,不过未来可能会加入 IOPS、吞吐量等指标的配置。accessModes,访问模式, 是用来对 PV 进行访问模式的设置,用于描述用户应用对存储资源的访问权限,访问权限包括下面几种方式:
ReadWriteOnce(RWO):读写权限,但是只能被单个节点挂载
ReadOnlyMany(ROX):只读权限,可以被多个节点挂载
ReadWriteMany(RWX):读写权限,可以被多个节点挂载persistentVolumeReclaimPolicy,pv的回收策略, 目前只有 NFS 和 HostPath 两种类型支持回收策略
Retain(保留)- 保留数据,需要管理员手工清理数据
Recycle(回收)- 清除 PV 中的数据,效果相当于执行 rm -rf /volume_yuchaoit.cn/*
Delete(删除)- 与 PV 相连的后端存储完成 volume 的删除操作,当然这常见于云服务商的存储服务,比如 ASW EBS。
目前只有NFS、HostPath两个类型的PV支持Recycle,直接删除。
PV不属于集群资源
因为PV是直接对接底层存储的,就像集群中的Node可以为Pod提供计算资源(CPU和内存)一样,PV可以为Pod提供存储资源。
因此PV不是namespaced的资源,属于集群层面可用的资源。
Pod如果想使用该PV,需要通过创建PVC挂载到Pod中。
当PV进入Released状态备注
若PVC被删除,PV会进入Released状态,PVC也无法重新绑定,PVC只能和Availabel状态的PV绑定。生产做法是
1. 备份PV数据,迁移走
2. 修改PV状态,删除对PVC的引用记录,此时k8s的PV控制器watch到PV变化,更新PV状态,恢复Availabel状态。