别让 Docker 毁了你的 MySQL!

小程序云存储算法

近年来,随着 Docker 容器技术的火热,越来越多的应用开始被"装箱"。我们这些开发者享受着 Docker 带来的便捷和灵活,几乎恨不得把所有东西都塞进容器里。于是,连 MySQL 这样的有状态服务,也开始频频出现在 Docker 的舞台上。

但是,把 MySQL 装进 Docker,真的是个明智的选择吗 ?是否会给系统稳定性和数据安全带来隐患?这个问题在社区里引发了激烈的讨论。

"Docker 与有状态服务无缘"派

持反对意见的一派认为,所有有状态的服务,都不应该放在 Docker 里跑 。他们列举了 MySQL、Redis、Elasticsearch、ActiveMQ 等服务作为例子,理由是这些服务都需要保证高可用和稳定性,而这恰恰是 Docker 难以做到的。

即便是在 Kubernetes 这样的容器编排平台中,他们也不建议把有状态服务放进去。这也是为什么云厂商会专门提供 MySQL、Redis、MQ 等服务的原因。

那么,究竟是什么原因让"Docker 与有状态服务无缘"呢?

首先,传统的高可用方案在容器中难以实现。以 MySQL 为例,传统的 HA 方案通常是两台机器+共享存储+Fence 设备。

但在 Kubernetes 中,这种方案如何配置?Fence 设备又该如何在容器中实现?这些都是没有现成答案的问题。

其次,一些 MySQL 的高可用和集群方案与 Docker 的理念不太兼容。

比如,MySQL 8.0 的 InnoDB Cluster 通常采用 1 主 2 从的模式,这在 Kubernetes 中如何实现?虽然有 MySQL Operator 这样的尝试,但成熟度和可行性还有待验证。

最后,对于 DBA 来说,在虚拟机上部署 MySQL 才是最熟悉和放心的方式。

毕竟数据库最需要的是稳定,调整 CPU、内存、磁盘等参数,再加上定期备份,就可以做到大多数时候"甩手掌柜"。

如果是在公有云上,那就更应该直接用云厂商提供的 MySQL 服务。

在他们看来,Docker 适合运行无状态服务 。因为无状态服务挂了就拉起来,不需要做额外的检查,而有状态服务则可能由于数据不一致而带来新的问题。

"MySQL 照样可以容器化"派

但支持在 Docker 中运行 MySQL 的声音也不小。毕竟,所有主流数据库都已经提供了官方镜像,多数也有容器化的集群方案 。他们认为,只要在部署时遵循一些最佳实践,就可以充分发挥 Docker 的优势,而不必担心稳定性和性能问题。

首先,在部署 MySQL 容器时,一定要记得挂载数据卷(Data Volume) 。通过数据卷,可以将容器内的数据目录映射到宿主机上,这样不仅可以避免容器删除时数据丢失,还能减少额外的 I/O 开销。例如,如果我们希望将容器内的 /var/lib/mysql 目录(MySQL 默认的数据目录)映射到宿主机的 /my/own/datadir 目录,可以在启动容器时使用 -v 参数:


        
          
docker run --name some-mysql -v /my/own/datadir:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag  

      

除了手动指定目录,我们也可以使用 Docker 的命名卷(Named Volume)功能 。命名卷可以由 Docker 来管理,不需要我们关心具体的存储位置:


        
          
docker run --name some-mysql -v mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag  

      

如果要实现 MySQL 的配置文件外挂 ,也可以通过数据卷来实现:


        
          
docker run --name some-mysql -v /my/own/datadir:/var/lib/mysql -v /my/custom/mysql.cnf:/etc/mysql/conf.d/mysql.cnf -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag  

      

其次,使用容器部署 MySQL 有诸多优点。容器可以封装不同版本的 MySQL,而不用担心与宿主机的兼容性问题 。同时,由于容器之间是隔离的,可以保证 MySQL 不会与其他服务产生干扰。此外,通过容器还能在单机上部署多个 MySQL 实例,提高资源利用率

至于性能问题,支持者认为在正确使用数据卷的情况下,MySQL 容器的性能损失微乎其微 。毕竟容器只是一层轻量级的封装,并不会对 I/O、网络等产生实质影响。

在 Kubernetes 中部署有状态服务,通常需要用到 StatefulSet 和 PersistentVolumeClaim(PVC) 。StatefulSet 用于管理有状态的应用,它为每个 Pod 提供一个唯一且固定的标识符。PVC 则用于申请持久化存储。下面是一个简单的 StatefulSet 示例,用于部署一个单节点的 MySQL:


        
          
apiVersion: apps/v1  
kind: StatefulSet  
metadata:  
  name: mysql  
spec:  
  serviceName: mysql  
  replicas: 1  
  selector:  
    matchLabels:  
      app: mysql  
  template:  
    metadata:  
      labels:  
        app: mysql  
    spec:  
      containers:  
        - name: mysql  
          image: mysql:5.7  
          env:  
            - name: MYSQL\_ROOT\_PASSWORD  
              value: my-secret-pw  
          volumeMounts:  
            - name: data  
              mountPath: /var/lib/mysql  
  volumeClaimTemplates:  
    - metadata:  
        name: data  
      spec:  
        accessModes: ["ReadWriteOnce"]  
        resources:  
          requests:  
            storage: 10Gi  

      

在这个例子中,StatefulSet 会自动为 MySQL 的 Pod 创建一个专属的 PVC,并将其挂载到容器的 /var/lib/mysql 目录。这样,即使 Pod 重建,它的数据也不会丢失。

当然,这只是一个最简单的示例。在实际使用中,我们可能还需要配置 MySQL 的主从复制、读写分离等,这就需要更复杂的 StatefulSet 和 Service 配置了。

求同存异,因地制宜

对于我这个又做开发又做 DevOps 的过来人觉得,MySQL 是否适合容器化,还是要具体问题具体分析。正如 Stackoverflow 上一位答主所说,

技术只是达成目标的工具,适合自己的才是最好的

对于开发和测试环境,或者对性能和稳定性要求不高的场景,Docker 化的 MySQL 确实能带来不少便利 。开发者可以快速搭建数据库,方便地进行各种实验和测试。

对于生产环境尤其是核心系统的数据库,稳定性和数据安全性无疑是第一位的 ,这时谨慎一些,采用成熟的方案或许更有保障。

同时也要认识到,容器技术正在飞速发展,很多以前难以想象的场景,现在都已逐渐成为可能 。比如有了 Kubernetes、Operator 这样的云原生技术,有状态服务在容器中的管理已经比以前简单很多。未来会怎样,现在下定论还为时尚早。

在 Docker 和 Kubernetes 中运行有状态服务,关键是要充分利用数据卷和 PVC,确保数据的持久性和可恢复性 。同时,也要根据实际需求,合理配置服务的高可用和负载均衡。

或许,比较理想的方式是在掌握传统运维的基础上,多了解和学习云原生的新技术,根据自己的实际情况分析利弊,然后再决定是否要上容器的"车"。

与其教条地说"必须用"或"绝不用",不如开放一些,拥抱变化

关注公众号: 程序员安仔 ,回复: "aigc大礼包 "

免费获取详尽 AI 入门资料

注意,不要乱回复

(一定要回复 **"aigc大礼包 "

)** 否则啥得不到

picture.image

安仔唯一官方公众号

点击下方 小卡片 回复: "aigc大礼包 "

0
0
0
0
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论