[译] 去掉云计算和k8s —— 把应用迁移回本地

2023-4-5|2023-4-11
麦兜
麦兜
type
Post
status
Published
date
Apr 5, 2023
slug
summary
tags
category
翻译
password
icon
对于 37signals 的业务团队来说,2023年最大的努力成果就是消除云服务的依赖和迁移我们的应用到用我们自己搭建的数据中心。我们在非常短的时间得到令人惊叹的进展——让我们了解些细节。
 

我们为什么要这样做?

我们大多数的应用已经经历过各种云服务商和服务的漫长旅程。
 
起初,我们将应用从我们自己的数据中心迁移到 AWS ECS(Elastic Container Service),并许诺使用 Docker 容器化最终能节约成本。
 
我们非常喜欢 Docker,但是在 ECS 相对来说比较缺乏灵活性。因此,我们转向了 Goole Cloud 平台的 GKE (Google Kubernetes Engine) 尝试 Kubernetes,但是因为网络控制面板故障的阻碍我们不得不迅速撤退。我们没有被云服务劝退,我们迁移传统的应用至 AWS Kubernetes (EKS),直到今天有些还保留在那。
 
在这条路上你无法避免一些技术债和复杂性的积累。这不仅仅是改变你的部署方式:你还要发明一些工具去管理这些技术,还要创建有效的 CI/CD 去满足运维和开发。大多数情况下你还要重新思考你的监控策略。
 
甚至没有提到对于信息安全和运维安全的完全不同规范的必要性。接下来你还要培训员工这一切。稍等一会,我们去看一下由公有云服务商发来关于该资源维护终止的邮件… 等等 us-east-1 挂了?
 
Bottom line:你需要大量的流程才能把这件事做对。在很多地方,我们的投入超过了产出,这不仅仅是经济上还有运营上,这是我们的应用 Tadalist 运行在 EKS 的样子,这是从我们内部文档的到的信息。
 
 
+--------------------------------------------------------+ | eksctl VPC | | +----------------------------------------------+ | | | EKS | | | | +------------------------------+ +---------+ | | | | |app namespace | |default | | | | | | | |namespace| | | +-------------------+ | | +--------+ +--------+ +--------+ +---------+ | | | tadalist VPC | | | |pod | |pod | |pod | |pod | | | | | | | +--------+ +--------+ +--------+ +---------+ | | | +---------------+ | | | |Unicorn | |Unicorn | |Unicorn +-+Logstash | | | | | Services | | | | | | | | | | | | | | | | | | VPC | | +--------+ +--------+ +--------+ +---+-----+ | | | | +-----------+ | | Peering | | |Nginx | |Nginx | |Nginx | | | | | | | RDS | | <---------> | | | | | | +-----+ | | | | +-----------+ | | | | +-^------+-+-^------+-+-^------+ | | | +---------------+ | | | | | | | | +-------------------+ | | | | | | | | +----------------------------------------------+ | | | | | | | +-+----------+----------+---+ | | | Application Load Balancer | | | +------------^--------------+ | | | | +--------------------------------------------------------+ | | + Internet Traffic
 
看起来很简单吧? 注意仅仅是粗糙基础架构轮廓——运行它不包含全部辅助组件,比如
  • cluster-autoscaler
  • ingress controllers
  • storage drivers
  • external-dns
  • node termination handlers
  • complex networking concepts around VPN, peering, route tables, NAT, …
  • where DNS is handled
 
这也忽略了鉴权和资源访问管理组件这些也是需要维护的。甚至也没提到基础架构所需的代码。可以说,云计算并未实现使我们生活简便的承诺。
 
然而 Tadalist 是一个基础而且独立的 Rails 核心应用,对于我们其他更复杂的程序,它们的后端服务的依赖更多,所以并这不会变得更加容易。
 
我们的首次消除云服务的推动是把 (服务商提供的) Kubernetes 运行在我们自己的服务器,这样我们还能继续保持我们多年以来投资的大部分工作,"仅仅"需要把我们的工具迁移到新地方。另一个挑战是我们大部分的应用程序几年前已经被容器化,以更轻松地满足遗留要求 —— 我们希望保持这种方式。
 
这一切听起来像是双赢的局面,但是结果证明这是一个成本非常昂贵和在操作上非常复杂的想法,所以我们很快不得不重新考虑这个计划。
 

容器不错:迁移 Tadalist

Enter mrsk
mrsk 成为我们去云计算和k8s的计划核心典范:它为我们的容器化应用部署创造了简化的方法,同时极大提高了这个流程。我们能够保持大多数现有的容器化技术,同时还能保持在相对新的技术运行,新颖又熟悉的方式——我们已经使用 capistrano 部署了 Basecamp 4 和其他应用在数据中心好几年,而 mrsk也采用了同样的命令式。没有多余的控制面板,迁移的部件也很少。Nice!
 
Tadalist 是完美的候选项目:它在我们所有项目中风险是最低的而且也没有付费用户。它以前在我们所有的运营扮演了探索者的角色,这次也是这样。
 
当然不是那种”丢上去运行然后不管“那种过程。mrsk 在基础设施方面开始构建的同时也在积极地进行开发。我们不可能从一开始就就能迅速上手!我们还需要处理其他一些事情。

配置虚拟机

我们近年来非常注重云及其周边技术,因此我们对于本地基础设施供应的流程落后了一些。除了云迁移工作之外,我们还开始全面升级和简化我们的配置管理,并升级至最新版的 Chef
 
由于 mrsk 针对本地服务器进行部署,我们需要一个新的流程来快速且轻松地配置虚拟机。我们利用我们已有运行在纯 KVM-based VM 的经验,使用 cloud-init 简化了初始化,并将所有这些编排成一个单一的 Cookbook。这些改进使我们能够将每个虚拟机的全面bootstrapp 过程时间从约20分钟缩短到不到一分钟 —— 并且我们可以在KVM主机使用一个 chef converge 同时定义和启动多个虚拟机。
 
# Example definition from our cookbook node.default['guests'] = case node['hostname'] when "kvm-host-123" { "test-guest-101": { ip_address: "XX.XX.XX.XX/XX", memory: "8192", cpu: "4", disk: "30G", os: "ubuntu22.04", os_name: "jammy", domain: "guest.internal-domain.com" }, } when "kvm-host-456" { "test-guest-08": { ip_address: "XX.XX.XX.XX/XX", memory: "4096", cpu: "2", disk: "20G", os: "ubuntu18.04", os_name: "bionic", domain: "guest.internal-domain.com" }, } end include_recipe "::_create_guests"
 
# Excerpt from our ::_create_guests Chef recipe node['guests'].each do |guest_name, guest_config| execute "Create and start a new guest with virt-install" do command "virt-install --name #{guest_name} --memory #{guest_config[:memory]} \ --vcpus #{guest_config[:cpu]} --network bridge=br0,model=virtio --graphics none \ --events on_reboot=restart --os-variant #{guest_config[:os]} \ --import --disk /u/kvm/guests-vol/#{guest_name}-OS.qcow2 \ --noautoconsole --cloud-init user-data=/u/kvm/guests-config/user-data-#{guest_name},network-config=/u/kvm/guests-config/network-config-#{guest_name} \ --autostart" end end
 
这是一个巨大的速度提升,因为我们很快就会创建虚拟机,这些大多数都是简单的 boxes,除了基本的用户管理、Filebeat 配置和 Docker 安装之外,没有什么别的东西。

Logging

我们的日志记录管道是一个完全集成的 ELK 堆栈,可以与云端和本地堆栈进行互操作。mrsk 的日志是构建在 Docker logs 基础之上,因此我们只需要重新定向 Filebeat 来捕获位于 /var/lib/docker/containers/ 目录下的日志,并将它们发送到我们正在安装中的 Logstash。

CDN

多年以来,我们的利用 CloudFront 和 Route53 满足 CDN 和 DNS 需求,自然我们想切换用Cloudflare,它现在位于我们本地 F5 均衡负载的上层。

CI/CD

之前运行在 Buildkite,现在我们想切换到 Github Actions 的 CI/CD。
 
Spring Security 系列第0章InnoDB 的 Redo Log