业务docker化改造

在业务逐渐变大后,系统维护工作需要投入越来越多的精力,于是开始了docker化改造。期间也遇到了一些实际问题,总结了一些经验,希望对已在生产环境中使用docker或者正在准备进行服务docker化改造的童鞋有所帮助!

为什么docker化

mahua

  • 开发过程中一个常见的问题是环境一致性问题。由于开发环境、测试环境、生产环境不一致,导致有些 bug 并未在开发过程中被发现。而 Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 「这段代码在我机器上没问题啊」 这类问题。
  • 对开发和运维(DevOps)人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行。使用docker的镜像,完成一次build,轻松部署。
  • 对于系统的运维、扩展、迁移,docker有着天然的优势。

为什么没有选择k8s

  • k8s对于我们现有的业务系统来说,还是太大太重了。且k8s的学习成本也是相对较大的,当然后期我们应该也会投入研究。总之一句话,就现阶段来说,k8s还不太适合我们。

Docker相关组件介绍

1. image

  • 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。
  • 镜像最大的特点就是它是分层存储的,这对于你写出好的Dockerfile有很大的帮助。

2. container

  • 容器是镜像运行时的实体,它的实质是进程,但与直接在宿主机执行的进程不同,容器进程运行于属于自己的独立的命名空间。
  • 容器可以被创建、启动、停止、删除、暂停等。

3. compose

  • Docker三剑客之一
  • 负责实现对Docker容器集群的快速编排。它允许用户通过一个单独的docker-compose.yml模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)。

4. machine

  • Docker三剑客之一
  • 可以通过machine连接操作远程docker。

5. swarm mode

  • Docker三剑客之一
  • Swarm是使用SwarmKit构建的Docker引擎内置(原生)的集群管理和编排工具。

6. traefik

  • traefik是一个HTTP反向代理、负载均衡工具。
  • traefik本身也可以运行在docker swarm中,可以作为docker服务的外部流量入口。

7. portainer

  • Portainer是Docker的图形化管理工具。
  • 提供状态显示面板、应用模板快速部署、容器镜像网络数据卷的基本操作(包括上传下载镜像,创建容器等操作)、事件日志显示、容器控制台操作、Swarm集群和服务等集中管理和操作、登录用户管理和控制等功能。

业务Docker化改造图

mahua

说明

  • 首先要说明的是,我们只是进行了部分核心业务的docker化改造。
  • Docker Manager节点运行了traefik服务,其作为反向代理,接收外网及内网的流量,然后再反向代理到docker swarm内部服务。
  • Docker Manager节点还运行了portainer服务,作为图形化工具,可以让我们轻松的通过web端来控制docker swarm中的服务,例如重启service,新增stack等。当然,这里的portainer服务也是通过traefik反向代理过来的。
  • Docker Worker节点上运行着我们的业务服务,他们都是没有开放流量入口的,唯一的方式就是通过traefik反向代理过来。
  • Docker Private Registry是我们的私有镜像仓库,是使用了开源的工具Harbor构建的,负责整个swarm集群私有镜像的push和pull。
  • 在我们自己的机器上,远程控制swarm集群节点,可以使用docker-machine,非常的方便(包括新增swarm节点,查看集群状态等)。
  • 在docker之外,我们有一个consul服务发现的集群(都在同一内网)。docker外部的内网服务可以通过consul的dns解析,内网请求到docker内部的服务。当然,docker内部的容器服务也可以通过指定consul的dns解析来内网访问外部的服务。
  • 外网域名解析到traefik几台机器上,使用AWS的route 53的健康检查服务,来尽量保证服务的高可用。而内网域名解析是使用consul,其自带服务发现功能(需要在traefik服务的机器节点上安装consul client服务),同样也能保证服务的高可用。

遇到的问题及建议

  • linode服务器问题:我们的docker swarm集群是在linode服务器上部署的(centos7),由于要使用到overlay网络,服务器的内核必须选择GRUB2。具体可以参考issue:https://github.com/docker/machine/issues/2753
  • Dockerfile写法问题:python等代码COPY操作,可以放在最后,因为在后续开发过程中,类似”RUN apk update && apk –update add –no-cache lapack-dev”这种安装系统依赖的内容大部分情况下不会再变,变得只有代码,这样的话,只有第一次构建镜像会运行”RUN”的操作(有点慢),后续再次构建镜像时,由于前面的层已经构建了,不需要再次构建,只会把代码加入到镜像中,构建镜像会很快。
  • docker swarm集群在多次发布新的镜像后,会产生一些虚悬镜像,可以在docker宿主机上设置一个定时任务,每天清除这些虚悬镜像,命令为:docker image prune -f
  • 我们的基础镜像大部分选择了alpine,其体积非常之小。
  • docker-machine如何在开发成员之间共享已连接的远程机器,我们选择了npm的machine-share工具,其方便的给出了导入导出machine的命令。具体可以参考issue:https://github.com/docker/machine/issues/23
  • 关于使用traefik之后,如何在反向代理的service中取得用户真实的ip,需要配置traefik使用”mode: host”的方式。具体可以参考stackoverflow:https://stackoverflow.com/questions/44639958/nginx-behind-traefik-docker-swarm-mode-real-ip
  • 在portainer中,首先要配置的就是registries(我们的私有仓库),这样的话,我们才能保证正常拉取到镜像。
坚持原创技术分享,您的支持将鼓励我继续创作!