我的 kamal 生产环境配置

Kamal 是 Basecamp 开源的一款部署工具,它的工作模式类似 Capistrano,但使用 docker 解决依赖封装。它原始设计用于 Rails 应用,由于使用了 docker,只要应用可以 docker 化也能使用 kamal 部署。

Kamal 的使用率在 Rails 社区越来越高,问题也随之出现:Build 的过程遇到网络问题怎么办?Secret 应该存在哪里?怎么配置 CI/CD?

这些问题我在实践中也解决过,在此分享我的解决方案。方案不是唯一的,有其他方案欢迎在评论区留言。

本文假设你已经读过 Kamal 官方文档,熟悉 Docker 使用,熟悉云平台 VPC、安全组等设置。

概览

首先对整个部署架构有个整体概览:

kamal-production.png

下面我逐个分析。

为什么需要 deploy server

Kamal 的配置和运行应该放在哪里?我的选择是单独配置一台 deploy server,并且放在境外机房。这是有两个考虑:

网络问题

Docker build 的过程很容易被网络问题阻塞,只要把 deploy server 放在境外,问题就解决了。一并解决的还有 rubygem、npm 包安装的网络问题等,不用再配置国内镜像。

Secrets 管理

Secrets 管理是我不在 CI/CD 服务器(例如 GitHub Action)上配置 Kamal 的原因。

当前 Kamal 2.x 版本需要在 deploy 的时候获取所有环境变量,然后覆盖到 app server。如果在 CI/CD 服务器执行 kamal,就要让 CI/CD 服务器获取所有环境变量,包括 secrets。我认为这是一个安全隐患,试想一下某一天 CI/CD 服务器泄漏了支付网关的密钥?

作为参考,GitHub Action 一个流行插件 Tj-actions/changed-files 被注入恶意代码事件:https://news.ycombinator.com/item?id=43367987

额外配置一台 deploy server,将 kamal 配置和 secrets 放在 deploy server 上。需要人工操作的时候登录 deploy server 执行。

CI/CD 如何触发 Deploy

CI/CD 通过 ssh 连接 deploy server,并且使用 ForceCommand 限制这个 ssh key 只能执行 deploy 命令。

ForceCommand 的设置方法是在 .ssh/authorized_keys 的对应 public key 位置添加 command="..." 参数,例如:

command="/path/to/deploy.sh" ssh-ed25519 AAA... GHA

其中 deploy.sh 脚本包含执行 kamal deploy 的所有操作,例如:

#!/bin/bash

cd /path/to/source
git fetch origin
git reset --hard origin/master
kamal deploy

ForceCommand 的设置很重要,不然 CI/CD 的 key 泄露会成为一个安全漏洞。

VPC 设置

如果 deploy server 和 app server 在同一家云服务商,可以通过跨 VPC 互联的方式将两类服务器置于同一个局域网下。app server 只需要内网 IP,不暴露在公网。Deploy server 通过内网 IP 部署到 app server。

Docker Registry 的位置

Kamal deploy 的过程需要将 app 镜像 push 到 docker registry。由于网络原因,Docker Registry 最好贴近部署区域。以阿里云为例,如果部署在阿里云杭州区域,那么选择阿里云 registry 的杭州区域。

在实践中我发现从境外往境内 push 问题较少,从境外往境外 pull 问题较多。

Registry 代理

Kamal deploy 的过程需要在 app server pull kamal proxy 的镜像,也会遇到网络问题(wtf)。我的解决方法是自建 docker registry 代理,之前已经写了一篇博客:自建 docker 镜像服务

使用托管数据库

虽然 kamal accessory 有管理 DB 的能力,但容器不擅长管理有持久化需求的服务,所以我建议使用云平台的数据库。使用托管数据库更容易实现备份、升级等操作。

总结

以上就是我的 kamal 生产环境配置的要点。一些与 kamal 无关的配置例如 CI 配置、Web server 配置就不在这里赘述。

可以看到 kamal 生产环境需要一些额外资源和配置,对于小型应用来说有点繁琐。所以我的个人项目会使用 Fly 部署,平台默认提供了以上基础设施。对于需要部署在国内的应用,我会用 Kamal,因为它相比其他容器部署工具要简单。

有任何意见建议?欢迎在评论区交流。

4
所有评论 2
avatar

感谢分享。请问这个经验适用于最新 kamal 2 吗?