Spotify的容器使用情况

2017 年 7 月 13 日

本文最初发布于 Spotify 官方博客,原作者: David Xia 。经授权由 InfoQ 中文站翻译并分享。阅读英文原文: Improving Critical Infrastructure Rollouts

Spotify 最初于 2014 年通过几个原型服务开始使用 Docker。自那之后,我们进行了多次升级和配置,而几乎每次都遇到了一些难以检测并修复的问题。在通过 Docker 运行很少量后端服务时,这些问题的影响范围还较小。但随着 Docker 使用率增加,Docker 中存在的错误造成的风险和影响也水涨船高,最终到了不可接受的程度。2016 年 10 月,由于部署了一个错误的配置,甚至对用户体验产生了严重影响。

仔细思考后,我们意识到需要一种全新的解决方案,以更加细化并且受控的方式部署可能影响整个公司基础架构的变更。本文将介绍 Spotify 如何受到 Docker 运维工作的启发构建新服务,让我们更好地控制为包含数千台服务器的基础架构推送变更的过程。

1. 每次 Docker 升级都会遇到问题

每次升级 Docker 后,我们都会在 Docker 本身的变更以及其中运行的软件等方面遇到有关回归或不兼容的问题。更麻烦的是,这些问题往往很难排错,因此会造成更大影响。

在将 Docker 从 1.0.0 升级至 1.3.1 的过程中,曾遇到两个很好解决的 Bug。 Docker 改变了设置容器主机名的方式,以及处理CMD 和ENTRYPOINT 设置的方式。在几天里,我们部署了针对这两个回归问题的修复措施。这些都不严重,只有少数团队的构建流程受到影响。但随后的一次升级就没那么幸运了。

2015 年夏天,我们刚刚从 1.3.1 升级到 1.6.2,感觉一切都很顺利。但很快发现这两个 Docker 版本的升级会导致产生“孤本(Orphaned)”容器,即无法由 Docker 守护进程管理的容器。这些容器依然会绑定原本使用的端口,导致我们的 Docker 编排工具 Helios 会将流量路由至错误的容器。通过反复升级和降级 Docker,我们成功重现了这个问题。问题根源在于 Docker 没能正确关闭,进而导致产生孤本进程。我们开始监视孤本容器进程,并提交了一个补丁,以便为Docker 提供更多时间,让它能够正确关闭。相比之前的两个Bug,这次的Bug 更严重,同时也更难修复。

去年11 月,我们完成了从1.6.2 到1.12.1 的升级。一周后,11 月3 日,我们发现1.12.1 版有一个 Bug 会创建孤本的 Docker 代理进程,进而因为端口没能成功释放导致容器无法运行。我们很快解决了一些团队因为这个 Bug 无法部署服务的问题,同时帮助他们将实例升级到 1.12.3 版。与上次升级遇到的 Bug 类似,这次的问题也很严重并且难以修复。

2. Docker 对 Spotify 后端重要性越来越高,Docker 问题的风险和影响力也水涨船高

Spotify 最初于 2014 年通过几个原型服务开始使用 Docker,当时仅通过数百个 Docker 实例运行了少数几个服务。借此建立了信心后,我们升级了整个测试环境,一周后升级了生产环境。虽然遇到过几个 Bug,但并不严重。

但 2016 年 10 月从 1.6.2 到 1.12.1 的升级,情况完全不同了。当时我们已经通过数千个 Docker 实例运行了几个关键业务服务,承担了用户登录、事件交付,以及客户端与后端的所有通信任务。升级 Docker 实例会导致该实例上运行的所有容器重启动,为避免大量服务同时重启动,只能循序渐进地升级。如果同时重启动访问点以及用户登录等重要服务,会导致用户体验严重受影响,甚至因为重启动之后的“重连接风暴”影响下游服务。

截止 2017 年 2 月,我们生产环境中 80% 的后端服务都在容器中运行。Docker 已经从实验对象成功变身为 Spotify 后端基础架构的重要组成部分。我们团队负责运营维护横跨数千台主机的 Docker 守护进程,需要通过比以往更慎重的方式逐步进行升级。

3. 我们最终决定为整个基础架构创建一种循序渐进的发布解决方案

当时我们正着手向 1.12.1 版升级,并已完成 30%。随后 10 月 14 日周五,在修复供应新 Docker 实例过程中遇到的一个罕见小问题时,我们犯了一个严重的错误。这次事件让我们意识到自己的 Docker 部署方式与影响整个公司的变更结合在一起到底会产生多大的影响力。最终我们集思广益开发了一个服务,帮助我们以更细化可控的方式发布基础架构变更。

这就是 Tsunami

Tsunami 使得我们可以通过无人值守的方式,循序渐进地将有关配置和基础架构组件的变更发布出去。我们可以让 Tsunami“在两周内将 Docker 从版本 A 升级至版本 B”。Tsunami 从本质上可以作为一种服务以线性方式发挥作用,而拉长部署工作持续的时间段有助于提高可靠性。我们可以在只产生小范围影响时发现可能存在的问题。

Tsunami 解决的问题

  1. 以我们 Docker 基础架构的规模和职责来说,所需的循序渐进升级机制。
  2. 通过循序渐进升级限制 Bug 的影响范围,为工程师留出足够时间检测并上报问题。
  3. 我们目前的环境,无法仅通过对自己的服务进行 Docker 升级,或对其他服务的实例进行测试的方式检测到升级过程中可能出现的全部问题。我们需要对真实的生产服务进行升级,这就必须针对所有后端服务以均匀分布的方式缓慢推进。

“变量(Variable)”是 Tsunami 中的一个重要概念。每个变量都有自己的名字和配置,借此控制着变量可以提供的值,以及在一个较长时间段内的变化情况。我们的所有 Docker 实例会查询 Tsunami 以了解自己需要运行的 Docker 版本。Tsunami 只需要返回一个代表所需状态的平坦(Flat)JSON 对象即可,随后将由客户端自己决定如何实现所需的状态。

这样即可获得我们所需要的发布方式。

不同版本 Helios 代理的数量

Tsunami 可在 24 小时内将新版 Helios 发布至上千台主机,黄线代表老版本,蓝线代表新版本。

通过一个集中化的服务控制发布过程,使得我们可以构建所有客户端都能“免费”获取的功能,包括:

  1. 通过审计日志查看某台主机在何时,出于什么原因需要运行某一特定版本的系统服务。
  2. 对于特定角色中多大比例的主机会受到某个基础架构变更的影响,获得更细化的控制逻辑,并能设置上限和下限(例如角色中 30% 的主机,但至少一台主机)。
  3. 监视计算机的服务级别目标,如果目标无法达到则自动终止发布。

我们目前已经在使用 Tsunami 升级 Helios、Docker 和 Puppet。Tsunami 还帮助我们更好地对需要重启动服务的配置变更作出安排。希望在不远的将来能够将 Tsunami 开源给整个社区。


感谢郭蕾对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2017 年 7 月 13 日 19:002073
用户头像

发布了 283 篇内容, 共 84.3 次阅读, 收获喜欢 34 次。

关注

评论

发布
暂无评论
发现更多内容

从零实现一个动态表单设计(编辑)器

徐小夕

Java 编辑器 H5 Node React

Flink State 误用之痛,你中招了吗?

Apache Flink

flink

JAVA魅力之神奇的数组带给你不一样的乐趣

小Q

Java 学习 架构 面试 数组

WebSocket连接错误Error during WebSocket handshake Unexpected response code 404

李浩宇/Alex

阿里二面惨败,痛定思痛狂刷1000+面试题,成功五面上岸滴滴(面经+面试题分享)

Java架构追梦

Java 架构 腾讯 面试 蚂蚁金服

交易所画k线市值管理机器人,做市机器人开发

WX13823153201

详解软件行业低代码开发平台以及敏捷开发方案

Marilyn

敏捷开发

Java-技术专题-时间工具类的使用方案

李浩宇/Alex

sharding-jdbc 分库分表的 4种分片策略,还蛮简单的

程序员内点事

Java 分库分表

阿里P8架构师呕心沥血整理的【Docker实战】文档带你玩转Docker。

Java架构之路

Java 程序员 架构 面试 编程语言

华为云“创原会”:40+技术精英论道云原生2.0

华为云开发者社区

k8s 华为云

国家超算深圳中心计划2年内提升计算能力至少1000倍;图神经网络的生成式预训练论文解读

京东智联云开发者

云计算

华为云FusionInsight湖仓一体解决方案的前世今生

华为云开发者社区

数据库 华为 仓库

华为20级工程师吐血整理出600页Spring微服务架构设计,绝了!

996小迁

Java spring 编程 架构 spring微服务

MySQL-技术专题-创建临时表

李浩宇/Alex

丑陋的程序员

陆陆通通

程序员 职场 认知

【原创】SpringBoot 这几种配置文件方式,你都用过吗?

田维常

spring Boot Starter

架构师训练营第 1 期第 7 周作业

业哥

物联网时代存储告急 边缘存储如何缓解存储压力?

京东智联云开发者

云计算 云服务 云存储

区块链数字货币商城系统开发技术

薇電13242772558

区块链 数字货币

MySQL-技术专题-STRAIGHT_JOIN

李浩宇/Alex

如何快速构建Spring Boot基础项目?

田维常

spring Boot Starter

浅析一个较完整的SpringBoot项目

田维常

spring Boot Starter

2020双十一终极清单!阿里云CDN&视频云最全优惠攻略

巨侠说

CDN

产品经理团队的管理秘法

马踏飞机747

管理 产品经理 团队

阿里P8Java大神给迷茫的程序员一些中肯建议:“请不要再虚度光阴了!”

Java架构之路

Java 阿里巴巴 程序员 架构 编程语言

Go 与异步 IO - io_uring 的思考

IceberGu

golang Linux 异步IO io_uring

只需三步,带你从0到1玩转React,附源码我一定给你讲明白

小Q

Java 学习 编程 架构 面试

为什么11·11物流一年比一年快?奥秘就在这里!

华为云开发者社区

物联网 物流 仓储

用时半个月,终于把2020年各大公司的Java面试题精选整理成文档了

Java架构之路

Java 架构 面试 编程语言

【原创】Spring Boot集成Redis的玩法

田维常

spring Boot Starter

Spotify的容器使用情况-InfoQ