Kubernetes中常见的volumes数据卷
华子目录
- volumes
- k8s支持的卷的类型
- `emptyDir`卷
- 功能
- `emptyDir`的使用场景
- 示例
- `hostPath`卷
- 功能
- 用法
- 安全隐患
- 示例
- `nfs`卷
- 功能
- 应用
- 示例:部署一台`nfs服务器`并在所有`k8s节点`中安装`nfs-utils`
volumes
容器
中文件
在磁盘上
是临时存放
的,这给容器
中运行的特殊应用程序
带来一些问题
- 当
容器崩溃
时,kubelet
将重新
启动容器
,容器
中的文件将会丢失
,因为容器
会以干净
的状态重建
- 当在一个
Pod
中同时
运行多个容器
时,常常需要在这些容器
之间共享文件
- 当
Kubernetes数据卷
具有明确
的生命周期
与使用它的Pod
具有相同的生命周期
Kubernetes数据卷
比Pod
中运行的任何容器
的存活期
都长,在容器重新启动
时数据
也会得到保留
- 当一个
Pod
不再存在
时,Kubernetes数据卷
也将不再存在
Kubernetes
可以支持许多类型的卷
,Pod
也能同时
使用任意数量的卷
Kubernetes数据卷
不能挂载
到其他Kubernetes卷
,也不能
与其他卷
有硬链接
。Pod
中的每个容器
必须单独
地指定
每个卷
的挂载位置
k8s支持的卷的类型
官网
:https://kubernetes.io/zh/docs/concepts/storage/volumes/
k8s
支持的卷
的类型
如下:
awsElasticBlockStore 、azureDisk、azureFile、cephfs、cinder、configMap、csi
downwardAPI、emptyDir、fc (fibre channel)、flexVolume、flocker
gcePersistentDisk、gitRepo (deprecated)、glusterfs、hostPath、iscsi、local
nfs、persistentVolumeClaim、projected、portworxVolume、quobyte、rbd
scaleIO、secret、storageos、vsphereVolume
emptyDir
卷
功能
- 当
Pod
指定到某个node节点
上时,首先创建
的是一个emptyDir卷
- 并且只要
Pod
在该节点
上运行,卷
就一直存在
。 卷
最初是空
的。- 尽管
Pod
中的容器
挂载emptyDir卷
的路径
可能相同
也可能不同
,但是这些容器
都可以读写emptyDir卷
中相同的文件
。 - 当
Pod
因为某些原因
被从节点
上删除
时,emptyDir卷
中的数据
也会永久删除
emptyDir
的使用场景
缓存空间
,例如基于磁盘
的归并排序
耗时较长
的计算任务
提供检查点
,以便任务
能方便地从崩溃前
状态恢复执行
- 在
Web
服务器容器服务数据
时,保存内容管理器容器
获取的文件
[root@k8s-master ~]# mkdir volume
[root@k8s-master ~]# cd volume/
示例
- 创建一个名为
testpod
的自主式pod
,pod
中运行一个busyboxplus
和一个nginx
,两个容器
共用同一个卷
#创建一个名为testpod的自主式pod,pod中运行一个busyboxplus和一个nginx,两个容器共用同一个卷
[root@k8s-master volume]# vim pod1.yml
[root@k8s-master volume]# cat pod1.yml
apiVersion: v1
kind: Pod
metadata:
labels:
run: testpod
name: testpod
spec:
containers:
- image: busyboxplus
name: busyboxplus
command: ["/bin/sh","-c","sleep 10000"]
volumeMounts: #声明容器的挂载点
- name: vol1 #将k8s中名为vol1的卷挂载到容器中/volume1位置
mountPath: /volume1
- image: nginx
name: nginx
volumeMounts: #声明容器的挂载点
- name: vol1 #将k8s中名为vol1的卷挂载到容器中/usr/share/nginx/html位置
mountPath: /usr/share/nginx/html
volumes: #定义Pod中可以使用的所有卷
- name: vol1 #为卷指定了一个名称vol1,这个名称将在Pod的volumeMounts部分被引用,以便容器可以挂载这个卷。
emptyDir: #表明这个卷是一个emptyDir卷,主要用于临时数据的存储
medium: Memory #指定了emptyDir卷的存储介质为内存,这意味着卷的内容将存储在节点的RAM中,而不是磁盘上。使用内存作为存储介质可以提供更快的读写速度,但数据不是持久的,一旦Pod被删除或节点发生故障,数据就会丢失。
sizeLimit: 100Mi #为emptyDir卷设置了100MiB的大小限制。当卷中的数据量达到这个限制时,写入操作可能会被阻止
[root@k8s-master volume]# kubectl apply -f pod1.yml
pod/testpod created
[root@k8s-master volume]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
testpod 2/2 Running 0 30s 10.244.2.33 k8s-node2.org <none> <none>
#查看testpod的详细信息
[root@k8s-master volume]# kubectl describe pods testpod
#发现了了busyboxplus中的挂载目录/volume1
[root@k8s-master volume]# kubectl exec -it pods/testpod -c busyboxplus -- /bin/sh
/ # ls
bin etc lib linuxrc mnt proc run sys usr volume1
dev home lib64 media opt root sbin tmp var
/ # cd volume1/ #因为volume1和nginx中的/usr/share/nginx/html是共用的同一个名为vol1的卷,所以数据都是共享的
/volume1 # ls
/volume1 # echo hello world > index.html #我们在busyboxplus中的volume1挂载目录中创建一个index.html文件,这个index.html文件就自动同步到nginx中的/usr/share/nginx/html目录下
/volume1 # ls
index.html
/volume1 # curl localhost #因为pod中所有容器都是共享同一个pod中的所有资源,所以在busyboxplus中是可以访问到nginx的
hello world
#这条命令的作用是使用/dev/zero作为输入源,创建一个名为bigfile的文件,该文件的大小为99MB
/volume1 # dd if=/dev/zero of=bigfile bs=1M count=99
99+0 records in
99+0 records out
/volume1 # dd if=/dev/zero of=bigfile bs=1M count=100
100+0 records in
99+1 records out
/volume1 # dd if=/dev/zero of=bigfile bs=1M count=101 #因为我们对emptyDir卷设置的最大空间是100M,这个101M超出了,所以会报错
dd: writing 'bigfile': No space left on device
101+0 records in
99+1 records out
dd
: 这是一个在Unix
和类Unix系统
中用于转换
和复制文件
的命令
。它可以用来创建文件
的副本
,同时对其进行各种转换
。if=/dev/zero
:if
代表输入文件
(input_file
)。/dev/zero
是一个特殊的设备文件
,读取它
会产生无限的零
(0x00字节
)。使用/dev/zero
作为输入源
意味着你正在创建一个全部
由零字节
组成的文件
。of=bigfile
:of
代表输出文件
(output_file
)。这里指定输出文件
的名称为bigfile
bs=1M
:bs
代表块大小
(block_size
)。这里设置为1M
,意味着每次读取
或写入
操作处理的数据块大小
为1MB
(兆字节
)count=99
:count
代表要复制
的块的数量
。这里设置为99
,意味着从输入文件
读取99个块
并写入到输出文件
。由于每个块
的大小
是1MB
,所以最终生成
的文件大小
将是99MB
#回收
[root@k8s-master volume]# kubectl delete -f pod1.yml
pod "testpod" deleted
hostPath
卷
功能
hostPath卷
能将node主机
节点文件系统
上的文件
或目录
挂载到Pod
中,不会
因为pod关闭
而被删除
hostPath
想当于docker -v
操作hostPath卷
会创建在被调度
的node主机上
用法
运行
一个需要访问Docker引擎内部机制
的pod
中的容器
,挂载/var/lib/docker
路径- 在
容器
中运行cAdvisor
(监控
) 时,以hostPath
方式挂载/sys
- 允许
Pod
指定给定的hostPath
在运行Pod
之前是否应该存在
,是否应该创建
以及应该以什么方式
存在
安全隐患
- 具有
相同配置
(例如从podTemplate
创建)的多个Pod
会由于node节点
上文件不同
而在不同节点
上有不同的行为
- 当
Kubernetes
按照计划
添加资源感知
的调度
时,这类调度机制
将无法考虑
由hostPath
使用的资源
- 基础主机上
创建的文件
或目录
只能由root
用户写入
。需要在特权容器
中以root
身份运行进程
,或者修改
主机上的文件权限
以便容器
能够写入hostPath卷
示例
- 创建一个名为
testpod
的自主式pod
,运行一个名为nginx
的容器
,再声明
一个hostPath类型
的卷
#创建一个名为testpod的自主式pod,运行一个名为nginx的容器,在声明一个hostPath类型的卷
[root@k8s-master volume]# vim pod2.yml
[root@k8s-master volume]# cat pod2.yml
apiVersion: v1
kind: Pod
metadata:
labels:
run: testpod
name: testpod
spec:
containers:
- image: nginx
name: nginx
volumeMounts: #容器挂载点声明
- name: vol2 #将k8s中名为vol2的卷挂载到容器中的/usr/share/nginx/html位置
mountPath: /usr/share/nginx/html #挂载点目录
volumes: #pod中的卷
- name: vol2 #指定一个名为vol2的卷
hostPath: #这个卷的类型是hostPath类型
path: /huazi #在被调度的node节点上创建huazi这个目录
type: DirectoryOrCreate #当/huazi目录不存在时自动建立
[root@k8s-master volume]# kubectl apply -f pod2.yml
pod/testpod created
[root@k8s-master volume]# kubectl describe pods testpod
#我们发现调度到了node2主机上
[root@k8s-master volume]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
testpod 1/1 Running 0 17s 10.244.2.34 k8s-node2.org <none> <none>
#我们发现在node2节点上创建了/huazi/这个目录
[root@k8s-node2 ~]# ls /
afs boot etc home lib media opt root sbin sys usr
bin dev guangpan huazi lib64 mnt proc run srv tmp var
#当我们第一次访问的时候是403,因为nginx中/usr/share/nginx/html目录下没有index.html文件
[root@k8s-master volume]# curl 10.244.2.34
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.27.1</center>
</body>
</html>
#在node2上,进入/huazi目录中,创建index.html文件
[root@k8s-node2 ~]# cd /huazi/
[root@k8s-node2 huazi]# echo hello world > index.html
#这时再访问,就有效果了
[root@k8s-master volume]# curl 10.244.2.34
hello world
#回收
[root@k8s-master volume]# kubectl delete -f pod2.yml
pod "testpod" deleted
nfs
卷
功能
nfs卷
允许将一个现有的nfs服务器
上的目录
挂载到Kubernetes
中的Pod
中。这对于在多个Pod
之间共享数据
或持久化
存储数据
非常有用
应用
例如
,如果有多个容器
需要访问
相同的数据集
,或者需要将容器
中的数据持久
保存到外部存储
,nfs卷
可以提供一种方便的解决方案
示例:部署一台nfs服务器
并在所有k8s节点
中安装nfs-utils
这里,我就在harbor主机
上部署nfs服务器
- 部署
nfs服务端
[root@harbor ~]# yum install nfs-utils -y
- 部署
nfs客户端
[root@k8s-master ~]# yum install nfs-utils -y
[root@k8s-node1 ~]# yum install nfs-utils -y
[root@k8s-node2 ~]# yum install nfs-utils -y
- 启动服务端
[root@harbor ~]# systemctl enable --now nfs-server
服务端
创建nfs共享目录
[root@harbor ~]# mkdir /nfsdata
- 编辑
服务端
的/etc/exports
文件
[root@harbor ~]# vim /etc/exports
[root@harbor ~]# cat /etc/exports
/nfsdata *(rw,sync,no_root_squash)
[root@harbor ~]# exportfs -rv
exporting *:/nfsdata
- 客户端连接服务端
#172.25.254.250是nfs服务端的ip
[root@k8s-master ~]# showmount -e 172.25.254.250
Export list for 172.25.254.250:
/nfsdata *
[root@k8s-node1 ~]# showmount -e 172.25.254.250
Export list for 172.25.254.250:
/nfsdata *
[root@k8s-node2 ~]# showmount -e 172.25.254.250
Export list for 172.25.254.250:
/nfsdata *
- 创建一个名为
testpod
的自主式pod
,运行一个nginx容器
,容器
中挂载
名为vol3
的卷
,vol3卷
的类型为nfs
#创建一个名为testpod的自主式pod,运行一个nginx容器,容器中挂载名为vol3的卷,vol3卷的类型为nfs
[root@k8s-master volume]# vim pod3.yml
[root@k8s-master volume]# cat pod3.yml
apiVersion: v1
kind: Pod
metadata:
labels:
run: testpod
name: testpod
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- name: vol3 #将名字为vol3的卷,挂载到nginx容器中的/usr/share/nginx/html位置
mountPath: /usr/share/nginx/html
volumes: #pod存储卷定义的开始
- name: vol3 #pod存储卷的名称
nfs: #pod存储卷的类型是NFS
server: 172.25.254.250 #NFS服务器的IP地址
path: /nfsdata #nfs服务器上的共享目录
[root@k8s-master volume]# kubectl apply -f pod3.yml
pod/testpod created
[root@k8s-master volume]# kubectl describe pods testpod
[root@k8s-master volume]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
testpod 1/1 Running 0 97s 10.244.2.35 k8s-node2.org <none> <none>
#当我们第一次访问的时候是403,因为nginx中/usr/share/nginx/html目录下没有index.html文件
[root@k8s-master volume]# curl 10.244.2.35
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.27.1</center>
</body>
</html>
#在nfs服务器上,进入/nfsdata共享目录中,创建index.html文件
[root@harbor ~]# cd /nfsdata/
[root@harbor nfsdata]# echo hello world > index.html
#再次访问,就看到效果了
[root@k8s-master volume]# curl 10.244.2.35
hello world