Docker集群模式的落地方案尝试

docker 集群模式的落地方案尝试

最近一直在探索 docker 的集群模式在公司实际环境中的落地方案. 公司现有docker 的使用方式为单机, 且在日志收集, 网络模式, 存储引擎等方面的配置和用法比较分散, 尤其是现有使用的 devicemapper 存储引擎模式, 官方明确表示不适合生产环境中使用.

docker 的集群方案目前比较火热的有三种, 一种是 docker 在1.12版本中集成的 swarmkit, 一种是 Google 开源的 kubernetes, 还有一种是 Apache 开源的 mesos. 虽然 kubernetes 是被认为是轻量级的 PaaS 平台, 但如果考虑在公司落地, kubernetes 对我们来说仍然是”重量级”的产品, 考虑到公司现有基于的架构(IaaS), 最终还是选择了 docker 自家的 swarmkit 集群平台进行 PaaS 平台的初步尝试.

swarmkit 的一大好处是安装好 docker 引擎后, 不需要安装任何其他组件, 只需要开启 docker 的 swarm 模式即可. dev 环境现有的 swarmkit 平台由 3 台入口服务器和6台后端应用服务器组成, 其中入口的3台服务器也可以当做应用服务器来部署 docker 应用, 加起来整个平台有9个节点可以分布式的部署 docker 应用.

平台搭建好后, 我首先拿 Apache 服务做测试, 使用 Apache 镜像运行了一个静态页面, 指定后端启动6个容器提供服务, 服务启动后, 可以通过3台入口服务器的任何一个入口进行访问, 请求会被打到后端的 Apache 容器中. 在这个模式下, 我们老雪进行压力测试, 最终在并发1000, 循环100次的量级下, 错误率达到将近50%的情况下结束测试, 寻找瓶颈. 经过排查, 瓶颈不是平台的吞吐量到达上线, 也不是容器处理的请求到达上限, 而是宿主机的日志收集导致宿主机的 IO wait 飙升, 在严苛的测试要求下(500ms的响应时间), 导致大量的请求由于宿主机的 IO wait 而导致响应超时. 我们当初已这样的模式进行测试的目的其实是测试平台的吞吐量, 以及平台网络的稳定性, 没想到这样的量级下,这两点都没有任何问题, 反而是 IO 拖了后腿.

在北京三区生产环境中, 每台 Nginx 网络的瞬时最大吞吐量为30MB左右, 在 swarmkit 平台测试的一个入口的网络瞬时吞吐量也达到了将近20MB, 由于大量的 IO wait, 导致没有测试到入口的实际最大承载量. 但是按照现有三个入口的架构来看, 每个入口20MB 的流量, 加起来也可以承受60MB的吞吐能力, 相当于将近500Mb 带宽的水平, 而三区生产环境的公网 IP 也只有300Mb 的带宽, 在平台稳定性, 以及虚拟网络稳定性及吞吐量上来看, swarmkit 就已经完全符合我们生产环境入口量级的吞吐能力.

接下来的测试中, 上线了用户体系的一个服务, 后端仍旧为6个节点提供服务, 在压力测试中, 基本上所有的错误都来自数据库连接的错误

接下来我们打算上线用户体系第二个服务的时候遇到了问题, 该服务需要向 Zookeeper 注册信息, 而在集群中, 整个集群是一个大型的 VLAN 网络, 每个容器拥有三个 IP, 一个是 docker 桥接给每个容器的 IP, 一个是 VLAN 网络的 IP, 一个是前端用于负载均衡用的 VIP(虚 IP), 当容器内的服务向Zookeeper 注册时, 默认拿的是自己主机上 hosts 中 localhost 对应的 IP 地址, 而且最重要的是, 不管这三个拿哪个 IP 地址, 都只能从内往外连通, 外部主机不可能主动连接进来. 这也就导致了容器内的服务向 Zookeeper 注册时的 IP, 在其他消费者拿到此 IP 的时候, 发现这个 IP 根本就连不上.

对于上面的问题, 我们想了很多解决办法, 我们想过通过路由的方式, 让集群外部主机连通集群内部的网络, 但是这样做的后果是又多增加了一个不稳定因素, 集群外所有需要连进来的流量都会通过我们自己的一台网关服务器做转发, 这相当于我们自己维护了一个虚拟交换机, 增加了两个环境之间交互的稳定性的风险.

还有一个办法是把 docker 集群模式关闭, 当做单机来使用, 但是又发现一个问题, 我们测试的这个服务, 在dubbo 向 Zookeeper 注册时, 默认监听了自己的20880端口(记不清了, 好像是这个) 不管是使用网桥模式映射出去, 还是使用
host 模式让他监听宿主机的端口, 问题都是一个: 这一台 docker 宿主机上, 只能启动一个监听20880的服务, 也就是说, 在发布应用容器的时候, 我们需要人为的去判断, 或是用其他方式去判断目标 docker 主机上是否已经存在与自己端口冲突的服务, 这无疑也是加大了 docker 使用难度, 而且这种模式明显是把 docker 当做虚拟机来使用, 仍然是 IaaS 平台的老思路, 违背了 docker 倡导的使用规则.

由于Zookeeper 的原因, 到目前为止, 对 docker 集群平台(PaaS) 平台的探索将放慢脚步, 也希望在以后的一段时间能找到行之有效的完美解决方案, 如果大家有什么想法, 可以沟通一下, 让我开阔一下眼界.