一、介绍
容器的生命周期可能很短,会被频繁地创建和销毁。那么容器在销毁时,保存在容器中的数据也会被清除。这种结果对用户来说,在某些情况下是不乐意看到的。为了持久化保存容器的数据,kubernetes引入了
Volume
的概念。
Volume
是
Pod
中能够被多个容器访问的共享目录,它被定义在
Pod
上,然后被一个
Pod
里的多个容器挂载到具体的文件目录下,kubernetes
通过
Volume
实现同一个
Pod
中不同容器之间的
数据共享以及数据的持久化存储
。Volume
的生命容器不与
Pod
中单个容器的生命周期相关,当容器终止或者重启时,Volume中的数据也不会丢失。
- kubernetes的Volume支持多种类型,比较常见的有下面几个:
简单存储:EmptyDir 、 HostPath 、 NFS高级存储:PV 、 PVC配置存储:ConfigMap 、 Secret
二、基本存储
1、EmptyDir
EmptyDir
是最基础的
Volume
类型,一个
EmptyDir
就是
Host
上的一个空目录。
EmptyDir
是在
Pod
被分配到
Node
时创建的,它的初始内容为空,并且无须指定宿主机上对应的目录文件,因为kubernetes
会自动分配一个目录,
当Pod销毁时, EmptyDir中的数据也会被永久删除。
EmptyDir
用途如下:
- 临时空间,例如用于某些应用程序运行时所需的临时目录,且无须永久保留
- 一个容器需要从另一个容器中获取数据的目录(多容器共享目录)
接下来,通过一个容器之间文件共享的案例来使用一下
EmptyDir
。
在一个
Pod
中准备两个容器
nginx
和
busybox
,然后声明一个
Volume
分别挂在到两个容器的目录中,然后nginx
容器负责向
Volume
中写日志,
busybox
中通过命令将日志内容读到控制台。

#写一个yaml文件
[root@k8s-master ~]#vim volume-emptydir.yaml
apiVersion: v1
kind: Pod
metadata:
name: volume-emptydir
namespace: dev
spec:
volumes:
- name: logs-volume
emptyDir: {}
containers:
- name: nginx
image: nginx:1.17.1
ports:
- containerPort: 80
volumeMounts:
- name: logs-volume
mountPath: /var/log/nginx
- name: busybox
image: busybox:1.30
command: ["/bin/sh", "-c", "tail -f /logs/access.log"]
volumeMounts:
- name: logs-volume
mountPath: /logs
#创建pod
[root@k8s-master ~]# kubectl apply -f volume-emptydir.yaml
pod/volume-emptydir created
#查看
[root@k8s-master ~]# kubectl get po volume-emptydir -n dev -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
volume-emptydir 2/2 Running 0 104s 100.97.125.27 k8s-node01 <none> <none>
#进入到nginx容器中修改nginx默认文件
[root@k8s-node01 ~]# kubectl exec -it volume-emptydir -c nginx -n dev -- /bin/bash
root@volume-emptydir:/# echo "this is empty dir" >/usr/share/nginx/html/index.html
#访问
[root@k8s-master ~]# curl 100.97.125.27
this is empty dir
#查看日志
[root@k8s-node01 ~]# kubectl logs -f volume-emptydir -n dev -c busybox
100.116.59.64 - - [11/Apr/2025:05:00:07 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0"
100.116.59.64 - - [11/Apr/2025:05:00:09 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0"
100.116.59.64 - - [11/Apr/2025:05:00:49 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0"
100.116.59.64 - - [11/Apr/2025:05:00:51 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0"
192.168.8.188 - - [11/Apr/2025:05:03:24 +0000] "GET / HTTP/1.1" 200 18 "-" "curl/7.29.0"
192.168.8.188 - - [11/Apr/2025:05:03:26 +0000] "GET / HTTP/1.1" 200 18 "-" "curl/7.29.0"
100.116.59.64 - - [11/Apr/2025:05:04:46 +0000] "GET / HTTP/1.1" 200 18 "-" "curl/7.29.0"
100.116.59.64 - - [11/Apr/2025:05:04:48 +0000] "GET / HTTP/1.1" 200 18 "-" "curl/7.29.0"
100.116.59.64 - - [11/Apr/2025:05:04:49 +0000] "GET / HTTP/1.1" 200 18 "-" "curl/7.29.0"
2、HostPath
EmptyDir
中数据不会被持久化,它会随着
Pod
的结束而销毁,如果想简单的将数据持久
化到主机中,可以选择
HostPath
。
HostPath
就是将
Node
主机中一个实际目录挂在到
Pod
中,以供容器使用,这样的设计就可以保证
Pod 销毁了,但是数据依据可以存在于Node
主机上。


#写一个yaml文件
[root@k8s-master ~]# cat volume-hostpath.yaml
apiVersion: v1
kind: Pod
metadata:
name: volume-hostpath
namespace: dev
spec:
volumes:
- name: logs-volume
hostPath:
path: /root/logs
type: DirectoryOrCreate
containers:
- name: nginx
image: nginx:1.17.1
ports:
- containerPort: 80
volumeMounts:
- name: logs-volume
mountPath: /var/log/nginx
- name: busybox
image: busybox:1.30
command: ["/bin/sh", "-c", "tail -f /logs/access.log"]
volumeMounts:
- name: logs-volume
mountPath: /logs
#创建并查看pod
[root@k8s-master ~]# kubectl apply -f volume-hostpath.yaml
pod/volume-hostpath created
[root@k8s-master ~]# kubectl get pod volume-hostpath -n dev -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
volume-hostpath 2/2 Running 0 96s 100.97.125.37 k8s-node01 <none> <none>
[root@k8s-master ~]# curl 100.97.125.37
在pod 所在节点上面查看 /root/logs 目录下的存储文件,同时在该目录下创建一个文件并写入内容,进入到容器中也能看到
删除pod:
数据依然存在Node节点上:
3、NFS
HostPath
可以解决数据持久化的问题,但是一旦
Node
节点故障了,
Pod
如果转移到了别的节点,又会出现问题了,此时需要准备单独的网络存储系统,比较常用的用NFS
、
CIFS
。
NFS
是一个网络文件存储系统,可以搭建一台
NFS
服务器,然后
将Pod中的存储直接连接到NFS系统上
,这样的话,无论Pod
在节点上怎么转移,只要
Node
跟NFS的对接没问题,数据就可以成功访问。


(1)准备一个NFS服务器:192.168.8.149
[root@server ~]# yum install nfs-utils -y
[root@server ~]# mkdir /nfs
[root@server ~]# systemctl start rpcbind nfs-server
[root@server ~]# showmount -e localhost
Export list for localhost:
/nfs *
(2)每个节点安装NFS,这样的目的是为了node节点可以驱动nfs设备
[root@k8s-node01 ~]# yum install nfs-utils
[root@k8s-node01 ~]# showmount -e 192.168.8.149
Export list for 192.168.8.149:
/nfs *
(3)编写yaml:
yaml文件:
[root@k8s-master ~]# cat volume-nfs.yaml
apiVersion: v1
kind: Pod
metadata:
name: volume-nfs
namespace: dev
spec:
volumes:
- name: logs-volume
nfs:
server: 192.168.8.149
path: /nfs
containers:
- name: nginx
image: nginx:1.18.0
ports:
- containerPort: 80
volumeMounts:
- name: logs-volume
mountPath: /var/log/nginx
- name: busybox
image: busybox:1.31
command: ["/bin/sh", "-c", "tail -f /logs/access.log"]
volumeMounts:
- name: logs-volume
mountPath: /logs
#然后创建并查看
[root@k8s-master ~]# kubectl apply -f volume-nfs.yaml
pod/volume-nfs created
[root@k8s-master ~]# kubectl get -f volume-nfs.yaml
NAME READY STATUS RESTARTS AGE
volume-nfs 2/2 Running 0 8s
[root@k8s-master ~]# kubectl get po volume-nfs -n dev -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
volume-nfs 2/2 Running 0 35s 100.97.125.38 k8s-node01 <none> <none>
(4)测试:


