MySQL必须用StatefulSet而非Deployment,因其依赖稳定网络标识、有序启停和独占PV;需禁用symbolic-links、显式设置volumeMode、修复initContainer权限,并配置utf8mb4字符集与严格SQL模式。

MySQL StatefulSet 为什么不能用 Deployment
因为 MySQL 是有状态服务,主从复制、数据目录持久化、节点网络身份(如 mysql-0.mysql)都依赖稳定的身份和存储。Deployment 重启后 Pod 名称、IP、PV 绑定全不可控,mysqld 启动直接报错:Can't start server: Bind on TCP/IP port: Address already in use 或反复初始化数据目录。
- StatefulSet 提供稳定的网络标识(
mysql-0.mysql、mysql-1.mysql)、有序部署/滚动更新、一对一 PV 绑定 - 必须配合 Headless Service(
clusterIP: None),否则 DNS 解析不到单个 Pod 的 A 记录 - 不要给 MySQL 容器加
livenessProbe执行mysqladmin ping—— 主库启动慢时探针会误杀,改用exec检查/var/lib/mysql/ibdata1是否存在更稳妥
StorageClass 和 PVC 必须显式指定 volumeMode
MySQL 要求块设备(volumeMode: Block)或至少是文件系统模式(volumeMode: Filesystem)的持久卷;默认 StorageClass 创建的 PVC 如果没声明 volumeMode,K8s 可能 fallback 到不兼容的模式,导致 mysqld 启动失败并报错:InnoDB: Operating system error number 13 in a file operation(权限或挂载失败)。
- 确认底层 StorageClass 支持
volumeMode: Filesystem(多数云厂商默认支持,但本地hostPath或某些 NFS provisioner 不支持) - PVC 中必须写明:
volumeMode: Filesystem,不能省略 - 推荐使用
accessModes: ["ReadWriteOnce"],MySQL 单实例不支持多写 - 避免用
emptyDir或hostPath做生产数据盘 —— 节点宕机即丢数
initContainer 初始化 MySQL 数据目录权限
很多镜像(比如官方 mysql:8.0)以非 root 用户(uid 999)运行 mysqld,但 PVC 挂载后目录属主可能是 root,导致启动时提示:mysqld: Can't create/write to file '/var/lib/mysql/is_writable'。
- 必须加
initContainer修正权限:chown -R 999:999 /var/lib/mysql - initContainer 需和主容器共用同一 volumeMount,且
securityContext.runAsUser: 0(即 root) - 别在 main container 里用
command覆盖启动命令来 chown —— 这会绕过 mysqld 的初始化逻辑,首次启动失败 - 如果用
mysql:5.7,注意 uid 是 999 还是 1001,不同版本有差异,查镜像Dockerfile确认
ConfigMap 配置文件里禁用 symbolic-links 和严格模式
MySQL 容器在 K8s 里默认启用 symbolic-links=1,而大多数云盘或 CSI 插件不支持符号链接,会导致建表失败;另外,默认 SQL mode 缺少 STRICT_TRANS_TABLES,容易掩盖字段超长等隐性错误。
- 在 ConfigMap 的
my.cnf里显式关闭:symbolic-links=0 - 设置安全的 SQL mode:
sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION" - 别把
bind-address写成127.0.0.1—— 这会让其他 Pod 连不上,应设为0.0.0.0或留空 - 字符集统一用
utf8mb4,在[mysqld]下加:character-set-server=utf8mb4和collation-server=utf8mb4_unicode_ci
最易被忽略的是 initContainer 权限修复和 ConfigMap 中 symbolic-links 的关闭 —— 这两个点不处理,MySQL 往往能跑起来,但建表失败、主从同步中断、或者某次滚动更新后整个集群不可写,问题现象分散,排查成本远高于初期加两行配置。










