【问题标题】:Cloud run with database migrations云运行与数据库迁移
【发布时间】:2020-05-02 07:49:18
【问题描述】:

我想在云运行入口点(例如 php artisan migrate)中运行数据库迁移,以避免在升级之前必须使用外部工具来运行这些。

在 kubernetes 中,可以通过让部署中的 init 容器运行迁移并将最大浪涌设置为 1 来实现此功能,确保只有一个 pod 尝试迁移,然后再部署到其他容器。

CloudRun 的推出策略是否已在任何地方定义?如果 CloudRun 在修改批发之前等待一个容器处于健康状态会很好,这将满足此目的(尽管如果多个容器尝试迁移,postgres 事务 DDL 的问题还不错)。我认为这是我观察到但不确定的行为。

有没有比在每个入口点运行迁移更好/维护成本低的方法?

【问题讨论】:

    标签: google-cloud-run


    【解决方案1】:

    在 kubernetes 中,可以通过让部署中的 init 容器运行迁移并将最大浪涌设置为 1 来实现此功能,确保只有一个 pod 尝试迁移,然后再部署到其他容器。

    这通常不是一个好的做法,即使在 Kubernetes 中也是如此。

    理想情况下,您的数据库迁移代码应为idempotent。尤其是在无服务器世界中,除非您转变思维方式并思考这些概念,否则您会发现缺少这些原语令人惊讶。

    Cloud Run 的推出策略是通过配置手动流量拆分 - 根据您定义的百分比在修订之间路由流量。

    您可以开发 Cloud Run 服务的新版本,接收 0% 的流量。

    部署修订版后,Cloud Run 仍将运行至少一个容器,以查看应用是否准备就绪(即进程开始在 PORT 上侦听)。不过,您可能不应该依赖在此过程中仅出现 1 个实例,因为这不是保证行为。

    使用此技巧,您可以在侦听端口号之前执行数据库迁移(请注意启动超时文档的“限制”部分)。但是您需要编写一些逻辑(或使用外部锁定/同步机制)以确保代码路径不会在未来(或在迁移发生的同时)一遍又一遍地执行。

    【讨论】:

    • 谢谢,这澄清了事情。 db 迁移是幂等的(在 laravel 中)并且也是容错的(仅在 postgres 中),因此同时尝试不会导致数据损坏,并且不需要单独的锁定解决方案。如果同时进行 10 次尝试,最好避免其他容器迁移失败的错误。我知道上面描述的方法并不能保证只有一次并发尝试,而是最干净的方法,无需借助例如在 helm 中预安装钩子。但是我发现每次在入口点运行artisan migrate 太慢了
    • 我也在使用云运行管理,所以不能做流量拆分。我最初的测试表明,每次在入口点运行 php artisan migrate 太慢并且影响了 pod 启动时间,但这可能可以通过更多检查来解决。
    • 我的糟糕,流量拆分即将推出完全托管的 Cloud Run,敬请期待。
    【解决方案2】:

    Cloud Run 上没有就绪探测。部署新修订时:

    • 容器已下载
    • 容器已启动
      • 如果容器启动失败 -> 错误消息
      • 否则,将流量配置切换到新版本

    通过这最后一步,新流量被路由到新修订版,之前收到的请求并已路由到之前的修订版继续在之前的实例上处理。

    这是简单的版本。在可持续流量的情况下,并行有多个实例,它会更加复杂。

    希望这些意见对您有所帮助!

    【讨论】:

    • 谢谢!后一种情况是我感兴趣的。假设 10 个容器在修订版 1 下运行,部署了修订版 2,它是启动第 11 个容器并等到健康,还是同时启动 11 和 12 个容器(相当于 25% k8s 部署的推出策略)。另一个问题,我没有在任何地方看到实际的运行状况检查,它是针对 $PORT 的 HttpGet 吗?
    • 当容器启动时,检查完成:进程是否正在运行?预期的端口是开放的吗?没有特别的健康检查,可能一天。关于多实例滚动更新,目前还没有明确的解决方案。谷歌方面总是有演变。据我所知,流量是在大部分实例更新后路由的。
    猜你喜欢
    • 2011-06-25
    • 1970-01-01
    • 2022-12-23
    • 2014-03-05
    • 1970-01-01
    • 2016-09-19
    • 1970-01-01
    • 1970-01-01
    • 2020-09-25
    相关资源
    最近更新 更多