容器化已经成为一种趋势,它能够解决不少运维中的痛点,好比效率、成本、稳定性等问题,而接入容器的过程当中每每也会碰到不少问题和不便。在有赞最开始作容器化是为了快速交付开发测试环境,在容器化的过程当中,咱们碰到过容器技术、运维体系适配、用户使用习惯改变等各类问题,本文主要介绍有赞容器化过程当中碰到的问题以及采起的方案。php
在有赞同时会有不少个项目、平常在并行开发,环境的抢占问题严重影响了开发、测试和上线的效率,咱们须要给每一个项目提供一套开发联调(daily)、测试环境(qa),而且随着项目、平常的生命周期项目环境也会随着建立和销毁,咱们最先的容器化需求就是怎么解决环境快速交付的问题。前端
[有赞环境]java
上面是有赞大体的研发流程,在标准流程中咱们有四套稳定环境,分别是 Daily 环境、Qa 环境、预发环境和测试环境。咱们的开发、测试、联调工做通常并不会直接在稳定环境中进行,而是会拉一套独立的项目环境出来,随着代码通过开发、测试、预发验收最终发布到生产环境后再同步回 Daily/Qa 的稳定环境中。node
[项目环境]python
咱们提供了一套以最小的资源投入知足最大项目并行度的环境交付方案,在 Daily/Qa 稳定环境的基础上,隔离出N个项目环境,在项目环境里只须要建立该项目所涉及应用的计算资源,其它缺失的服务调用由稳定环境提供,在项目环境里,咱们大量使用了容器技术。git
[持续交付]github
后面咱们又在项目环境快速交付的解决方案的基础上实现了持续交付流水线,目前已经有超过 600 套项目/持续交付环境,加上 Daily/Qa 稳定环境,涉及计算实例四五千个,这些计算实例不管是 cpu 仍是内存使用率都是很是低的,容器化能够很是好的解决环境交付的效率问题,以及提升资源使用率来节省成本的投入。docker
咱们的容器化方案基于 kubernetes(1.7.10)和 docker(1.12.6)、docker(1.13.1),下面介绍一下咱们在各个方面遇到的问题以及解决方案。后端
有赞后端主要是 java 应用,采用定制的 dubbo 服务化方案,过程当中没法作到整个单元全量容器化,和原有集群在网络路由上互通也就成了刚需,因为咱们没法解决公有云上 overlay 网络和公有云网络的互通问题,因此一开始咱们放弃了 overlay 网络方案,采用了托管网络下的 macvlan 方案,这样既解决了网络互通的问题也不存在网络性能问题,可是也就享受不到公有云弹性资源的优点了。随着有赞多云架构的发展以及愈来愈多的云厂商支持容器 overlay 网络和 vpc 网络打通,弹性资源的问题才获得了缓解。api
容器的隔离主要利用内核的 namespace 和 cgroup 技术,在进程、cpu、内存、IO等资源隔离限制上有比较好的表现,但其余方面和虚拟机相比存在着不少的不足,咱们在使用过程当中碰到最多的问题是容器里看到的 cpu 数和内存大小不许确,由于/proc文件系统没法隔离,致使容器里的进程"看到"的是物理机的 cpu 数以及内存大小。
咱们的 java 应用会根据服务器的内存大小来决定 jvm 参数应该怎么配置,咱们是采用 lxcfs 方案来规避的。
由于咱们有超卖的需求以及 kubernetes 默认也是采用 cpu share 来作 cpu 限制,虽然咱们使用了 lxcfs,CPU 数仍是不许的。jvm 以及不少 Java sdk 都会根据系统的 CPU 数来决定建立多少线程,致使 java 应用在线程数和内存使用上都比虚拟机多的多,严重影响运行,其余类型的应用也有相似的问题。 咱们会根据容器的规格内置一个环境变量 NUM_CPUS,而后好比 nodejs 应用就会按照这个变量来建立它的 worker 进程数。在解决 java 类应用的问题时,咱们索性经过 LD_PRELOAD 将 JVM_ActiveProcessorCount 函数覆盖掉,让它直接返回 NUM_CPUS 的值[1]。
在容器化以前,有赞的应用已经所有接入到发布系统,在发布系统里已经标准化了应用的打包、发布流程,因此在应用接入方面成本仍是比较小的,业务方无需提供 Dockerfile。
咱们涉及到灰度发布的流量主要包含三部分:
通过以前项目/持续交付的上线和迭代,大部分应用自己已经具有了容器化的条件。不过对于上线来讲,须要整个运维体系来适配容器化,好比监控、发布、日志等等。目前咱们生产环境容器化准备基本完成,生产网已经上了部分前端 nodejs 应用,其余应用也在陆续推进中,但愿之后能够分享更多生产环境中的容器化经验。
以上是有赞在容器化上的应用,以及在容器化过程当中碰到的一些问题和解决方案,咱们生产环境的容器化还处于开始阶段,后面还会碰到各类个样的问题,但愿可以和你们互相学习,后面可以有更多的经验分享给你们。