为何要给Docker提交代码

 

每一个互联网人都很清楚,拥抱开源的最大好处是当我们发现什么地方不爽时,可以随心所欲的改造它,让它趋于完美。Docker生态系统正在迅速发展,这还得归功于其充满活力的开源社区以及各个Docker管理工具项目的诞生。希云cSphere的存在,正是为了实现“让Docker更加完美”这一目标。我们在使用Docker的时候,发现过各种各样的坑,本文将结合实际案例,为您详细描述我们在实现目标的路上所做出的各种努力。希望对您有所帮助。

这得从2014年底说起。当我们决定做Docker容器管理平台时,我们参考了一系列开源的cluster工具,比如:shipyard, kubernets, swarm等。但通过对比,我们发现shipyard功能太简陋,kubernets复杂度高。所以我们选择了以swarm为原型开发我们的产品。但当时swarm版本是0.1.0,问题较多,而且有不少功能上缺失。

 

节点无法删除

在swarm的0.1.0版本,节点只能添加到集群,但无法从集群中移除。做过运维的同学都知道,节点移除在服务维护以及容量伸缩时会经常用到。如果无法把节点从集群中移除,意为着节点一旦加入集群,就无法进行临时下线维护,无法把A集群中的机器抽调到B集群中使用。这在实际生产中是无法忍受的。
考虑到到此问题对swarm的用户体验影响较大,我们第一时间向swarm项目的维护者进行了报告(详见issues197),并试图提供一些可能的解决方案。但当时swarm处于快速迭代期,很多方面的发展趋势都不明了,我们决定先在希云cSphere内部的版本中对此问题进行修复。我们采用MongoDB来保存节点信息,利用swarm的discovery接口,实现了基于MongoDB的discovery服务,并提供了节点删除功能。此MongoDB服务后来演化为集群状态数据存储服务,这跟swarm 0.2.0引入的持久状态存储在功能上惊人的相似。而swarm本身,在经过半年多的激烈讨论后,在0.3.0中也引入了节点删除功能。

 

镜像分发问题

swarm 0.1.0中,虽然创建容器的函数提供了个”pullImage”参数,但实际上并没有利用到,这导致swarm API的行为不符合预期。对此我们向swarm项目提交了个Pull Request,此PR虽然功能上比较简单,但这预示着我们开始从开源代码的使用者转变为贡献者,给了我们不小的鼓舞。

 

事件通知异常

 

Docker的events接口,对容器运行状态监控很有帮助。swarm会聚合集群内所有节点的事件,然后通过统一的API返回给用户。节点加入集群时,manager会主动与Docker daemon建立一个长连接,实时获取处节点上的容器事件。swarm进程会开启个定时器,每隔30秒把集群内的所有节点上的容器、镜像、节点剩余内存等信息收集过来,作为容器调度的依据。这个定期同步机制还充当着健康检查的角色,当某次同步失败时,会把失败的节点标记为unhealthy; 在30秒后的下次同步时,如果同步成功,会把节点重新标记为health,这时新的容器就可以在这个节点上创建。但是在节点由不健康恢复为健康时,manager没有重新建立事件监听连接,而原连接很可能已经中断。这导致节点恢复后其事件全部丢失。此问题详情参考PR230 。在解决这个问题的时候,我们考虑到节点健康状态变化本身也是一种非常重要的事件,用户需要及时知道这个事件,于是我们提议swarm应该对Docker本身的事件进行扩充。此提议得到swarm团队的认可,并合并进0.2.0版本。

 

前面介绍了在swarm项目中,我们所做的一些工作。但当时对于Docker本身,我们还处于尽力想办法绕过问题的层面。直到我们开始提供“docker commit”功能时,遇到一个非常影响用户体验的问题,我们首次尝试向Docker项目提交代码。

 

问题是这样的,当commit个容器时,会把容器里的pid文件提交到镜像里。但有些程序(如 apache)在pid文件存在的情况下,启动会失败。这样通过”docker commit”制作的镜像根本无法运行。

 

为此我们给”docker commit”命令添加了个”—exclude”参数,这样用户可以决定在commit镜像的时候,把某些特定的目录或者文件排除在外。这个PR详情可参考PR12594 。提交以后马上得到Docker团队的认可,并得到Docker用户的支持。但经过综合考虑,此PR提供的功能,通过正在讨论中的tmpfs方案也可得到解决,此PR未被合并。

 

在为”docker commit”提交patch的同时,我们发现了Docker核心库(pkg/archive)的一个潜在问题和文档方面的一个错误,并第一时间进行了修复,参考:PR13590PR12536

 

随着我们对Docker源码不断深入的研究,越来越多的问题正在被挖掘。我们也将更加积极的投入到Docker的贡献之中,截止发稿,我们一共为Docker项目提供6个PR,合并了3个,两个正在讨论;  在swarm项目的贡献者排名中占第13名。

 

好了,上面记录了一些我们在Docker代码贡献中的经历,接下来分享一些在Docker项目代码贡献过程中的几点心得。

 

代码贡献心得体会

首先,Docker的质量管理做的很不错,每个改动基本上都必须有相应的测试用例,尤其是bugfix类,必须有regression测试,这充分保证了任何一个BUG只要修复过,以后就不会再次出现。每个功能点也都有相应的功能性测试用例,主要在Docker源码的integration-cli目录下,这些测试是直接通过dind(Docker in Docker)启动个基于最新代码编译的Docker Daemon,然后通过Docker命令行进行真实操作,并对每条命令的输出和返回状态进行验证,这样真实度非常高。所有PR会自动通过Jenkins执行所有测试用例,测试结果通过Github的API自动标注到Github页面上,一旦有任何质量问题,大家可以第一时间发现。
其次,每一个PR提交以后,都要做好过关斩将的准备,要面对社区的各种问题与质疑,需要不断完善,最终与大家达成一致。这个过程可能是漫长的,必须有足够的耐心,并且需要不断的往前推进。作为一个码农,当看到自己的代码能够帮助成千上万的用户解决实际问题时,那份喜悦真的就像游戏中干掉大boss升级了一样。
第三,Docker的主要维护者都在美国,由于存在十几个小时的时差,所以中国开发者最好在早上提交你的PR或者Issue,这样更加利于沟通。当然如果你精力非常旺盛,在半夜提交也是不错的选择(本人曾在4点多起来帮助swarm团队修复一个诡异的panic问题,已合并进刚刚发布的0.3.0版本)。在沟通方面,比较重要的观点和信息一定要能够在PR或者issue页面体现出来,如果涉及很多细节的讨论,可以通过IRC与其他开发者进行实时交流。
最后,众人拾柴火焰高,希望更多的人能加入Docker项目的开发中来。Docker官方刚刚在DockerCon上宣布成立Open Container Project,相信容器技术在IT运维和应用发布方面会有更加美好的明天。希云cSphere也将继续贡献自己的力量,与大家一起共同推动 Docker项目快速发展,真正方便到每一个使用Docker的开发者。

 

作者:魏世江,希云(https://cSphere.cn)联合创始人兼高级副总裁,资深DevOps研发工程师,Docker及Swarm项目代码贡献者。 专注于Linux环境Web应用及周边服务的配置管理自动化。擅长使用Go语言及PHP语言, 对Linux容器技术有深入的研究,目前正集中精力做基于Docker的企业级解决方案。 创业之前在新浪云平台(SAE)任技术经理,负责各种服务管理系统的研发工作。

希云cSphere的Docker代码贡献心得

发表评论

电子邮件地址不会被公开。 必填项已用*标注