通过 RexRay 为 Docker Swarm 提供 EBS 卷的生命周期管理
解读
在国内公有云与混合云场景下,Docker Swarm 仍被不少金融、运营商及传统 ISV 用作轻量级编排方案。Swarm 自带的本地卷驱动无法跨节点漂移,而 AWS 官方提供的 Cloudstor 插件 在国内可用区受限,因此 RexRay 成为连接 Swarm 与 AWS EBS 的“桥梁”。面试官想验证候选人是否真正落地过 生产级持久化存储:既要让 EBS 卷像本地盘一样被容器声明,又要保证 故障转移、并发挂载、权限收敛、成本可控 四大维度无短板。回答时必须体现 国内网络隔离(VPC 内网 API 访问)、IAM 最小权限、Swarm 服务模型、故障演练 等真实痛点,而非简单跑通 hello-world。
知识点
- RexRay 架构:独立进程运行于每个 Swarm 节点,通过 libStorage 抽象层调用 AWS EC2 API,把 EBS attach/detach 动作翻译成 Docker Volume API。
- 并发控制:EBS 一次只能挂载到一台 EC2,RexRay 利用 AttachMutex 保证同一时刻仅一个节点持有设备;Swarm 通过 volume affinity 把 Pod(Task)调度到已挂载节点。
- IAM 最小权限:国内账号必须显式开启 “宁夏/北京区域”,策略仅允许
ec2:AttachVolume、ec2:DetachVolume、ec2:CreateVolume、ec2:DescribeVolumes、ec2:CreateSnapshot,禁止通配符。 - 安装方式:国内源推荐使用 阿里云 Docker CE 镜像站 安装 rexray/ebs 0.11.4 以上版本,配置
/etc/rexray/config.yml时 region 写成 cn-northwest-1 并指定 internal-endpoint=true,避免走公网。 - Swarm 服务声明:Compose v3.8 文件中使用 driver: rexray/ebs、driver_opts:size=20,iops=3000,encrypted=true,并加 volume-nocopy 防止初始化数据覆盖。
- 故障演练:模拟 EC2 宕机,观察 Swarm 在 30 s 内 将 Task 迁移到另一节点,RexRay 完成 detach→attach→mount→chown 全链路,业务 Pod 拉起后数据 MD5 一致;同时验证 快照策略 每日凌晨 02:00 自动创建,保留 7 天。
- 成本优化:使用 gp3 类型,基准 IOPS 3000 以下无需额外费用;启用 DeleteOnTermination=false 防止服务缩容时误删数据盘,通过 Tag 打上 Project/Owner,结合 Lambda+CloudCustodian 定时回收孤儿盘。
- 高阶加固:
- 开启 KMS 加密,密钥放在 北京区域 KMS;
- RexRay 进程以 非 root 用户 运行,配置 systemd 限制 MemoryMax=200M、CPUQuota=10%;
- 利用 AWS Config Rule 审计未加密卷;
- 在 Swarm 里给卷加 label:backup=true,结合 restic 做跨区备份到 S3 中国北。
答案
“我曾在某券商容器云项目落地 RexRay + EBS,支撑 200 节点的 Swarm 集群。总体分四步:
第一步,节点级安装与 IAM 角色。把 EC2 按照 Swarm worker/admin 两种角色分组,统一绑定 InstanceProfile,策略仅放开 EBS 生命周期 5 个 API;在 cn-northwest-1 内部 yum 源安装 rexray-0.11.4-1.x86_64.rpm,配置片段如下:
libstorage:
service: ebs
integration:
volume:
operations:
mount:
preempt: true
ebs:
region: cn-northwest-1
maxRetries: 10
tag: swarm
statusMaxAttempts: 30
statusInitDelay: 2s
useLargeDeviceRange: true
internal-endpoint=true 保证所有 AWS 调用走 VPC 内网,避免跨境流量。
第二步,Swarm 服务模板。Compose 文件采用 external: false 让 RexRay 按需创建 20 GiB gp3 卷,示例:
volumes:
orderdb:
driver: rexray/ebs
driver_opts:
size: 20
type: gp3
iops: 3000
encrypted: "true"
kmsKeyID: arn:aws-cn:kms:cn-northwest-1:123456:key/abcd
services:
mysql:
image: registry.cn-shanghai.aliyuncs.com/xxx/mysql:8.0
volumes:
- orderdb:/var/lib/mysql
deploy:
replicas: 1
placement:
constraints:
- node.labels.db==true
通过 node label 把有状态服务固定在 3 台 IO 优化型 c5d.xlarge,防止 EBS 频繁漂移。
第三步,故障转移验证。使用 chaosblade 模拟 EC2 强制关机,Swarm 在 28 s 后将 mysql 服务漂到另一台节点,RexRay 完成 detach/attach 耗时 17 s,容器重新挂载后 InnoDB 正常恢复,数据零丢失。期间 CloudWatch 记录到 VolumeState=available→in-use 状态变更。
第四步,运维闭环。
- 每天 02:00 通过 rexray snapshot create 生成快照,保留 7 天,快照名带 $(date +%F);
- 用 Lambda+CloudCustodian 扫描 status=available 且 CreateTime>7d 的卷,自动发企业微信告警,人工二次确认后删除;
- 接入 Prometheus,暴露 rexray_volume_used_percent 指标,>85% 触发 Alertmanager 回调扩容脚本,自动创建新卷并通过 mysqldump+replication 在线扩容。
上线半年,500+ EBS 卷 稳定运行,I/O 平均延迟 2.1 ms,存储成本较早期自建 Ceph 降低 38%,并一次性通过 等保 2.0 三级 评审。
拓展思考
- 如果客户要求 多可用区容灾,RexRay 无法直接挂载跨区卷,可考虑 EBS snapshot+AMI 方式在 灾备区 启动新实例,结合 Swarm global mode 做 冷备;或放弃 RexRay,改用 EFS 并部署 EFS-OneZone 以换取 RPO≈0,但需评估 IOPS 上限 10k 是否满足核心业务。
- 国内 金融专区 无法访问 AWS API,可把 RexRay 后端换成 华为云 EVS 或 阿里云 ESSD,开源 rexray/evs 驱动已停止维护,需要自研 CSI-Connector 并封装成 Docker Volume Plugin,此时建议直接迁移到 Kubernetes+CSI,Swarm 仅做过渡。
- 当容器密度高、卷数量 >1 k 时,RexRay 的 AttachMutex 会成为全局锁,并发创建耗时线性增长,可修改源码把 mutex key 由 volumeID 改为 volumeID+nodeID 分段锁,或采用 AWS Batch Attach 接口批量预挂载,降低 60% 等待时间。