目录
简介
在Kubernetes的世界里,数据持久化是一个至关重要的话题。容器的临时性意味着我们不能将关键数据存储在容器内部,而Kubernetes提供的存储解决方案正是为了解决这一难题。本文将介绍Kubernetes中的存储机制,从基础的Volume概念到高级的PV/PVC管理,全方位掌握数据持久化的实现方式。
一、Volume的概念
在Kubernetes中,容器的文件系统是临时的,当容器重启时,所有数据都会丢失。而且,一个Pod中的多个容器可能需要共享数据。为了解决这些问题,Kubernetes引入了Volume(卷)的概念。
Kubernetes Volume vs Docker Volume
- Docker卷:功能有限,生命周期不受管理,每个容器仅允许一个卷驱动程序。
- Kubernetes卷:与Pod具有相同的生命周期,比容器寿命更长,支持多种类型,一个Pod可同时使用多个卷。
Volume的本质
从本质上讲,Kubernetes卷在挂载后就是容器中的一个目录,容器可以像操作本地目录一样对其进行读写。使用卷只需两步:
- 在Pod的
.spec.volumes
字段中定义卷。 - 在容器的
.spec.containers.volumeMounts
字段中指定挂载目录。
二、Volume的类型
Kubernetes支持多种Volume类型,以适应不同的存储需求。常见的类型包括:
- 网络存储:CephFS、GlusterFS、NFS等
- 云服务存储:Cinder、EBS等
- Kubernetes特有:ConfigMap、Secret、emptyDir、PersistentVolumeClaim等
接下来,我们将详细介绍几种常用的Volume类型及其实践方法。
三、通过emptyDir共享Pod内容器数据
emptyDir是一种简单的Volume类型,它在Pod被创建时自动创建,当Pod被删除时也会被一并删除。适合用于Pod内多个容器之间的临时数据共享。
示例:使用emptyDir实现容器间数据共享
-
创建Deployment配置文件
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 # 第一个容器使用nginx镜像
imagePullPolicy: IfNotPresent # 本地有镜像则不重新拉取
name: nginx01
volumeMounts: # 挂载卷到/opt目录
- mountPath: /opt
name: share-volume
- image: nginx:1.7.9 # 第二个容器也使用nginx镜像
imagePullPolicy: IfNotPresent
name: nginx02
command: # 让容器休眠3600秒,避免立即退出
- sh
- -c
- sleep 3600
volumeMounts: # 挂载卷到/mnt目录
- mountPath: /mnt
name: share-volume
volumes: # 定义名为share-volume的emptyDir卷
- name: share-volume
emptyDir: {}
# medium: Memory # 可选,设置为Memory则使用内存作为存储介质 -
部署Deployment
kubectl create -f nginx-empty.yaml
此命令通过指定的配置文件创建Deployment资源,Kubernetes会根据配置创建Pod及相关容器。
-
查看部署结果
kubectl get pod
该命令用于查看当前命名空间下的Pod状态,确认Pod是否正常运行(STATUS为Running)。
-
验证数据共享
进入第一个容器
kubectl exec -ti <pod名称> -c nginx01 -- sh
在/opt目录下创建一个测试文件
echo "hello from nginx01" > /opt/test.txt
退出第一个容器
exit
进入第二个容器
kubectl exec -ti <pod名称> -c nginx02 -- sh
查看/mnt目录下是否存在test.txt文件并检查内容
cat /mnt/test.txt
通过以上操作,我们可以看到在nginx01的/opt目录创建的文件,在nginx02的/mnt目录下也能看到,证明数据共享成功。
emptyDir的注意事项
- 当Pod被删除时,emptyDir中的数据也会被删除。
- 若设置
medium: Memory
,则使用tmpfs(内存文件系统),速度更快,但节点重启时数据会丢失,且占用容器的内存配额。
四、使用HostPath挂载宿主机文件
HostPath卷用于将宿主机上的文件或目录挂载到Pod中,实现Pod与宿主机之间的数据共享。常见用途包括挂载宿主机的时区文件、日志目录等。
示例:挂载宿主机时区文件到Pod
-
创建Deployment配置文件
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: # 将时区文件挂载到容器的/etc/localtime
- mountPath: /etc/localtime
name: timezone-time
volumes: # 定义hostPath卷,指向宿主机的/etc/localtime
- name: timezone-time
hostPath:
path: /etc/localtime # 宿主机上的文件路径
type: File # 指定挂载类型为文件 -
部署Deployment
kubectl create -f nginx-hostPath.yaml
-
验证时区挂载结果
进入容器
kubectl exec -ti <pod名称> -- sh
查看容器内的时间,确认是否与宿主机一致
date
若容器内的时间与宿主机时间一致,说明时区文件挂载成功。
HostPath的type参数
HostPath的type参数用于指定挂载类型,常用值包括:
- 空字符串(默认):挂载前不进行任何检查。
- DirectoryOrCreate:若路径不存在,则创建一个权限为0755的目录。
- Directory:路径必须存在且为目录。
- FileOrCreate:若路径不存在,则创建一个权限为0644的文件。
- File:路径必须存在且为文件。
- Socket:路径必须存在且为UNIX套接字。
- CharDevice:路径必须存在且为字符设备。
- BlockDevice:路径必须存在且为块设备。
HostPath的注意事项
- 使用HostPath时,Pod调度到不同节点可能会出现问题(如节点上不存在指定的文件/目录)。
- 需谨慎使用,避免Pod对宿主机文件系统进行未授权的修改。
五、挂载NFS共享存储至容器
NFS(网络文件系统)是一种常用的网络存储解决方案,通过NFS卷可以实现多个节点之间的数据共享。
示例:部署NFS服务并挂载到Pod
步骤1:在NFS服务器上安装并配置NFS
# 安装NFS服务(以CentOS为例)
yum -y install nfs-utils rpcbind
# 创建共享目录
mkdir /opt/wwwroot
# 在共享目录中创建测试文件
echo "This is my test file" > /opt/wwwroot/index.html
# 配置NFS exports文件
vim /etc/exports
# 添加以下内容,允许192.168.10.0/24网段访问该目录
/opt/wwwroot 192.168.10.0/24(rw,sync,no_root_squash)
# 启动NFS和rpcbind服务
systemctl start nfs
systemctl start rpcbind
systemctl enable nfs
systemctl enable rpcbind
/etc/exports
配置项说明:
rw
:允许读写sync
:同步写入磁盘no_root_squash
:客户端以root身份访问时,保留root权限
步骤2:在所有Kubernetes节点安装NFS客户端
yum -y install nfs-utils
确保节点能够正常访问NFS服务器的共享目录:
showmount -e <NFS服务器IP>
步骤3:创建Deployment配置文件挂载NFS
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: # 将NFS卷挂载到nginx的默认网页目录
- mountPath: /usr/share/nginx/html
name: nfs-volume
volumes: # 定义NFS卷
- name: nfs-volume
nfs:
server: 192.168.10.101 # NFS服务器IP地址
path: /opt/wwwroot # NFS共享目录路径
步骤4:部署并验证
# 部署Deployment
kubectl create -f nginx-nfsvolume.yaml
# 查看Pod状态
kubectl get pod
# 进入容器验证NFS挂载
kubectl exec -ti <pod名称> -- bash
# 查看nginx网页目录下的文件
cat /usr/share/nginx/html/index.html
若能看到之前创建的测试文件内容,说明NFS挂载成功。
六、PersistentVolume(PV)
虽然Volume已经能满足基本的存储需求,但在实际使用中仍存在一些问题:
- 无法对存储的生命周期进行精细化管理。
- 普通用户可能不了解存储的具体配置参数。
为此,Kubernetes引入了PersistentVolume(PV)和PersistentVolumeClaim(PVC)两个资源对象。
PV是由管理员配置的持久化存储,具有独立于Pod的生命周期,可以使用NFS、Ceph等多种存储后端,并支持访问模式、回收策略等高级配置。
PV的核心属性
- 回收策略:当PVC被删除后,PV的处理方式。
- Retain:保留PV和数据,需手动回收。
- Recycle:清理PV中的数据(仅NFS和HostPath支持),该策略已被弃用。
- Delete:删除PV及数据(部分云存储支持)。
- 访问模式:定义PV的访问权限。
- ReadWriteOnce(RWO):单节点读写。
- ReadOnlyMany(ROX):多节点只读。
- ReadWriteMany(RWX):多节点读写。
- ReadWriteOncePod(RWOP):单Pod读写(Kubernetes 1.22+)。
- 配置方式:
- 静态配置:管理员手动创建PV。
- 动态配置:根据PVC的需求自动创建PV(需配置StorageClass)。
示例:创建基于HostPath的PV
-
在所有节点创建目录
mkdir /mnt/data
-
创建PV配置文件
kind: PersistentVolume
apiVersion: v1
metadata:
name: mypv-hostpath # PV名称
labels:
type: local
spec:
storageClassName: pv-hostpath # 存储类名称,用于匹配PVC
capacity:
storage: 10Gi # PV容量
accessModes:- ReadWriteOnce # 访问模式:单节点读写
hostPath:
path: "/mnt/data" # 宿主机目录路径
- ReadWriteOnce # 访问模式:单节点读写
-
创建PV
kubectl create -f hostpath-pv.yaml
-
查看PV状态
kubectl get pv
创建成功后,PV状态为Available,表示可被PVC绑定。
示例:创建基于NFS的PV
-
确保NFS服务已正确配置(参考前面的NFS配置步骤)
-
创建PV配置文件
apiVersion: v1
kind: PersistentVolume
metadata:
name: mypv-nfs # PV名称
spec:
capacity:
storage: 5Gi # PV容量
volumeMode: Filesystem # 卷模式:文件系统
accessModes:- ReadWriteOnce # 访问模式
persistentVolumeReclaimPolicy: Recycle # 回收策略
storageClassName: pv-nfs # 存储类名称
nfs:
path: /opt/wwwroot # NFS共享目录
server: 192.168.10.101 # NFS服务器IP
- ReadWriteOnce # 访问模式
-
创建PV并查看
kubectl create -f nfs-pv.yaml
kubectl get pv
七、PersistentVolumeClaim(PVC)
PVC是用户对PV的请求,用户通过PVC指定所需的存储大小、访问模式等,Kubernetes会自动匹配合适的PV并进行绑定。
PVC与PV绑定的条件:
- accessModes、storageClassName、volumeMode必须一致。
- PVC请求的存储大小不得超过PV的容量。
示例:创建PVC并绑定PV
步骤1:为HostPath类型PV创建PVC
-
创建PVC配置文件
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: mypvc-hostpath # PVC名称
spec:
storageClassName: pv-hostpath # 存储类名称,需与PV一致
accessModes:- ReadWriteOnce # 访问模式,需与PV一致
resources:
requests:
storage: 3Gi # 请求的存储大小,不超过PV容量
- ReadWriteOnce # 访问模式,需与PV一致
-
创建PVC并查看
kubectl create -f pvc-hostpath.yaml
kubectl get pvc
创建成功后,PVC状态为Bound,表示已与PV绑定。
步骤2:为NFS类型PV创建PVC
-
创建PVC配置文件
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: mypvc-nfs # PVC名称
spec:
storageClassName: pv-nfs # 存储类名称,需与PV一致
accessModes:- ReadWriteOnce # 访问模式,需与PV一致
resources:
requests:
storage: 3Gi # 请求的存储大小
- ReadWriteOnce # 访问模式,需与PV一致
-
创建PVC并查看
kubectl create -f pvc-nfs.yaml
kubectl get pvc
示例:在Pod中使用PVC
PVC创建并绑定PV后,就可以在Pod中像使用普通Volume一样使用PVC了。
-
创建使用HostPath类型PVC的Pod
kind: Pod
apiVersion: v1
metadata:
name: hostpath-pv-pod
spec:
volumes:- name: task-pv-storage # 卷名称
persistentVolumeClaim:
claimName: mypvc-hostpath # 关联的PVC名称
containers: - name: task-pv-container
image: nginx:1.7.9
ports:- containerPort: 80
name: "http-server"
volumeMounts: - mountPath: "/usr/share/nginx/html" # 容器内挂载路径
name: task-pv-storage # 关联的卷名称
- containerPort: 80
- name: task-pv-storage # 卷名称
部署并验证:
# 部署Pod
kubectl create -f pvc-pv-pod-hostpath.yaml
# 在宿主机的PV目录中创建文件
touch /mnt/data/aaa.txt
# 进入Pod查看文件
kubectl exec -ti hostpath-pv-pod -- bash
ls /usr/share/nginx/html/
-
创建使用NFS类型PVC的Pod
kind: Pod
apiVersion: v1
metadata:
name: pvc-nfs
spec:
volumes:- name: pvc-nfs01 # 卷名称
persistentVolumeClaim:
claimName: mypvc-nfs # 关联的PVC名称
containers: - name: task-pv-container
image: nginx:1.7.9
ports:- containerPort: 80
name: "http-server"
volumeMounts: - mountPath: "/usr/share/nginx/html" # 容器内挂载路径
name: pvc-nfs01 # 关联的卷名称
- containerPort: 80
- name: pvc-nfs01 # 卷名称
部署并验证:
# 部署Pod
kubectl create -f pvc-pv-pod-nfs.yaml
# 进入Pod查看NFS共享目录中的文件
kubectl exec -ti pvc-nfs -- bash
ls /usr/share/nginx/html/
总结
本文介绍了Kubernetes中的存储解决方案,从基础的Volume类型(emptyDir、HostPath、NFS)到高级的PV/PVC机制,涵盖了从临时存储到持久化存储的各种场景。
通过学习这些知识,您可以根据实际需求选择合适的存储方式:
- 临时共享数据:使用emptyDir。
- 与宿主机交互:使用HostPath。
- 跨节点共享:使用NFS。
- 企业级持久化存储:使用PV/PVC,实现存储与应用的解耦。
掌握Kubernetes存储管理,将为构建高效、可靠的容器化应用奠定坚实的基础。在实际生产环境中,还需要根据业务需求和存储特性,选择合适的存储后端和配置方式,确保数据的安全性和可用性。