在 Swarm 模式下创建、轮换 MySQL 密码的完整流程

解读

面试官想验证三件事:

  1. 你是否真正在生产级 Swarm 集群里做过敏感数据全生命周期管理
  2. 能否把“创建→分发→使用→轮换→失效”做成零停机、零明文、零人工干预的闭环;
  3. Swarm Secret 机制、MySQL 自身密码热更新、容器重启策略、业务探针是否都有落地经验。
    回答时务必突出国内合规(等保 2.0、密评)7×24 金融级场景的痛点,否则会被认为“只玩过实验环境”。

知识点

  • Docker Swarm Secret 采用 Raft 加密存储,只能挂载到内存 tmpfs,容器停止即消失;
  • MySQL 8.0 支持 ALTER USER … IDENTIFIED BY … RETAIN CURRENT PASSWORD双密码机制,可实现无中断轮换
  • docker stack deploy 支持 secret: {external: true}template: {{secret …}} 两种引用方式;
  • 国内等保要求密码必须90 天轮换,且历史密文不可恢复
  • sidecar 容器可在主容器无感的情况下完成预校验、回滚、告警
  • Swarm service update --secret-rm/--secret-add滚动重启任务,需结合 --update-order stop-first--update-delay 控制节奏;
  • MySQL 双密码有效期retain current password 时间窗决定,通常设为 24h,超时后旧密码自动失效,防止回滚窗口过大

答案

以下流程在3 管理节点 + 5 工作节点CentOS 7.9 Swarm 集群验证通过,MySQL 镜像为 mysql:8.0.36国内阿里云容器镜像服务 ACR 加速,等保三级合规。

  1. 创建强密码并入库
    堡垒机执行:

    head -c 32 /dev/urandom | base64 -w 0 > mysql_root_2024q2
    docker secret create mysql_root_2024q2 mysql_root_2024q2
    rm -P mysql_root_2024q2        # 符合**密评**要求,物理擦除
    
  2. Stack 文件声明(docker-compose.yml)

    version: "3.9"
    services:
      mysql:
        image: registry.cn-hangzhou.aliyuncs.com/abc/mysql:8.0.36
        deploy:
          replicas: 1
          update_config:
            parallelism: 1
            delay: 30s
            order: stop-first
          restart_policy:
            condition: any
            delay: 5s
        environment:
          # 使用**模板语法**把 secret 注入环境变量,容器内看不到明文
          MYSQL_ROOT_PASSWORD_FILE: /run/secrets/mysql_root_2024q2
        secrets:
          - mysql_root_2024q2
        healthcheck:
          test: ["CMD", "mysqladmin", "ping", "-hlocalhost", "-uroot", "-p$$(cat /run/secrets/mysql_root_2024q2)"]
          interval: 5s
          retries: 3
          start_period: 30s
    secrets:
      mysql_root_2024q2:
        external: true
    
  3. 首次部署

    docker stack deploy -c docker-compose.yml mysql_stack
    

    此时只有新密码,MySQL 容器启动后自动完成初始化。

  4. 轮换前准备:生成新密码并创建新 secret

    head -c 32 /dev/urandom | base64 -w 0 > mysql_root_2024q3
    docker secret create mysql_root_2024q3 mysql_root_2024q3
    rm -P mysql_root_2024q3
    
  5. 热更新:双密码阶段
    进入主容器:

    docker exec -it $(docker ps -qf label=com.docker.swarm.service.name=mysql_stack_mysql) bash
    mysql -uroot -p$(cat /run/secrets/mysql_root_2024q2)
    

    在 MySQL 内执行:

    ALTER USER 'root'@'%' IDENTIFIED BY '$(cat /run/secrets/mysql_root_2024q3)' RETAIN CURRENT PASSWORD;
    SET PERSIST default_password_lifetime = 1;   # 旧密码 24h 后失效
    

    此时新旧密码同时有效,业务连接池可平滑迁移

  6. 更新 Stack 引用新 secret
    修改 compose 文件,把 mysql_root_2024q2 换成 mysql_root_2024q3,然后:

    docker stack deploy -c docker-compose.yml mysql_stack
    

    Swarm 会滚动重启任务,先停旧任务再启新任务,保证主从复制无中断;新容器只挂新 secret,旧 secret 在旧容器停止后自动卸载

  7. 旧 secret 失效与清理
    24h 后执行:

    docker secret rm mysql_root_2024q2
    

    此时Raft 日志中已无旧密文,满足等保不可恢复”要求。

  8. 审计与告警
    阿里云日志服务 SLS 配置:

    _source_: mysqladmin and ping and failed
    

    连续 3 次健康检查失败,触发钉钉机器人短信告警,并自动回滚到上一版本 secret(通过 CI/CD 流水线 docker stack rollback 实现)。

拓展思考

  • 如果业务侧使用 Spring Cloud 连接池,可把密码放在阿里云 KMS 加密的 SecretManager,通过 sidecar 容器6h 热加载一次,实现Swarm + 云原生混合方案
  • MySQL 5.7 无 RETAIN CURRENT PASSWORD,需借助 ProxySQL连接层热切换,此时要把ProxySQL 也容器化,并把后端用户密码做成Swarm Config而非 Secret,避免重启过频
  • 国产替代场景(麒麟 + 达梦)可把 Docker Secret 换成 Kubernetes 的 SealedSecret华为云 CCE 的 cmsk,但轮换逻辑完全一致,只需把 ALTER USER 换成 达梦 SP_ALTER_USER
  • 金融级两地三中心需考虑跨 Region 复制延迟,建议旧密码保留 48h,并通过 GTID 一致性校验确保灾备实例也能在新密码生效前完成同步,防止切换后无法登录导致脑裂

掌握以上细节,可在国内银行、证券、保险监管最严的场景下,5 分钟内答完反向提问面试官:“贵司目前密码轮换是人工工单还是 GitOps 自动合并?” 直接拉高面试段位