跳到内容
SIAX.io

迁移指南 · 来自 Heroku

从 Heroku 迁移到 SIAX

Heroku 在别人之前就实现了轻松部署,这种简洁性有一部分至今仍然难以超越。真正让团队迁移的原因很少是技术,而常常是成本:按 dyno 定价、每个单独看起来都不贵但加在一起成为一笔可观开支的 add-on,以及一个近年来发展缓慢的平台。

在我们这里,你把 web 进程和后台进程作为容器运行在 App Hosting 上,数据库用 Managed Postgres,凡是没有托管对应物的东西就放在 VPS 上。月费用变得可预测,而且在你需要的地方还有 root 权限。

棘手的部分不是应用,而是 add-on 生态。Heroku 让点击一下就能接入一个服务变得很容易,大多数团队拥有的 add-on 比他们记得的还多。每一个都必须单独替换,而有些根本没有明显的对应物。这部分预计会比应用本身的迁移花更多时间。

所需时间

一个带一个 web 进程和一个 Postgres 的应用需要一天。如果你有五个以上 add-on、后台任务和定时运行,则需要一到两周。

停机时间

并行运行的话,应用可以不间断迁移。数据库需要一个写入窗口:对小型数据库来说,dump 加 restore 只需几分钟;大型数据库则更久。用逻辑复制可以缩短到几秒。

01

操作步骤

  1. 1

    盘点 dyno、add-on 和 config vars

    为每个应用运行 heroku ps、heroku addons 和 heroku config 并保存输出。记录每个进程类型的 dyno 类型和数量,以及每个 add-on 所在的计划档位。这份清单就是新环境的规格说明,而且它几乎总是比团队猜测的要长。

  2. 2

    用 Dockerfile 替换 buildpack

    Heroku 在背后替你做了大量无形的工作:安装依赖、编译资源、设置 PORT,并启动 Procfile 里定义的东西。所有这些都需要在你的 Dockerfile 中显式表达。绑定环境变量指定的 PORT,而不是硬编码端口。如果你想再多用一段时间 buildpack 模式,也可以选择用 pack CLI 运行 Cloud Native Buildpacks。

  3. 3

    逐个替换每个 add-on

    逐条过这份清单。Heroku Postgres 变成 Managed Postgres。Heroku Data for Redis 变成 VPS 上的 Redis 或 Valkey,由你自己更新和备份。Papertrail 之类的日志和正常运行时间服务,由我们的监控来替代(用于检查)以及一个你自选的日志接收端。通过 SendGrid 发送的外发邮件换成我们的邮件服务或外部 SMTP 提供商。没有对应物的 add-on 要么保留为供应商的独立订阅,要么由你自己运营。

  4. 4

    迁移 Postgres

    先确认你实际用到的扩展,而不是碰巧安装了哪些。用 custom 格式导出一份 pg_dump,然后对新实例执行 pg_restore,并在碰生产环境之前先针对副本测试整条路径。对于超过几十 GB 的数据库,设置逻辑复制,等副本追上进度后再切换连接字符串。注意 Heroku 的 DATABASE_URL 可能被轮换,而且 sslmode 设置往往不同。

  5. 5

    迁移 worker 进程和定时任务

    Procfile 中的每种进程类型在咱们这里都成为独立的部署。Worker dyno 变成面对同一队列的独立容器。Heroku Scheduler 由容器内的 cron 或 CI 定时任务替代。你以前用 heroku run 做的一次性运行需要新的例行做法,比如在运行中的容器里开 shell,或手动触发的任务。

  6. 6

    设置部署与密钥

    把仓库连接到 Git 和 CI,让推送到 main 时构建镜像并部署。把所有 config vars 移到密钥管理器,并在迁移的同时轮换它们,因为它们现在已经经历了一次导出。验证应用恰好用你打算在生产运行的那组变量启动,而不是一个子集。

  7. 7

    并行运行、切换 DNS 并停用

    让 Heroku 应用继续承载生产流量,同时新环境驻留在暂存地址上。用至少一整天的真实流量比较日志、错误率和响应时间。然后降低 TTL、切换 DNS,再让 Heroku 运行大约一周,之后把 dyno 缩到零并取消 add-on。

02

真正棘手的地方

  • Add-on 不是按一个按钮就能替换的。每项服务都必须单独评估、替换和测试,有些甚至完全没有好的对应物。这通常是时间表上最大的一项。
  • 我们没有托管 Redis 这个产品。需要 Redis 或 Valkey?那就运行在 VPS 上,从每月 59 克朗起,更新、内存限制和备份都由你负责。
  • Buildpack 的魔法在消失之前是看不见的。自动资源编译、PORT 绑定和被注入的环境变量不再自动发生,必须在 Dockerfile 里显式写出来。
  • Heroku 每天都会重启你的 dyno。存在缓慢内存泄漏的代码可能一直藏着在这个周期后面,只有容器得以存活数周后才会暴露出来。
  • Review apps 和 pipelines 不是内置功能。你可以用 CI 里的分支部署来构建等价物,但这是你需要规划的活,而不是一个设置开关。
03

成本示例

一个应用,带一个 web 进程、一个 worker、一个 Postgres、Redis 和每日备份:App Hosting 的 web 从 99 克朗起、worker 从 99 克朗起,Managed Postgres 从 89 克朗起,用于 Redis 的 VPS 从 59 克朗起,100 GB 备份 19 克朗,因此每月大约 365 克朗,不含增值税。在 Heroku 那边,两个 Standard dyno、Postgres Standard-0 和一个 Redis 计划,按月费表大约在 1,200 到 1,400 克朗之间,而且价格一直在变。

04

常见问题

我们能保留现有的 buildpack 吗?
不能直接保留,我们运行容器。要么你写一个 Dockerfile(我们长期来看也建议这么做),要么你用 pack CLI 从现有 buildpack 构建一个 OCI 镜像。第二个选择能缩短迁移时间,但会把工作推迟到以后。
你们有托管 Redis 吗?
没有。Redis 和 Valkey 运行在 VPS 或专用服务器上。最终会比 Heroku 的计划更便宜,但运营要由你接手:更新、内存策略、持久化和备份。
我们的 Postgres 扩展能带过来吗?
常见的都可以,包括 pg_stat_statements、pgcrypto、uuid-ossp 和 PostGIS。非常规或 Heroku 特有的扩展必须在你规划切换之前验证,而不是之后。把数据库里的清单发给我们,我们会给你一个具体的答复。
Heroku Connect 或其他没有对应物的 add-on 怎么办?
要么你把这服务保留为供应商的独立订阅,要么你用一个自己运营的东西来替代这个功能。我们不会假装一切都能无缝搬运,而且这个评估应该在设定迁移日期之前完成。