Contents
本地存储卷¶
在容器化环境中,如何可靠地共享数据,并保证这些数据在容器重启间隙始终是可用的,一直都是一个挑战。
容器运行时通常会提供一些机制来将存储附加到容器上,这类容器的存留时间超过其他容器的生命周期,但实现起来通常缺乏灵活性。
为了解决这些问题,Kubernetes定义了自己的存储卷(volume)抽象,它们所提供的数据存储功能非常强大。
不仅可以通过配置将数据注入Pod中,在Pod内部,容器之间还可以共享数据。
而对于不同机器的Pod,可以通过定义存储卷来实现数据共享。
Kubernetes 中定义的存储卷主要分为 4种类型。
本地存储卷:主要用于Pod中容器之间的数据共享,或Pod与Node中的数据存储和共享。
网络存储卷:主要用于多个Pod之间或多个Node之间的数据存储和共享。
持久存储卷:基于网络存储卷,用户无须关心存储卷所使用的存储系统,只需要自定义具体需要消费多少资源即可,可将Pod与具体的存储系统解耦。
配置存储卷:主要用于向各个Pod注入配置信息
本地存储卷有emptyDir和hostPath这两种,它们都会直接使用本机的文件系统,用于Pod中容器之间的数据共享,或Pod与Node中的数据存储和共享。
1. emptyDir¶
顾名思义,emptyDir是指一个纯净的空目录,这个目录映射到主机的一个临时目录下,Pod中的容器都可以读写这个目录,其生命周期 和Pod完全一致。
如果Pod销毁,那么存储卷也会同时销毁。emptyDir主要用于存放和共享Pod的不同容器之间在运行过程中产生的文件。
examplepodforemptydir.yml
apiVersion: v1
kind: Pod
metadata:
name: examplepodforemptydir
spec:
containers:
- name: containerforwrite
image: busybox
imagePullPolicy: IfNotPresent
command: ['sh', '-c']
args: ['echo "test data!" > /write_dir/data; sleep 3600']
volumeMounts:
- name: filedata
mountPath: /write_dir
- name: containerforread
image: busybox
imagePullPolicy: IfNotPresent
command: ['sh', '-c']
args: ['cat /read_dir/data; sleep 3600']
volumeMounts:
- name: filedata
mountPath: /read_dir
volumes:
- name: filedata
emptyDir: {}
本例中创建了两个容器。
一个是containerforwrite,用于向数据卷写入数据,向/write_ dir/data文件写入“test data!”文本。
容器内的数据卷地址为/write_dir,它引用的存储卷为filedata。
另一个容器是containerforread,从/read_dir/data文件中读取文本,并将其输出到控制台(后续可以通过日志查询方式读取输出到 控制台的文本)。
容器内的数据卷地址为/read_dir,它引用的存储卷为filedata。
本例中创建的存储卷名称为filedata,这个名称会被容器设置中的数据卷引用。存储卷的类型是emptyDir,这表示是一个纯净的空目 录,其生命周期和所属的Pod完全一致。
例子中的两个容器虽然数据卷地址不同(一个是/write_dir,一个是/read_dir),但它们都映射到同一个空目录,所以本质上仍在同一个文件夹内操作。
执行以下命令,创建Pod
$ kubectl apply -f examplepodforemptydir.yml
接着通过kubectl get pod命令,查看Pod的运行情况,如图所示,READY为2/2,这表示两个容器都已成功运行。
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
examplepodforemptydir 2/2 Running 0 35s
此时通过logs命令,可以查看Pod中containerforread容器的日志。
$ kubectl logs examplepodforemptydir containerforread
test data!
可以看到,containerforread 容器已经读取了在 containerforwrite容器中写入的文本,并将其输出到控制台。
默认情况下,emptyDir在主机硬盘上创建一个临时目录,还可以将emptyDir.medium设置为Memory来生成一个基于内存的临时目录,其速度会比硬盘快,但机器重启之后数据就会丢失。定义临时目录的方式如下所示。
volumes:
- name: data
emptyDir:
medium: Memory
2. hostPath¶
hostPath主要用于把主机上指定的目录映射到Pod中的容器上。如果Pod需要在主机上存储和共享文件,或使用主机上的文件,就可以使 用这种方式。
存放在主机上的文件不会被销毁,会永久保存。Pod销毁后,若又在这台机器上重建,则可以读取原来的内容,但如果机器出现故障或者Pod被调度到其他机器上,就无法读取原来的内容了。
这种方式特别适合DaemonSet控制器,运行在DaemonSet控制器下的Pod可直接操作和使用主机上的文件,如日志类或监控类应用可以读取主机指定目录下的日志或写入信息等。
examplepodforhostpath.yml
apiVersion: v1
kind: Pod
metadata:
name: examplepodforhostpath
spec:
containers:
- name: containerforhostpath
image: busybox
imagePullPolicy: IfNotPresent
command: ['sh', '-c']
args: ['echo "test data!" > /write_dir/data; sleep 3600']
volumeMounts:
- name: filedata
mountPath: /write_dir
volumes:
- name: filedata
hostPath:
path: /home/k8sadmin/testhostpath
本例中创建的名为containerforhostpath的容器向数据卷写入数据,它会向/write_dir/data文件写入“test data!”文本。
容器内的数据卷地址为/write_dir,它引用的存储卷为filedata。
执行以下命令,创建Pod。
$ kubectl apply -f examplepodforhostpath.yml
接下来,通过$ kubectl get pods -o wide命令,查看Pod的运行情况
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
examplepodforhostpath 1/1 Running 0 102s 10.0.32.124 gitee-k8s-w05 <none> <none>
注意,其NODE属性为 gitee-k8s-w05,表示这个Pod被调度到gitee-k8s-w05这台机器上。
接下来,登录gitee-k8s-w05这台机器,并在机器上执行以下命令,输出主机上指定目录中的内容。
[root@gitee-k8s-w05 ~]# cat /home/k8sadmin/testhostpath/data
test data!
接下来,编辑这个文件,执行以下命令。
$ echo "hujianli2022" >> /home/k8sadmin/testhostpath/data
$ cat /home/k8sadmin/testhostpath/data
test data!
hujianli2022
这相当于进入examplepodforhostpath这个Pod下的containerforhostpath容器中,以便在容器内部执行命令行。
进入容器后执行cat /write_dir/data命令,可以看到容器中读取的信息也发生了变化
$ kubectl exec -it pod/examplepodforhostpath -- /bin/sh
/ # cat /write_dir/data
test data!
hujianli2022