额。。。你没看错,就是在 Kubernetes 中部署 MySQL 主从,虽然我感觉 MySQL 丢 Kubernetes 有点蛋疼吧,但没办法,公司要求我只能照做了。。
思路
就直接说一下编写下面 YAML 的思路了:
- 首先,创建了一个
ConfigMap
,其中包含了 MySQL 配置文件的模板,用于动态为各个 MySQLPod
生成配置文件,这个功能由StatefulSet
中的initContainers
中的mysql-sidecar-init
容器提供,在模板中可以看到已经开启了binlog
和relaylog
了; - 然后创建了一个
StatefulSet
,就是用它来管理 MySQLPod
,它有一个特点就是Pod
名称是有编号的,比如下面的StatefulSet
名称为mysql-server
,那么它管理的Pod
名称就为mysql-server-0
、mysql-server-1
、mysql-server-2
...; - 所以这里我就约定第一个创建的
Pod
为主库,后续所有创建的Pod
都是第一个Pod
的从库,所以这里就可以确定主库的名字就一直是mysql-server-0
了; - 现在唯一的一个问题就是如何构建主从关系了,这里就要用到 Kubernetes 内部的 DNS 了,在 Kubernetes 中可以通过
<pod_name>.<service_name>.<namespace>.svc.cluster.local
的方式来访问名为<pod_name>
的Pod
,所以在下面的示例中,主库的访问地址就固定为mysql-server-0.mysql-server.test.svc.cluster.local
了,<server_name>
通过环境变量SERVICE_NAME
传入,<pod_name>
和namespace
直接通过 DownwardAPI 获取; - 主库的地址已经确定了,最后就要考虑的是如何去执行 SQL 了,因为构建 MySQL 主从关系首先需要在主库创建复制用户,然后在从库执行
change master ...
,这里就用到了Pod
的生命周期钩子了,如下通过lifecycle.postStart
指定了 Pod 处于running
状态之前执行的命令,这个命令指定了运行一个/opt/run
二进制文件,它是我用python
的并打包好的二进制文件(需要源码的可以留言邮箱我发,绝对无毒。),可以自动根据上述逻辑完成主从关系的维护。当然,在这里你完全可以在钩子这写一大片 Shell 来完成我上述所说的功能,但是实在是太不优雅了? - 最后就可以运行这个 YAML 了,当然前提是你也准备好了
StorageClassName
提供 PV 的动态创建供给,我这里底层存储用的 Ceph,当然你也可以用 NFS 或其它的;
效果
YAML
镜像我已经提交到了公开的阿里云仓库,所以下面 YAML 的镜像可以直接使用。
评论区