在 Kubernetes 中,Volume 是一种用于持久化存储和共享数据的机制。Volume 提供了一种在容器中使用存储的方式,确保数据在容器重启或重建时不会丢失。
在Kubernetes中,volume支持Kubernetes特有的存储卷类型,也支持传统的存储卷类型。
Kubernetes独有的类型:
常见的卷:
emptyDir是一个特殊的Volume类型,与上述Volume不同的是,如果删除Pod,EmptyDir卷中的数据也将被删除,所以一般emptyDir用于Pod中不同容器共享数据,比如一个Pod存在两个容器A和容器B,容器A需要使用容器B产生的数据,此时可以采用emptyDir共享数据,类似的使用如Filebeat收集容器内程序产生的日志。
使用emptyDir卷时, 直接指定emptyDir:{}即可
vim nginx-empty.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:1.7.9
imagePullPolicy: IfNotPresent
name: nginx01
volumeMounts:
- mountPath: /opt
name: share-volume
- image: nginx:1.7.9
imagePullPolicy: IfNotPresent
name: nginx02
command:
- sh
- -c
- sleep 3600
volumeMounts:
- mountPath: /mnt
name: share-volume
volumes:
- name: share-volume
emptyDir: {}
#medium: Memory
备注:
volumeMounts: #定义了容器内的挂载点
- mountPath: /mnt #指定容器内的路径 /mnt
,Volume 将挂载到这里
name: share-volume #指明要挂载的 Volume 的名称,必须与 volumes
部分的名称匹配。
volumes: #定义了 Volume 的来源
- name: share-volume #指定 Volume 的名称,容器中的挂载名称必须与此匹配。
emptyDir: {} #表示一个临时目录 Volume,数据存储在 Pod 的本地磁盘上,当 Pod 被删除时数据也会丢失。
此部署文件创建一个Deployment,采用spec.voluem字段配置一个名字为share-volume,类型为emptyDir的volume,同时里面包含两个容器nginx01和nginx02,并将volume挂载到了/opt和/mnt目录下,此时/opt和/mnt目录的数据就实现了共享。
默认情况下,emptyDir支持节点上的任何介质,可以是SSD,磁盘或是网络存储,具体取决于自身环境。可以将emptyDir.medium字段设置为Memory,让Kubernetes使用tmpfs(内存支持的文件系统),虽然tmpfs非常快,但是在节点重启时,数据同样会被清除,并且设置的大小被记为Container(容器)的内存限制。
ku create -f nginx-empty.yaml
[root@k8s-master ~]# ku get pod
NAME READY STATUS RESTARTS AGE
nginx-8f8dcfd8c-4dj6h 2/2 Running 0 8s
[root@k8s-master ~]# ku get pod
NAME READY STATUS RESTARTS AGE
nginx-8f8dcfd8c-4dj6h 2/2 Running 0 8s
[root@k8s-master ~]# ku exec -it nginx-8f8dcfd8c-4dj6h -c nginx01 -- bash
root@nginx-8f8dcfd8c-4dj6h:/# cd opt/
root@nginx-8f8dcfd8c-4dj6h:/opt# touch aaa
root@nginx-8f8dcfd8c-4dj6h:/opt# exit
exit
[root@k8s-master ~]# ku exec -it nginx-8f8dcfd8c-4dj6h -c nginx02 -- bash
root@nginx-8f8dcfd8c-4dj6h:/# cd /mnt
root@nginx-8f8dcfd8c-4dj6h:/mnt# ls
aaa
HostPath卷可以将节点上的文件或目录挂载到pod上,用于实现Pod和宿主机之间的数据共享,常用的示例有挂载宿主机的时区至Pod,或者将Pod的日志文件挂载到宿主机。
以下为使用HostPath卷的示例,实现将主机的/etc/localtime文件挂载到pod的/etc/loacltime
[root@k8s-master ~]# vim nginx-hostPath.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:1.7.9
imagePullPolicy: IfNotPresent
name: nginx
volumeMounts:
- mountPath: /etc/localtime
name: timezone-time
volumes:
- name: timezone-time
hostPath:
path: /etc/localtime
type: File
备注:关于时区的设置,通过配置/etc/localtime文件设置系统的时区
/etc/localtime用于配置系统时区(此文件是一个链接文件,链接自/usr/share/zoneinfo/Asia/shanghai)
[root@k8s-master ~]# ku create -f nginx-hostPath.yaml
deployment.apps/nginx created
[root@k8s-master ~]# ku get pod
NAME READY STATUS RESTARTS AGE
nginx-59f95c99b5-ld58v 1/1 Running 0 10s
[root@k8s-master ~]# ku exec -it nginx-59f95c99b5-ld58v -- bash
root@nginx-59f95c99b5-ld58v:/# date
Mon Aug 26 12:31:25 CST 2024
在配置Hostpath时,有一个type参数,用于表达不同的挂载类型,Hostpath卷常用的类型有:
[root@k8s-master ~]# yum -y install nfs-utils
(1)创建共享目录
mkdir /henan/xiaoman
(2)设置共享的网段
[root@k8s-master ~]# vim /etc/exports
/henan/xiaoman 192.168.10.0/24(rw,sync,no_root_squash)
/henan/xiaoman
:这是 NFS 服务器上要共享的目录路径。客户端将能够访问这个目录及其内容。
192.168.10.0/24
:这是允许访问这个共享目录的客户端 IP 地址范围。192.168.10.0/24
表示子网掩码为 255.255.255.0
的网络,允许这个子网中的所有主机访问共享目录。
(rw,sync,no_root_squash)
:
这是一组 NFS 导出选项,用于控制访问权限和行为:
rw
:表示客户端可以读写这个目录。客户端不仅可以读取目录中的文件,还可以向其中写入数据。
sync
:表示所有写入操作都将同步到磁盘,这样可以确保数据的一致性和可靠性,但可能会稍微降低性能。
no_root_squash
:表示 NFS 服务器不将客户端的 root 用户映射为匿名用户(nobody)。如果使用 root_squash
,root 用户的权限会被映射成匿名用户的权限,增加了安全性。
[root@k8s-master ~]# systemctl start nfs
[root@k8s-master ~]# systemctl start rpcbind
[root@k8s-master ~]# vim nginx-nfsVolume.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:1.7.9
imagePullPolicy: IfNotPresent
name: nginx
volumeMounts:
- mountPath: /usr/share/nginx/html
name: nfs-volume
volumes:
- name: nfs-volume
nfs:
server: 192.168.10.101
path: /henan/xiaoman
[root@k8s-master ~]# ku create -f nginx-nfsVolume.yaml
[root@k8s-master ~]# echo "my name is henanxiaoman">/henan/xiaoman/index.html
[root@k8s-master ~]# ku get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-5c94b6fc6b-bsmns 1/1 Running 0 115s 10.244.140.72 node02
[root@k8s-master ~]# curl 10.244.140.72
my name is henanxiaoman
或
[root@k8s-master ~]# ku exec -it nginx-5c94b6fc6b-bsmns -c nginx -- bash
root@nginx-5c94b6fc6b-bsmns:/# cd /usr/share/nginx/html/
root@nginx-5c94b6fc6b-bsmns:/usr/share/nginx/html# ls
index.html
[root@nginx-5c94b6fc6b-bsmns:/usr/share/nginx/html# cat index.html
my name is henanxiaoman
为此,kubernetes引入了两个新的API资源:Persistentvolume(持久卷,简称PV)PersistentVolumeclaim(持久卷声明,简称PVC)
PV是kubernetes管理员设置的存储,PVC是对PV的请求,标识需要什么类型的PV。他们同样是集群中的一类资源,但其生命周期比较独立,管理员可以单独对PV进行增删改查,不受Pod的影响,生命周期可能比挂载它的其他资源还要长。如果一个kubernetes集群的使用者并非只有kubernetes管理员,那么可以通过提前创建PV,用以解决对存储概念不是很了解的技术人员对存储的需求。和单独配置vo1ume类似,PV也可以使用NFS、GFS、CEPH等常见的存储后端,并且可以提供更为高级的配置,比如访问模式、空间大小以及回收策略等。目前PV的提供方式有两种:静态或动态。静态PV由管理员提前创建,动态PV无需提前创建。
1.PV回收策略
当用户使用完卷时,可以从API中删除PVC对象,从而允许回收资源。回收策略会告诉PV如何处理改卷。目前回收策略可以设置为Retain、Recycle和Delete。默认的为delete
在实际使用PV时,可能针对不同的应用会有不同的访问策略,比如某类Pod可以读写,某类Pod只能读,或者需要配置是否可以被多个不同的Pod同时读写等,此时可以使用PV的访问策略进行简单控制,目前支持的访问策略如下:
使用场景
虽然PV在创建时可以指定不同的访问策略,但是也要后端的存储支持才行。比如一般情况下,大部分块存储是不支持ReadWriteMany的。
在企业内,可能存储很多不同类型的存储,比如NFS、Ceph、GlusterFS等,针对不同类型的后端存储具有不同的配置方式,这也是对集群管理员的一种挑战,因为集群管理员需要对每种存储都要有所了解。
(1)静态配置
静态配置是手动创建PV并定义其属性,例如容量、访问模式、存储后端等。在这种情况下,Kubernetes管理员负责管理和配置PV,然后应用程序可以使用这些PV。静态配置通常用于一些固定的存储后端,如NFS
(2)动态配置
动态配置允许Kubernetes集群根据PVC的需求自动创建PV,在这种情况下,管理员只需为存储后端配置Storageclass,然后应用程序就可以通过PVC请求存储。Kubernetes将自动创建与PVC匹配的PV,并将其绑定到PVC上。这种方法使得存储管理更加灵活和可扩展,允许管理员在集群中动态添加、删除、和管理存储资源