mysql密码严禁硬编码,必须通过环境变量或加密配置文件管理;环境变量适用于容器化部署,加密配置文件适合遗留系统,二者均需配合权限控制与密钥轮换。

直接用环境变量或 ConfigMap 注入 MySQL 密码,在容器化微服务里不是动态下发,而是静态硬编码——一旦凭证轮换,就得重建镜像或重启 Pod,根本不符合“动态”要求。
为什么不能把密码写进 Dockerfile 或 Kubernetes YAML
明文密码会残留在镜像层、Git 历史、集群 etcd 中,审计时一查一个准;更关键的是,它和“动态下发”完全背道而驰:没有生命周期管理、无法自动过期、不能按需生成。Kubernetes 自身不提供凭据生成能力,Secret 只是安全容器,不是凭据工厂。
- 镜像构建阶段写死
MYSQL_ROOT_PASSWORD→ 该密码永远不变,除非重打镜像 - 用
kubectl create secret generic手动创建 → 仍是人工介入,无法对接轮换策略 - ConfigMap + downward API 暴露 serviceAccount token → 这个 token 不能直接换 MySQL 密码,没权限也没路径
真正可行的动态路径:走云厂商凭据服务 + OIDC 身份联邦
核心逻辑是让 Pod 自己“亮身份”,换取短期数据库密码,全程不碰长期密钥。腾讯云 TKE + CAM + SSM、AWS EKS + IRSA + Secrets Manager、Azure AKS + Workload Identity + Key Vault 都走这条路。以腾讯云为例,关键链路是:Pod → ServiceAccount → OIDC Token → CAM 角色 → SSM GetSecretValue → MySQL 动态密码。
- 必须开启集群的
ServiceAccountIssuerDiscovery,否则 Pod 拿不到可验证的 OIDC token - CAM 策略中
cam:BuildDataFlowAuthToken是唯一能兑换数据库临时密码的 action,漏掉就 403 - SSM 中的凭据必须设为“自动轮转”,且轮转函数要调用
mysql_rds_generate_db_auth_token类接口(非通用随机字符串) - 应用代码里不能缓存密码,每次连接前都应调用 SSM
GetSecretValue—— 否则拿到过期凭证直连失败
应用侧怎么安全获取并使用动态密码
不要在启动时只取一次密码然后复用整个进程生命周期。MySQL 连接池(如 HikariCP)会复用连接,但凭证本身有 TTL(通常 15–60 分钟),必须配合连接池的 connection-test-query 或 validation-timeout 主动探测失效。
- 推荐在数据源初始化阶段封装一个
DynamicPasswordSupplier,每次getConnection()前触发 SSM 请求 - 务必设置 HTTP client 超时(
connectTimeout=3s,readTimeout=5s),避免 SSM 不可用时拖垮整个服务 - 若用 Spring Boot,可通过
@ConfigurationProperties绑定 SSM endpoint 和 secret id,但禁止绑定 password 字段本身 - 错误日志里绝不能打印完整响应体,尤其要过滤掉
SecretString字段 —— 即便日志脱敏也要在 SDK 层做,不能靠 logback 正则
动态凭证真正的复杂点不在“怎么拿”,而在“怎么不用完就失效”:连接池保活、应用无感刷新、故障降级策略(比如 SSM 不可用时是否 fallback 到上一轮缓存密码?缓存多久?是否允许?)这些细节没对齐,再标准的 OIDC 流程也会在真实流量下暴露断连或雪崩风险。











