【TiDB 使用环境】生产环境 /测试环境
【TiDB 版本】
【部署方式】虚拟机部署
【操作系统/CPU 架构/芯片详情】
【机器部署详情】
【集群数据量】
【集群节点数】3
【问题复现路径】
【遇到的问题:问题现象及影响】
按照官网文档,使用TiDB Operator 部署3节点TiDB集群,tidb server节点为什么是以statefulset形式而不是deployment部署的?而且service类型是NodePort而不是ClusterIP?
PD和TiKV以这种方式部署我可以理解,tidb server似乎没有必要。
【资源配置】
【复制黏贴 ERROR 报错的日志】
【其他附件:截图/日志/监控】
wbslxw
(Ti D Ber Cl S0j Eng)
2
StatefulSet 为了稳定有序管理,NodePort 为了对外提供访问。
Deployment 管无状态,无序、可替换;StatefulSet 管有状态,有序、身份固定。
我问的不是pd和tikv,而是tidb server,它本身是无状态的啊,为什么不以deployment方式部署?
虽然 TiDB Server 是 无状态组件 ,但 TiDB Operator 依然用 StatefulSet
这不等于没说嘛,我就是想知道TiDB Operator 为什么用 StatefulSet?
WalterWj
(王军 - PingCAP)
10
结合源码解读,AI 总结:
一、StatefulSet vs Deployment:TiDB 为什么用 StatefulSet?
核心区别
| 特性 |
StatefulSet |
Deployment |
| Pod 标识 |
固定序号 tidb-0, tidb-1, tidb-2 |
随机后缀 tidb-7f8b9c-xxxx |
| 网络标识 |
稳定 DNS tidb-0.tidb-headless.ns.svc |
Pod 重建后 DNS 变化 |
| 存储卷 |
每个 Pod 绑定独立 PVC |
所有 Pod 共享 PVC 模板 |
| 扩缩顺序 |
有序:0→1→2,缩容 2→1→0 |
并发,无序 |
| 滚动更新 |
按序号逆序逐个更新 |
并发替换(可控制 maxSurge) |
TiDB 必须用 StatefulSet 的原因(v1 架构)
-
稳定网络身份:TiDB Server 是无状态节点,但客户端(如 TiDB Spark Connector、JDBC)通过 JDBC URL 连接,需要稳定的 DNS 名称。StatefulSet 提供的 <pod-name>.<headless-svc> DNS 是 TiDB 组件间互相发现的基础。
-
有序滚动更新:TiDB 升级需要按序逐个重启,确保集群始终有可用节点。Deployment 的并发更新策略可能导致同时重启多个 TiDB 实例。
-
独立 PVC 绑定:虽然 TiDB Server 本身不存数据,但 v1 架构中 StatefulSet 的 volumeClaimTemplates 为每个 Pod 独立创建 PVC,便于日志持久化等场景。
如果换成 Deployment 会怎样?
- Pod 重建后 DNS 变化:客户端连接中断,需要重新解析服务地址(虽然有 Service 做负载均衡,但定向连接场景会受影响)
- 扩缩容不可控:无法保证 TiDB 节点按序启停,对依赖启动顺序的场景有风险
- 无法按序号操作单个 Pod:比如想单独重启
tidb-2,Deployment 不支持
有趣的是:TiDB Operator v2 已经移除了 StatefulSet
v2 架构采用了 Instance CR 模式,每个 TiDB 实例直接管理独立 Pod,不再依赖 StatefulSet。原因在 docs/why.md 中有明确说明:
StatefulSet has significant limitations as a low-level abstraction for effectively managing TiDB:
- Cannot scale specific pod by index
- No pre/post hooks for lifecycle events
- Cannot modify volume template after creation
v2 通过 Pod Subdomain + Headless Service 手动实现了稳定的网络身份,绕过了 StatefulSet 的限制。
二、NodePort vs ClusterIP:Service 类型选择
核心区别
| 特性 |
NodePort |
ClusterIP |
| 访问范围 |
集群外部可通过 <NodeIP>:<Port> 访问 |
仅集群内部可访问 |
| 端口范围 |
30000-32767 |
任意端口 |
| 适用场景 |
开发测试、无 LoadBalancer 环境 |
生产环境 + Ingress/LB |
| 安全性 |
暴露节点端口,风险较高 |
集群内隔离,更安全 |
为什么帖子上看到的是 NodePort?
这很可能是 TiDB Operator v1 的默认行为。在 v1 源码 pkg/controllers/tidbgroup/tasks/svc.go 中,Internal Service 的类型是硬编码为 ClusterIP 的,但 External Service(用于外部访问 TiDB)使用的是 NodePort。
实际上这取决于部署配置中的 spec.tidb.service.type 字段:
- 生产环境推荐
ClusterIP + LoadBalancer/Ingress
- 测试环境或无 LB 支持的环境使用
NodePort
实际影响
-
NodePort 的隐患:
- 端口范围有限(30000-32767),集群规模大时端口可能冲突
- 暴露节点 IP,安全边界扩大
- 节点 IP 变化时客户端需要更新连接地址
-
ClusterIP 的局限:
- 集群外无法直接访问,需要额外网关层
- 适合生产环境配合 Ingress Controller 或云厂商 LoadBalancer 使用
-
v2 的做法:v2 中 TiDB 的 Service 直接硬编码为 ClusterIP,不再提供 NodePort 选项,强制使用更安全的内部访问方式。
总结
| 问题 |
结论 |
| 为什么用 StatefulSet 不用 Deployment? |
稳定网络身份 + 有序管理 + 独立 PVC,但 v2 已改用 Instance CR 方案 |
| 为什么用 NodePort 不用 ClusterIP? |
便于外部访问,但生产推荐 ClusterIP + LB/Ingress,v2 已默认 ClusterIP |
| 实际影响? |
StatefulSet 保证运维可控性;NodePort 便于测试但不适合生产 |
帖子上用的 v8.5.3 对应的是 v1 Operator 架构(StatefulSet + 可选 NodePort),如果是新部署可以考虑 v2 架构。
独善其身
(Ti D Ber Bi Rqfz5 K)
11
k8s上的部署方式还是需要statefullset类型pod操作的