通过 RexRay 为 Docker Swarm 提供 EBS 卷的生命周期管理

解读

在国内公有云与混合云场景下,Docker Swarm 仍被不少金融、运营商及传统 ISV 用作轻量级编排方案。Swarm 自带的本地卷驱动无法跨节点漂移,而 AWS 官方提供的 Cloudstor 插件 在国内可用区受限,因此 RexRay 成为连接 Swarm 与 AWS EBS 的“桥梁”。面试官想验证候选人是否真正落地过 生产级持久化存储:既要让 EBS 卷像本地盘一样被容器声明,又要保证 故障转移、并发挂载、权限收敛、成本可控 四大维度无短板。回答时必须体现 国内网络隔离(VPC 内网 API 访问)、IAM 最小权限、Swarm 服务模型、故障演练 等真实痛点,而非简单跑通 hello-world。

知识点

  1. RexRay 架构:独立进程运行于每个 Swarm 节点,通过 libStorage 抽象层调用 AWS EC2 API,把 EBS attach/detach 动作翻译成 Docker Volume API。
  2. 并发控制:EBS 一次只能挂载到一台 EC2,RexRay 利用 AttachMutex 保证同一时刻仅一个节点持有设备;Swarm 通过 volume affinity 把 Pod(Task)调度到已挂载节点。
  3. IAM 最小权限:国内账号必须显式开启 “宁夏/北京区域”,策略仅允许 ec2:AttachVolumeec2:DetachVolumeec2:CreateVolumeec2:DescribeVolumesec2:CreateSnapshot,禁止通配符。
  4. 安装方式:国内源推荐使用 阿里云 Docker CE 镜像站 安装 rexray/ebs 0.11.4 以上版本,配置 /etc/rexray/config.yml 时 region 写成 cn-northwest-1 并指定 internal-endpoint=true,避免走公网。
  5. Swarm 服务声明:Compose v3.8 文件中使用 driver: rexray/ebsdriver_opts:size=20,iops=3000,encrypted=true,并加 volume-nocopy 防止初始化数据覆盖。
  6. 故障演练:模拟 EC2 宕机,观察 Swarm 在 30 s 内 将 Task 迁移到另一节点,RexRay 完成 detach→attach→mount→chown 全链路,业务 Pod 拉起后数据 MD5 一致;同时验证 快照策略 每日凌晨 02:00 自动创建,保留 7 天。
  7. 成本优化:使用 gp3 类型,基准 IOPS 3000 以下无需额外费用;启用 DeleteOnTermination=false 防止服务缩容时误删数据盘,通过 Tag 打上 Project/Owner,结合 Lambda+CloudCustodian 定时回收孤儿盘。
  8. 高阶加固
    • 开启 KMS 加密,密钥放在 北京区域 KMS
    • RexRay 进程以 非 root 用户 运行,配置 systemd 限制 MemoryMax=200MCPUQuota=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=availableCreateTime>7d 的卷,自动发企业微信告警,人工二次确认后删除;
  • 接入 Prometheus,暴露 rexray_volume_used_percent 指标,>85% 触发 Alertmanager 回调扩容脚本,自动创建新卷并通过 mysqldump+replication 在线扩容。

上线半年,500+ EBS 卷 稳定运行,I/O 平均延迟 2.1 ms存储成本较早期自建 Ceph 降低 38%,并一次性通过 等保 2.0 三级 评审。

拓展思考

  1. 如果客户要求 多可用区容灾,RexRay 无法直接挂载跨区卷,可考虑 EBS snapshot+AMI 方式在 灾备区 启动新实例,结合 Swarm global mode冷备;或放弃 RexRay,改用 EFS 并部署 EFS-OneZone 以换取 RPO≈0,但需评估 IOPS 上限 10k 是否满足核心业务。
  2. 国内 金融专区 无法访问 AWS API,可把 RexRay 后端换成 华为云 EVS阿里云 ESSD,开源 rexray/evs 驱动已停止维护,需要自研 CSI-Connector 并封装成 Docker Volume Plugin,此时建议直接迁移到 Kubernetes+CSI,Swarm 仅做过渡。
  3. 当容器密度高、卷数量 >1 k 时,RexRay 的 AttachMutex 会成为全局锁,并发创建耗时线性增长,可修改源码把 mutex keyvolumeID 改为 volumeID+nodeID 分段锁,或采用 AWS Batch Attach 接口批量预挂载,降低 60% 等待时间。