1.什么是持久化存储? For Example: 我们做系统迁移,要把原来的服务迁移到K8S中,系统用的Mysql数据库,也要迁移到K8S,我们知道,K8S运行的是一个一个Pod,K8S对Pod自动化管理,一个Pod挂了,另外一个Pod就会马上拉起来,假如运行Mysql的Pod挂了,马上重新拉起来,那原来Pod中存储的数据还会存在吗?或者说新拉起来的Pod会进行数据恢复吗?答案是:NO! 如果没有持久化存储,那兄弟,你真正的做到了从删库到跑路!从这样一个真实的场景,我们应该认识到K8S持久化存储的重要性,可以说,没有持久化技术,K8S就没有任何发展的前景!今天,我就深入的和大家聊一聊K8S中做持久化存储的几种解决方案,并用实操让大家玩转K8S!话不多说,撸起袖子,干就完了!
PV:
全称是PersistentVolumes,它是一种插件,它能够支持多种数据存储服务器,通过PV,我们能在K8S集群中,把我们的数据持久化到外部的服务器中。下图是PV能够支持的数据存储服务类型。
我们可以看到,它能支持这么多种数据存储服务,那我们来实战一下:选择NFS来作为我们的数据存储服务。
2.NFS服务器搭建
NFS 是什么? nfs(network file system) 网络文件系统,是FreeBSD支持的文件系统中的一种,允许网络中的计算机之间通过TCP/IP网络共享资源
1)找一台centos 7机器,执行以下脚本,搭建 NFS服务器:
vim install_nfs.sh
#!/bin/bash
# 安装nfs
yum install -y nfs-utils
# 创建nfs目录
mkdir -p /nfs/data/
mkdir -p /nfs/data/mysql
# 授予权限
chmod -R 777 /nfs/data
# 编辑export文件
cat > /etc/exports << EOF
/nfs/data *(rw,no_root_squash,sync)
EOF
# 使得配置生效
exportfs -r
# 查看生效
exportfs
# 启动rpcbind、nfs服务
systemctl restart rpcbind && systemctl enable rpcbind
systemctl restart nfs && systemctl enable nfs
# 查看rpc服务的注册情况
rpcinfo -p localhost
# showmount测试
showmount -e ip(ip地址)
复制代码
执行脚本:chmod +x install_nfs.sh && ./install_nfs.sh
2)在K8S集群所有节点上安装NFS客户端
yum -y install nfs-utils systemctl start nfs && systemctl enable nfs
NFS 服务器有了,那我们如何让PV和NFC关联上呢?看下面代码:
# 定义nginx pv(生产者)
apiVersion: v1
kind: PersistentVolume
metadata:
name: nginx-pv
labels:
app: nginx001
namespace: nginx-pv-pvc
spec:
accessModes:
- ReadWriteMany
capacity:
storage: 2Gi
nfs:
path: /nfs/data/nginx
server: 192.168.29.104
复制代码
PV也作为一种K8S的资源,被K8S管理,所以它的定义肯定也是yaml。上述代码我们定义了一个nginx-pv,accessModes权限是ReadWriteMany读写权限,capacity storage 定义了2G的存储空间,挂载目录是/nfs/data/nginx,NFS 服务器IP是192.168.29.104,好了,我们这样就定义了一个PV。
定义完了我们就能用了吗?
我们考虑一个问题: 假如你作为这一块儿的设计者,每次想使用外部存储服务,都要自己创建一个PV,这样做麻烦吗?一个公司中不仅有开发,还有运维,如果我们想用外部存储服务,直接告诉运维,让运维给我们在K8S中准备一些PV,我们自己挑选着用,这岂不是方便很多。
所以,“好事者” 想的比较周到。我们的PV是和外部的服务器相连,Pod是不能使用的,我们要用另外一种叫做PersistentVolumeClaim 简称 PVC 的资源来连接PV,我们的Pod连接PVC 就可以使用了。类似于消息中间件的生产者和消费者的关系。PV是生产者,PVC是消费者。
3)PersistentVolumeClaim
PVC定义:
# 定义nginx pvc(消费者,用于和pod绑定)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nginx-pvc
labels:
app: nginx001
namespace: nginx-pv-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 2Gi
复制代码
简单明了,我定义一个名字叫 nginx-pvc的PVC,权限是ReadWriteMany读写权限,需要的存储空间是 2G。
那我们思考一个问题:PV,PVC我们都定义好了,我们在PVC定义中并没有看到和PV绑定的相关配置,那他们两个是怎么绑定的呢?
其实,内部是配对是这样的:通过PVC定义的 accessModes 读写权限,和storage定义的2G内存,PVC会自动找到符合这些配置的PV进行绑定。一个PV被PVC绑定后,不能被别的PVC绑定。
4)PV、PVC实战
我们还来定义一个Nginx Pod,使用PV,PVC,NFS来做持久化存储;我这里就把上面定义的pv、pvc都写到一个yaml文件里
vim nginx-pv-pvc.yaml
---
# 定义nginx pv(生产者)
apiVersion: v1
kind: PersistentVolume
metadata:
name: nginx-pv
labels:
app: nginx001
namespace: nginx-pv-pvc
spec:
accessModes:
- ReadWriteMany
capacity:
storage: 2Gi
nfs:
path: /nfs/data/nginx
server: 192.168.29.104
---
# 定义nginx pvc(消费者,用于和pod绑定)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nginx-pvc
labels:
app: nginx001
namespace: nginx-pv-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 2Gi
---
# 定义nginx pod,绑定pvc(nginx-pvc)
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-wyn001
namespace: nginx-pv-pvc
spec:
replicas: 3
selector:
matchLabels:
app: nginx001
template:
metadata:
name: nginx-wyn001
labels:
app: nginx001
spec:
containers:
- name: nginx-wyn001
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: nginx-data-volume
mountPath: /usr/share/nginx/html
resources:
requests:
cpu: 1000m
memory: 200M
limits:
cpu: 2000m
memory: 300M
volumes:
- name: nginx-data-volume
persistentVolumeClaim:
claimName: nginx-pvc
复制代码
创建:
kubectl apply -f nginx-pv-pvc.yaml
我们可以看到 使用 persistentVolumeClaim:claimName: nginx-pvc 定义了我我们要使用名字为nginx-pvc的 PVC。
注意:我们在NFS服务器上定义的路径是/nfs/data/nginx 首先我们需要去 nfs/data下创建 nginx的文件夹,不然你的pod是启动不起来的,这个坑我替大家踩了!
接下来,在master节点上启动。
查看:kubectl get po,pv,pvc -n nginx-pv-pvc
现在的数据目录关系这样的:
容器数据目录:/usr/share/nginx/html 通过pvc,pvc又通过pv映射到了nfs服务器的 /nfs/data/nginx目录
现在我们在nfs服务器的 /nfs/data/nginx目录创建几个文件,然后到nginx pod中查看是否已经有了这些文件
ls /nfs/data/nginx/
查看pod:
kubectl exec -it -n nginx-pv-pvc nginx-wyn001-5fdbd66695-xs6p2 — ls /usr/share/nginx/html
从上图得知,容器内已经有了数据,现在我这个pod是部署在node1节点上面的,我把该pod删掉重建后,它正好部署到node2节点上,然后我再次查看了pod中容器的/usr/share/nginx/html目录,发现数据已经自动挂载上去了
当然,还可以采用 storage class方式实现数据的持久化,由于篇幅较长,下期再出一篇这方面的文章给大家