k8s中本地存储卷emptyDir、hostPath卷

前言

环境: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存储卷

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

hostPaht储存卷

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,下篇我们将介绍持久化存储。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值