本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。

ShareThis:生产环境中的 Kubernetes

ShareThis 自最初作为一个允许您分享到您喜爱社交服务的小部件以来,已经取得了巨大的发展。它现在每月服务超过450万个域名,帮助出版商创造更真实的数字体验。

快速增长也付出了代价。为了快速扩展和发展我们的产品,我们利用了技术债务,尤其是在基础设施方面。随着公司的扩张,基础设施成本也随之增加——无论是低效利用还是人员成本。大约1年前,很明显需要做出改变。

TL;DRKubernetes 一直是我们通过以下方式减少基础设施技术债务的关键组成部分:

  • 促进 Docker 的采用
  • 简化容器管理
  • 为开发人员提供基础设施培训
  • 实现持续集成和交付。我们通过彻底采用 Kubernetes 并将我们的 DevOps 团队转变为一个在容器和微服务方面工作的云平台团队来实现这一目标。这包括创建一些工具来解决我们自己的遗留债务。

问题

唉,云计算是新事物,我们当时也很年轻。我们从传统的数据中心思维方式开始。我们管理所有自己的服务:MySQL、Cassandra、Aerospike、Memcache,等等。我们像传统服务器一样设置虚拟机,在上面安装我们的应用程序,并在 Nagios 或 Ganglia 中进行管理。

不幸的是,这种思维方式与以云为中心的方法背道而驰。我们不是从服务的角度思考,而是从服务器的角度思考。我们没有使用现代的云方法,如自动伸缩、微服务,甚至托管虚拟机,而是考虑脚本化设置、服务器部署和避免供应商锁定。

这些思维方式本身并没有错,它们只是效率低下。它们没有充分利用云端正在快速发生的变化。这也意味着,当需要进行更改时,我们将其视为数据中心的重大缓慢更改,而不是云端的小型快速更改。

解决方案

Kubernetes 作为促进 Docker 采用的工具

随着 Docker 在我们行业中变得越来越强大,ShareThis 的工程师也开始尝试并取得了良好的效果。很快就显而易见,我们需要为公司中的每个应用程序提供一个工作容器,以便简化开发环境中的测试。

一些应用程序很快迁移到 Docker,因为它们简单且依赖项少。对于那些依赖项较小的应用程序,我们能够使用 Fig(Fig 是 Docker Compose 的原始名称)进行管理。尽管如此,我们的许多数据管道或相互依赖的应用程序都过于复杂,无法直接 Docker 化。我们仍然想这样做,但 Docker 仍不足够。

2015年末,我们对遗留基础设施的沮丧情绪达到了顶点,最终下定决心。我们评估了 Docker 的工具、ECS、Kubernetes 和 Mesosphere。很快就发现,Kubernetes 在稳定性和用户友好性方面比其竞争对手更适合我们的基础设施。作为一家公司,我们可以通过简单地设定将所有基础设施都迁移到 Kubernetes 的目标来巩固我们在 Docker 上的基础设施。

工程师们一开始持怀疑态度。然而,一旦他们看到应用程序能够轻松扩展到每个应用程序数百个实例,他们就被迷住了。现在,不仅有痛点推动我们转向 Docker,进而转向 Kubernetes,而且对这项技术也产生了真正的兴奋感。这使我们能够相当快地完成一次极其困难的迁移。我们现在在多个区域运行 Kubernetes,大约有65个大型虚拟机,并将在未来几个月内增加到100多个。我们的 Kubernetes 集群目前每天处理8亿个请求,并计划在未来几个月内每天处理超过20亿个请求。

Kubernetes 作为容器管理工具

我们最早使用 Docker 在开发方面前景光明,但在生产方面却不尽如人意。最大的摩擦点是无法大规模管理 Docker 组件。知道哪些容器在哪里运行,正在运行哪个部署版本,应用程序处于什么状态,如何管理子网和 VPC 等问题,都阻碍了它投入生产。所需的工具将是巨大的。

当您查看 Kubernetes 时,有几个关键功能立即吸引了我们:

  • 它很容易安装在 AWS 上(我们所有的应用程序都在那里运行)
  • 通过 yaml/json 文件,从 Dockerfile 到复制控制器有直接路径
  • Pod 数量可以轻松扩展
  • 我们可以轻松扩展 Kubernetes 集群中 AWS 上运行的虚拟机数量
  • 滚动部署和回滚内置于工具中
  • 每个 pod 都通过健康检查进行监控
  • 服务终结点由工具管理
  • 拥有一个活跃而充满活力的社区

不幸的是,最大的痛点之一是这些工具并没有解决我们现有的遗留基础设施问题,它只是提供了一个可以迁移到的基础设施。仍然存在各种网络问题,导致我们无法将应用程序直接迁移到新的 VPC 上。此外,对如此多应用程序的重构要求开发人员解决传统上由系统管理员和运营团队解决的问题。

Kubernetes 作为开发人员基础设施培训工具

当我们决定从本质上由 Chef 运行的设置切换到 Kubernetes 时,我想我们并没有完全理解所有会遇到的痛点。我们的服务器以各种不同的方式运行,配置了各种不同的网络,这与在全新 Kubernetes VPC 上找到的干净设置大相径庭。

在生产环境中,我们同时在多个区域的 AWS VPC 和 AWS 经典环境中运行。这意味着我们管理着几个具有不同访问控制的子网,这些子网跨越不同的应用程序。我们最近的应用程序也高度安全,没有公共端点。这意味着我们结合了 VPC 对等、网络地址转换 (NAT) 和以各种配置运行的代理。

在 Kubernetes 世界中,只有 VPC。所有 Pod 理论上都可以相互通信,并且服务终结点被明确定义。开发人员很容易忽略一些细节,并且它消除了(大部分)对操作的需求。

我们决定将所有基础设施/DevOps 开发人员转变为应用程序开发人员(真的!)。我们本来就根据他们的开发技能而非操作技能进行招聘,所以这听起来可能没有那么疯狂。

然后,我们决定对整个工程组织进行运维培训。开发人员适应性强,喜欢挑战,也喜欢学习。这真是了不起。仅仅一个月后,我们的组织就从只有少数 DevOps 人员,变成了每个工程师都能修改我们架构的团队。

网络、生产化、问题解决、根本原因分析等方面的入职培训,都是在将 Kubernetes 大规模投入生产中进行的。第一个月后,我还在咬指甲,担心我们的选择。两个月后,它看起来可能有一天会变得可行。三个月后,我们每周部署 10 次。四个月后,每周部署 40 个应用程序。虽然只有 30% 的应用程序完成了迁移,但所获得的收益不仅显著,而且令人惊叹。Kubernetes 让我们从一个“基础设施拖慢我们速度,太糟糕了!”的组织,变成了一个“基础设施加速我们速度,太棒了!”的组织。

Kubernetes 作为实现持续集成和交付的手段

我们是如何做到每周部署40多次的?简单来说,持续集成和部署(CI/CD)是我们迁移的副产品。我们在 Kubernetes 中的第一个应用程序是 Jenkins,并且每个进入 Kubernetes 的应用程序也都添加到了 Jenkins。随着我们前进,我们使 Jenkins 变得更加自动化,直到 Pod 被添加到 Kubernetes 和从 Kubernetes 中移除的速度快得我们无法跟上。

有趣的是,我们现在面临的扩展问题是,想要同时推出太多更改,人们不得不等待轮到他们。我们的目标是通过新基础设施每周实现100次部署。如果我们能继续执行我们的迁移和对 Kubernetes 和 Jenkins 上 CI/CD 流程的承诺,这是可以实现的。

后续步骤

我们需要完成迁移。目前,问题大多已解决,最大的困难在于任务的繁琐。将事物从我们的遗留基础设施中移出意味着更改网络配置,以允许访问 Kubernetes VPC 及其跨区域。这仍然是一个非常真实的痛点,我们仍在继续解决。

有些服务在 Kubernetes 中表现不佳——例如有状态分布式数据库。幸运的是,我们通常可以将这些服务迁移到第三方,由他们为我们管理。在本次迁移结束时,我们将只在 Kubernetes 上运行 Pod。我们的基础设施将变得更加简单。

所有这些改变都不是免费的;将我们整个基础设施都交给 Kubernetes 意味着我们需要有 Kubernetes 专家。我们的团队在基础设施方面已经摆脱了障碍,他们正忙于通过应用程序开发(这是他们应该做的)来增加业务价值。然而,我们目前还没有专门的工程师来及时了解 Kubernetes 和云计算的变化。

因此,我们已将一名工程师调到新的“云平台团队”,并将招聘另外几名工程师(我提到过我们正在招聘吗!)。他们将负责开发我们可以用来与 Kubernetes 良好交互并管理我们所有云资源的工具。此外,他们还将参与 Kubernetes 源代码,成为 Kubernetes SIG 的一部分,理想情况下,还会将代码推送到开源项目中。

总结

总而言之,虽然迁移到 Kubernetes 最初看起来令人生畏,但它远没有我们想象的那么复杂和具有破坏性。而最终的回报是,公司能够像客户期望的那样快速响应。编者注:在最近的一次 Kubernetes 聚会上,ShareThis 团队就他们在生产环境中使用 Kubernetes 进行了演讲。视频嵌入在下方。