Docker学习第十一天——k8s之持久化存储
1、做持久化存储的原因在k8s中部署的应用都是以pod容器的形式运行的,假如我们部署MySQL、Redis等数据库,需要对这些数据库产生的数据做备份。因为Pod是有生命周期的,如果pod不挂载数据卷,那pod被删除或重启后这些数据会随之消失,如果想要长久的保留这些数据就要用到pod数据持久化存储。2、常用持久化存储类型• emptyDir• hostPath• nfs• cephfs• secre
目录
一、持久化存储基本介绍
1、做持久化存储的原因
在k8s中部署的应用都是以pod容器的形式运行的,假如我们部署MySQL、Redis等数据库,需要对这些数据库产生的数据做备份。因为Pod是有生命周期的,如果pod不挂载数据卷,那pod被删除或重启后这些数据会随之消失,如果想要长久的保留这些数据就要用到pod数据持久化存储。
2、常用持久化存储类型
• emptyDir
• hostPath
• nfs
• persistentVolumeClaim
• glusterfs
• cephfs
• configMap
• secret
3、持久化存储步骤
1)定义pod的volume,这个volume指明它要关联到哪个存储上的
2)在容器中要使用volumeMounts挂载对应的存储
二、emptyDir
1、概念及应用场景
emptyDir类型的Volume是在Pod分配到Node上时被创建,Kubernetes会在Node上自动分配一个目录,因此无需指定宿主机Node上对应的目录文件。 这个目录的初始内容为空,当Pod从Node上移除时,emptyDir中的数据会被永久删除。emptyDir Volume主要用于某些应用程序无需永久保存的临时目录,多个容器的共享目录等。
2、yaml文件
imagePullPolicy: IfNotPresent ports: - containerPort: 80 volumeMounts: - mountPath: /cache name: testvolume volumes: - emptyDir: {} name: testvolume
三、hostPath
1、概念及应用
• hostPath Volume是指Pod挂载宿主机上的目录或文件。 hostPath Volume使得容器可以使用宿主机的文件系统进行存储。
• hostpath(宿主机路径):节点级别的存储卷,在pod被删除,这个存储卷还是存在的,不会被删除,所以只要同一个pod被调度到同一个节点上来,在pod被删除重新被调度到这个节点之后,对应的数据依然是存在的。
2、搭建流程
[root@hd1.com ~]# vim hostpath.yaml apiVersion: v1 kind: Pod metadata: name: test-hostpath spec: containers: - image: nginx imagePullPolicy: IfNotPresent name: test-nginx volumeMounts: #挂载卷 - mountPath: /test-nginx #挂载到容器内目录位置 name: test-volume #卷名 - image: tomcat:8.5-jre8-alpine name: test-tomcat imagePullPolicy: IfNotPresent volumeMounts: - mountPath: /test-tomcat name: test-volume volumes: - name: test-volume hostPath: path: /data1 #指定宿主机上的挂载目录 type: DirectoryOrCreate #有data1目录则使用,无则在pod调度到的节点时自动创建 #更新资源清单文件 [root@hd1.com ~]# kubectl apply -f hostpath.yaml pod/test-hostpath created #查看pod调度到了哪个物理节点 [root@hd1.com ~]# kubectl get pods -o wide | grep hostpath test-hostpath 2/2 Running 10.244.209.153 hd2.com #由上面可以知道pod调度到了hd2.com上,登录到hd2.com机器,查看是否在这台机器创建了存储目录 [root@hd2.com ~]# ll /data1/ total 0 #上面可以看到已经创建了存储目录/data1,这个/data1会作为pod的持久化存储目录 #在hd2.com上的/data1下创建一个目录 [root@hd2.com ~]# cd /data1/ [root@hd2.com data1]# mkdir aa #测试存储卷是否可以正常使用,登录到nginx容器 [root@hd1.com ~]# kubectl exec -it test-hostpath -c test-nginx -- /bin/bash root@test-hostpath:/# cd /test-nginx/ #/test-nginx/目录存在,说明已经把宿主机目录挂载到了容器里 root@test-hostpath:/test-nginx# ls aa #测试存储卷是否可以正常使用,登录到tomcat容器 [root@hd1.com ~]# kubectl exec -it test-hostpath -c test-tomcat -- /bin/bash root@test-hostpath:/usr/local/tomcat# cd /test-tomcat/ #/test-tomcat/目录存在,说明已经把宿主机目录挂载到了容器里 root@test-hostpath:/test-tomcat# ls aa
四、nfs
1、概念及应用
hostPath存储,存在单点故障,pod挂载hostPath时,只有调度到同一个节点,数据才不会丢失。那可以使用nfs作为持久化存储。
2、搭建流程
#以k8s的控制节点作为NFS服务端 [root@hd1.com ~]# yum install nfs-utils -y #在宿主机创建NFS需要的共享目录 [root@hd1.com ~]# mkdir /data/volumes -pv mkdir: created directory ‘/data’ mkdir: created directory ‘/data/volumes’ #配置nfs共享服务器上的/data/volumes目录 [root@hd1.com ~]# systemctl start nfs [root@hd1.com ~]# vim /etc/exports /data/volumes 192.168.1.0/24(rw,no_root_squash) #no_root_squash: 用户具有根目录的完全管理访问权限 squash 表示挤压,no表示否定,不对root的权限做挤压 #使NFS配置生效 [root@hd1.com ~]# exportfs -arv exporting 192.168.1.0/24:/data/volumes [root@hd1.com ~]# service nfs start Redirecting to /bin/systemctl start nfs.service #设置成开机自启动 [root@hd1.com ~]# systemctl enable nfs #查看nfs是否启动成功 [root@hd1.com ~]# systemctl status nfs Active: active #看到nfs是active,说明nfs正常启动了 #hd3.com和hd2.com上也安装nfs驱动 yum install nfs-utils -y systemctl enable nfs 在hd2.com上手动挂载试试: [root@hd2.com ~]# mkdir /test [root@hd2.com ~]# mount 192.168.1.11:/data/volumes /test/ [root@hd2.com ~]# df -h 192.168.1.11:/data/volumes 50G 5.2G 45G 11% /test #nfs可以被正常挂载 #手动卸载: [root@hd2.com ~]# umount /test #创建Pod,挂载NFS共享出来的目录 Pod挂载nfs的官方地址: https://kubernetes.io/zh/docs/concepts/storage/volumes/ [root@hd1.com ~]# vim nfs.yaml apiVersion: v1 kind: Pod metadata: name: test-nfs-volume spec: containers: - name: test-nfs image: nginx imagePullPolicy: IfNotPresent ports: - containerPort: 80 protocol: TCP volumeMounts: - name: nfs-volumes mountPath: /usr/share/nginx/html volumes: - name: nfs-volumes nfs: path: /data/volumes server: 192.168.1.11 #注:path: /data/volumes #nfs的共享目录 #server:192.168.1.11是hd1.com机器的ip,这个是安装nfs服务的地址 #更新资源清单文件 [root@hd1.com ~]# kubectl apply -f nfs.yaml #查看pod是否创建成功 [root@hd1.com volumes]# kubectl get pods -o wide | grep nfs test-nfs-volume 1/1 Running 10.244.187.108 hd3.com #登录到nfs服务器,在共享目录创建一个index.html root@hd1.com volumes]# pwd /data/volumes [root@hd1.com volumes]# cat index.html Helloworld #请求pod,看结果 [root@hd1.com volumes]# curl 10.244.187.108 helloworld
五、PVC
1、 PersistentVolume(PV)是群集中的一块存储,由管理员配置或使用存储类动态配置。 它是集群中的资源,就像pod是k8s集群资源一样。 PV是容量插件,如Volumes,其生命周期独立于使用PV的任何单个pod。
2、 PersistentVolumeClaim(PVC)是一个持久化存储卷,我们在创建pod时可以定义这个类型的存储卷。 它类似于一个pod。 Pod消耗节点资源,PVC消耗PV资源。 Pod可以请求特定级别的资源(CPU和内存)。 pvc在申请pv的时候也可以请求特定的大小和访问模式(例如,可以一次读写或多次只读)。
3、 PVC和PV工作原理:PV是群集中的资源。 PVC是对这些资源的请求。PV和PVC之间的相互作用遵循以下生命周期:
(1) pv的供应方式:静态或动态。
▪ 静态的:集群管理员创建了许多PV。它们包含可供群集用户使用的实际存储的详细信息。它们存在于Kubernetes API中,可供使用。
▪ 动态的:当管理员创建的静态PV都不匹配用户的PersistentVolumeClaim时,群集可能会尝试为PVC专门动态配置卷。此配置基于StorageClasses,PVC必须请求存储类,管理员必须创建并配置该类,以便进行动态配置。
(2)绑定:用户创建pvc并指定需要的资源和访问模式。在找到可用pv之前,pvc会保持未绑定状态
(3)使用:
a)需要找一个存储服务器,把它划分成多个存储空间;
b)k8s管理员可以把这些存储空间定义成多个pv;
c)在pod中使用pvc类型的存储卷之前需要先创建pvc,通过定义需要使用的pv的大小和对应的访问模式,找到合适的pv;
d)pvc被创建之后,就可以当成存储卷来使用了,我们在定义pod时就可以使用这个pvc的存储卷
e)pvc和pv它们是一一对应的关系,pv如果被pvc绑定了,就不能被其他pvc使用了;
f)我们在创建pvc的时候,应该确保和底下的pv能绑定,如果没有合适的pv,那么pvc就会处于pending状态。
(4) 回收策略:当我们创建pod时如果使用pvc做为存储卷,那么它会和pv绑定,当删除pod,pvc和pv绑定就会解除,解除之后和pvc绑定的pv卷里的数据需要怎么处理,目前,卷可以保留,回收(Retain)或删除(Delete)
▪ Retain:当删除pvc的时候,pv仍然存在,处于released状态,但是它不能被其他pvc绑定使用,里面的数据还是存在的,当我们下次再使用的时候,数据还是存在的,这个是默认的回收策略。
▪ Delete:删除pvc时即会从Kubernetes中移除PV,也会从相关的外部设施中删除存储资产
4、 创建pod,使用pvc作为持久化存储卷流程
• 创建nfs共享目录:
#在宿主机创建NFS需要的共享目录 [root@hd1.com ~]# mkdir /data/volume_test/v{1,2,3,4,5,6,7,8,9,10} -p #配置nfs共享宿主机上的/data/volume_test/v1..v10目录 [root@hd1.com ~]# cat /etc/exports /data/volumes 192.168.1.0/24(rw,no_root_squash) /data/volume_test/v1 192.168.1.0/24(rw,no_root_squash) /data/volume_test/v2 192.168.1.0/24(rw,no_root_squash) /data/volume_test/v3 192.168.1.0/24(rw,no_root_squash) /data/volume_test/v4 192.168.1.0/24(rw,no_root_squash) /data/volume_test/v5 192.168.1.0/24(rw,no_root_squash) /data/volume_test/v6 192.168.1.0/24(rw,no_root_squash) /data/volume_test/v7 192.168.1.0/24(rw,no_root_squash) /data/volume_test/v8 192.168.1.0/24(rw,no_root_squash) /data/volume_test/v9 192.168.1.0/24(rw,no_root_squash) /data/volume_test/v10 192.168.1.0/24(rw,no_root_squash) #重新加载配置,使配置成效 [root@hd1.com ~]# exportfs -arv
• 编写pv的资源清单文件
[root@hd1.com ~]# vim pv.yaml apiVersion: v1 kind: PersistentVolume metadata: name: v1 spec: capacity: storage: 1Gi #pv的存储空间容量 accessModes: ["ReadWriteOnce"] nfs: path: /data/volume_test/v1 #把nfs的存储空间创建成pv server: 192.168.1.11 #nfs服务器的地址 --- apiVersion: v1 kind: PersistentVolume metadata: name: v2 spec: capacity: storage: 2Gi accessModes: ["ReadWriteMany"] nfs: path: /data/volume_test/v2 server: 192.168.1.11 --- apiVersion: v1 kind: PersistentVolume metadata: name: v3 spec: capacity: storage: 3Gi accessModes: ["ReadOnlyMany"] nfs: path: /data/volume_test/v3 server: 192.168.1.11 --- apiVersion: v1 kind: PersistentVolume metadata: name: v4 spec: capacity: storage: 4Gi accessModes: ["ReadWriteOnce","ReadWriteMany"] nfs: path: /data/volume_test/v4 server: 192.168.1.11 --- apiVersion: v1 kind: PersistentVolume metadata: name: v5 spec: capacity: storage: 5Gi accessModes: ["ReadWriteOnce","ReadWriteMany"] nfs: path: /data/volume_test/v5 server: 192.168.1.11 --- apiVersion: v1 kind: PersistentVolume metadata: name: v6 spec: capacity: storage: 6Gi accessModes: ["ReadWriteOnce","ReadWriteMany"] nfs: path: /data/volume_test/v6 server: 192.168.1.11 --- apiVersion: v1 kind: PersistentVolume metadata: name: v7 spec: capacity: storage: 7Gi accessModes: ["ReadWriteOnce","ReadWriteMany"] nfs: path: /data/volume_test/v7 server: 192.168.1.11 --- apiVersion: v1 kind: PersistentVolume metadata: name: v8 spec: capacity: storage: 8Gi accessModes: ["ReadWriteOnce","ReadWriteMany"] nfs: path: /data/volume_test/v8 server: 192.168.1.11 --- apiVersion: v1 kind: PersistentVolume metadata: name: v9 spec: capacity: storage: 9Gi accessModes: ["ReadWriteOnce","ReadWriteMany"] nfs: path: /data/volume_test/v9 server: 192.168.1.11 --- apiVersion: v1 kind: PersistentVolume metadata: name: v10 spec: capacity: storage: 10Gi accessModes: ["ReadWriteOnce","ReadWriteMany"] nfs: path: /data/volume_test/v10 server: 192.168.1.11 #更新资源清单文件 [root@hd1.com ~]# kubectl apply -f pv.yaml #查看pv资源 [root@hd1.com ~]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS v1 1Gi RWO Retain Available v10 10Gi RWO,RWX Retain Available v2 2Gi RWX Retain Available v3 3Gi ROX Retain Available v4 4Gi RWO,RWX Retain Available v5 5Gi RWO,RWX Retain Available v6 6Gi RWO,RWX Retain Available v7 7Gi RWO,RWX Retain Available v8 8Gi RWO,RWX Retain Available v9 9Gi RWO,RWX Retain Available #STATUS是Available,表示pv可用
• 创建pvc,和符合条件的pv绑定
[root@hd1.com ~]# cat pvc.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-pvc spec: accessModes: ["ReadWriteMany"] resources: requests: storage: 2Gi #更新资源清单文件 [root@hd1.com ~]# kubectl apply -f pvc.yaml persistentvolumeclaim/my-pvc created #查看pv和pvc [root@hd1.com ~]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM v1 1Gi RWO Retain Available v10 10Gi RWO,RWX Retain Available v2 2Gi RWX Retain Bound default/my-pvc v3 3Gi ROX Retain Available v4 4Gi RWO,RWX Retain Available v5 5Gi RWO,RWX Retain Available v6 6Gi RWO,RWX Retain Available v7 7Gi RWO,RWX Retain Available v8 8Gi RWO,RWX Retain Available v9 9Gi RWO,RWX Retain Available #STATUS是Bound,表示这个pv已经被my-pvc绑定了 [root@hd1.com ~]# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES my-pvc Bound v2 2Gi RWX #pvc的名字-绑定到pv-绑定的是v2这个pv-pvc可使用的容量是2G
• 创建pod,挂载pvc
[root@hd1 volume]# cat pod_pvc.yaml apiVersion: v1 kind: Pod metadata: name: pod-pvc spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent volumeMounts: - name: nginx-html mountPath: /usr/share/nginx/html volumes: - name: nginx-html persistentVolumeClaim: claimName: my-pvc #和pvc名对应 #更新资源清单文件 [root@hd1~]# kubectl apply -f pod_pvc.yaml #查看pod状态 [root@hd1 ~]# kubectl get pods | grep pod-pvc pod-pvc 1/1 Running 0 27s #通过上面可以看到pod处于running状态,正常运行 #在挂载目录写入index.html数据 [root@hd1 ~]# echo "hello world" > /data/volume_test/v2/index.html #访问一下nginx容器的首页内容 [root@hd1 ~]# curl 10.244.156.146 hello world #删除pod-pvc这个pod,pvc依旧存在 [root@hd1 ~]# kubectl delete pods pod-pvc [root@hd1 ~]# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE my-pvc Bound v2 2Gi RWX 2d21h #删除pvc [root@hd1 ~]# kubectl delete pvc my-pvc #发现pv的状态发生了变化 [root@hd1 ~]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM v1 1Gi RWO Retain Available v10 10Gi RWO,RWX Retain Available v2 2Gi RWX Retain Released default/my-pvc v3 3Gi ROX Retain Available v4 4Gi RWO,RWX Retain Available #此时进入nfs共享目录,发现index.html仍然存在 [root@hd1 ~]# cat /data/volume_test/v2/index.html hello world
5、使用PVC和PV注意事项
• 我们每次创建pvc的时候,需要事先有划分好的pv,这样可能不方便,那么可以在创建pvc的时候直接动态创建一个pv这个存储类,pv事先是不存在的。
• pvc和pv绑定,如果使用默认的回收策略retain,那么删除pvc之后,pv会处于released状态,我们想要继续使用这个pv,需要手动删除pv(kubectl delete pv pv_name)。
• 删除pv,不会删除pv里的数据,当我们重新创建pvc时还会和这个最匹配的pv绑定,数据还是原来数据,不会丢失。
更多推荐
所有评论(0)