赞
踩
环境:centos7.9 docker-ce-20.10.9 kubernetes-version v1.22.6
存储卷,简称卷,卷是pod的一部分,卷在pod创建时创建,删除pod时卷也会被销毁,卷可以为pod中的所有容器使用,前提是所有容器都将卷挂载到容器里,卷可以挂载到容器的文件系统中的任意位置。一个pod可以定义多个不同类型的卷,一个容器也可以使用不同类型的多个卷。pod需要设置卷来源(spec.volume)和挂载点(spec.containers.volumeMounts)两个信息后才可以使用相应的Volume。
emptyDir:用于存储临时数据的简单空目录;
hostPath:用于将目录从工作节点的文件系统挂载到pod中;
nfs:挂载到pod中的nfs共享卷;
congfigMap、secret:特殊的卷,不是用于存储数据,而是用于将配置文件公开给pod中的应用程序;
persistentVolumeClaim:一种持久化存储卷,使用预置或动态配置。
本篇我们只介绍emptyDir卷和hostPath卷,这两种本地存储卷。
emptyDir卷是最简单的卷,主要用于存储临时数据,当pod生命周期结束,emptyDir卷也就销毁。
emptyDir卷应用场景一般是pod中多个容器共享数据,即在pod中定义一个emptyDir卷,然后容器A挂载到某个目录,容器B也挂载到某个目录,这样,容器A和容器B就能读写文件,就能共享数据。如下演示:
[root@master ~]# cat deplyment_nginx_emptyDir.yaml #创建一个有两个容器的pod apiVersion: apps/v1 kind: Deployment metadata: name: deployment-nginx-emptydir namespace: default spec: replicas: 1 selector: matchLabels: app: nginx-emptyDir template: metadata: labels: app: nginx-emptyDir spec: containers: - image: nginx:1.7.9 #容器A的定义 name: nginx-container ports: - name: http containerPort: 80 volumeMounts: - name: emptydir-volume #容器A挂载了一个名为emptydir-volume的卷,挂载到/test目录 mountPath: /test - image: tomcat #容器B的定义,容器B是一个Tomcat容器 name: tomcat ports: - name: http containerPort: 8080 volumeMounts: - name: emptydir-volume #容器B也挂载了一个名为emptydir-volume的卷,挂载到/test1目录 mountPath: /test1 volumes: #这是定义存储卷,存储卷的类型为emptyDir类型 - name: emptydir-volume emptyDir: {} [root@master ~]# kubectl get po #查看pod,pod已经正常启动 NAME READY STATUS RESTARTS AGE deployment-nginx-emptydir-5bcc7d467-rx5b6 2/2 Running 0 2m55s [root@master ~]# kubectl exec -it deployment-nginx-emptydir-7bb448744d-kkt5d -c nginx-container -- bash #进入nginx的容器 root@deployment-nginx-emptydir-5bcc7d467-rx5b6:/# ls /test/ #查看nginx容器挂载的目录,是空的,没有任何文件 root@deployment-nginx-emptydir-5bcc7d467-rx5b6:/# exit [root@master ~]# kubectl exec -it deployment-nginx-emptydir-7bb448744d-kkt5d -c tomcat -- bash #进入Tomcat容器 root@deployment-nginx-emptydir-7bb448744d-kkt5d:/# ls /test1/ #查看tomcat容器挂载的目录,是空的,没有任何文件 #下面我们在tomcat的挂载目录/test1/中创建一个文件,然后去nginx容器中查看是否能正常共享: root@deployment-nginx-emptydir-7bb448744d-kkt5d:/test1# touch file{1..10} #随便创建一些文件 root@deployment-nginx-emptydir-7bb448744d-kkt5d:/test1# ls file1 file10 file2 file3 file4 file5 file6 file7 file8 file9 root@deployment-nginx-emptydir-7bb448744d-kkt5d:/test1# echo "hello world" >file1 #模拟写入数据 root@deployment-nginx-emptydir-7bb448744d-kkt5d:/test1# echo "hello world" >file2 #模拟写入数据 root@deployment-nginx-emptydir-7bb448744d-kkt5d:/test1# echo "hello world" >file3 #模拟写入数据 root@deployment-nginx-emptydir-7bb448744d-kkt5d:/test1# cat file1 #查看数据 hello world root@deployment-nginx-emptydir-7bb448744d-kkt5d:/test1# exit #下面进入nginx容器: [root@master ~]# kubectl exec -it deployment-nginx-emptydir-7bb448744d-kkt5d -c nginx-container -- bash root@deployment-nginx-emptydir-7bb448744d-kkt5d:/# cd /test/ root@deployment-nginx-emptydir-7bb448744d-kkt5d:/test# ls #正常查看文件 file1 file10 file2 file3 file4 file5 file6 file7 file8 file9 root@deployment-nginx-emptydir-7bb448744d-kkt5d:/test# cat file1 #正常读写文件内容 hello world root@deployment-nginx-emptydir-7bb448744d-kkt5d:/test#
以上就成功演示了在一个pod多个容器中使用emptyDir共享数据。emptyDir的数据随着容器的消亡也会销毁。
默认情况下,emptyDir卷实在node节点上的磁盘创建的,其实还可以让emptyDir卷存在于内存中而不是磁盘,通过设置medium参数即可。
volumes: #这是定义存储卷,存储卷的类型为emptyDir类型
- name: emptydir-volume
emptyDir:
medium: Memory
hostPath:用于将目录从工作节点的文件系统挂载到pod中。
我们知道,虽然hostPath卷实现pod中数据存储到节点的文件系统中,但是pod的调度不是固定的,也就是当pod消失后deployment重新创建一个pod,而这pod如果不是被调度到之前pod的节点,那么该pod就不能访问之前的数据。
下面我们在node1节点上创建2目录,/usr/share/nginx/html/、/var/log/nginx/目录,/usr/share/nginx/html/目录存放nginx的html文件,/var/log/nginx/目录存放nginx的log日志,这样我们在定义pod时,就可以把目录挂载到pod中的nginx容器中去,这样就可以实现模拟:更新node1中目录的/usr/share/nginx/html/下的文件,就能实现pod的nginx容器升级,已经可以存储nginx的日志,如下所示:
[root@node1 ~]# mkdir -p /var/log/nginx/ #在node1节点上创建日志目录 [root@node1 ~]# mkdir -p /usr/share/nginx/html #在node1节点上创建存放网页html文件的目录 [root@node1 ~]# touch index.html #创建一个我们的网页文件,内容如下: <html> <head><title>Nginx</title></head> <body> <center><h1>Hello Wolrd,I am liming</h1></center> #定义了一些基本的内容 <hr><center>nginx</center> </body> </html> [root@node1 html]# [root@master ~]# vim deplyment_nginx_hostPath.yaml #现在我们在master节点上创建一个Deployment资源 apiVersion: apps/v1 kind: Deployment metadata: name: deployment-nginx-hostpath namespace: default spec: replicas: 1 selector: matchLabels: app: nginx-hostPath template: metadata: labels: app: nginx-hostPath spec: containers: - image: nginx:1.7.9 name: nginx-container ports: - name: http containerPort: 80 volumeMounts: #定义挂载点 - name: html-volume #第一个卷的名称 mountPath: /usr/share/nginx/html #挂载路径,表示将html-volume卷挂载到该路径下 - name: log-volume #第二个卷的名称 mountPath: /var/log/nginx #挂载路径,表示将log-volume卷挂载到该路径下 volumes: #定义两个hostPath类型的卷 - name: html-volume #存储卷名称为html-volume hostPath: #存储卷的类型为hostPath path: /usr/share/nginx/html #主机路径,即实际的node节点上的目录(目录必须要先存在) type: Directory #表示存储卷为目录 - name: log-volume #存储卷名称为log-volume hostPath: #存储卷的类型为hostPath path: /var/log/nginx #主机路径,即实际的node节点上的目录(目录必须要先存在) type: Directory #表示给定的path路径目录必须存在,type的类型还可以是DirectoryOrCreate(不存在目录则创建)、FileOrCreate(不存在文件则创建)、File(文件必须存在)、CharDevice(字符设备必须存在)、BlockDevice(块设备必须存在) [root@master ~]# #以上,我们就定义个两个存储卷,挂载到了容器的不同目录中去。下面,我们来访问访问一下nginx(要能正常访问nginx,必须先创建service暴露服务这里创建service这步省略): [root@master ~]# curl 10.104.5.99 #访问nginx,成功,(这个ip是service暴露的集群内部ip) <html> <head><title>Nginx</title></head> <body> <center><h1>Hello Wolrd,I am liming</h1></center> <hr><center>nginx</center> </body> </html> [root@master ~]# [root@node1 ~]# tail -222f /var/log/nginx/access.log #到node1节点上查看挂载点的日志,发现日志也正常存储了 10.244.0.0 - - [19/Feb/2022:03:13:42 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-" 10.244.0.0 - - [19/Feb/2022:03:23:19 +0000] "GET / HTTP/1.1" 200 141 "-" "curl/7.29.0" "-" 10.244.0.0 - - [19/Feb/2022:03:23:54 +0000] "GET / HTTP/1.1" 200 141 "-" "curl/7.29.0" "-"
以上就演示了如何创建hostPath卷,但是实际生产中,并不会使用hostPath类型的存储卷来持久化存储数据,因为还是那句话,当pod消失后deployment重新创建一个pod,而这pod如果不是被调度到之前pod的节点,那么该pod就不能访问之前的数据。
1、存储卷是pod的一部分,卷在pod创建时创建,删除pod时卷也会被销毁,卷可以为pod中的所有容器使用,前提是所有容器都将卷挂载到容器里,卷可以挂载到容器的文件系统中的任意位置; 2、一个容器可以使用不同类型的多个卷; 3、emptyDir存储卷:用于存储临时数据的简单空目录,适用于一个pod中多个容器共享数据的场景; spec: containers: - image: nginx:1.7.9 #容器A的定义 name: nginx-container ports: - name: http containerPort: 80 volumeMounts: - name: emptydir-volume #容器A挂载了一个名为emptydir-volume的卷,挂载到/test目录 mountPath: /test - image: tomcat #容器B的定义,容器B是一个Tomcat容器 name: tomcat ports: - name: http containerPort: 8080 volumeMounts: - name: emptydir-volume #容器B也挂载了一个名为emptydir-volume的卷,挂载到/test1目录 mountPath: /test1 volumes: #这是定义存储卷,存储卷的类型为emptyDir类型 - name: emptydir-volume emptyDir: {} emptyDir卷适用于一个pod多个容器中使用emptyDir卷进行数据共享,emptyDir的数据随着容器的消亡也会销毁,还可以通过设置medium参数让emptyDir卷存在于内存中而不是磁盘,这样的数据读取会更快。 4、hostPath存储卷:用于将目录从工作节点的文件系统挂载到pod中; spec: containers: - image: nginx:1.7.9 name: nginx-container ports: - name: http containerPort: 80 volumeMounts: #定义挂载点 - name: html-volume #第一个卷的名称 mountPath: /usr/share/nginx/html #挂载路径,表示将html-volume卷挂载到该路径下 - name: log-volume #第二个卷的名称 mountPath: /var/log/nginx #挂载路径,表示将log-volume卷挂载到该路径下 volumes: #定义两个hostPath类型的卷 - name: html-volume #存储卷名称为html-volume hostPath: #存储卷的类型为hostPath path: /usr/share/nginx/html #主机路径,即实际的node节点上的目录(目录必须要先存在) type: Directory #表示存储卷为目录 - name: log-volume #存储卷名称为log-volume hostPath: #存储卷的类型为hostPath path: /var/log/nginx #主机路径,即实际的node节点上的目录(目录必须要先存在) type: Directory #表示存储卷为目录 [root@master ~]# 使用hostPath存储卷,当pod消失后deployment重新创建一个pod,而这pod如果不是被调度到之前pod的节点,那么该pod就不能访问之前的数据,所以,不应该使用hostPath卷来做持久化数据。
以上我们介绍了emptyDir和hostPath卷的使用情况,由于两者都是属于本地的存储卷,而且都有自己的缺点,所以不应该使用它两作为持久化存储数据,我们需要某种远程的网络存储,如nfs,下篇我们将介绍持久化存储。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。