前言

以下以mysql:5.7.31为例,mysql8.0版本增强了密码功能,如果不熟悉这块内容,会引发了很多问题,包括这次研究使用mysqldump数据迁移,也有坑,这里就不细说了,现在看来,如果对于mysql8.0版本的新特性没研究,也没必要使用的,自己学习测试还是老老实实使用5.x版本。

docker run --name mysql5.7 -e MYSQL_ROOT_PASSWORD=root -d -p3306:3306 mysql:5.7.31

mysql is a simple SQL shell with input line editing capabilities. It supports interactive and noninteractive use.

众所周知,mysqldump是官方提供的数据迁移工具,它集成在mysql-client中,所以要使用这个工具,先在本地安装mysql-client。现在是容器,云原生时代,本地docker部署,线上k8s部署mysql是必然。要做备份,你需要解决两个问题,第一,如何连接到数据库;第二,如何获取备份后的文件。在物理机下本不是问题的问题,在容器环境下却变得非常复杂。

docker与k8s环境下,数据迁移复杂度来源是网络模型与存储卷。

docker网络有linux network namespace,bridge模式,host模式等知识点,docker是直接挂载宿主机作为持久存储,还可以知道数据存在硬盘什么位置。k8s环境下,docker只是作为一种容器运行时,不关心docker容器运行在那台机器上,k8s有跨主机通信,三层网络模型等,k8s的存储类直接屏蔽了存储细节。

下面逐层分析物理机,docker,k8s环境下的数据备份迁移方式。

mysqldump用法

直接参阅官方文档,以下是参考官方文档稍微做几点说明:

调用语法:

shell> mysqldump [options] db_name [tbl_name ...]

shell> mysqldump [options] --databases db_name ...

shell> mysqldump [options] --all-databases

--opt参数

Shorthand for --add-drop-table --add-locks --create-options --disable-keys --extended-insert --lock-tables --quick --set-charset

-h -u 是host, user 缩写

--disable-keys:surround INSERT statements with statements to disable and enable keys,用来避免导入时的外键冲突。

单机备份

方式一:宿主机mysqldump

不知道你没有没有试过物理机安装mysql-client,docker 安装mysql,然后物理机使用熟悉的命令行mysql -uroot -p root去连接这个docker的mysql?

熟悉docker网络模型的就知道怎么连接了,如果docker网络是网桥模式,则容器有自己独立的network namespace,通过宿主机的docker0网桥进行通信,假设宿主机ip为192.168.1.31,我们通过-p参数暴露mysql容器的端口为3306,此时应该怎么连接呢?

mysql -h 192.168.1.31 -uroot -proot? 很明显是不可以的,这样连接你会得到一个socket错误,这里正确的用法是先docker inspect命令查看mysql容器的ip地址,我这里是172.17.0.5,然后mysql -h172.17.0.5 -uroot -proot如下

63686f0d52a450d09b4d6d516e344919.png

f5a31853bd04de201fc76ffca39fb749.png

方式二:docker exec

虽说mysql -server ,mysql-client 是独立的,但是容器里也有mysql-client的,用于在命令行操作数据库。所以了,直接docker exec 进入容器,执行mysqldump命令,指定一个位置,再从容器里把文件拷贝出来,最简单的,该位置直接就是mysql数据卷位置,这样在物理机上就可以看到了,不再赘述。

方式三:mysqldump 容器(最佳实践)

docker容器之间可以使用--link互联,所以如果mysqldump也是一个容器的话不就可以完成备份么。docker hub 搜索mysqldump,找到这个工具:

Use for a single backup

In this case you simply empty the entrypoint and run the mysqlump command.

docker run

--rm --entrypoint ""

-v `pwd`/backup:/backup

--link="container:alias"

schnitzler/mysqldump

mysqldump --opt -h alias -u user -p"password" "--result-file=/backup/dumps.sql" database

简单解释下,docker run命令的格式是:docker run [OPTIONS] IMAGE [COMMAND] [ARG...],让两个容器网络互通是通过 --link参数,覆盖默认的entrypoint命令为空,执行mysqldump命令,绑定宿主机数据卷,从而实现把容器里数据备份出来。此方法配合docker compose可以实现定期自动备份。

k8s集群下备份

方式一:mysqldump

k8s存储类屏蔽了存储细节,哪种存储方式是可以自己管理存储细节的?手动挂载PV,使用emptydir或者hostpath类型,给mysql容器单独挂载一个目录,然后执行命令行mysqldump将数据导出到这个目录里,ssh连接宿主机获取文件。

方式二:kubectl

使用kubectl命令,kubectl cp复制容器里的文件到宿主机目录,此方法建立在手动搭建k8s集群,在我的Rancher环境里测试失败,虽然执行命令成功,但是不清楚文件存放位置。操作见这篇文档。

kubectl exec mysql-0 -n db -- mysqldump -u root -proot auth --result-file=/mysql-dump/auth_dump.sql

kubectl cp -n db mysql-0:/mysql-dump/auth_dump.sql /tmp

方式三:helm mysqldump ssh(最佳实践)

mysqldump is a tool for creating backups of MySQL databases in the form of a .sql file.

helm商店搜索“mysql”,你会看到一个“Mysqldump”,是alibaba-app-hub提供的,毫无疑问这是一个mysql数据备份工具,他使用的镜像叫做monotek/gcloud-mysql,查看它的使用说明,你会看到,它支持将备份数据上传到googlestoragebucket,openstack,这俩存储都不符合国情,好在还有一个ssh,支持通过ssh方式将备份数据上传至远程服务器。我们重写他的配置:

mysql:

host: "mysql-temp"

password: "root"

db: auth

schedule: "0/1 * * * *"

persistence:

enabled: false

allDatabases:

enabled: false

upload:

ssh:

enabled: "true"

dir: ~/backup

host: "192.168.1.31"

user: "songkaizong"

privatekey: "-----BEGIN RSA PRIVATE KEY-----

MIIEowIBAAKCAQEAtHHlYs2geA3DI24ZhuYBgsws3YQUHfEZ+ohziQGtz4i4EIf4

LNyS5EE6ldUL2j291TUCKj6ifnwnBMAjAJNGJZ/GFKnLe/p1UgXI0USujBe7vhAD

4RnPeN/fycxGG8c3YETaeNr35Ri1AWgFG4HmCFNzBE+c2sK8vTp44WCcZdeX4O/Z

DG79LrtkL99dl4mEAzqz+vOh7ld16J/W1HrabGRDFi9HWQMaAA74a6dPfWMJF5rx

Et2rAD8CmsMt2pozrzX5SDNuG+diHByyD2szwbDXQf3GAMmQWXAdCNQuvYkD9wUJ

O8+oAlBLVsCwF1D0ZOcgtW+Q3boaS4Ug3NaDcQIDAQABAoIBAA58OirVUPVyPWEB

vKDco/BpDYz2xlqk+S3oeEXeUaKgWg5Rq/WF+3DBX7+Za6soW63a5IKZppe6xbMW

7XhlWjM5AUC1ZLVeJL7h4f4SomRyn0qhpH4UgVg1uJRNhq9CLcrXnCYphc7pTdaA

EDDmG549fLUy4ueYzGfwYrXM+KEgK+rxH201dT6ZVoBiiqFEowuTZSO+00TSzyE6

l6xxOVEiCk17tg2bi1Id219nkVsf9c7nAvlMikbGXLr77y6sHsKtslZBCk4xTIE1

QD+jNsF2ISTNfdLbS6Al+Pn2tKxSoxfJ9L4tgiiWWGsPRSWFi59oqwvhi1qpHGNw

fXnBs1UCgYEA4+7KHy3dyYg/xHzZ4fNHFTjyCHVvTVLc8yP4EoWN8vBgogNzHG0M

qGMJf+yfR5l6Zdta+dNk2i7t9QMb5wtGtkYD/aiqIX5Gog5BnqRKGilh4a5HNicq

lxrO7fVE8Ta3yeuSqt8K+IAk7brC0ntRLK7UpPUOxFho0P+4uJOGVJcCgYEAyqog

8H+WraNXH7yz4SfSsbxk9I2lE/SSNeI0l+3BqEH+f6q/f8Toh9GdN56pycQ3OgoK

o/nEEIv+Z2bdIpPM4Bpkfb4HG0/XBVI8IVc0co+nDZHVSNaZKNx0Ee6kYF2iyPAx

3khqjQ11VBnXag1X2PzbuAOx2t2QZViaGNyAQTcCgYA3MdXkIvk4GjRG4mzomD64

VufVQIrJUK2Me0NRSOIM2ESuNuOjGI0eIY1lWulfLz1CeRHYuWYMp5yb3jrdgg+H

iADjZfp8zdVQ3N7rCaGgIDFBszAvXuCjYqyFVwVw2+05ikAj/IrtjipjHvyad546

kcOQhn8i8L3BDouutpqq1QKBgBKN4NYj2DetbJyLOiyy6Kc9CEEbdrGNApXMT+RY

8BHneNVXXJDmBiPpHOuqqwC95hB6Ot8oTrr1FiWBVV2FCoy53dllPGFTvevOy5KB

2Vtjq3eiklRI0VzcUgQSRRpNeEnNM8OV/atMQCGi/AXJkvFatQLz06SmBEJDClic

V2GhAoGBAKFa6IWGnH5fYsoUyZ8EY6CnjcjMZdqFsC1fN2lkIzzuNYkZPeiUjKLR

jOf9pYFX4VcX0z+ertHsRpF5cYGhIxdg4bqWaXs/s7VoSSFknkKLm7GeVFf5eJPi

tQKF1HIvUc3BVdv9LSIHr7jGgaPjsS095EgyaAjyPfTe/rOk3Cav

-----END RSA PRIVATE KEY-----"

以上配置的含义首先是mysql地址,密码配置,然后是禁用存储卷,使用ssh上传到192.168.1.31我的机器,这个应用的资源种类的cronjob,也就是支持定时来备份,这里是每隔1分钟执行一次来测试。这里的问题在于,ssh要使用秘钥来进行免密码登录,所以有一个privatekey字段填写秘钥。怎么处理呢?这就需要理解ssh协议及免密登录了,首先在上传的目标服务器上生成密钥对,将公钥添加至同目录下authorized_keys文件,私钥填写在privatekey字段。使用的命令如下:

cd ~/.ssh

ssh-keygen

cat id_rsa.pub >> authorized_keys

cat id_rsa

b079cdac52ef5a993275cbc5145ec606.png

完成之后,执行成功结果:

b384ab255781180d61cb7e2e40501594.png

dc3cbb7df8ca288893a21ddd6c3418b3.png

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐