基于docker容器服务持续交付实践

简介

docker容器技术在17年可谓是炽手可热,docker不仅仅改变了传统软件服务的交付流程,更是为云计算和微服务大规模集群管理部署,提供了强有力的技术支撑。当今各大公司企业也是把容器化技术作为不可或缺的技术战略,于17年初我们也开始步入docker技术的生态圈,尝试进行对当前服务做容器化的改造,而持续交付作为项目开发流程中较为核心的一步,也是落地实践最早一步。

我们的问题

17年初,基于微服务的架构,仅我们团队内的服务单元已经过百,特别是经历网站的促销活动,机器扩容,资源分配等问题真的是苦不堪言,除此之外更是有一些困绕已久的问题等待解决:

1. 发布系统不统一

因为涉及到不同语言的系统开发,各个系统的构建流程都有不同,涉及到node,C#,Java还有python,发布到不同服务器上,需要通过对应的发布系统,各个系统之间记录关联很难核对,不便于追踪。

2. 多环境的管理

服务器资源新增,修改部署的配置比较多,包括打通与发布系统的环境相关联,基础服务的安装配,包括node,jdk和tomcat服务器等。

3. 环境的一致性

由于各种历史问题,导致项目发布的测试环境、集成环境和产线环境配置不一致,给系统问题的排查定位带来一定的难度,项目部署目录,服务启动用户,甚至包括jdk版本的问题,这些问题同时加重了运维工作的复杂度。

4. 资源的分配

主要是软资源的计算分配,因为服务单元非常多,每个服务单元的内存,端口分配问题会随着服务数量的增加,越来越难以计算和管理,CMDB统计不够实时,造成最终的结果就是资源利用率比较低。

微服务架构

选择docker一个重要的原因,就不得不提到微服务了,微服务相比传统的服务采用单体的架构方式,部署方式和开发模式上有很大优势。单体架构的方式,服务系统过于庞大臃肿,项目发布部署风险较高,迭代开发周期较长,而微服务按照业务维度进行功能模块拆分,使其各自成为一个可独立提供服务,可独立部署运行的单元模块,通过指定的网络协议模块之间进行通信,并且在开发模式上,也是相互独立,大幅提高了项目开发上线的周期,做到快速迭代。但是随着则业务复杂性的提升,微服务的集群数量也会急速上升,带来的问题就是面对如此多服务如何高效的管理,部署,监控等一些问题,而docker处理这些却有着得天独厚的优势。

我们微服务架构核心采用的框架是基于Spring Boot和Dubbo,并且是支持双协议的通信,http/https和Dubbo RPC的调用方式,Dubbo的主要是内部模块调用依赖,而http的接口主要是提供给异构系统的接入。整体的项目架构图如下。

容器化之路

如今再次说到docker的时候,我们往往已经不仅仅谈论的只是docker本身,因为docker engine 只是改变了应用运行时的状态管理,更多的我们还关注到服务的调度,编排,网络管理,存储,监控,配置管理等等一系列的服务,docker 俨然已经是一个庞大的技术生态圈,这个生态圈里面,大家比较关心的其中一个核心服务的就是容器编排了,因为容器编排彻底的改变了传统软件服务交付流程,而容器编排则又以k8s 和mesos 为主的居多,更确切的说,k8s已经不仅仅是作为一个编排工具了,此处暂时不做讨论,两者的选型介绍可后续关注,此次也不做过多讨论。

我们选择的容器编排是以mesos为主的,简单介绍一个以mesos为核心的各个组件以及服务依赖。

zk 注册中心,这个注册并不是服务的注册,而是用来管理mesos集群状态数据的中心服务,通过zk来构建一套高可用的mesos集群。

mesos-slave 部署在每个node(主机)节点的服务,用来采集服务器数据信息,执行指令。

mesos-master 管理服务器资源信息,分派mesos-slave资源调度指令。

marathon 资源计算服务,根据应用部署需要的资源信息,提供资源分配,并且提供了一套UI,通过UI可方便的进行管理操作。

各个组件服务结构如下图:

镜像

我们的服务,主要的包括Java和node两种类型的服务,所以基础镜像也根据不同的版本号,提供了多种类型。镜像基础使用的是alpine的版本,镜像文件非常小,jdk使用的openjdk,加上启动服务的脚本以及其他配置,配置内容,镜像最终大小100M左右,加上项目打包好以后的镜像,在150M上下,当然为了一些项目的特殊需求,也提供了oracle jdk的镜像版本,但是至今未使用过。

构建

我们的技术框架最初是基于Spring Boot,通过Spring Boot提供的打包插件,可以方便的把项目构建成一个运行时需要的jar包,启动jar包和指定的运行时的一些参数信息,是通过gitlab统一管理的一些shell文件,通过jenkins构建过程,动态的把项目的jar包和启动脚本,封装在一起,然后发布到应用服务器,解压启动。但是如果采用docker部署,这种方式就不可行了,因为docker部署面向的是镜像。

docker镜像的构建方式有多种,最合理的一种莫过于Dockerfile了,但此时我们产线运行的项目已经非常多了,一个个往里面添加Dockerfile已经不现实,所以就提供了一个Dockerfile模板,里面标注了基础镜像信息,在项目构建的流程中,通过获取一些项目参数,动态生成一个Dockerfile文件,最后通过docker build生成镜像文件,然后提交到镜像库,这个过程对于开发人员完全无感知,就这样悄无声息的完成了项目格式的转化,并且对于不同类型的项目,提供了不同类型的Dockerfile模板,甚至可以通过项目做定制化。

上面说Dockerfile是动态生成并且对开发人员无感知的,而这个构建过程,也是通过执行容器实现的,通过容器挂载的方式,把构建的结果显示在宿主机上,这整个的过程都做成了docker镜像,并且使用Dockerfile管理这些镜像,通过不同的Dockerfile轻而易举的自定义各个类型项目的构建过程,比如node项目的构建和Java的构建不同,就定义两个Dockerfile就可以了,统一在gitlab上管理,维护成本变得非常低。

发布

项目构建完成,容器的的编排部署,主要是通过marathon操作。marathon本身提供了一些对外开放的api接口,这个开放接口也是我们做自动化基石。项目构建完毕,流程并没有结束。marathon管理的服务编排,主要是配置文件,定义应用,内存,端口,以及健康监测都是在配置文件里面管理的,所以基于此,我按照格式定义了一个项目,专门来管理这些项目的配置,并且把这些配置提交到gitlab上进行管理,项目结构如下:

每一个环境对应的目录下,都是一个marathon的配置文件模板,之所以是模板,因为每次构建生成不同的镜像tag是系统自动生成的,会动态替换参数,并且调用marathon的api接口进行服务更新,服务的更新策略也都配置在marathon配置文件中的,整个的构建和发布流程,分为各自独立的两模块,通过一套shell完成,也可以独立使用,但还是为了考虑操作的简单性,接入了jenkins,并且通过jenkins增强了权限控制,并且对操作记录可追踪。构建流程结构如下图:

运行

一开始我们采用docker,只是拿了部分服务测试,并非一蹴而就,全部直接推广使用。项目测试运行刚上线,开始遇到第一个问题。写到这里,简单普及一下docker的网络模式,docker的网络模式默认的四种方式host,bridge,none和自定义的网络模式,host的方式就是容器和主机共享网络空间,容器和主机共用网络端口,这种方式的弊端不言而喻,就是部署应用的时候要关注服务器的端口分配。bridge的方式是采用的独立的网络空间,通过虚拟网桥的方式利用主机的网卡进行通信,容器的网络空间是独立的,容器内部服务端口和主机映射端口是随机的。none的形式就是关闭网络模式,这种适合于计算的服务类型。而自定义的网络模式,主要是来解决跨主机网络通信的问题,每个容器网络空间也是各自独立的,而我们的服务主要采用的就是种方式,问题也恰恰出在这里。

由于采用的是部分服务做docker化,老的服务可能需要访问新的服务,但是这个时候,老服务在利用Dubbo调用新服务的通信的时候,发现对方注册是IP地址无法访问,原因就是docker容器内的Dubbo提供的服务,注册上去的其实是个虚拟IP地址,和原有老的服务根本就不同一个网络内。所以网络单向是不通的,网络调用结构如下图:

既然是网络的问题,那么针对该问题的解决方案也列了几个:

方案一:所有服务进行docker容器化部署,这样的话所有服务就处于同一个虚拟网络段内,但是这个迁移的成本和风险非常大。

方案二:基于物理层面网络做修改配置,但是这种维护的成本较大,可扩展性不好。

方案三:更改容器内服务运行的网络,采用host的方式配置,这种方式其实并没有充分利用容器化带来的便利之处,但是确实最简单解决这个问题的方法,所以最终考虑,选择这个方案解决,而后期的优化方案,去Dubbo化。

其实针对容器网络的模块,这里也只是冰山一角,未来面临更复杂的产线环境,将会遇到更多网络的配置问题。

总结

容器化之路是,这里仅仅只是起点,本次只是简单的介绍了最开始容器化项目构建交付的流程,实际上在实践中遇到的问题不止如此,希望对大家有所帮助,思路上也希望能有共鸣,后续对相关细节问题还会再次介绍。

1

nginx

本号专注于linux+nginx+mysql+php 知识交流和分享,有理论知识,更有实际项目的经历。能保证的是本号所有分享都或多或少可以助你在技术的道路上向高处奔走。

2

Java北京

从算法基础到常用框架的知识体系,从初级程序员到高级架构师的成长之路,从创业小团队到Google、BAT的工作机会,始于JAVA而又不止于JAVA。JAVAer在北京,我们一起成长。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180509G0N7RU00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券