pod的生命周期可能很短,会被频繁地创建和销毁。那么pod在销毁时,保存在容器中的数据也会被清除。这种结果对用户来说,在某些情况下是不乐意看到的。为了持久化保存容器的数据,kubernetes引入了Volume的概念。
目录
kubernetes的Volume支持多种类型,比较常见的有下面几个:
1、emptyDir & hostpath
2、共享文件存储NFS
3、pv/pvc
4、存储类StorageClass
5、配置存储:ConfigMap、Secret
实验环境:
kubernetes: v1.23.5
emptyDir
当创建pod时指定的volume为emptyDir时,会在hosts上自动创建一个空的目录用储存容器的临时文件,当pod销毁时该目录也会清空。
如果容器不需要共享文件,那么创不创建emptyDir类型的volume都是一样的,创建或者不创建都会在主机上生成一个临时的目录,都会随着pod销毁而销毁。
应用场景:同一个pod中多容器之间的文件共享。
示例
接下来,通过一个容器之间文件共享的案例来使用一下emptyDir。在一个pod中准备两个容器nginx和busybox,然后声明一个volume分别挂在到两个容器的目录中,然后nginx容器负责向volume中写日志,busybox中通过命令将日志内容读到控制台。
# 演示通过emptydir类型的volume来实现容器见的数据共享。
# 在一个pod中部署两个容器nginx和busybox,
# 声明(创建)一个emptydir类型的volume分别挂在到两个容器的目录中,
# 然后nginx容器负责向volume中写日志,
# busybox中通过命令将日志内容读到控制台。
apiVersion: v1
kind: Pod
metadata:
name: volume-emptydir
namespace: dev
spec:
containers:
- name: nginx
image: nginx:1.17.1
ports:
- containerPort: 80
volumeMounts: #将logs-volume挂载到nginx容器的/var/log/nginx目录下
- name: logs-volume
mountPath: /var/log/nginx
- name: busybox
image: busybox:1.30
command: ["/bin/sh","-c","tail -f /logs/access.log"] # 初始命令,动态读取指定文件中内容
volumeMounts: #将logs-volume挂载到busybox容器的/log目录下
- name: logs-volume
mountPath: /logs
volumes: #创建volume,命名为logs-volume,类型为emptyDir
- name: logs-volume
emptyDir: {}
#编写yaml文件
[root@master volume]# vim emptyDir-volume.yaml
#创建pod
[root@master volume]# kubectl create -f emptyDir-volume.yaml
pod/volume-emptydir created
#查看pod信息,ip
[root@master volume]# kubectl get pod -n dev -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
volume-emptydir 2/2 Running 0 116s 10.122.166.155 node1 <none> <none>
#同时打开两个ssh窗口,一个用curl访问nginx
[root@master volume]# curl 10.122.166.155
......
<title>Welcome to nginx!</title>
......
#一个查看busybox的日志
[root@master volume]# kubectl logs -f volume-emptydir -n dev -c busybox
10.122.219.64 - - [18/May/2023:08:13:28 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
10.122.219.64 - - [18/May/2023:08:14:53 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
#可以发现每访问一个nginx,busybox都会输入一次nginx的访问日志,即实现了容器间的数据共享。
hostPath
emptyDir中数据不会被持久化,它会随着Pod的结束而销毁,如果想简单的将数据持久化到主机中,可以选择HostPath。顾名思义,hostpath就是将数据存储在host的某个目录下,这样即使pod销毁数据仍在host的目录中。
示例
创建一个nginx容器,将主机的/root/logs挂载到容器的/var/log/nginx,销毁nginx pod查看/root/logs目录下的文件是否被销毁。
# 创建一个nginx容器,将主机的/root/logs挂载到容器的/var/log/nginx
# 销毁nginx pod查看/root/logs目录下的文件是否被销毁
apiVersion: v1
kind: Pod
metadata:
name: volume-hostpath
namespace: dev
spec:
containers:
- name: nginx
image: nginx:1.17.1
ports:
- containerPort: 80
volumeMounts: #将logs-volume挂载到nginx容器的/var/log/nginx目录下
- name: logs-volume
mountPath: /var/log/nginx
volumes: #声明(创建)一个volume,命名为logs-volume,类型为hostPath
- name: logs-volume
hostPath:
path: /root/logs #使用host主机的/root/logs目录
type: DirectoryOrCreate # 目录存在就使用,不存在就先创建后使用
#关于type的值的一点说明:
DirectoryOrCreate 目录存在就使用,不存在就先创建后使用
Directory 目录必须存在
FileOrCreate 文件存在就使用,不存在就先创建后使用
File 文件必须存在
Socket unix 套接字必须存在
CharDevice 字符设备必须存在
BlockDevice 块设备必须存在
#创建yaml文件
[root@master volume]# vim hostPath-volume.yaml
#创建pod
[root@master volume]# kubectl create -f hostPath-volume.yaml
pod/volume-hostpath created
#pod被调度到node1上,IP为10.122.166.154
[root@master volume]# kubectl get pod -n dev -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
volume-hostpath 1/1 Running 0 27s 10.122.166.154 node1 <none> <none>
#切换到node1上查看挂载的目录
[root@master volume]# ssh 172.31.246.54
[root@node1 ~]# cd /root/logs/
#此时可以发现多了/root/logs目录和两个文件
[root@node1 logs]# ls
access.log error.log
#实时文件内容为空
[root@node1 logs]# cat access.log
[root@node1 logs]#
#用curl访问nginx
[root@node1 logs]# curl 10.122.166.154
......
<title>Welcome to nginx!</title>
......
#可以发现access.log文件中有访问记录了
[root@node1 logs]# cat access.log
172.31.246.54 - - [18/May/2023:08:47:47 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
#回到master节点删除pod
[root@node1 logs]# exit
[root@master volume]# kubectl delete -f hostPath-volume.yaml
pod "volume-hostpath" deleted
[root@master volume]# kubectl get pod -n dev -o wide
No resources found in dev namespace.
#再到node1节点可以发现/root/logs目录和目录中的文件都存在,说明使用hostPath类型的volume存储pod中容器的数据可以实现数据持久化
[root@master volume]# ssh 172.31.246.54
[root@node1 ~]# cd /root/logs/
[root@node1 logs]# ls
access.log error.log
[root@node1 logs]# cat access.log
172.31.246.54 - - [18/May/2023:08:47:47 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
[root@node1 logs]#
hostPath可以解决数据持久化的问题,但是一旦host节点故障了,或者pod转移到了别的host,又会出现新的问题。此时需要准备单独的网络存储系统,比较常用的用NFS、cephFS。