崔婧雯 译 分布式实验室
Pinterest堪称图片版的Twitter,网民可以将感兴趣的图片在Pinterest保存,其他网友可以关注,也可以转发图片。
过去的一年里,Pinterest云管理平台和站点可靠性工程团队关注于将工作负载从EC2实例迁移到Docker容器上。到目前为止,我们已经迁移了超过一半的无状态服务,包括所有的API fleet。该博文给大家分享整个过程中我们的经历和收获。
最近这些年里,Docker和容器编排技术,比如Mesos和Kubernetes已经成为了业界热点,证明了构建基于容器的平台的优势。对于我们来说,实现容器平台可以带来如下优势:
让开发人员无需再学习Puppet这样的工具,从而提升了他们的效率
提供不可变基础架构,带来更好的可靠性
提高基础架构的敏捷性
我们在2016年初开始了调研,评估和测试。最开始的计划是不仅仅将工作负载迁移到Docker容器上,而且同时引入容器编排器技术,以多租户的方式运行容器。随着进一步的调研,我们决定分阶段实施。首先将服务移动到Docker上,让大家不需要再花时间在Puppet上,并且构建好不可变基础架构。同时,我们也引入容器编排技术,更好地利用资源并使用开源的容器编排技术。
在迁移之前
在容器化工作之前,Pinterest的服务的开发和启动如下图所示:
有一个基础的Amazon Machine Image(AMI),包括操作系统,通用共享包和安装好的工具。对于一些服务来说,大多数是那些大型并且复杂的服务,还有一个服务特定的AMI,它基于基础AMI构建,包含服务所依赖的包。
这之上,我们使用两个部署工具:Puppet和Teletraan。Puppet用来预配cron job,infra组件,比如服务发现,度量和日志及其配置文件。Teletraan部署生产服务代码以及一些机器学习模型。
这些服务由不同的流程管理器,包括Monit,Supervisor和Upstart运行。
但是,这些流程有如下痛点:
工程师需要负责AMI build以及学习这些流程管理器的不同的配置语言,包括Puppet。
Puppet变更可能在任意时间应用到主机上,缺乏更细粒度的控制。
随着时间的流逝,主机上的环境渐渐产生差异,导致运维的问题。
迁移
对于Pinterest 来说,基础架构的迁移是很大的挑战,因为规模大复杂度高。编程语言各异,跨越技术堆栈的技术依赖,性能和可用性的严苛要求,以及技术债务都需要考虑到。
我们的容器化从小型的,CMP和SRE团队负责的不那么重要的应用程序开始。同时,在开发和测试环境里,我们开始将重要的服务放到容器里。以此为基础,容器化开始广泛***。
最先迁移的应用程序之一是我们主要的API fleet。我们认为在早期迁移最大最复杂的系统之一有助于从一开始就能遇到并且解决重要的问题。这样的流程帮助我们创建并且加强了基础架构所需的工具集。这样做还降低了未来不得不花时间重写工具以包含其他特性的风险。
早期最大的挑战是性能问题。虽然Docker网络对于开发来说非常棒,但是众所周知,在生产环境中性能不太好。所以我们最终决定使用主机的网络,而不依赖于Docker网络。我们运行了一些测试确保在容器里运行API Fleet不会遇到什么问题。
对于API迁移,我们确保有一个完善的度量集来比较在容器内运行和外部运行。该流程帮助确定哪些运行在Docker里,哪些运行在主机上。它还帮助我们在早期发现测试环境里转换流程导致的问题,并且最终让我们有信心推送到生产环境上。在回归和问题监控下,迁移流程在一个月内就完成了。很庆幸这个流程总体平稳,没有造成任何大问题。
迁移之后
在使用API fleet为基础之上构建primitive后,公司的容器化旅程持续进行。我们能够利用创建的工具来支持最复杂的应用程序,从而支撑其他应用程序的迁移。
Docker平台现在如下:
所有容器服务只有一个AMI。服务特定的所有依赖都被放入容器内。除了服务容器,所有支持组件(服务发现,度量,日志,服务代理等等)都运行在Docker容器内,和服务容器一起协作。
工程师们仍然使用Teletraan接口部署容器,但是现在使用的是Telefig,我们自己构建的工具,来启动以及停止容器,并且管理容器之间的依赖。
Docker容器引擎作为流程管理器来监控并且重启容器。引擎的重启策略设置为永不停止,并且开启了live-restore。
如下是我们如何运行这些Docker容器的更为详细的信息:
所有容器运行在net=host,这样让我们拥有原生的网络性能。AWS依赖,比如IAM角色和安全组还在原模型下运行,无需任何代码变更。
Amazon ECR是主要的Docker registry。同时自己维护了第二个Docker registry,从ECR复制而来,保证生产环境的高可用。
工程师用YAML文件描述服务,和Docker compose文件语法类似。它包含一系列Pinterest特定的primitive,这样让开发人员无需编写太长的配置。
每个容器的tag格式为[Name]:[git commit hash],表示唯一的build。
运行在Ubuntu上,使用的是自定制的最新Linux kernel。
一开始使用的是Docker 1.11,现在是在Docker 17.03.1-ce上运行fleet。
展望未来
我们已经达成了容器化服务的第一阶段的目标。下一个阶段里将引入容器编排,构建多租户的集群,为长期运行的服务和批量job提供唯一的接口。
原文链接:https://medium.com/@Pinterest_Engineering/containerization-at-pinterest-92295347f2f3