k8s中的Mysql数据库持久化存储
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了k8s中的Mysql数据库持久化存储相关的知识,希望对你有一定的参考价值。
参考技术A一、配置:
环境:
CentOS7
VMware
笔者配置了四台虚拟机:
K8S-Master节点: 3GB内存 2核CPU 20GB硬盘空间
K8S-node1节点: 2GB内存 2核CPU 30GB硬盘空间
K8S-node2节点: 2GB内存 2核CPU 30GB硬盘空间
镜像仓库节点: 2GB内存 2核CPU 50GB硬盘空间
二、节点规划:
使用三台虚拟机搭建K8S集群,使用一台虚拟机搭建镜像仓库。
每台虚拟机配置两块网卡,其中一块为“NAT模式”,用于拉取镜像等功能。
另外一块网卡为“仅主机模式”,用于集群节点间的通信。归划如下:
K8s-master节点:
仅主机模式:10.10.10.200
NAT模式: 192.168.200.130
K8S-node1节点:
仅主机模式:10.10.10.201
NAT模式: 192.168.200.131
K8S-node2节点:
仅主机模式:10.10.10.202
NAT模式: 192.168.200.132
镜像仓库节点:
仅主机模式:10.10.10.101
NAT模式: 192.168.200.150
三、版本信息
Linux内核版本:
Linux version 3.10.0-862.el7.x86_64 (builder@kbuilder.dev.centos.org)
(gcc version 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC) )
#1 SMP Fri Apr 20 16:44:24 UTC 2018
K8s集群版本为1.15.0版本:
四、基于StatefulSet与PV/PVC的mysql持久化存储实验
1. 在每个节点安装nfs服务
在“镜像仓库”节点,执行以下命令:
yum install -y nfs-common nfs-utils rpcbind
在k8s集群,执行以下命令:
yum install -y nfs-utils rpcbind
2. 在“镜像仓库”节点下,配置nfs服务器
mkdir /nfs_mysql
Chmod 777 /nfs_mysql/
(在测试环境中,为了不考虑用户属性,暂时赋予777权限,但在生产环境不推荐这样做)
Chown nfsnobody /nfs_mysql/
echo “/nfs_mysql *(rw,no_root_squash,no_all_squash,sync)” >> /etc/exports
cat /etc/exports
/nfs_mysql *(rw,no_root_squash,no_all_squash,sync)
systemctl start rpcbind
systemctl start nfs
3. 测试nfs服务是否可用
mkdir /test
showmount -e 10.10.10.101
可见/nfs_mysql *已暴露于共享目录,接下来测试挂载是否可用:
在master节点下执行:
mount -t nfs 10.10.10.101:/nfs_mysql /test/
echo "hello-world">>/test/1.txt
在镜像仓库节点下查看1.txt是否存在,若存在则挂载成功:
可见nfs服务可以正常使用,接下来删除test目录和1.txt
在镜像仓库下:
[root@hub nfs_mysql]# rm -f 1.txt
在Master节点下:
[root@k8s-master ~]# umount /test/
[root@k8s-master ~]# rm -rf /test/
同理,依照以上步骤同时创建:(提供多个mysql副本进行挂载)
nfs_mysql1
nfs_mysql2
完成后需要重启nfs服务
systemctl restart rpcbind
systemctl restart nfs
最终效果:
4. 将nfs封装成pv
创建mysql_test文件夹,将yaml文件统一保存在此目录下
mkdir mysql_test
cd mysql_test
vim mysql-pv.yml
mysql-pv.yml配置如下:
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /nfs_mysql
server: 10.10.10.101
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv1
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /nfs_mysql1
server: 10.10.10.101
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv2
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /nfs_mysql2
server: 10.10.10.101
注意:
在k8s集群15版本中recycle回收策略已被删除,只能用retain策略或者Delete策略。这里我们使用 persistentVolumeReclaimPolicy: Retain
执行命令:
kubectl create -f mysql-pv.yml
kubectl get pv
如图所示,即为Pv创建成功。
5. 部署MySQL,在mysql_test目录下编写mysql.yml,配置文件如下
apiVersion: v1
kind: Service
metadata:
name: mysql
labels:
app: mysql
spec:
ports:
- port: 3306
name: mysql
clusterIP: None
selector:
app: mysql
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
serviceName: "mysql"
replicas: 3
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.6
env:
- name: MYSQL_ROOT_PASSWORD
value: password
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: mysql-persistent-storage
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "nfs"
resources:
requests:
storage: 1Gi
执行以下命令,部署mysql服务:
kubectl create -f mysql.yml
如图可知,mysql按StatefulSet依次创建了mysql-0 mysql-1 mysql-2
查看各个Pod部在哪个节点:
6. 通过创建临时容器,使用MySQL客户端发送测试请求给MySQL master节点
注意:
主机名为mysql-0.mysql;跨命名空间的话,主机名请使用mysql-0.mysql. [NAMESPACE_NAME].如果没有指定命名空间,默认为default,即 mysql-0.mysql. default。
这里笔者打算关闭node2节点来模拟node2宕机,来测试是否实现数据的持久化存储,
所以我们向node2上的mysql1写入数据。
执行以下命令,访问mysql1:
kubectl run mysql-client --image=mysql:5.6 -it --rm --restart=Never -- mysql -h mysql-1.mysql.default -p password
创建数据库demo,并向messages表中写入hello-world
CREATE DATABASE demo;
CREATE TABLE demo.messages (message VARCHAR(250));
INSERT INTO demo.messages VALUES ('hello-world');
如图所示
接下来我们来关闭k8s-node2虚拟机,模拟宕机
查看nodes的运行状态,可知node2的状态已转变为NotReady
一段时间后,k8s将Pod MySql -1迁移到节点k8s-node1
由于时间过长,笔者把三个Pod都删除重启后,验证数据:
MySQL服务恢复,数据完好无损!
Docker数据持久化
一、前言当我们使用Docker创建一个mysql的container, 数据是存储在container内的.
如果有一天不小心执行了docker rm $(docker ps -aq)删除所有container. 那么mysql里的数据也会被删掉, 这是不安全的.
我们需要将数据持久化, 存储在container外部. 即使删除container也不会删除原有的数据.
二、容器的缺陷
容器中的数据可以存储在容器层。但是将数据存放在容器层存在以下问题:
1.数据不是持久化。意思是如果容器删除了,这些数据也就没了
2.主机上的其它进程不方便访问这些数据
3.对这些数据的I/O会经过存储驱动,然后到达主机,引入了一层间接层,因此性能会有所下降
三、data volume有两种挂载方式:
1)bind mount(用户管理):将宿主机上的某个目录或文件(不可以是没有格式化的磁盘文件),挂载到容器中,默认在容器内对此目录是有读写权限的,如果只需要向容器内添加文件,不希望覆盖目录,需要注意源文件必须存在,否则会被当做一个目录bind mount给容器。
2)docker manager volume(docker自动管理):不需要指定源文件,只需要指定mount point(挂载点)。把容器里面的目录映射到了本地。
这种方式相比bind mount 缺点是无法限制对容器里边目录或文件的权限。
使用第二种挂载方式,-v 挂载时,不指定源文件位置,则默认挂载的路径是:
[root@sqm-docker01 _data]# pwd
/var/lib/docker/volumes/dd173640edd5b0205bb02f3c4139647be12528b38289b9f93f18123a6b1266a8/_data
#当有目录挂载时,默认在/var/lib/docker/volumes/下会生成一串hash值,hash值下有一个_data的目录,容器内映射的文件就在此路径下。
四、Storage Driver
数据存储方式
Centos7版本的docker,Storage Driver(数据存储方式)为:overlay2 ,Backing Filesystem(文件系统类型): xfs
可使用 “docker inspect 容器名称” 来查看数据存储方式
五、Data Volume
(Bind mount)
持久化存储:本质上是DockerHost文件系统中的目录或文件,能够直接被Mount到容器的文件系统中。在运行容器时,可通过-v实现。
特点:
**1. Data Volume是目录或文件,不能是没有格式化的磁盘(块设备)。
- 容器可以读写volume中的数据。
- Volume数据可以永久保存,即使使用它的容器已经被销毁。**
小实验:
运行一个nginx服务,做数据持久化
(1)Data Volume是目录或文件,不能是没有格式化的磁盘(块设备)。
[root@docker01 ~]# mkdir html
//创建测试目录
[root@docker01 ~]# cd html/
[root@docker01 html]# echo "This is a testfile in dockerHost." > index.html
//创建测试网页
[root@docker01 ~]# docker run -itd --name testweb -v /root/html/:/usr/share/nginx/html nginx:latest
//运行一个nginx容器,并挂载目录
[root@docker01 ~]# docker inspect testweb
[root@docker01 ~]# curl 172.17.0.3
注意:dockerhost上需要被挂载的源文件或目录,必须是已经存在,否则,会被当作一个目录挂载到容器中。
(2)容器可以读写volume中的数据。
[root@docker01 ~]# docker exec -it testweb /bin/bash
root@ef12d312a94e:/# cd /usr/share/nginx/html/
root@ef12d312a94e:/usr/share/nginx/html# echo "update" > index.html
//容器中更新网页
root@ef12d312a94e:/usr/share/nginx/html# exit
[root@docker01 ~]# cat html/index.html
//可以看到宿主目录的挂载目录也更新了
(3)Volume数据可以永久保存,即使,使用它的容器已经被销毁,也可以通过宿主机的挂在目录重新启动一个容器挂载这个目录进行访问。
[root@docker01 ~]# docker ps -a -q |xargs docker rm -f
//删除所有容器
[root@docker01 ~]# cat html/index.html
//容器删除之后,宿主机的测试网页也在
[root@docker01 ~]# docker run -itd --name t1 -P -v /root/html/:/usr/share/nginx/html nginx:latest
//基于测试网页创建一个容器
[root@docker01 ~]# docker ps
[root@docker01 ~]# curl 127.0.0.1:32768
//访问一下
[root@docker01 ~]# echo "update-new" > html/index.html
//再次更新测试网页
[root@docker01 ~]# curl 127.0.0.1:32768
//在宿主机更新测试网页,刚刚创建的容器的测试网页也会更新
(5)默认挂载到容器内的文件,容器是有读写权限。可以在运行容器是-v 后边加“:ro”限制容器的写入权限
[root@docker01 ~]# docker run -itd --name t2 -P -v /root/html/:/usr/share/nginx/html:ro nginx:latest
//创建容器设置指读权限
[root@docker01 ~]# docker exec -it t2 /bin/bash
//进入容器
root@4739c0f5d970:/# cd /usr/share/nginx/html
root@4739c0f5d970:/usr/share/nginx/html# echo 1234 > index.html
//修改测试网页(失败,因为是只读的)
[root@docker01 ~]# echo 654321 > html/index.html
//宿主机可以更改
[root@docker01 ~]# curl 127.0.0.1:32768
(6)并且还可以挂载单独的文件到容器内部,一般他的使用场景是:如果不想对整个目录进行覆盖,而只希望添加某个文件,就可以使用挂载单个文件。
<1>测试1
[root@docker01 ~]# docker run -itd --name v6 -P -v /root/html/index.html:/usr/share/nginx/html/index.html nginx:latest
[root@docker01 ~]# docker ps
[root@docker01 ~]# curl 127.0.0.1:32770
<1>测试2
[root@docker01 ~]# echo test > test.html
[root@docker01 ~]# docker run -itd --name t8 -P -v /root/test.html:/usr/share/nginx/html/test.html nginx:latest
[root@docker01 ~]# curl 127.0.0.1:32772/test.html
六,Docker Manager Volume
会自动在宿主机生成目录,所以在挂载目录的时候只用写容器中的目录。
[root@docker01 ~]# docker run -itd --name t1 -P -v /usr/share/nginx/html nginx:latest
[root@docker01 ~]# docker ps
[root@docker01 ~]# docker inspect t1
[root@docker01 _data]# cd /var/lib/docker/volumes/17c50a065a6b10ccd01ca1ce8091fdf6282dc9dcb77a0f6695906257ecc03a63/_data
[root@docker01 _data]# echo "this is a testfile" > index.html
[root@docker01 _data]# docker ps
[root@docker01 _data]# curl 127.0.0.1:32777
[root@docker01 _data]# docker volume ls
[root@docker01 _data]# docker rm t1 -f
[root@docker01 _data]# cat index.html
1.删除容器的操作,默认不会对dockerhost上的源文件操作,如果想要在删除容器时把源文件也删除,可以在删除容器时添加-v选项(一般不推荐使用这种方式,因为文件有可能被其他容器使用)
[root@docker01 _data]# docker run -itd --name t2 -P -v /usr/share/nginx/html nginx:latest
[root@docker01 ~]# docker inspect t2
[root@docker01 ~]# cd /var/lib/docker/volumes/2781dbfdc673fc7d149dc4f6217ef277fe72e05ba2e20fcebb617afe97eccb30/_data
[root@docker01 _data]# docker rm -v t2 -f
t2
[root@docker01 _data]# ls
七,容器与容器的数据共享
Volume container:给其他容器提供volume存储卷的容器。并且它可以提供bind mount,也可以提供docker manager volume。
创建一个vc_data容器
[root@docker01 ~]# docker create --name vc_data -v ~/html:/usr/share/nginx/html -v /other/useful/tools busybox
[root@docker01 ~]# docker inspect vc_data
[root@docker01 ~]# docker run -itd --name t3 -P --volumes-from vc_data nginx:latest
[root@docker01 ~]# docker ps
[root@docker01 ~]# curl 127.0.0.1:32779
以上是关于k8s中的Mysql数据库持久化存储的主要内容,如果未能解决你的问题,请参考以下文章