本文通过几个比较常用的类型的Volume配置演示一下Volume的使用
- 示例1---通过emptyDir共享数据
- 示例2---使用HostPath挂载宿主机文件
- 示例3---挂载NFS至容器
一、通过emptyDir共享数据¶
EmptyDir是一个特殊的Volume类型,与上述Volume不同的是,如果删除Pod,emptyDir卷中的数据也将被删除,所以一般emptyDir用于Pod中的不同Container共享数据,比如一个Pod存在两个容器A和B,容器A需要使用容器B产生的数据,此时可以采用emptyDir共享数据,类似的使用如Filebeat收集容器内程序产生的日志。
默认情况下,emptyDir 卷支持节点上的任何介质,可能是 SSD、磁盘或网络存储,具体取 决于自身的环境。可以将 emptyDir.medium 字段设置为 Memory,让 Kubernetes 使用 tmpfs(内存支持的文件系统),虽然 tmpfs 非常快,但是 tmpfs 在节点重启时,数据同样会被清除,并且 设置的大小会被计入到 Container 的内存限制当中。
1.定义一个yaml文件
[root@k8s-master01 practice]# vim emptydir.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2
imagePullPolicy: IfNotPresent
name: nginx
volumeMounts:
- mountPath: /opt
name: share-volume
- image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2
imagePullPolicy: IfNotPresent
name: nginx2
command:
- sh
- -c
- sleep 3600
volumeMounts:
- mountPath: /mnt
name: share-volume
volumes:
- name: share-volume
emptyDir: {}
#medium: Memory
2.重新部署
[root@k8s-master01 practice]# kubectl apply -f emptydir.yaml
3.查看pod状态
[root@k8s-master01 practice]# kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-d8f544fdd-qgllm 2/2 Running 0 12m
4.验证-进入nginx的容器创建文件后,在nginx2容器查看 (1)进入nginx容器后,进入/opt目录下创建123文件
[root@k8s-master01 practice]# kubectl exec -it nginx-d8f544fdd-qgllm -c nginx -- sh
root@nginx-d8f544fdd-qgllm:/# cd /opt
root@nginx-d8f544fdd-qgllm:/opt# touch 123
(2)进入nginx2容器后,进入/mnt目录下查看123文件是否创建成功
[root@k8s-master01 practice]# kubectl exec -it nginx-d8f544fdd-qgllm -c nginx2 -- bash
root@nginx-d8f544fdd-qgllm:/# cd /mnt/
root@nginx-d8f544fdd-qgllm:/mnt# ls
123
二、使用HostPath挂载宿主机文件¶
hostPath 卷可将节点上的文件或目录挂载到 Pod 上,用于 Pod 自定义日志输出或访问 Docker 内部的容器等。
hostPath常用类型有如下:
| 取值 | 行为 |
|---|---|
| 默认选项,意味着挂载 hostPath 卷之前不会执行任何检查 | |
| DirectoryOrCreate | 如果给定的 path 不存在任何东西,那么将根据需要创建一个权限为 0755 的空目录,和 Kubelet 具有相同的组和权限 |
| Directory | 目录必须存在于给定的路径下 |
| FileOrCreate | 如果给定的路径不存储任何内容,则会根据需要创建一个空文件,权限设 置为 0644,和 Kubelet 具有相同的组和所有权。 |
| File | 文件必须存在于给定路径中 |
| Socket | 在给定路径上必须存在的 UNIX 套接字 |
| CharDevice | 在给定路径上必须存在的字符设备 |
| BlockDevice | 在给定路径上必须存在的块设备 |
hostPath注意事项有如下:
- HostPath 卷可能会暴露特权系统凭据(例如 Kubelet)或特权 API(例如容器运行时套接字),可用于容器逃逸或攻击集群的其他部分。
- 具有相同配置(例如基于同一 PodTemplate 创建)的多个 Pod 会由于节点上文件的不同而在不同节点上有不同的行为。
- 下层主机上创建的文件或目录只能由 root 用户写入。 你需要在特权容器中以 root 身份运行进程,或者修改主机上的文件权限以便容器能够写入
hostPath卷。
下面进行hostPath示例说明,将主机的/etc/timezone文件挂载到 Pod 的/etc/timezone:
1.定义一个yaml文件
[root@k8s-master01 practice]# vim emptydir-hostpath.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2
imagePullPolicy: IfNotPresent
name: nginx
volumeMounts:
- mountPath: /opt
name: share-volume
- mountPath: /etc/timezone
name: timezone
- image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2
imagePullPolicy: IfNotPresent
name: nginx2
command:
- sh
- -c
- sleep 3600
volumeMounts:
- mountPath: /mnt
name: share-volume
volumes:
- name: share-volume
emptyDir: {}
#medium: Memory
- name: timezone
hostPath:
path: /etc/timezone
type: File
2.重新部署
[root@k8s-master01 practice]# kubectl apply -f emptydir-hostpath.yaml
3.查看pod状态
[root@k8s-master01 practice]# kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-85fdffcd78-f9pwz 2/2 Running 0 12m
4.查看挂载情况,观察到设置的nginx已成功进行挂载;而未设置的nginx2未进行挂载
[root@k8s-master01 practice]# kubectl exec nginx-85fdffcd78-f9pwz -c nginx -- cat /etc/timezone
Asia/Shanghai
[root@k8s-master01 practice]# kubectl exec nginx-85fdffcd78-f9pwz -c nginx2 -- cat /etc/timezone
cat: can't open '/etc/timezone': No such file or directory
三、挂载NFS至容器¶
在生产环境中,考虑到数据的高可用性,仍然不建议使用NFS作为后端存储。因为NFS存在单点故障,很多企业并非对其实现高可用,并且NFS的性能存在很大的瓶颈。所以生产中,建议使用分布式存储,在公有云中建议使用公有云提供的NAS存储来替代NFS,并且NAS性能更好,可用性更高。NFS作为一个比较流行的远端存储工具,在非生产环境中是一个比较好用的选择,可以快速地搭建使用。
首先我们需要安装一下NFS
1.每台机器安装NFS客户端
$ yum install nfs-utils -y
2.在k8s-node01(192.168.1.34)启动nfs
[root@k8s-node01 ~]# systemctl start nfs-server
在k8s-node01(192.168.1.34)查看nfs支持的版本
[root@k8s-node01 ~]# cat /proc/fs/nfsd/versions
-2 +3 +4 +4.1 +4.2
3.在k8s-node01(192.168.1.34)上创建一个共享目录
[root@k8s-node01 ~]# mkdir -p /data/nfs/test_nfs
4.在k8s-node01(192.168.134)编辑授权文件,这里网段根据自己主机来定,我这里网段是192.168.1.0/24
[root@k8s-node01 ~]# vim /etc/exports
/data/nfs/ 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)
5.在k8s-node01(192.168.1.34)配置生效
[root@k8s-node01 ~]# exportfs -r
6.在k8s-node01(192.168.1.34)重新加载NFS
[root@k8s-node01 ~]# systemctl reload nfs-server
7.在k8s-master01上进行挂载测试
[root@k8s-master01 ~]# mount -t nfs 192.168.1.34:/data/nfs /mnt/
[root@k8s-master01 ~]# cd /mnt/
[root@k8s-master01 mnt]# touch test123
8.在k8s-node01(192.168.1.34)进行验证
[root@k8s-node01 ~]# cd /data/nfs/
[root@k8s-node01 nfs]# ls
test123 test_nfs
接下来,我们对上面的测试进行卸载
1.针对上诉测试进行卸载
[root@k8s-master01 ~]# umount /mnt/
最后,和emptyDir、HostPath的配置方法类似,NFS的Volume配置也是在Volumes字段中配置的,和emptyDir不同的是,NFS属于持久化存储的一种,在Pod删除或者重启后,数据依旧会存储在NFS节点上。
1.在k8s-master01上定义一个yaml文件
[root@k8s-master01 ~]# vim nfs.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2
imagePullPolicy: IfNotPresent
name: nginx
volumeMounts:
- mountPath: /opt
name: share-volume
- mountPath: /etc/timezone
name: timezone
- image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2
imagePullPolicy: IfNotPresent
name: nginx2
command:
- sh
- -c
- sleep 3600
volumeMounts:
- mountPath: /mnt
name: share-volume
- mountPath: /opt
name: nfs-volume
volumes:
- name: share-volume
emptyDir: {}
#medium: Memory
- name: timezone
hostPath:
path: /etc/timezone
type: File
- name: nfs-volume
nfs:
server: 192.168.1.34
path: /data/nfs/test_nfs
2.在k8s-master01重新部署
[root@k8s-master01 ~]# kubectl replace -f nfs.yaml
3.在k8s-master01查看pod状态
[root@k8s-master01 ~]# kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-5f974586bc-wv89n 2/2 Running 0 29s
4.在k8s-master01以容器的方式进入pod,查看挂载已经成功
[root@k8s-master01 ~]# kubectl exec -it nginx-5f974586bc-wv89n -c nginx2 -- sh
/ # df -Th
Filesystem Type Size Used Available Use% Mounted on
overlay overlay 35.0G 4.5G 30.4G 13% /
tmpfs tmpfs 64.0M 0 64.0M 0% /dev
tmpfs tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
/dev/mapper/centos-root
xfs 35.0G 4.5G 30.4G 13% /mnt
192.168.1.34:/data/nfs/test_nfs
nfs4 35.0G 3.6G 31.4G 10% /opt
5.在k8s-master01挂载目录中创建文件
[root@k8s-master01 ~]# kubectl exec -it nginx-5f974586bc-wv89n -c nginx2 -- sh
/ # cd /opt/
/opt # touch 11111
6.在k8s-node01上进行结果验证
[root@k8s-node01 ~]# cd /data/nfs/test_nfs
[root@k8s-node01 test_nfs]# ls
11111
注意:Kubernetes所有的节点都需要安装上nfs-utils才可以正常挂载NFS。