我们将 GitLab.com 迁移到 Kubernetes 一年的发现

笔记。 翻译。:GitLab 采用 Kubernetes 被认为是促进公司发展的两个主要因素之一。 然而,直到最近,GitLab.com 在线服务的基础设施还是建立在虚拟机上,大约一年前才开始向 K8s 迁移,目前还没有完成。 我们很高兴提供 GitLab SRE 工程师最近发表的一篇文章的翻译,介绍了这种情况是如何发生的以及参与该项目的工程师得出的结论。

我们将 GitLab.com 迁移到 Kubernetes 一年的发现

大约一年来,我们的基础设施部门一直在将 GitLab.com 上运行的所有服务迁移到 Kubernetes。 在此期间,我们遇到的挑战不仅涉及将服务迁移到 Kubernetes,还涉及在过渡期间管理混合部署。 我们将在本文中讨论我们学到的宝贵经验教训。

从 GitLab.com 一开始,它的服务器就在云中的虚拟机上运行。 这些虚拟机由 Chef 管理并使用我们的安装 官方Linux包. 部署策略 如果需要更新应用程序,只需使用 CI 管道以协调、顺序的方式更新服务器群即可。 这个方法——虽然慢而且有点 平淡 - 确保 GitLab.com 使用与离线用户相同的安装和配置实践 (自我管理) 为此,使用我们的 Linux 软件包进行 GitLab 安装。

我们使用这种方法是因为体验社区普通成员在安装和配置 GitLab 副本时所经历的所有悲欢离合是极其重要的。 这种方法在一段时间内效果很好,但当 GitLab 上的项目数量超过 10 万时,我们意识到它不再满足我们扩展和部署的需求。

Kubernetes 和云原生 GitLab 的第一步

该项目创建于2017年 亚搏体育appGitLab图表 准备 GitLab 进行云部署,并使用户能够在 Kubernetes 集群上安装 GitLab。 当时我们就知道,将 GitLab 迁移到 Kubernetes 将提高 SaaS 平台的可扩展性、简化部署并提高计算资源的效率。 同时,我们应用程序的许多功能都依赖于挂载的 NFS 分区,这减慢了从虚拟机的过渡速度。

云原生和 Kubernetes 的推动使我们的工程师能够计划逐步过渡,在此期间我们放弃了应用程序对网络存储的一些依赖,同时继续开发新功能。 自从我们在 2019 年夏天开始计划迁移以来,许多限制已经得到解决,将 GitLab.com 迁移到 Kubernetes 的过程现在正在顺利进行!

Kubernetes 中 GitLab.com 的功能

对于 GitLab.com,我们使用单个区域 GKE 集群来处理所有应用程序流量。 为了最大限度地降低(已经很棘手的)迁移的复杂性,我们专注于不依赖本地存储或 NFS 的服务。 GitLab.com 主要使用整体 Rails 代码库,我们根据工作负载特征将流量路由到隔离到各自节点池中的不同端点。

就前端而言,这些类型分为对 Web、API、Git SSH/HTTPS 和注册表的请求。 在后端的情况下,我们根据不同的特征来拆分队列中的作业,具体取决于 预定义的资源边界,这使我们能够为各种工作负载设置服务级别目标 (SLO)。

所有这些 GitLab.com 服务都是使用未经修改的 GitLab Helm 图表进行配置的。 配置是在子图中进行的,随着我们逐步将服务迁移到集群中,可以选择性地启用子图。 尽管我们决定不在迁移中包含一些有状态服务,例如 Redis、Postgres、GitLab Pages 和 Gitaly,但使用 Kubernetes 使我们能够从根本上减少 Chef 当前管理的虚拟机数量。

Kubernetes 配置可见性和管理

所有设置均由 GitLab 本身管理。 为此,使用了三个基于 Terraform 和 Helm 的配置项目。 我们尝试尽可能使用 GitLab 本身来运行 GitLab,但对于操作任务,我们有单独的 GitLab 安装。 这是为了确保您在执行 GitLab.com 部署和更新时不依赖于 GitLab.com 的可用性。

尽管我们的 Kubernetes 集群管道在单独的 GitLab 安装上运行,但代码存储库的镜像可在以下地址公开获得:

  • k8s-工作负载/gitlab-com — GitLab Helm 图表的 GitLab.com 配置框架;
  • k8s-工作负载/gitlab-helmfiles - 包含与 GitLab 应用程序不直接关联的服务的配置。 其中包括日志记录和集群监控的配置,以及 PlantUML 等集成工具;
  • Gitlab-com-基础设施 — Kubernetes 和旧 VM 基础设施的 Terraform 配置。 您可以在此处配置运行集群所需的所有资源,包括集群本身、节点池、服务帐户和 IP 地址预留。

我们将 GitLab.com 迁移到 Kubernetes 一年的发现
进行更改时会显示公共视图。 简短的摘要 包含指向 SRE 在对集群进行更改之前分析的详细差异的链接。

对于 SRE,该链接会导致 GitLab 安装中的详细差异,该安装用于生产且访问受到限制。 这使得员工和社区无需访问运营项目(仅对 SRE 开放)即可查看建议的配置更改。 通过将代码的公共 GitLab 实例与 CI 管道的私有实例相结合,我们维护了单一工作流程,同时确保配置更新独立于 GitLab.com。

我们在迁移过程中发现了什么

在迁移过程中,我们获得了应用于 Kubernetes 中新迁移和部署的经验。

1. 可用区之间的流量导致成本增加

我们将 GitLab.com 迁移到 Kubernetes 一年的发现
GitLab.com 上 Git 存储库群的每日出口统计信息(每天字节数)

谷歌将其网络划分为多个区域。 这些又被划分为可访问区域 (AZ)。 Git托管与大量数据相关,因此控制网络出口对我们来说很重要。 对于内部流量,只有在同一可用区域内,出口才是免费的。 截至撰写本文时,我们在一个典型工作日中提供大约 100 TB 的数据(这仅适用于 Git 存储库)。 在基于 VM 的旧拓扑中,驻留在同一虚拟机中的服务现在在不同的 Kubernetes Pod 中运行。 这意味着之前位于虚拟机本地的一些流量可能会传输到可用区域之外。

区域 GKE 集群允许您跨越多个可用区以实现冗余。 我们正在考虑可能性 将区域 GKE 集群拆分为单专区集群 用于产生大量流量的服务。 这将降低出口成本,同时保持集群级冗余。

2. 限制、资源请求和扩展

我们将 GitLab.com 迁移到 Kubernetes 一年的发现
在registry.gitlab.com 上处理生产流量的副本数量。 世界标准时间 (UTC) 左右的流量高峰期为 15:00。

我们的迁移故事始于 2019 年 XNUMX 月,当时我们将第一个服务 GitLab 容器注册表迁移到 Kubernetes。 这种关键任务、高流量的服务是第一次迁移的不错选择,因为它是一个无状态应用程序,几乎没有外部依赖项。 我们遇到的第一个问题是由于节点内存不足而导致大量 pod 被驱逐。 因此,我们必须更改请求和限制。

人们发现,在内存消耗随时间增加的应用程序的情况下,低请求值(为每个 Pod 保留内存)加上“慷慨”的使用硬限制会导致饱和 (饱和) 节点和高水平的驱逐。 为了解决这个问题, 决定增加请求并降低限制。 这减轻了节点的压力,并确保 Pod 的生命周期不会给节点带来太大的压力。 现在,我们以慷慨(且几乎相同)的请求和限制值开始迁移,并根据需要进行调整。

3. 指标和日志

我们将 GitLab.com 迁移到 Kubernetes 一年的发现
基础设施部门重点关注延迟、错误率和已安装的饱和度 服务水平目标 (SLO) 链接到 我们系统的普遍可用性.

在过去的一年里,基础设施部门的关键事件之一是监控和与 SLO 合作的改进。 SLO 使我们能够为迁移过程中密切监控的各个服务设定目标。 但即使可观察性得到提高,也并不总是能够使用指标和警报立即发现问题。 例如,通过关注延迟和错误率,我们并没有完全涵盖正在迁移的服务的所有用例。

在将一些工作负载迁移到集群后几乎立即发现了这个问题。 当我们必须检查请求数量很少但具有非常具体的配置依赖性的函数时,它变得尤其尖锐。 迁移的主要教训之一是不仅需要在监控时考虑指标,还需要考虑日志和“长尾” (这是关于 这样他们的分布 在图表上 - 大约。 译) 错误。 现在,对于每次迁移,我们都包含详细的日志查询列表 (日志查询) 并计划明确的回滚程序,如果出现问题,可以从一个班次转移到下一个班次。

在旧的虚拟机基础设施和新的基于 Kubernetes 的基础设施上并行服务相同的请求提出了独特的挑战。 与直接迁移不同 (将应用程序“按原样”快速转移到新的基础设施;可以阅读更多详细信息,例如, 这里 - 大约。 译),“旧”虚拟机和 Kubernetes 上的并行工作要求监控工具与这两种环境兼容,并且能够将指标组合到一个视图中。 重要的是,我们使用相同的仪表板和日志查询来在过渡期间实现一致的可观察性。

4. 将流量切换到新集群

对于 GitLab.com,部分服务器专用于 金丝雀阶段。 Canary Park 服务于我们的内部项目,也可以 由用户启用。 但它的主要目的是测试对基础设施和应用程序所做的更改。 第一个迁移的服务首先接受有限数量的内部流量,我们继续使用此方法来确保在将所有流量发送到集群之前满足 SLO。

在迁移的情况下,这意味着对内部项目的请求首先发送到 Kubernetes,然后我们通过 HAProxy 改变后端的权重来逐渐将其余流量切换到集群。 在从虚拟机迁移到 Kubernetes 的过程中,很明显,有一种简单的方法可以在新旧基础设施之间重定向流量,从而使旧基础设施在迁移后的最初几天内做好回滚的准备。

5. Pod 的储备容量及其使用

几乎立即就发现了以下问题:Registry 服务的 pod 启动很快,但启动 Sidekiq 的 pod 需要花费 XNUMX分钟。 当我们开始将需要快速处理作业和快速扩展的工作负载迁移到 Kubernetes 时,Sidekiq Pod 的启动时间过长就成为了一个问题。

在这个案例中,我们得到的教训是,虽然 Kubernetes 的 Horizo​​ntal Pod Autoscaler (HPA) 可以很好地处理流量增长,但考虑工作负载的特征并向 Pod 分配备用容量(特别是当需求分布不均匀时)也很重要。 在我们的例子中,作业突然激增,导致快速扩展,从而导致 CPU 资源在我们有时间扩展节点池之前就饱和。

总是有一种诱惑,即从集群中挤出尽可能多的资源,但是,由于最初遇到了性能问题,我们现在从慷慨的 pod 预算开始,然后减少预算,密切关注 SLO。 Sidekiq 服务的 pod 启动速度显着加快,现在平均需要约 40 秒。 减少吊舱的启动时间 赢得了 GitLab.com 和我们使用官方 GitLab Helm 图表进行自我管理安装的用户。

结论

迁移每个服务后,我们对在生产中使用 Kubernetes 的好处感到高兴:更快、更安全的应用程序部署、扩展和更高效的资源分配。 此外,迁移的优势不仅仅限于 GitLab.com 服务。 官方 Helm 图表的每一项改进都会让用户受益。

我希望您喜欢我们的 Kubernetes 迁移冒险故事。 我们继续将所有新服务迁移到集群。 更多信息可在以下出版物中找到:

译者PS

另请阅读我们的博客:

来源: habr.com

添加评论