有赞容器化实践

标签: 安全 运维 devops 容器 工具 | 发表时间:2018-09-28 18:00 | 作者:有赞技术
出处:https://segmentfault.com/blogs

前言

容器化已经成为一种趋势,它可以解决很多运维中的痛点,比如效率、成本、稳定性等问题,而接入容器的过程中往往也会碰到很多问题和不便。在有赞最开始做容器化是为了快速交付开发测试环境,在容器化的过程中,我们碰到过容器技术、运维体系适配、用户使用习惯改变等各种问题,本文主要介绍有赞容器化过程中碰到的问题以及采取的方案。

有赞容器化的初衷

在有赞同时会有很多个项目、日常在并行开发,环境的抢占问题严重影响了开发、测试和上线的效率,我们需要给每个项目提供一套开发联调(daily)、测试环境(qa),并且随着项目、日常的生命周期项目环境也会随着创建和销毁,我们最早的容器化需求就是怎么解决环境快速交付的问题。

[有赞环境]
图片描述
上面是有赞大致的研发流程,在标准流程中我们有四套稳定环境,分别是 Daily 环境、Qa 环境、预发环境和测试环境。我们的开发、测试、联调工作一般并不会直接在稳定环境中进行,而是会拉一套独立的项目环境出来,随着代码经过开发、测试、预发验收最终发布到生产环境后再同步回 Daily/Qa 的稳定环境中。

[项目环境]
图片描述

我们提供了一套以最小的资源投入满足最大项目并行度的环境交付方案,在 Daily/Qa 稳定环境的基础上,隔离出N个项目环境,在项目环境里只需要创建该项目所涉及应用的计算资源,其它缺失的服务调用由稳定环境提供,在项目环境里,我们大量使用了容器技术。

[持续交付]
图片描述

后面我们又在项目环境快速交付的解决方案的基础上实现了持续交付流水线,目前已经有超过 600 套项目/持续交付环境,加上 Daily/Qa 稳定环境,涉及计算实例四五千个,这些计算实例无论是 cpu 还是内存使用率都是非常低的,容器化可以非常好的解决环境交付的效率问题,以及提高资源使用率来节省成本的投入。

有赞容器化方案

我们的容器化方案基于 kubernetes(1.7.10)和 docker(1.12.6)、docker(1.13.1),下面介绍一下我们在各个方面遇到的问题以及解决方案。

网络

有赞后端主要是 java 应用,采用定制的 dubbo 服务化方案,过程中无法做到整个单元全量容器化,和原有集群在网络路由上互通也就成了刚需,由于我们无法解决公有云上 overlay 网络和公有云网络的互通问题,所以一开始我们放弃了 overlay 网络方案,采用了托管网络下的 macvlan 方案,这样既解决了网络互通的问题也不存在网络性能问题,但是也就享受不到公有云弹性资源的优势了。随着有赞多云架构的发展以及越来越多的云厂商支持容器 overlay 网络和 vpc 网络打通,弹性资源的问题才得到了缓解。

隔离性

容器的隔离主要利用内核的 namespace 和 cgroup 技术,在进程、cpu、内存、IO等资源隔离限制上有比较好的表现,但其他方面和虚拟机相比存在着很多的不足,我们在使用过程中碰到最多的问题是容器里看到的 cpu 数和内存大小不准确,因为/proc文件系统无法隔离,导致容器里的进程"看到"的是物理机的 cpu 数以及内存大小。

内存问题

我们的 java 应用会根据服务器的内存大小来决定 jvm 参数应该怎么配置,我们是采用 lxcfs 方案来规避的。
图片描述

CPU 数的问题

因为我们有超卖的需求以及 kubernetes 默认也是采用 cpu share 来做 cpu 限制,虽然我们使用了 lxcfs,CPU 数还是不准的。jvm 以及很多 Java sdk 都会根据系统的 CPU 数来决定创建多少线程,导致 java 应用在线程数和内存使用上都比虚拟机多的多,严重影响运行,其他类型的应用也有类似的问题。
我们会根据容器的规格内置一个环境变量 NUM_CPUS,然后比如 nodejs 应用就会按照这个变量来创建它的 worker 进程数。在解决 java 类应用的问题时,我们索性通过 LD_PRELOAD 将 JVM_ActiveProcessorCount 函数覆盖掉,让它直接返回 NUM_CPUS 的值[1]。

应用接入

在容器化之前,有赞的应用已经全部接入到发布系统,在发布系统里已经标准化了应用的打包、发布流程,所以在应用接入方面成本还是比较小的,业务方无需提供 Dockerfile。

  1. nodejs, python,php-soa 等用 supervisord 托管的应用,只需要在 git 仓库里提供 app.yaml 文件定义运行需要的 runtime 和启动命令即可。 图片描述
  2. java 标准化启动的应用业务方无需改动
  3. java 非标准化的应用需要做标准化改造

镜像集成

图片描述
容器镜像我们分了三层,依次为 stack 层(os),runtime 层(语言环境),应用层(业务代码和一些辅助agent),应用以及辅助 agent 由 runit 来启动。由于我们的配置还没有完全分离,在应用层目前还是每个环境独立打包,镜像里除了业务代码之外,我们还会根据业务的语言类型放一些辅助的 agent。我们一开始也想将各种 agent 拆成多个镜像,然后每个 pod 运行多个容器,后来因为解决不了 pod 里容器的启动顺序(服务启动有依赖)问题,就把所有服务都扔到一个容器里去运行了。

图片描述
我们的容器镜像集成过程也是通过 kubernetes 来调度的(会调度到指定的打包节点上),在发布任务发起时,管控系统会在集群中创建一个打包的 pod,打包程序会根据应用类型等参数编译代码、安装依赖,并且生成 Dockerifile,然后在这个 pod 中使用 docker in docker 的方式来集成容器镜像并推送到仓库。
为了加速应用的打包速度,我们用 pvc 缓存了 python 的 virtualenv,nodejs 的 node_modules,java 的 maven 包等文件。另外就是 docker 早的版本里,Dockerfile ADD 指令是不支持指定文件属主和分组的,这样会带来一个问题就是需要指定文件属主时(我们的应用是以 app 账号运行的)需要多运行一次 RUN chown,这样镜像也就多了一层数据,所以我们打包节点的 docker 版本采用了官方比较新的 ce 版本,因为新版本支持 ADD --chown 特性。

负载均衡(ingress)

图片描述
有赞的应用内部调用有比较完善的服务化和 service mesh 方案,集群内的访问不用过多考虑,负载均衡只需要考虑用户和系统访问的 http 流量,在容器化之前我们已经自研了一套统一接入系统,所以在容器化负载均衡上我们并没有完整按照 ingress 的机制来实现 controller,ingress 的资源配置是配在统一接入里的,配置里面转发的 upstream 会和 kubernetes 里的 service 关联,我们只是做了一个 sync 程序 watch kube-api,感知 service 的变化来实时更新统一接入系统中 upstream 的服务器列表信息。

容器登录和调试

图片描述
在容器化接入过程中开发会反馈是控制台比较难用,虽然我们优化了多次,和 iterm2 等的体验还是有所不足,最终我们还是放开了项目/持续交付环境这种需要频繁登陆调试的 ssh 登陆权限。
另外一个比较严重的问题是,当一个应用启动后健康检查有问题会导致 pod 一直在重新调度,而在开发过程中开发肯定是希望看到失败现场的,我们提供了调试发布模式,让容器不做健康检查。

日志

图片描述
有赞有专门的日志系统,我们内部叫天网,大部分日志以及业务监控数据都是通过 sdk 直接打到天网里去了,所以容器的标准输出日志仅仅作为一种辅助排查问题的手段。我们容器的日志收集采用的是 fluentd,经过 fluentd 处理后按照天网约定的日志格式打到 kafka,最终由天网处理进入 es 做存储。

灰度发布

我们涉及到灰度发布的流量主要包含三部分:

  1. 用户端的 http 访问流量
  2. 应用之间的 http 调用
  3. 应用之间的 dubbo 调用

首先,我们在入口的统一接入上统一打上灰度需要用的各种维度的标签(比如用户、店铺等),然后需要对统一接入、http client 以及 dubbo client 做改造,目的是让这些标签能够在整个调用链上透传。我们在做容器灰度发布时,会发一个灰度的 deployment,然后在统一接入以及灰度配置中心配置灰度规则,整个链路上的调用方都会感知这些灰度规则来实现灰度发布。

标准环境容器化

标准环境的出发点

  1. 和项目环境类似,标准稳定环境中的 daily,qa,pre 以及 prod 中超过一半运行在低水位的服务器的资源非常浪费。
  2. 因为成本考虑 daily,qa,pre 里都是以单台虚拟机运行的,这样一旦需要发布稳定环境将会造成标准稳定环境和项目环境的短暂不可用。
  3. 虚拟机交付速度比较慢,使用虚拟机做灰度发布也比较复杂。
  4. 虚拟机往往会存在几年甚至更长的时间,运行过程中操作系统以及基础软件版本的收敛非常麻烦。

标准环境容器化推进

经过之前项目/持续交付的上线和迭代,大部分应用本身已经具备了容器化的条件。不过对于上线来说,需要整个运维体系来适配容器化,比如监控、发布、日志等等。目前我们生产环境容器化准备基本完成,生产网已经上了部分前端 nodejs 应用,其他应用也在陆续推动中,希望以后可以分享更多生产环境中的容器化经验。

结束语

以上是有赞在容器化上的应用,以及在容器化过程中碰到的一些问题和解决方案,我们生产环境的容器化还处于开始阶段,后面还会碰到各种个样的问题,希望能够和大家互相学习,后面能够有更多的经验分享给大家。

参考文献

[1] https://github.com/fabianenar...

图片描述

相关 [容器 实践] 推荐:

有赞容器化实践

- - SegmentFault 最新的文章
容器化已经成为一种趋势,它可以解决很多运维中的痛点,比如效率、成本、稳定性等问题,而接入容器的过程中往往也会碰到很多问题和不便. 在有赞最开始做容器化是为了快速交付开发测试环境,在容器化的过程中,我们碰到过容器技术、运维体系适配、用户使用习惯改变等各种问题,本文主要介绍有赞容器化过程中碰到的问题以及采取的方案.

容器运维最佳实践

- - IT瘾-tuicool
本文介绍了一组使容器更易于运维的最佳实践. 这些实践涉及安全性、监控和日志记录等广泛的主题,旨在使应用程序更容易在 Kubernetes Engine和一般的容器中运行. 这里讨论的许多实践都受到 12因子方法的启发 ,12因素方法是一个构建云原生应用程序的优质资源. 这些最佳实践的重要等级不一样.

美团容器平台架构及容器技术实践

- - 美团点评技术团队
本文根据美团基础架构部/容器研发中心技术总监欧阳坚在2018 QCon(全球软件开发大会)上的演讲内容整理而成. 美团的容器集群管理平台叫做HULK. 漫威动画里的HULK在发怒时会变成“绿巨人”,它的这个特性和容器的“弹性伸缩”很像,所以我们给这个平台起名为HULK. 貌似有一些公司的容器平台也叫这个名字,纯属巧合.

京东容器集群支持数据库实践

- - DockerInfo
京东 容器数据库系统,管理1800台物理计算节点,生产1W+ 多MySQL Docker容器实例. 架构简单可靠,Docker容器计算平台与MySQL集群管理平台解耦处理. 为描述方便,京东容器化数据库系统命名为CDS,底层京东Docker容器计算平台命名为JDOS. 本文重点介绍JDOS如何支持CDS.

[译] 谷歌团队的容器运维最佳实践

- - 编程学习网
谷歌大神们带你进行容器运维最佳实践. 本文介绍了一组使容器更易于运维的最佳实践. 这些实践涉及安全性、监控和日志记录等广泛的主题,旨在使应用程序更容易在 Kubernetes Engine 和一般的容器中运行. 这里讨论的许多实践都受到 12 因素方法的启发 ,12 因素方法是一个构建云原生应用程序的优质资源.

新浪微博混合云架构实践挑战之容器编排设计与实践

- - IT瘾-tuicool
《微博混合云架构》专栏是InfoQ向新浪微博技术团队的系列约稿,本专栏包含8篇内容,详细阐述以DCP设计理念为指导思想的混合云架构实践. 本文是该系列的第五篇,主要介绍容器编排的设计与实现. 《微博混合云架构》专栏主要包括以下8篇内容:. DCP的容器编排设计与实践. 最近由于个人原因,与InfoQ约稿的专栏《微博混合云架构》很久没更新了,在此深表歉意.

聊一聊互联网公司Docker容器化是如何实践的?

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

个推 Node.js 微服务实践:基于容器的一站式命令行工具链

- - DiyCode - 致力于构建开发工程师高端交流分享社区社区
由于工程数量的快速增长,个推在实践基于 Node.js 的微服务开发的过程中,遇到了如下问题:. 每次新建项目都需要安装一次依赖,这些依赖之间基本相似却又有微妙的区别;. 每次新建项目都要配置一遍相似的配置(比如 tsconfig、lint 规则等);. 本地 Mac 环境与线上 Docker 内的 Linux 环境不一致(尤其是有 C++ 依赖的情况).

OpenStack实践

- - 开放博客
作者:Baihuogou DevOps Team. 我们在公司内部部署OpenStack主要是内部管理虚拟机的需要. 公司内部之前使用virt-manager来管理内部虚拟机,但是缺点有二:. 虽然提供图形界面,但是是桌面软件形式,需要安装软件. 所以现在需要一个新的管理软件来解决这些问题,满足两个特性:.

jQuery最佳实践

- andi - 阮一峰的网络日志
上周,我整理了《jQuery设计思想》. 那篇文章是一篇入门教程,从设计思想的角度,讲解"怎么使用jQuery". 今天的文章则是更进一步,讲解"如何用好jQuery". 我主要参考了Addy Osmani的PPT《提高jQuery性能的诀窍》(jQuery Proven Performance Tips And Tricks).