持久化存储
在K8S中部署的应用都是以pod容器的形式运行的,假如部署数据库服务 例如:MySQL、Redis等,需要对产生的数据做备份。如果pod不挂载数据卷,那pod被删除或重启后这些数据会随之消失,想要长久的保留这些数据就要用到pod数据持久化存储。
支持的持久化存储类型
查看K8S支持哪些存储
bash
kubectl explain pods.spec.volumes
常用的如下:
- emptyDir :临时性存储卷类型
- hostPath :在节点上使用本地磁盘进行数据存储
- nfs:通过 Network File System(网络文件系统)共享文件系统进行数据存储
- persistentVolumeClaim:持久卷声明,是K8S的一个特定类型的存储资源
- glusterfs:通过分布式文件系统GlusterFS进行数据存储
- cephfs:通过分布式文件系统Ceph进行数据存储
- configMap: 通过ConfigMap资源存储应用程序的配置文件
- secret:通过Secret资源存储应用程序的机密信息
本篇对前三种进行展开介绍,并例举实践中的使用
EmptyDir
emptyDir类型的Volume是在Pod分配到Node上时被创建,K8S会在Node上自动分配一个目录,无需指定宿主机Node上对应的目录文件。 这个目录的初始内容为空,当Pod从Node上移除时,emptyDir中的数据会被永久删除。
emptyDir 主要用于某些应用程序无需永久保存的临时目录,多个容器的共享目录等。
实践
创建一个pod,挂载临时目录emptyDir
bash
vim emptydir.yaml
yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-empty
spec:
containers:
- name: container-empty
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: cache-volume # 匹配volumes.name。把卷挂载到容器里
mountPath: /cache # 挂载到容器里的目录下
volumes:
- name: cache-volume
emptyDir:{}
更新资源清单文件
bash
kubectl apply -f emptydir.yaml
bash
kubectl describe pods pod-empty
查看分配到Node上的临时目录存在的位置
1、查看pod的uid
bash
kubectl get pods pod-empty -o yaml | grep uid
uid: adff4bf3-62ac-41fe-9b25-abcae1c8598a
2、查看pod调度到哪个节点
bash
kubectl get pods -o wide | grep empty
3、登录到k8s-node1上
ps. 安装tree 方便看目录结构
bash
yum install tree -y
根据 uid 看目录
bash
tree /var/lib/kubelet/pods/adff4bf3-62ac-41fe-9b25-abcae1c8598a
由上可知,临时目录在本地的/var/lib/kubelet/pods/adff4bf3-62ac-41fe-9b25-abcae1c8598a/volumes/kubernetes.io~empty-dir/cache-volume/下
pod删了,临时目录也没了
bash
kubectl delete -f emptydir.yaml
该类型可使用的场景:测试数据
HostPath
hostPath Volume是指Pod挂载宿主机上的目录或文件。 hostPath Volume使得容器可以使用宿主机的文件系统进行存储,hostpath(宿主机路径):节点级别的存储卷 ,在pod被删除,这个存储卷还是存在的,不会被删除。
所以只要同一个pod被调度到同一个节点上来,在pod被删除重新被调度到这个节点之后,对应的数据依然是存在的。
查看hostPath存储卷的用法
bash
kubectl explain pods.spec.volumes.hostPath
hostPath的type类型:
实践
创建一个pod,挂载hostPath存储卷
bash
vim hostpath.yaml
yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-hostpath
spec:
containers:
- name: container-nginx
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: hostpath-volume
mountPath: /hostpath-nginx
- name: container-tomcat
image: tomcat:8.5-jre8-alpine
imagePullPolicy: IfNotPresent
volumeMounts:
- name: hostpath-volume
mountPath: /hostpath-tomcat
volumes:
- name: hostpath-volume
hostPath:
path: /data-hostpath # 必须字段,指定存储目录
type: DirectoryOrCreate # 表示本地有/data-hostpath目录,就用本地的,本地没有就会在pod调度到的节点自动创建一个
更新资源清单文件
bash
kubectl apply -f hostpath.yaml
查看pod调度到了哪个物理节点
bash
kubectl get pods -o wide | grep hostpath
由上面可以知道pod调度到了k8s-node1上,登录到k8s-node1机器,查看是否在这台机器创建了存储目录
bash
ll /data-hostpath/
上面可以看到已经创建了存储目录/data-hostpath,这个【/data-hostpath】会作为pod的持久化存储目录
在k8s-node1上的/data-hostpath下创建一个目录
bash
cd /data-hostpath
mkdir aa
测试存储卷是否可以正常使用
1、登录到nginx容器
bash
kubectl exec -it pod-hostpath -c container-nginx -- /bin/bash
bash
cd /hostpath-nginx/
/hostpath-nginx/目录存在,说明已经把宿主机目录挂载到了容器里
bash
ls
2、登录到tomcat容器
bash
kubectl exec -it pod-hostpath -c container-tomcat -- /bin/bash
bash
cd /hostpath-tomcat/
/hostpath-tomcat/目录存在,说明已经把宿主机目录挂载到了容器里
bash
ls
通过上面测试可以看到,同一个pod里的 container-nginx 和 container-tomcat 这两个容器是共享存储卷的
删除pod,指定调度到另外的node上
bash
kubectl delete -f hostpath.yaml
bash
vim hostpath.yaml
yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-hostpath
spec:
nodeName: k8s-node2 # 指定调度到node2节点上
containers:
- name: container-nginx
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: hostpath-volume
mountPath: /hostpath-nginx
- name: container-tomcat
image: tomcat:8.5-jre8-alpine
imagePullPolicy: IfNotPresent
volumeMounts:
- name: hostpath-volume
mountPath: /hostpath-tomcat
volumes:
- name: hostpath-volume
hostPath:
path: /data-hostpath
type: DirectoryOrCreate
更新资源清单文件
bash
kubectl apply -f hostpath.yaml
看容器里的目录,登录到nginx容器
bash
kubectl exec -it pod-hostpath -c container-nginx -- /bin/bash
bash
cd /hostpath-nginx
bash
ls
aa 文件不在了
hostpath存储卷缺点:单节点,pod删除之后重新创建必须调度到同一个node节点,数据才不会丢失
NFS
以上 emptyDir 和 hostPath 是两种本地存储解决方案,仅适用于单个节点上的容器。如果需要在多个Pod或多节点之间共享持久化存储,可使用NFS。
NFS存储允许多个Pod从网络共享中读取数据,还支持高可用性配置,可以使用多个NFS服务器来提供容错和负载均衡。此外NFS还支持更高级的存储管理功能,如快照和备份,以及可配置的访问控制策略。
实践
1、搭建NFS服务
以k8s的控制节点(k8s-master1)作为NFS服务端
bash
yum install nfs-utils -y
该命令的主要作用是使用yum包管理器自动安装nfs-utils软件包,以支持NFS协议的功能。
2、在宿主机创建NFS需要的共享目录,作为NFS服务端
bash
mkdir /data/volumes -pv
-p表示:创建目录的过程中,如果父级不存在,则自动创建父目录。
-v表示:可向用户展示更多信息,例如显示执行mkdir创建了哪些目录等。
3、配置NFS共享服务器上的/data/volumes目录
执行以下命令启动NFS
bash
systemctl start nfs
编辑配置NFS服务访问的目录/data/volumes的访问权限
bash
vim /etc/exports
powershell
# 允许任何客户端挂载
/data/volumes *(rw,no_root_squash)
参数说明:
- /data/volumes:要共享的目录
- '**':允许哪些客户端挂载NFS共享的目录,"*"表示允许任何能访问NFS服务的网段客户端挂载NFS共享的目录
- rw 该主机对该共享目录有读写权限
- no_root_squash 登入:用户具有根目录的完全管理访问权限
4、使NFS配置生效
执行以下命令使NFS配置生效
bash
exportfs -arv
bash
service nfs restart
查看nfs是否启动成功
bash
systemctl enable nfs
查看nfs是否启动成功
bash
systemctl status nfs
Active: active
看到nfs是active,说明nfs正常启动了
5、k8s-node2和k8s-node1上也安装nfs驱动
bash
yum install nfs-utils -y
systemctl enable nfs --now
在k8s-node1上手动挂载
bash
mkdir /test
bash
mount 192.168.40.182:/data/volumes /test/
以上【192.168.40.182】为服务端(k8s-master1)的IP
bash
df -h
nfs可以被正常挂载
手动卸载
bash
umount /test
6、创建Pod,挂载NFS共享出来的目录
bash
vim nfs.yaml
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-test
spec:
replicas: 3
selector:
matchLabels:
storage: nfs
template:
metadata:
labels:
storage: nfs
spec:
containers:
- name: container-nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
protocol: TCP
volumeMounts:
- name: nfs-volumes
mountPath: /usr/share/nginx/html
volumes:
- name: nfs-volumes
nfs:
server: 192.168.40.182 # 安装nfs服务的地址
path: /data/volumes # nfs的共享目录
更新资源清单文件
bash
kubectl apply -f nfs.yaml
查看pod是否创建成功
bash
kubectl get pods -owide
登录到nfs服务器,在共享目录创建一个index.html
bash
cd /data/volumes/
vim index.html
请求pod,看结果
通过上面可以看到,在共享目录创建的index.html已经被pod挂载了
登录到pod验证下
bash
kubectl exec -it nfs-test-65db89988d-4hs7h -- /bin/bash
bash
cat /usr/share/nginx/html/index.html
上面说明挂载nfs存储卷成功了,nfs支持多个客户端挂载,可以创建多个pod,挂载同一个nfs服务器共享出来的目录;
但是nfs如果宕机了,数据也就丢失了,想要高可用可使用分布式存储,常见的分布式存储有glusterfs和cephfs。