欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  网络运营

蘑菇街 私有云Docker实例应用

程序员文章站 2022-03-18 12:55:04
对于蘑菇街而言,每年的11.11已经成为一年中最大的考验,考验的是系统稳定性,容灾能力,紧急故障处理,运维等各个方面的能力。蘑菇街的私有云平台,从无到有,已经经过了近一年的...

对于蘑菇街而言,每年的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等进程。

蘑菇街 私有云Docker实例应用

我们在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的热升级等特性。

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