DockOne微信分享(一三五):求取一份极致的简单:海量应用容器化改造之路


【编者的话】公司内部近千个应用,从需求、开发、测试、发布及后期运维都是各自为营,没有一个统一的平台来标准化应用的整个流程,由此,设计一个这样的标准化平台就极其迫切,同时为了享受当前容器化技术带来的福利,我们决定完全基于容器技术来进行全面的应用容器化改造,以下就是我们团队在平台研发及应用容器化改造过程的一些经历和思考向大家分享一下,思虑不周之处,望大家斧正。

【3 天烧脑式基于Docker的CI/CD实战训练营 | 北京站】本次培训围绕基于Docker的CI/CD实战展开,具体内容包括:持续集成与持续交付(CI/CD)概览;持续集成系统介绍;客户端与服务端的 CI/CD 实践;开发流程中引入 CI、CD;Gitlab 和 CI、CD 工具;Gitlab CI、Drone 的使用以及实践经验分享等。

平台架构

二._平台架构_.png

  1. Git Repository:管理应用源码;
  2. Maven Repository:管理应用依赖的外部框架包及内部二方包;
  3. Docker Registry:管理各业务镜像依赖的基础镜像及业务镜像;
  4. Config Center:基于ZK做的实现,管理应用本身的配置文件、Leader控制、分布式锁等;
  5. Rabbit MQ:用于解耦各应用之间的通信;
  6. DB:用于存储应用的一些管理数据和配置数据等;
  7. Kubernetes Cluster:供业务系统运行的一个统一的环境,所有环境的应用全部容器化;
  8. Publish Service:用于管理公司应用,包括用户权限的管理、应用元数据的管理、应用Kubernetes配置元数据的管理、应用的发布、自动扩缩容、手工扩缩容、手工回滚等;
  9. Build Service:用于业务镜像的构建及推送:收到Publish Service发送的构建消息后,从Git Repository拉取应用源码,经过编译、打包、部署、镜像构建及推送到Docker Registry。


构建服务

构建服务依赖的环境主要包括JDK、Git、Maven、Docker,主要功能包括应用源码检出、编译、打包、部署及Dockerfile生成、镜像构建、推送几个阶段,整个过程我们编写了一个sh脚本,由这个脚本来完成整个过程。
  1. 源码检出:接收到发布发送的构建消息时,由JDK中的Process对象来启动这个sh脚本文件,进行应用源码检出,检出来过程有任何异常,发送失败消息给发布服务;
  2. 编译:调用Maven的mvn compile命令进行编译,编译过程中有任务异常,发送失败消息给发布服务;
  3. 打包:调用Maven的mvn package命令进行打包,打包过程中有任务异常,发送失败消息给发布服务;
  4. 调用Maven的mvn deploy命令将打好的包部署到内部Maven仓库,部署过程中有任务异常,发送失败消息给发布服务;如果是二方库应用,流程到些就完成了,如果是非二方库应用则继续5、6、7三步;
  5. Dockerfile生成:Dockerfile每次都是动态生成的,Dockerfile的内部结构基本上比较确定,包括FROM基础镜像、ADD第3步打好的包、EXPOSE端口、ENTRYPOINT java –jar、CMD一些参数;
  6. 镜像构建:调用”docker build –t 内部Docker仓库/产品线名/应用名:标签 .”进行镜像构建,构建过程中有任务异常,发送失败消息给发布服务;
  7. 镜像推送:首先登录内部Docker仓库,登录成功后调用”docker push 内部Docker仓库/产品线名/应用名:标签”进行镜像推送。


发布服务

发布服务本身比较大一些,包括用户权限管理、需求管理、产品线管理、应用管理、在线文档管理、缺陷管理、变更管理、Kubernetes应用配置管理、发布管理等,在这里主要介绍一下应用管理、Kubernetes应用配置管理、应用发布管理三个模块:
  1. 应用管理:应用管理主要维护了应用本身的一些元数据,还一些辅助配置,像编译应用时使用的JDK版本、生成Dockerfile时使用的基本镜像等;

  2. Kubernetes应用配置管理:这部分的配置是和应用直接挂钩的,最终存储下来的是Kubernetes的REST接口能识别的一个对象JSON串。这部分主要维护了Kubernetes的Deployment、Service、HorizontalPodAutoscaler、Scale四个对象,对Service、HorizontalPodAutoscaler两个对象都添加了启用、停用开关,Service对象默认打开,而HPA对象默认关闭,我们使用Scale对象主要用于对某些应用进行手工扩缩容,来解决一些特殊场景的需求;图示如下:
    K8s应用配置管理-1.png

    K8s应用配置管理-2.png

    K8s应用配置管理-3.png

  3. 应用发布管理:每次发布是针对某个应用的代码分支进行发布,首先由构建服务将对应分支的镜像构建并推送完成,对应应用还要提前做Kubernetes相关的配置,然后调用我们进行一次薄封装后的Kubernetes的REST接口:pulish(k8s-master:port,Kubernetes应用配置生成的JSON串)进行应用的发布,发布之后还要进行发布状态的监控,要让每个应用的应用负责人清楚看到这次发布的结果。


改造过程中的问题

在这次改造过程遇到了很多千奇百怪的问题,在这里介绍几个印象比较深的问题及解决办法:
  1. 在每次重新发布,更新Kubernetes的Service对象时,报无法更新的错误,查官方文档获知更新Service对象时,还要通过GET请求获取resourceVersion、clusterIP两个值put进来才可以;
  2. 在使用Logstash将采集的日志输出到HDFS时,开始使用WebHDFS插件,配置是完全按照官方文档的配置,可是一直报一个Error错误,最后我们改用HttpFS插件解决的;
  3. 最初构建服务使用JDK7进行编译打包的,后来发现别的很多应用是在JDK 8下开发的,所以这就要求构建服务要能提供JDK多版本编译环境,我们当时是用Maven的toolchains插件解决的;
  4. 在Kubernetes环境,有些时候会出现某些pod删除不掉,到现在为止没想到太好的办法,我们暂时是靠到杀掉Node上的进程解决的。


Q&A

Q:构建镜像用的什么技术?

A:我们使用的是Docker自身提供的docker build命令进行镜像构建的。
Q:Config Center能否详细说一下?

A:我们使用Config Center主要来管理应用自身的配置文件,应该在启动前首先拽下自己的配置文件;还有就是对应用进行Leader控制,因为应用可能会跑多个实例的,像定时任务类的功能,在同一个时间点只能其中一个实例生效。
Q: 如何动态生成Dockerfile,如何在Docker镜像里配置JVM参数?

A:Dockerfile文件:我们是使用sh脚本生成的,将内容>>Dockerfile中;JVM参数是在应用中配置的,发送构建消息时,作为消息内容送过去。
Q: Deployment 滚动更新如何设置间隔时间呢?

A:Deployment对象有个minReadySeconds属性就是来解决这个问题的。
Q: Logstash的日志为啥是发送到HDFS而不是ES?有什么考虑么?

A:我们将Logstash采集到的日志输出到两个地方:ES、HDFS,输出到ES直接在Kibana上搜索到,而输出到HDFS便于在Kibana上面将日志文件进行下载下来。
Q:Docker Registry的在garbage collect时怎么保证高可用?

A:我们使用的由VMware公司中国团队开源的Harbor,无论安全、效率、可用性方面都提供了很强的保障了。
Q:kubectl set image的时候 能不能限制 每变更一个容器,再保证http访问正常的前提下,再变更下一个容器 。毕竟有的服务启动时间超过30秒,对外的服务忍受不了信么久的不可访问时间的?

A:这个可以直接借助Kubernetes的RollingUpdate功能就可以做了。
Q:Dockerfile动态生成怎么做的,用的是什么生成工具?

A:使用sh脚本生成,将内容>>Dockerfile中去可以了。
Q:统一的流程给实际的生产带来了怎样的好处能否介绍一下?

A:流程统一后,像源码管理、日志采集及搜索、应用发布,应用滚动升级等就不需要应用本身来管了,这样各业务系统本身就会更加专注于自身的业务功能了。
以上内容根据2017年08月01日晚微信群分享内容整理。分享人杨新伦,上海钢联产品研发中心高级工程师,现主要负责公司内部应用的容器化改造等相关的后台研发工作。 DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiesa,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。

0 个评论

要回复文章请先登录注册