上一篇:K8S实战基础篇:一文带你深入了解K8S实战部署SpringBoot项目
K8S实战进阶篇:一文带你深入了解K8S持久化存储解决方案
1. 前言
经过上一篇K8S实战部署SpringBoot项目的解读,我相信很多老铁都已经对K8S部署项目有了一个初步的认识,我们了解了K8S的Ingress网络
,但简单的SpringBoot项目部署只是K8S使用的基础,我们使用K8S另一个绕不开的话题就是K8S持久化存储
。什么是持久化存储
? For Example: 我们做系统迁移,要把原来的服务迁移到K8S中,系统用的Mysql数据库,也要迁移到K8S,我们知道,K8S运行的是一个一个Pod,K8S对Pod自动化管理,一个Pod挂了,另外一个Pod就会马上拉起来,假如运行Mysql的Pod挂了,马上重新拉起来,那原来Pod中存储的数据还会存在吗?或者说新拉起来的Pod会进行数据恢复吗?答案是:NO! 如果没有持久化存储,那兄弟,你真正的做到了从删库到跑路!从这样一个真实的场景,我们应该认识到K8S持久化存储
的重要性,可以说,没有持久化技术,K8S就没有任何发展的前景!今天,我就深入的和大家聊一聊K8S中做持久化存储的几种解决方案,并用实操让大家玩转K8S!话不多说,撸起袖子,干就完了!
这里没有任何马后炮套话,只有粗暴的干货。写大家看得懂、用得着、赚得到的文章是唯一宗旨!
2. Storage
2.1. Volume
官方定义:On-disk files in a Container are ephemeral, which presents some problems for non-trivial applications when running in Containers. First, when a Container crashes, kubelet will restart it, but the files will be lost - the Container starts with a clean state. Second, when running Containers together in a Pod it is often necessary to share files between those Containers. The Kubernetes Volume abstraction solves both of these problems.
容器中的磁盘上文件是短暂的,这给在容器中运行的非平凡应用程序带来了一些问题。首先,当一个容器崩溃时,kubelet将重新启动它,但文件将丢失-容器以一个干净的状态开始。其次,在Pod中一起运行容器时,常常需要在这些容器之间共享文件。Kubernetes卷抽象解决了这两个问题。
2.2. Host类型volume实战
假如我们来设计K8S的Storage
方案,我们会怎么做?如果你想到了这样一个解决方案:在Pod所在的宿主机上,我有一个数据存储目录,和Mysql Pod的数据存储目录做一下关联,让后者共享宿主机的存储目录,那在Pod挂掉之后,重新拉取还是同样的共享目录,那数据不久能恢复了?这样听起来是不是和docker的 -v 设置目录挂载有异曲同工之妙!那我们来实操一下!
2.2.1. 创建Nginx Pod的yaml文件
我们首先创建一个nginx的pod的yaml文件,volumeMounts
定义了pod内的存储目录是根目录的nginx-volume
文件夹下,volumes
定义了的挂载类型是hostPath
, 目录是 /tmp/volume-pod
,我们都是有经验的开发人员,我想这个文件应该很好理解。
apiVersion: v1
kind: Pod
metadata:
name: volume-pod
spec:
containers:
- name: nginx-container
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: volume-pod
mountPath: /nginx-volume
volumes:
- name: volume-pod
hostPath:
path: /tmp/volume-pod
我们在集群中master节点保存这个yaml文件,起名字为volume-pod.yaml
,然后执行
$ kubectl apply -f volume-pod.yaml
然后查看详细信息,我们发现它在worker02节点创建了pod。
$ kubectl get pod -o wide
2.2.2. 验证
接下来就是验证:我们要查看worker02节点和pod内目录是否进行了关联
宿主机:
Pod内:
果然,宿主机和Pod内都存在!那么接下来我们验证一下,我在宿主机这个目录建个文件,Pod内会不会出现这个文件。我在宿主机上建了一个 index.html文件,在Pod查看。
果然,同步了!
那接下来,我们删除Pod,重新拉起一个Pod,看会不会还存在这个index.html文件
果然,index.html存在!
重点来了: 这种共享宿主机存储的方法似乎可以解决Mysql数据库数据恢复的场景,我们似乎可以万事大吉了!But,有的老铁会问:如果我得宿主机挂了怎么办?或者Pod没有在上一次节点上拉起,而是在新的节点上拉起,那数据都不在一个宿主机上,还恢复个锤子! 听起来有点儿道理啊,确实存在这个问题那怎么解决呢?还是那句话 :总有”好事者”替我们解决了这个问题!
2.3. PersistentVolumes
官方文档
既然Host类型
的持久化存储无法解决节点宕机或者pod在另外的机器上拉起导致数据无法恢复的Bug,那我们就应该思考一个问题:既然我无法在宿主机持久化,那我在集群之外的服务器上存储数据,让我的Pod关联到这个数据存储服务器上,同时我对这个数据存储服务器做高可用,岂不美哉? 此处应该有掌声,三分钟!
想法很好,那我们来介绍一下K8S给我们的解决方案: PersistentVolumes 简称PV
PV 是什么?它是一种插件,它能够支持多种数据存储服务器,通过PV,我们能在K8S集群中,把我们的数据持久化到外部的服务器中。下图是PV能够支持的数据存储服务类型
我们可以看到,它能支持这么多种数据存储服务,那我们来实战一下:选择NFS来作为我们的数据存储服务。
2.3.1. NFS服务器搭建
NFS 是什么? nfs(network file system) 网络文件系统,是FreeBSD支持的文件系统中的一种,允许网络中的计算机之间通过TCP/IP网络共享资源
- 找一台centos 7机器,执行以下脚本,搭建 NFS服务器:
# 安装nfs
yum install -y nfs-utils
# 创建nfs目录
mkdir -p /nfs/data/
mkdir -p /nfs/data/mysql
# 授予权限
chmod -R 777 /nfs/data
# 编辑export文件
vi /etc/exports
/nfs/data *(rw,no_root_squash,sync)
# 使得配置生效
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地址)
- 在K8S集群所有节点上安装NFS客户端
yum -y install nfs-utils
systemctl start nfs && systemctl enable nfs
2.3.2. PV定义
NFS 服务器有了,那我们如何让PV和NFC关联上呢?看下面代码:
# 定义PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: nginx-pv
spec:
accessModes:
- ReadWriteMany
capacity:
storage: 2Gi
nfs:
path: /nfs/data/nginx
server: 10.6.229.62
PV也作为一种K8S的资源,被K8S管理,所以它的定义肯定也是yaml。上述代码我们定义了一个nginx-pv,accessModes
权限是ReadWriteMany
读写权限,capacity
storage
定义了2G