在 Swarm 模式下创建、轮换 MySQL 密码的完整流程
解读
面试官想验证三件事:
- 你是否真正在生产级 Swarm 集群里做过敏感数据全生命周期管理;
- 能否把“创建→分发→使用→轮换→失效”做成零停机、零明文、零人工干预的闭环;
- 对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 加速,等保三级合规。
-
创建强密码并入库
在堡垒机执行: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 # 符合**密评**要求,物理擦除 -
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 -
首次部署
docker stack deploy -c docker-compose.yml mysql_stack此时只有新密码,MySQL 容器启动后自动完成初始化。
-
轮换前准备:生成新密码并创建新 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 -
热更新:双密码阶段
进入主容器: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 后失效此时新旧密码同时有效,业务连接池可平滑迁移。
-
更新 Stack 引用新 secret
修改 compose 文件,把mysql_root_2024q2换成mysql_root_2024q3,然后:docker stack deploy -c docker-compose.yml mysql_stackSwarm 会滚动重启任务,先停旧任务再启新任务,保证主从复制无中断;新容器只挂新 secret,旧 secret 在旧容器停止后自动卸载。
-
旧 secret 失效与清理
24h 后执行:docker secret rm mysql_root_2024q2此时Raft 日志中已无旧密文,满足等保“不可恢复”要求。
-
审计与告警
在阿里云日志服务 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 自动合并?” 直接拉高面试段位。