写点什么

Slack 的部署实践

2020 年 5 月 02 日

Slack的部署实践


在 Slack,我们重视快速迭代、快速反馈和对客户的及时响应。同时,我们也拥有数百人的工程师团队,大家一直在努力提高工作效率。公司在不断壮大的同时始终坚持这些价值理念,这意味着我们在不断完善部署系统。我们必须对更高的可视化和可靠性进行投入,以适应正在进行的大量工作。


这篇文章主要阐述我们的流程和一些主要项目,正是这些让我们取得今天的成就。


我们怎样开展部署工作?

在 Slack,每一次 PR 都需要经过代码评审和所有测试。一旦这些条件被满足,工程师就可以将他们的代码合并到主分支上。但是,合并后的代码只能在北美工作时间部署,以确保我们有足够的人力来处理任何意外问题。


我们每天会进行近 12 次计划内的部署活动。每次部署期间,我们会指定一名工程师全权负责,他负责将新的构建发布到生产环境。这个过程有很多详细步骤,可以确保构建缓慢部署,以便在错误产生更大影响前检测它们。


如果出现大量错误,这些构建也能回滚。如果在发布后检测到问题,也能轻松地发布修补程序。



这是我们管理部署的图形化界面


1. 创建一个发布分支(branch)

每个版本都从一个新的发布分支开始,这是我们 Git 历史中允许我们标记发布的一个点。如果在生产环境发现问题,我们也能在这里完成修补程序。


2. 部署到临时生产环境

下一步是将构建部署到临时生产环境的服务器,并运行自动 smoke test。同时,临时生产环境也是生产环境,但它不接受外部流量。


我们还会在临时生产环境中做更多的手动测试,因为与只在开发环境中进行测试相比,这样能让我们对代码可以正确工作更有信心。


3. 部署到 dogfood 和 canary 环境

发布到生产环境的第一步是发布到 dogfood 环境,它是一组服务器,为我们的一些内部 Slack workspaces 提供服务。自己尝鲜,我们自己就是非常活跃的 Slack 用户,dogfooding 能帮助我们及早发现问题。


一旦,我们确信核心功能没有受到不良影响,构建就会部署到 canary,其中大约有 2%的生产流量会路由到 canary。


4. 按百分比发布到生产环境

如果各种曲线图保持稳定,没有异常提醒,我们将继续以百分比的节奏将构建发布到生产环境。我们会将发布量划分为 10%、25%、50%、75%和 100%等五个阶段,以便可以将生产流量缓慢地引入新版本,同时给我们留下时间来调查是否有任何特别的波动或异常。


如果部署过程出现问题如何应对?

代码变更总会有风险,但我们会让经验丰富的部署指挥官掌控每一个新版本的部署过程,观察图表了解情况,和发布代码的工程师协调沟通,来管理风险。


如果在部署过程中出现问题,我们的目标是尽早发现。先对问题调查,找出哪次的代码提交导致问题,回滚,然后在回滚后的代码基础上再完成新构建。不过,有些问题是只有发布到生产环境后才能发现的。在这种情况下,恢复服务显得至关重要。所以在开展问题调查前,我们会立即回滚到上一个可以正常工作的构建。


Building blocks

快速部署

在大家看来,上面描述的工作流程似乎并无新意,但是我们的部署系统经历多次迭代后,才演化到现在样子。


当公司规模还很小的时候,10 个 Amazon EC2 实例就能运行我们所有的应用程序,一次部署意味着对所有服务器做一次快速 rsync 而已。


因此,以前在生产环境前面只有一层:临时生产环境。构建将在临时生产环境终进行验证,然后直接发布到所有生产服务器。这个系统简单易懂,任何工程师都可以随时部署自己的代码。


但是,随着客户数量的增长,运行应用程序所需的基础设施数量也在快速增加。很快,我们基于推送的部署模型就无法处理添加的服务器数量了。每增加一台服务器,都会增加部署时间。即使是使用并行 rsyncs 这样的办法也有其局限性。


最后,我们切换到完全并行的基于拉模式的系统上,解决了这个问题。


我们不再使用同步脚本将新的构建推送到服务器上,而是在发出了 Consul 密钥更改的信号后,每台服务器都会同时 pull 构建。即使规模不断扩大,这也能让我们保持高速度的部署。



原子部署

另一个为分层部署铺平道路的项目是原子部署。


在原子部署前,每次部署操作都会导致一系列的错误,因为将新文件复制到生产服务器的过程不是 atomic。在这个过程中,它会产生一个比较小的时间窗口,在这个窗口中,新函数的调用点已经有了,而实际的实现函数还不可用。当调用这些调用点时,它们会返回内部错误,最终表现为失败的 API 请求和受损的 web 页面。


为解决这个问题而组织起来的团队最终使用冷热目录的方法解决了它。热目录用于处理生产流量,而冷目录则用于准备上线。在部署期间,新代码将被复制到未被使用的冷目录中。然后,等服务器上的所有活动进程都完全退出,我们就立即切换目录。



重新聚焦可靠性

2018 年,我们遇到一个问题,即不顾一切地快速部署,这只会对我们产品的稳定性造成损害。我们有一个非常强大的部署系统,公司也对它投入很大成本,但与部署有关的流程也有必要随之发展。随着我们的公司规模越来越大,在全球范围内为越来越多的关键任务协作提供支持,可靠性就成为重中之重。


对更安全部署的需求促使我们对部署系统进行彻底检查,由此引发的行动最终促成前面描述的基于百分比的部署系统。在底层,我们继续使用快速部署和原子部署,但我们改变了部署方式。这个系统以层的方式发布更新,再加上非常好用的监控系统和工具,让我们能在有缺陷的情况下,在对用户产生影响前找到问题,并减轻影响。


但是,我们还没有做到完美。通过更好的工具和自动化,我们不断改进这个系统。


特别感谢

本文讨论的工作包含以下同事的努力和项目:


  • 原子部署:Saroj Yadav、Chase Jenkins、Jamie Scheinblum

  • 部署系统的图形化界面:Andrew Morrison、Zack Sultan、Jonathan Chang

  • 快速部署:Paul Hammond、Joe Smith

  • 基于百分比的部署:David Stern、Harrison Page、Travis Crawford、Patrick Bogen

  • Dogfood Tier:Derek Smith、Jamie Scheinblum、Eve Killaby

  • 工作流和流程:Pooja Rana、Karen Xu


英文原文:


Deploys at Slack


2020 年 5 月 02 日 14:004391
用户头像

发布了 152 篇内容, 共 59.9 次阅读, 收获喜欢 55 次。

关注

评论

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

新手讲解this

前端树洞

JavaScript 面试 前端 js

(VMware)ubuntu 环境下搭建docker环境

逸少

Docker Docker-compose vmware Ubuntu20.04

ES2021 带来的新特性

KooFE前端团队

JavaScript 6 月日更 ES2021

这可能是介绍Android UvcCamera最详细的文章了

小驰嘻嘻

android 音视频 UvcCamera

网络攻防学习笔记 Day44

穿过生命散发芬芳

网络攻防 6月日更

【音视频】基于声网的多人视频通话功能建设

轻口味

android 音视频 IM 实时音视频 声网

MySQL基础之十一:创建表

打工人!

MySQL 6月日更

CSS 选择器总结

编程三昧

CSS html5 前端 DIV+CSS CSS选择器

模块6作业

薛定谔的指南针

架构实战营

中国数字化转型为全球带来机遇

CECBC区块链专委会

架构实战营-模块一作业

rubys_

架构实战营

《原则》(十三)

Changing Lin

6 月日更

从零开始搭建一个个人博客网站--Task0

IT蜗壳-Tango

django IT蜗壳教学 6 月日更 Datawhale

nacos配置中心模块详解

捉虫大师

nacos 配置中心

【21-6】PushGateway快速上手

耳东

Prometheus 6月日更 PushGateway

Kubernetes手记(10)- POD 存储卷

雪雷

k8s 六月日更

架构实战营模块6作业

梦寐凯旋

#架构实战营

架构实战营 - 模块 6- 作业

请弄脏我的身体

架构实战营

Git 各指令的本质,真是通俗易懂啊

xcbeyond

6月日更

JavaScript学习(二)

空城机

JavaScript 前端 6月日更

产品开发的过程

Qien Z.

运营管理 6月日更

我在Dubbo源码里学到了如何保证虚拟节点均匀分布!

Kareza

dubbo dubbo源码

🍃【SpringBoot技术专题】「StateMachine」FSM状态机设计及实现

李浩宇/Alex

springboot 6月日更 6 月日更 状态机 StateMachine

拆分电商系统为微服务

chenmin

不支持markdown表格内容导入离开这里了

Kevin

☕【JVM技术探索】重塑虚拟机性能调优计划

李浩宇/Alex

JVM jvm调优 GC调优 6月日更 6 月日更

【经验分享】RTC 技术系列之视频编解码

Hanson

实时音视频

「SQL数据分析系列」2. 创建和使用数据库

数据与智能

数据库 语法

算法之统计岛屿数量

Skysper

算法 深度优先搜索

【Vue2.x 源码学习】第十三篇 - 生成 ast 语法树 - 正则说明

Brave

源码 vue2 6 月日更

LeetCode 每日一题「判定字符是否唯一」

陈皮的JavaLib

Java 算法 LeetCode

新晋管理者都会遇到的6个问题

新晋管理者都会遇到的6个问题

Slack的部署实践-InfoQ