蘑菇街 私有云Docker实例应用

对于蘑菇街而言,每年的11.11已经成为一年中最大的考验,考验的是系统稳定性,容灾能力,紧急故障处理,运维等各个方面的能力。蘑菇街的私有云平台,从无到有,已经经过了近一年的发展,生产环境上经历了3次大促,稳定性方面得到了初步验证。本文我将从架构、技术选型、应用等角度来谈谈蘑菇街的私有云平台。

另,ArchSummit全球架构师峰会北京站将于2015年12月18日~19日在北京国际会议中心召开,大会设置了《揭秘双十一背后的技术较量》专题来深入解读双十一背后的技术故事,欢迎关注。

蘑菇街的私有云平台(以下简称蘑菇街私有云)是蘑菇街面向内部上层业务提供的基础性平台。通过基础设施的服务化和平台化,可以使上层业务能够更加专注在业务自身,而不是关心底层运行环境的差异性。它通过基于Docker的CaaS层和KVM的IaaS层来为上层提供IaaS/PaaS层的云服务,以提高物理资源的利用率,以及业务部署和交付的效率,并促进应用架构的拆分和微服务化。

在架构选型的时候,我们觉得Docker的轻量化,秒级启动,标准化的打包/部署/运行的方案,镜像的快速分发,基于镜像的灰度发布等特性,都十分适合我们的应用场景。而Docker自身的集群管理能力在当时条件下还很不成熟,因此我们没有选择刚出现的Swarm,而是用了业界最成熟的OpenStack,这样能同时管理Docker和KVM虚拟机。相对来说,Docker适合于无状态,分布式的业务,KVM适合对安全性,隔离性要求更高的业务。
对于上层业务来说,它不需要关心是运行在容器中,还是KVM虚拟机里。今后的思路是应用的微服务化,把上层的业务进行拆分,变成一个个微服务,从而对接PaaS基于容器的部署和灰度发布。

技术架构

在介绍双十一的准备工作之前,我先简单介绍一下蘑菇街私有云的技术架构。

我们采用的是OpenStack+novadocker+Docker的架构模式,novadocker是StackForge上一个开源项目,它做为nova的一个插件,通过调用Docker的RESTful接口来控制容器的启停等动作。每个Docker就是所谓的“胖容器”,它会有独立的IP地址,通过supervisord来管理容器内的子进程,常见的如SSHD、监控agent等进程。

我们在IaaS的基础上自研了PaaS层的编排调度等组件,实现了应用的弹性伸缩、灰度升级,支持一定的调度策略。我们通过Docker和Jenkins实现了持续集成(CI)。Git中的项目如果发生了git push等动作,便会触发Jenkins Job进行自动构建,如果构建成功便会生成Docker Image并push到镜像仓库。基于CI生成的Docker Image,可以通过PaaS的API或界面,进行开发测试环境的实例更新,并最终进行生产环境的实例更新,从而实现持续集成和持续交付。
网络方面,我们没有采用Docker默认提供的NAT网络模式,NAT会造成一定的性能损失。通过OpenStack,我们支持Linux bridge和openvswitch,不需要启动iptables,Docker的性能接近物理机的95%。

准备工作 稳定性

迎战双11,最重要的当然是确保稳定性。通过近一年的产品化和实际使用,我们积累了丰富的提高稳定性的经验。
对于那些已遇到过的问题,需要及时采用各种方式进行解决或者规避。

比如说,CentOS6.5对network namespace支持不好,在Docker容器内创建Linux bridge会导致内核crash,upstream在2.6.32-504中修复了这个bug,因此线上集群的内核版本,必须升级至2.6.32-504或以上。

又比如,CentOS6.5自带的device mapper存在dm-thin discard导致内核可能随机crash,这个问题我们早在四月份的时候已经发现并解决了,解决的办法是关闭discard support,在docker配置中添加“--storage-opt dm.mountopt=nodiscard --storage-opt dm.blkdiscard=false”,并且严格禁止磁盘超配,因为磁盘超配可能会导致整个device mapper无法分配磁盘空间,而把整个文件系统变成只读,从而引起严重问题。

监控

我们在双11前重点加强的是针对容器的监控。

在此之前,我们已经自研了一套container tools。主要功能有两个:一是能够以容器为粒度计算load值,可以根据load值进行容器粒度的qps限流。二是替换了原有的top、free、iostat、uptime等命令,确保运维在容器内使用常用命令时看到的是容器的值,而不是整个物理机的值。双十一之后我们还会把lxcfs移植到我们的平台上来。

在宿主机上,我们增加了多维度的阈值监控和报警,包括对关键进程的存活性监控/语义监控,内核日志的监控,实时pid数量的监控,网络连接跟踪数的监控,容器oom的监控报警等等。

实时pid数量监控

为什么要监控实时的pid数量呢?因为目前的Linux内核对pid的隔离性支持是不完善的。还没有任何Linux发行版能做到针对pid按照容器粒度进行pid_max限制。

曾经发生过一个真实的案例是:某个用户写的程序有bug,创建的线程没有及时回收,容器中产生了大量的线程,最后在宿主机上都无法执行命令或者ssh登陆,报的错是"bash: fork: Cannot allocate memory",但是此时通过free命令看到空闲的内存却是足够的。

为什么会这样呢?根本原因是内核中的pid_max(/proc/sys/kernel/pid_max)是全局共享的。当一个容器中的pid数目达到上限32768,会导致宿主机和其他容器无法创建新的进程。最新的4.3-rc1才支持对每个容器进行pid_max的限制。

内存使用监控

值得一提的是,我们发现cgroup提供的内存使用值是不准确的,比真实使用的内存值要低。因为内核memcg无法回收slab cache,也不对dirty cache量进行限制,所以很难估算容器真实的内存使用情况。曾经发生过统计的内存使用率一到70-80%,就发生OOM的情况。为此,我们调整了容器内存的计算算法,根据经验值,将cache的40%算做rss,调整后的内存计算比之前精确了不少。

日志乱序

还有一个问题是跑Docker的宿主机内核日志中经常会产生字符乱序,这样会导致日志监控无法取到正确的关键字进行报警。
经过分析发现,这个跟我们在宿主机和Docker容器中都跑了rsyslogd有关。由于内核中只有一个log_buf缓冲区,所有printk打印的日志先放到这个缓冲区中,docker host以及container上的rsyslogd都会通过syslog从kernel的log_buf缓冲区中取日志,导致日志混乱。通过修改container里的rsyslog配置,只让宿主机去读kernel日志,就能解决这个问题。

隔离开关

平时我们的容器是严格隔离的,我们做的隔离包括CPU、内存和磁盘IO,网络IO等。但双十一的业务量可能是平时的十几倍或几十倍。我们为双十一做了不少开关,在压力大的情况下,我们可以为个别容器进行动态的CPU,内存等扩容或缩容,调整甚至放开磁盘iops限速和网络的TC限速。

健康监测

我们还开发了定期的健康监测,定期的扫描线上可能存在的潜在风险,真正做到提前发现问题,解决问题。
灾备和紧急故障处理

除了稳定性,灾备能力也是必须的,我们做了大量的灾备预案和技术准备。比如我们研究了不启动Docker Daemon的情况下,离线恢复Docker中数据的方法。具体来说,是用dmsetup create命令创建一个临时的dm设备,映射到Docker实例所用的dm设备号,通过mount这个临时设备,就可以恢复出原来的数据。

我们还支持Docker容器的冷迁移。通过管理平台的界面可以一键实现跨物理机的迁移。
与已有运维系统的对接

Docker集群必须能与现有的运维系统无缝对接,才能快速响应,真正做到秒级的弹性扩容/缩容。我们有统一的容器管理平台,实现对多个Docker集群的管理,从下发指令到完成容器的创建可以在7秒内完成。

性能优化

我们从系统层面也对docker做了大量的优化,比如针对磁盘IO的性能瓶颈,我们调优了像vm.dirty_expire_centisecs,vm.dirty_writeback_centisecs, vm.extra_free_kbytes这样的内核参数。还引入了Facebook的开源软件flashcache,将SSD作为cache,显著的提高docker容器的IO性能。

我们还通过合并镜像层次来优化docker pull镜像的时间。在docker pull时,每一层校验的耗时很长,通过减小层数,不仅大小变小,docker pull时间也大幅缩短。


镜像


文件层数


文件大小


docker pull时间

原镜像 13 1.051 GB 2m13
新镜像 1 674.4 MB 0m26

总结

总的来说,双11是对蘑菇街私有云的一次年终大考,对此我们已有了充分的准备。随着Docker集群部署的规模越来越大,我们还有很多技术难题有待解决,包括容器本身的隔离性问题,集群的弹性调度问题等等。同时我们也很关注Docker相关的开源软件Kubernetes、Mesos、Hyper、criu、runC的发展,未来将引入容器的热迁移,Docker Daemon的热升级等特性。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • Centos 6.5中安装docker的步骤(简洁版)

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app).几乎没有性能开销,可以很容易地在机器和数据中心中运行.最重要的是,他们不依赖于任何语言.框架包括系统. 一.安装epel源 复制代码 代码如下: wget http://mirrors.yun-idc.com/epel/6/x86_64/epel-releas

  • Docker学习之常用的基础命令总结

    前言 Docker是一个用了一种新颖方式实现的超轻量虚拟机,在实现的原理和应用上还是和VM有巨大差别,专业的叫法是应用容器(Application Container).下面这篇文章将简单介绍一下Docker常用的一些基础命令. # 在ubuntu中安装docker $ sudo apt-get install docker.io # 查看docker的版本信息 $ docker version # 查看安装docker的信息 $ docker info # 查看本机Docker中存在哪些镜像

  • docker kubernetes dashboard安装部署详细介绍

    docker之kubernetes dashboard部署 1. 环境说明: 1). 架构: 注: 本次实验服务器环境均采用centos 7. 服务安装均采用yum install. 192.168.3.7 master 192.168.3.16 node 2).使用的软件包: master: docker kubernetes-master etcd flannel nodes: docker kubernetes-node flannel 3). 软件版本: docker: 1.10.3 k

  • 在CentOS 7上安装Docker环境的方法与注意事项

    官网文档:https://docs.docker.com/engine/installation/linux/centos/ ,本文大部分是照搬官方文档写的,如果你英文还不错,那么就直接移步官方文档吧,如果你英文实在是不行,那就勉强看一下本人这生涩的翻译~ 以下操作均在root用户下完成 docker的安装要求64位系统且内核版本大于3.10.所以如果是centos的话,必须安装CentOS7.0或以上版本. 我们这里使用的是CentOS7.2 mininul. uname -r 3.10.0-

  • 在docker中部署tomcat并且部署java应用程序的步骤详解

    先给大家简单说下Docker的概念 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不会有任何接口. 1.先说如何在docker中部署tomcat 第一步:root用户登录在系统根目录下创建文件夹tomcat7,命令如:mkdir tomcat7,并且切换到该目录下:cd tomcat7: 第二步:创建Dockerfile,命令如:touch Docker

  • Docker 搭建 Tomcat 运行环境的方法

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不会有任何接口. 1 Docker与虚拟机   2 搭建过程 2.1 准备宿主系统 准备一个 CentOS 7操作系统,具体要求如下: 必须是 64 位操作系统 建议内核在 3.8 以上 通过以下命令查看您的 CentOS 内核: # uname -r 2.2 安装Docker # yum install d

  • Docker 实用技巧总结

    我有机会建立一个以Docker为基础的微服务架构在我现在的工作中,很多人都会分享他们使用Docker的心得,我想我也不会例外.因此我总结了一些,可能你会在日常使用Docker的时候会用到. 1. 一台主机部署多个Docker实例 如果你想运行多个Docker 容器在一台主机上,如果要设置不同的TLS设置,网络设置,日志设置和存储驱动程序特定的容器,这是特别有用的.例如,我们目前正在运行一个标准设立两个Docker守护进程.一运行consul提供DNS解析,并作为群集存储为其他Docker 容器.

  • 什么是docker Docker入门教程第一篇

    Docker是个新生的事物,概念类似虚拟化.网上关于Docker入门的东西已经很多了.不过本文探讨了Docker的特点.特性.原理,还介绍了具有中国特色的安装测试过程,另外还谈到了Docker的社区生态和Dockerfile,并使用Dockerfile构建一个nginx环境. 缘起 在几个月前听说Docker,但是一直没有时间去研究,前一段时间趁着azure免费试用,赶紧实验一下,但是卡在了ubuntu基础镜像的下载上(由于国内网络的特殊原因),所以也就搁浅了,这里把经验和体会分享一下. Doc

  • Docker 容器虚拟化的实用技巧总结

    服务器虚拟化指的是在操作系统与硬件之间加一层,叫做hypervisor层,对下控制硬件,对上承载操作系统,操作系统os以文件形式封装运行,称为虚拟机,主要解决的问题是硬件利用率和灵活性的问题,常见的方案为vmware vsphere,xen,kvm,hyper-v..容器虚拟化指的是在os上将应用打包以进程的形式运行,应用和应用间非完全隔离,但是更轻量,效率高,lxc和docker都可以称为容器级虚拟化,区别在于docker可以理解为经过精美封装过更加好用的lxc,有更好的接口和更完善的配套.

  • 在Ubuntu15.04上安装Docker的步骤以及基本用法

    简介 Docker 是一个开源项目,为开发者和系统管理员提供了一个开放的平台,在任何地方通过打包和运行应用程序作为一个轻量级的容器.Docker 在软件容器内自动部署应用程序.Docker 最开始由 Solomon Hykes 作为 dotCloud 一个内部开发项目,一个企业级的 PaaS (platform as a service 服务平台),该软件现在由 Docker 社区和 Docker 公司维护. 我们可以通过 Docker 官方提供的 KVM 与 Docker 的图片更加形象的知道

随机推荐