前言
以下以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如下
方式二: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
完成之后,执行成功结果: