无状态应用 + 持久化数据
开始之前,请先阅读:
本文档将帮助你搭建“无状态应用 + 持久化数据”的方案。例如:使用 "php:7.4-apache" 托管的网站,将 "uploads"(/var/www/html/uploads)目录(或你自定义的其他目录)存放到 AWS、Wasabi S3 等对象存储,或任何其他 rclone 支持的存储系统。这样一来,原本可能被固定在某个节点(例如节点 X)上的应用,也可以在同一个 Docker swarm 内故障切换到其他节点。
为了实现上述方案,可以使用多种 Docker volume 插件。我 @Daniël 和同事 Floris 一开始使用的是 "rexray/s3fs",后来因为 "sapk/plugin-rclone" 更稳定、且更擅长处理从节点 X 切换到节点 Y 的故障转移,于是改用了它。
**重要说明:**以下步骤适用于中级与高级(Linux)用户。
占位变量
$volumename例如可以是captain--yourappname-rclone$remotename例如可以是captain--yourappname$remotename/path例如可以是captain--yourappname/_data$rcloneremotename例如可以是wasabi-s3
1) 准备 rclone
首先创建 rclone.conf 文件,你可以在任何安装了 rclone 的(本地)机器上完成。
为方便说明,本文档假设你已在 Docker swarm 的主节点上 安装 rclone。
在主节点上运行 "rclone config" 来创建配置文件,完成后再运行 rclone config file 以查看配置文件的存放位置。
如果你使用 root 用户,它通常会存放在 /root/.config/rclone/rclone.conf,后续内容将以此路径作为参考。
rclone.conf 文件大致如下所示:
[$rcloneremotename]
type = s3
provider = Wasabi
access_key_id = YourAccessKey
secret_access_key = YourSecretAccessKey
region = eu-central-1
endpoint = s3.eu-central-1.wasabisys.com
env_auth = false
upload_cutoff = 25M
chunk_size = 5M
disable_checksum = false
upload_concurrency = 3确保每个 swarm 节点都存在 /root/.config/rclone/rclone.conf,并且内容完全一致;你可以通过 md5sum /root/.config/rclone/rclone.conf 对比校验和来确认。
或者至少确保在存在多个配置时,你实际使用的那份配置在所有节点上是一致的。
2) 准备存储系统
确保你的 S3 bucket(或你在 rclone config 中配置的存储系统上将要使用的目录)实际存在,并且 bucket/目录名与 $remotename 一致。
3) 准备 Docker rclone 插件
在每个 swarm 节点上,通过 docker plugin install sapk/plugin-rclone 安装 Docker volume 插件。
然后在每个节点上执行下面的命令。以下命令是专为 "php:N.N-apache" 容器准备的(例如 php:7.4-apache)。
docker volume create --driver sapk/plugin-rclone --opt config="$(base64 /root/.config/rclone/rclone.conf)" --opt args="--uid 33 --gid 33 --allow-root --allow-other" --opt remote=$rcloneremotename:$remotename/path --name $volumename如果你使用的是 S3 bucket,且文件会通过 AWS/Wasabi 的 Web 界面或其他方式(例如将 SFTPGo 挂载到 S3 bucket)上传,那么你需要让 rclone 刷新其目录缓存:
docker volume create --driver sapk/plugin-rclone --opt config="$(base64 /root/.config/rclone/rclone.conf)" --opt args="--uid 33 --gid 33 --allow-root --allow-other --dir-cache-time 5s" --opt remote=$rcloneremotename:$remotename/path --name $volumename其工作方式是:通过 "rclone mount" 将 volume 挂载到 Docker swarm 节点上。不过需要注意,其他参数/标志位可能会改善或降低你的应用体验,因此建议在使用过程中进行充分测试。
上面的 UID 与 GID 是为 Apache2 匹配的;对于其他应用可能需要使用不同的值。
4) 准备应用
接下来部署一个空白应用,并确保 "Has Persistent Data" 未勾选,然后在 "HTTP Settings"、"App Configs" 与 "Deployment" 标签页中按需配置参数。
在 "App Configs" 的 "Service Update Override" 区域,填入如下内容。
注意:/var/www/html/uploads 是示例路径/目录,你应根据自己的应用情况自行定义,这里仅作参考。
根据你的应用需求,将 "ReadOnly" 设置为 true 或 false。
如果你的 PHP 应用允许用户上传文件,请将其设为 false。
TaskTemplate:
ContainerSpec:
Mounts: [
{
"Type": "volume",
"Source": "$volumename",
"Target": "/var/www/html/uploads",
"ReadOnly": false
}
]这样运行在 "php:7.4-apache" 上的应用就可以从 node1 迁移到任何已正确配置的其他节点上。
如果你有问题或遇到故障,请在 Slack 的 General 频道联系;如有需要可以 @ 我 @Daniël,我或其他人会尽力协助你解决。