S6 在 LAIN 集群中的应用实践

转载 2017年12月29日 00:00:00

?wxfrom=5&wx_lazy=1


近几年,容器技术迅猛发展,并在各大企业得到了广泛应用。它标准化了应用程序的运行环 境,从而简化了程序的部署流程,同时也促进了 PaaS(Platform as a Service)系统的发展,LAIN 即为其中之一。作为一种革命性的新技术,Docker 具有种种优点,比如一处编译、处处运行,易于编排和轻量等等;但是,由于发展时间较短, 在生产环境中使用时,Docker 在一些环节出现了性能问题,另外,Docker 容器与虚拟机之 间也有一些微妙的区别,在生产环境中使用时需要给予特别的注意。下面分享一下 LAIN 生 产集群在运行过程中遇到的一些问题和解决方案。


不断累积的僵尸进程

?wxfrom=5&wx_lazy=1


为了方便管理,我们把 Jenkins 搬进了容器。但是,Jenkins 容器经常停止响应, 需要定期重启。为什么在虚拟机上可以正常运行的程序到了容器里就出现问题了呢? 通过 ps aux 可以发现,Jenkins 容器里有大量的僵尸进程,即图 1 中的 [git-remote-http] 进程。


A1HKVXsfHNm4eiczAw1zOVof93621hs5cvXUTMBibdeHZfTLAUl2eYnQLAPNJB9oJ8vtcu3F4EEAVez18tz79e5g


图 1:zombie processes


进程表是有限的系统资源,当僵尸进程占用了大量的进程表空间时,就会导致无法启动新的 进程。那为什么容器里会产生大量的僵尸进程呢?因为在类 UNIX 系统中,PID 为 1 的 进程是特殊的:它负责收割僵尸进程。在虚拟机中,PID 为 1 的进程通常是 Systemd、 Sys Vinit 或者 upstart,它们都能自动收割僵尸进程;在容器里,情况有很大的不同: PID 为 1的进程常常是用户自己写的程序,很可能不会收割僵尸进程,比如上面的 jenkins-master,这时候就会造成僵尸进程的累积,最终导致容器内无法再启动新的进程。


偶尔卡死的 Docker Daemon

b2YlTLuGbKDsbJzupnILVFhPtMaRjmvPKYRqTMjibE9pnd8oiawLVrQbOHQe4wBXkBQkzpKCWPKBqWgOLgwccBug


Docker Daemon 可以收集容器的标准输出,然后使用 syslog 或 json-file 等 log-driver 处理。但是,这个架构是中心化的,Docker Daemon 会成为日志收集的瓶颈。 表 1 是我们测得的 Docker 收集日志的速度。


log-driver日志收集速度
syslog14.9 MB/s
json-file37.9 MB/s
表 1:Docker 的日志收集速度


可以看到,这个速度并不理想,当容器的标准输出较多时,Docker Daemon 不能及时处理, 就会影响这个容器的正常运行;同时,Docker Daemon 对标准输出的处理会阻塞其他操作, 比如 docker ps 和 docker stop 等命令也会卡死。这时,我们只能重启 Docker Daemon,同时禁止容器的标准输出。


一站式解决方案 —— S6

b2YlTLuGbKDsbJzupnILVFhPtMaRjmvPKYRqTMjibE9pnd8oiawLVrQbOHQe4wBXkBQkzpKCWPKBqWgOLgwccBug


上述 2 个问题严重地影响了应用的正常运行,是否有办法可以解决呢?即,我们希望找到 一个工具,既可以收割僵尸进程,又可以把标准输出重定向到文件并自动 rotate。 表 2 是我们找到的一些工具。


进程管理工具僵尸进程重定向标准输出并自动 rotate
S6收割支持
tini收割支持
systemd收割支持,但为二进制
phusion-baseimages收割不支持
daemontools不收割支持
supervisor不收割支持

表 2:进程管理工具的比较


从上表可以看出,S6 是最满足我们需求的解决方案。而且,它体积很小,只有 904 KB,启 动时间不超过 100 ms,运行时占用的 CPU 和内存可以忽略不计。


S6[1] 包含 s6-svscan、s6-supervise 和 s6-log 等组件。这些组件遵循 UNIX 设计哲学,相互独立,功能正交,通过适当组合可 以实现强大的功能。那具体怎样组合呢?S6 的作者把类 UNIX 系统的运行时可以分为 3 个 阶段(Bercot,n.d.),如图 2 所示。 而 s6-overlay[2] 实现了此方案,下面参考 s6-overlay 说明如何在容器中使用 S6 管理进程。


A1HKVXsfHNm4eiczAw1zOVof93621hs5cqbU0m1jrwnk0siaoV1JOy9LZcopq2mIK9Suic95sa1tjU3oYZ5Rbsia8g


图 2:类 UNIX 系统的运行时阶段8


阶段 1


在阶段 1,s6-overlay 准备环境变量和创建 s6 的工作目录 /var/run/s6/services 等, 然后启动 PID 为 1 的 s6-svscan 以管理 /var/run/s6/services下的服务:


s6-svscan -t0 /var/run/s6/services


为了适应 LAIN 的需求,我们还将 Dockerfile 里的 CMD 写入了 /etc/services.d/app/run。整个流程如图 3 所示。


A1HKVXsfHNm4eiczAw1zOVof93621hs5cbYP0VoUp6mibfoib2ichwH88Ix17icErZDtzPXXzDaLKp7IbNx7ayN9lQQ


图 3:阶段 1


阶段 2


在阶段 2,s6-overlay 首先把 /etc/services.d 里的文件复制到 s6-svscan 的运行时 目录 /var/run/s6/services,然后通过 s6-svscanctl -a /var/run/s6/services 触 发 s6-svcan 对此目录的检索;s6-svcan 发现 /var/run/s6/services/app/run 和 /var/run/s6/services/app/log/run 后,会调用 s6-supervise 分别启动这个两个服 务,如图 4 所示。


A1HKVXsfHNm4eiczAw1zOVof93621hs5cqCZblNDfgBqPuQPrVKepTSBHvZHRRPOp3t1OGdPOsULXDiaVmSt3SIA


图 4:阶段 2


首先,容器运行过程中,s6-svcan 会收割僵尸进程,解决了我们的第一个问题。


其次,s6-log 将 CMD 的标准输出重定向到 /lain/logs/default/current,而不是发送到 Docker Daemon,这样就避免了 Docker Daemon 收集日志的性能瓶颈, 表 3 是我们的测试结果。可以看到,在 日志文件 test.log 体积较小的时候,s6-log 收集日志的速度可以达到 200 MB/s 左 右,几乎与直接写入文件的速度相当;当 test.log 的体积逐渐增大时,因为会触发越来 越频繁的日志轮转,所以 s6-log 的速度逐渐降低,逐渐趋近于 90 MB/s 左右。 s6-log 只有在日志文件达到 256 MB 时才会触发轮转,而这种情况在实际的生成环境中 并不会频繁发生,因此 s6-log 的实际日志收集速度应该在 100 MB/s 以上,足以满足我 们的需求,解决了我们的第二个问题。


test.log 体积直接用文件收集日志的速度日志收集速度
80 MB94.5 MB/s209 MB/s
160 MB91.4 MB/s212 MB/s
320 MB90.5 MB/s103 MB/s
640 MB234 MB/s99.6 MB/s
1280 MB225 MB/s95.7 MB/s
2560 MB212 MB/s91.8 MB/s

表 3:s6-log 的日志收集速度


阶段 3


s6-supervise 还会监听 SIGTERM 信号,当 s6-supervise 收到此信号后进入阶段 3: 执行 /var/run/s6/services/app/finish,也就是 s6-svscanctl -t /var/run/s6/services,从而让整个容器优雅地退出,这比 Docker 默认的等待 10 秒后 强制杀死进程的行为友好很多。


综上,在 Docker 中使用 S6 可以获得以下好处:


  • 自动收割僵尸进程

  • 在保留自动 rotate 功能的同时提高日志收集的速度

  • 适当处理 SIGTERM 信号,优化 docker stop 的用户体验


参考文献:


  1. Bercot, Laurent. n.d. “How to Run S6-Svscan as Process 1.” http://skarnet.org/software/s6/s6-svscan-1.html.


相关链接:


  1. http://www.skarnet.org/software/s6/

  2. https://github.com/just-containers/s6-overlay


基于Kubernetes的容器云平台实践培训

?


本次培训包含:Kubernetes核心概念;Kubernetes集群的安装配置、运维管理、架构规划;Kubernetes组件、监控、网络;针对于Kubernetes API接口的二次开发;DevOps基本理念;Docker的企业级应用与运维等,点击识别下方二维码加微信好友了解具体培训内容


?


点击阅读原文链接即可报名。

浅谈web应用的负载均衡、集群、高可用(HA)解决方案

浅谈web应用的负载均衡、集群、高可用(HA)解决方案
  • pingdouble
  • pingdouble
  • 2016年02月15日 10:07
  • 2207

基于AWS的云服务架构最佳实践

近年来,对于打造高度可扩展的应用程序,软件架构师们挖掘了若干相关理念,并以最佳实践的方式加以实施。在今天的“信息时代”,这些理念更加适用于不断增长的数据集,不可预知的流量模式,以及快速响应时间的需求。...
  • wireless_com
  • wireless_com
  • 2015年01月30日 12:43
  • 6176

【Redis基础】Redis集群版在Java中的应用

前两天刚刚搭建完了redis集群,今天正好测试一下在Java中如何使用redis缓存一些东西。与spring是如何结合在一起的。封装一个操作redis的工具类,供项目中使用。   第一篇redis...
  • u010539352
  • u010539352
  • 2016年06月28日 19:48
  • 5688

基于k8s的jenkins构建集群实践

  • 2017年10月27日 10:13
  • 3.24MB
  • 下载

CentOS6.x部署实践 Oracle 11g RAC集群搭建

  • 2017年12月08日 14:08
  • 3.34MB
  • 下载

创建k8s集群(仅限于理论,无实践)

创建k8s集群(仅限于理论,无实践)   k8s可以在多种平台运行,笔记本电脑,到云服务商的虚拟机,再到机架上的裸机服务器.要创建一个k8s集群,可以根据多种不同的场景做不...
  • shanyongxu
  • shanyongxu
  • 2016年06月06日 00:52
  • 2907

Centos7.2部署HOR2.2(基于K8S集群的容器应用整合)

一. 部署本地yum源 二. 前置环境准备 1.配置主机名和hosts文件(每个节点) (1)hostnamectl set-hostname xxx (2)编辑各节点/etc/hos...
  • m0_37793527
  • m0_37793527
  • 2017年12月07日 15:05
  • 34

Spark技术解析及其在百度最大单集群1300台的应用实践

2015年1月10日,Databricks软件工程师连城、百度高级工程师甄鹏、百度架构师孙垚光、百度美国研发中心高级架构师刘少山四位专家联手为我们打造了一场基于Spark的高性能应用盛宴。其中,Dat...
  • furenjievip
  • furenjievip
  • 2015年01月19日 13:20
  • 833

大型网站系统架构实践(六)深入探讨web应用集群Session保持

原理        在第三,四篇文章中讲到了会话保持的问题,而且还遗留了一个问题,就是会话保持存在单点故障, 当时的方案是cookie插入后缀,即haproxy指负责分发请求,应用服务自行...
  • linux__xu
  • linux__xu
  • 2017年03月14日 19:10
  • 196

IBM InfoSphere DataStage 集群配置管理与应用实践

http://www.ibm.com/developerworks/cn/data/library/techarticle/dm-1111sunch/ IBM InfoSphere DataStag...
  • sadxhy
  • sadxhy
  • 2013年01月21日 14:36
  • 3397
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:S6 在 LAIN 集群中的应用实践
举报原因:
原因补充:

(最多只允许输入30个字)