虽然 kubernetes 社区一直在努力使得有状态应用成为一等公民,也推出了 statefulset 控制器支持 pod 的顺序部署,稳定的域名访问和存储访问。但鉴于 MySQL 部署运维的多样性和复杂性,在 kubernetes 上部署 MySQL 仍然要面临众多挑战。
1、业务流量入口的配置方式
传统虚拟机环境下,我们通过虚 IP 的方式,让业务应用都配置事先定义的一个虚 IP 为链接数据库的地址,然后由高可用服务保证虚 IP 始终能被路由到 master 数据库。在 kubernetes 中,出现了一层网络插件屏蔽了底层网络拓扑,高可用服务管理虚 IP 的方式需要随之适应调整,比如通过 service 结合标签完成虚 IP 的漂移,但 service 本身是 kubernetes 提供的一项功能,其可靠性和性能都取决于 kubernetes 服务的稳定。以性能来说,service 是 kube proxy 组件通过配置 iptables 实现的,当 iptables 规则较多时不可避免的会产生时延,需要我们针对性的解决。
2、容器隔离带来的监控视野问题
在 kubernetes 中,如果将 MySQL 制作为 container 运行在一个 pod 中,container 会将 MySQL 进程和运行环境隔离在一个单独的 namespace 中。监控组件在获取 MySQL 的一些 metirc 时,可能不得不进入与 MySQL 同一个 namespace 中,在部署和设计监控组件时需要考虑到这些限制。
3、存储
在 kubernetes 中,支持配置各种不同的存储。如果使用本地存储 local persistent volume,则需要绑定 MySQL 在一个固定的节点,这就完全浪费了 kubernetes 灵活调度的天然优势;而如果使用远程共享存储,确实是将 MySQL 进程与其存储完全解耦,使得 MySQL 进程可以在任意节点调度,然而考虑到高 I/O 吞吐量的情况,就不是那么美好了。设计时需要考量远程存储是否能够满足 MySQL 的带宽要求。
4、高可用/备份恢复
kubernetes 提供的 statefulset 控制器只能提供最基本的部署,删除功能,无法实现完善的 MySQL 集群高可用/备份恢复操作。对于有状态应用的部署,仍需要定制开发,所以多数公司提供了定制的 operator 来完成应用容器的管理。比如 etcd operator,MySQL operator,后文将为大家详述我测试使用 MySQL operator 的一些记录。
注:operator 是 CoreOS 推出的旨在简化复杂有状态应用管理的框架,我们可以通过 operator 自定义一个有状态应用容器的控制器,operator 通过 kubernetes API 观察集群现有状态,管理集群行为,以达到用户期望的集群状态。
说完了问题和挑战,我们来说说收益。
把 MySQL 塞进 kubernetes 生态带来了什么?
1. 丰富的网络配置
结合 kubernetes 的 cni 网络插件可以快速实现限流,黑白名单……
2. 各类 kubernetes 调度、运维功能
敏捷部署,滚动更新,依据负载情况的节点调度……
3. 与同样部署在 kubernetes 生态的业务应用紧密配合然而考虑到 MySQL 这类持久层软件的特殊性,不能简单的套用 kubernetes 的原生 API 功能,比如滚动更新需要考虑主从角色的先后顺序,配套高可用软件在 MySQL 更新阶段的行为,业务流量的切换等等。这些在传统环境中已经解决的问题在 kubernetes 中仍然需要被重新规划解决方案。
控制器介绍
鉴于以上种种挑战,在 kubernetes 上管理 MySQL 需要一套专为 MySQL 设计的控制器(就我们前面说到的 operator),目前开源社区中比较流行的有以下两个控制器:
Oracle MySQL operator
先简单过一遍功能:1. 最低支持 MySQL 8.0.11 版本2. 只能支持部署 MySQL Group Replication 架构,不支持 Master-Slave 部署3. operator 自动建立的 service 无法区分读写节点,推荐应用使用 mysql router,由 mysql router 路由至下游实例4. 提供 mysqldump(不支持其他备份工具)配置定时备份,备份文件上传远程存储,目前仅实现了 AWS S3 接口5. 支持从远程存储中获取备份执行回放还原6. operator 内置提供了一些基础 metric 监控集群状态