在 Kubernetes 中配置 TiDB 集群

本文档介绍了如何配置生产可用的 TiDB 集群。涵盖以下内容:

资源配置

部署前需要根据实际情况和需求,为 TiDB 集群各个组件配置资源,其中 PD、TiKV、TiDB 是 TiDB 集群的核心服务组件,在生产环境下它们的资源配置还需要按组件要求指定,具体参考:资源配置推荐

为了保证 TiDB 集群的组件在 Kubernetes 中合理的调度和稳定的运行,建议为其设置 Guaranteed 级别的 QoS,通过在配置资源时让 limits 等于 requests 来实现, 具体参考:配置 QoS

如果使用 NUMA 架构的 CPU,为了获得更好的性能,需要在节点上开启 Static 的 CPU 管理策略。为了 TiDB 集群组件能独占相应的 CPU 资源,除了为其设置上述 Guaranteed 级别的 QoS 外,还需要保证 CPU 的配额必须是大于或等于 1 的整数。具体参考: CPU 管理策略

部署配置

通过配置 TidbCluster CR 来配置 TiDB 集群。参考 TidbCluster 示例API 文档(示例和 API 文档请切换到当前使用的 TiDB Operator 版本)完成 TidbCluster CR(Custom Resource)。

配置 TiDB 集群 - 图1注意

建议在 ${cluster_name} 目录下组织 TiDB 集群的配置,并将其另存为 ${cluster_name}/tidb-cluster.yaml。默认条件下,修改配置不会自动应用到 TiDB 集群中,只有在 Pod 重启时,才会重新加载新的配置文件。

集群名称

通过更改 TiDBCuster CR 中的 metadata.name 来配置集群名称。

版本

正常情况下,集群内的各组件应该使用相同版本,所以一般建议配置 spec.<pd/tidb/tikv/pump/tiflash/ticdc>.baseImage + spec.version 即可。如果需要为不同的组件配置不同的版本,则可以配置 spec.<pd/tidb/tikv/pump/tiflash/ticdc>.version

相关参数的格式如下:

  • spec.version,格式为 imageTag,例如 v5.4.0
  • spec.<pd/tidb/tikv/pump/tiflash/ticdc>.baseImage,格式为 imageName,例如 pingcap/tidb
  • spec.<pd/tidb/tikv/pump/tiflash/ticdc>.version,格式为 imageTag,例如 v5.4.0

推荐配置

configUpdateStrategy

spec.configUpdateStrategy 字段默认值为 InPlace,表示当你修改某个组件的 config 更新后,需要手动触发滚动更新后才会应用新的配置。

建议设置 spec.configUpdateStrategy: RollingUpdate,开启配置自动更新特性,在某个组件的 config 更新时,自动对组件执行滚动更新,将修改后的配置应用到集群中。

enableDynamicConfiguration

建议通过设置 spec.enableDynamicConfiguration: true 配置 TiKV 的 --advertise-status-addr 启动参数。

版本支持:TiDB v4.0.1 及更高版本。

pvReclaimPolicy

建议设置 spec.pvReclaimPolicy: Retain,确保 PVC 被删除后 PV 仍然保留,保证数据安全。

mountClusterClientSecret

PD 和 TiKV 支持配置 mountClusterClientSecret。如果开启了集群组件间 TLS 支持,建议配置 spec.pd.mountClusterClientSecret: truespec.tikv.mountClusterClientSecret: true,这样 TiDB Operator 会自动将 ${cluster_name}-cluster-client-secret 证书挂载到 PD 和 TiKV 容器,方便使用 pd-ctl 和 tikv-ctl

存储

存储类型

如果需要设置存储类型,可以修改 ${cluster_name}/tidb-cluster.yaml 中各组件的 storageClassName 字段。关于 Kubernetes 集群支持哪些存储类型,请联系系统管理员确定。

另外,TiDB 集群不同组件对磁盘的要求不一样,所以部署集群前,要根据当前 Kubernetes 集群支持的存储类型以及使用场景,参考存储配置文档为 TiDB 集群各组件选择合适的存储类型。

配置 TiDB 集群 - 图2注意

如果创建 TiDB 集群时设置了 Kubernetes 集群中不存在的存储类型,则会导致 TiDB 集群创建处于 Pending 状态,需要将 TiDB 集群彻底销毁掉,再进行重试。

多盘挂载

TiDB Operator 支持为 PD、TiDB、TiKV、TiCDC 挂载多块 PV,可以用于不同用途的数据写入。

每个组件都可以配置 storageVolumes 字段,用于描述用户自定义的多个 PV。

配置 TiDB 集群 - 图3注意

你需要在集群创建之前配置 storageVolumes。集群创建完成后,不支持添加或者删除 storageVolumes。对于已经配置的 storageVolumes,除增大 storageVolume.storageSize 外,其他项不支持修改。如果要增大 storageVolume.storageSize,需要对应的 StorageClass 支持动态扩容

相关字段的含义如下:

  • storageVolume.name:PV 的名称。
  • storageVolume.storageClassName:PV 使用哪一个 StorageClass。如果不配置,会使用 spec.pd/tidb/tikv/ticdc.storageClassName。
  • storageVolume.storageSize:申请 PV 存储容量的大小。
  • storageVolume.mountPath:将 PV 挂载到容器的哪个目录。

例子:

  1. tikv:
  2. ...
  3. config: |
  4. [rocksdb]
  5. wal-dir = "/data_sbi/tikv/wal"
  6. [titan]
  7. dirname = "/data_sbj/titan/data"
  8. storageVolumes:
  9. - name: wal
  10. storageSize: "2Gi"
  11. mountPath: "/data_sbi/tikv/wal"
  12. - name: titan
  13. storageSize: "2Gi"
  14. mountPath: "/data_sbj/titan/data"
  1. tidb:
  2. config: |
  3. path = "/tidb/data"
  4. [log.file]
  5. filename = "/tidb/log/tidb.log"
  6. storageVolumes:
  7. - name: data
  8. storageSize: "2Gi"
  9. mountPath: "/tidb/data"
  10. - name: log
  11. storageSize: "2Gi"
  12. mountPath: "/tidb/log"
  1. pd:
  2. config: |
  3. data-dir=/pd/data
  4. [log.file]
  5. filename=/pd/log/pd.log
  6. storageVolumes:
  7. - name: data
  8. storageSize: "10Gi"
  9. mountPath: "/pd/data"
  10. - name: log
  11. storageSize: "10Gi"
  12. mountPath: "/pd/log"
  1. ticdc:
  2. ...
  3. config:
  4. dataDir: /ticdc/data
  5. logFile: /ticdc/log/cdc.log
  6. storageVolumes:
  7. - name: data
  8. storageSize: "10Gi"
  9. storageClassName: local-storage
  10. mountPath: "/ticdc/data"
  11. - name: log
  12. storageSize: "10Gi"
  13. storageClassName: local-storage
  14. mountPath: "/ticdc/log"

配置 TiDB 集群 - 图4注意

TiDB Operator 默认会使用一些挂载路径,比如会为 TiDB Pod 挂载 EmptyDir/var/log/tidb 目录。在配置 storageVolumes 的时候要避免配置重复的 mountPath

HostNetwork

PD、TiKV、TiDB、TiFlash、TiCDC 及 Pump 支持配置 Pod 使用宿主机上的网络命名空间 HostNetwork。可通过配置 spec.hostNetwork: true 为所有受支持的组件开启,或通过为特定组件配置 hostNetwork: true 为单个或多个组件开启。

Discovery

TiDB Operator 会为每一个 TiDB 集群启动一个 Discovery 服务。Discovery 服务会为每个 PD Pod 返回相应的启动参数,来辅助 PD 集群启动。你可以通过 spec.discovery 配置 Discovery 服务的资源,详见容器资源管理

spec.discovery 配置示例:

  1. spec:
  2. discovery:
  3. limits:
  4. cpu: "0.2"
  5. requests:
  6. cpu: "0.2"
  7. ...

集群拓扑

PD/TiKV/TiDB

默认示例的集群拓扑是:3 个 PD Pod,3 个 TiKV Pod,2 个 TiDB Pod。在该部署拓扑下根据数据高可用原则,TiDB Operator 扩展调度器要求 Kubernetes 集群中至少有 3 个节点。可以修改 replicas 配置来更改每个组件的 Pod 数量。

配置 TiDB 集群 - 图5注意

如果 Kubernetes 集群节点个数少于 3 个,将会导致有一个 PD Pod 处于 Pending 状态,而 TiKV 和 TiDB Pod 也都不会被创建。Kubernetes 集群节点个数少于 3 个时,为了使 TiDB 集群能启动起来,可以将默认部署的 PD Pod 个数减小到 1 个。

部署 TiFlash

如果要在集群中开启 TiFlash,需要在 ${cluster_name}/tidb-cluster.yaml 文件中配置 spec.pd.config.replication.enable-placement-rules: true,并配置 spec.tiflash

  1. pd:
  2. config: |
  3. ...
  4. [replication]
  5. enable-placement-rules = true
  6. tiflash:
  7. baseImage: pingcap/tiflash
  8. maxFailoverCount: 0
  9. replicas: 1
  10. storageClaims:
  11. - resources:
  12. requests:
  13. storage: 100Gi
  14. storageClassName: local-storage

TiFlash 支持挂载多个 PV,如果要为 TiFlash 配置多个 PV,可以在 tiflash.storageClaims 下面配置多项,每一项可以分别配置 storage requeststorageClassName,例如:

  1. tiflash:
  2. baseImage: pingcap/tiflash
  3. maxFailoverCount: 0
  4. replicas: 1
  5. storageClaims:
  6. - resources:
  7. requests:
  8. storage: 100Gi
  9. storageClassName: local-storage
  10. - resources:
  11. requests:
  12. storage: 100Gi
  13. storageClassName: local-storage

所有 PV 按照配置先后顺序分别挂载到容器内的 /data0/data1 等目录。TiFlash 有 4 个日志文件,其中 Proxy 日志打印到容器标准输出,另外 3 个日志存储在硬盘中,默认存储在 /data0 目录下,分别为 /data0/logs/flash_cluster_manager.log/data0/logs/error.log/data0/logs/server.log,如果要修改日志存储路径,可以参考配置 TiFlash 配置参数进行修改。

配置 TiDB 集群 - 图6警告

由于 TiDB Operator 会按照 storageClaims 列表中的配置按顺序自动挂载 PV,如果需要为 TiFlash 增加磁盘,请确保只在列表原有配置最后添加,并且不能修改列表中原有配置的顺序。

部署 TiCDC

如果要在集群中开启 TiCDC,需要在 ${cluster_name}/tidb-cluster.yaml 文件中配置 spec.ticdc

  1. ticdc:
  2. baseImage: pingcap/ticdc
  3. replicas: 3
  4. config:
  5. logLevel: info

值得注意的是,如果需要部署企业版的 TiDB/PD/TiKV/TiFlash/TiCDC,需要将 db.yaml 中 spec.<tidb/pd/tikv/tiflash/ticdc>.baseImage 配置为企业版镜像,格式为 pingcap/<tidb/pd/tikv/tiflash/ticdc>-enterprise

例如:

  1. spec:
  2. ...
  3. pd:
  4. baseImage: pingcap/pd-enterprise
  5. ...
  6. tikv:
  7. baseImage: pingcap/tikv-enterprise

配置 TiDB 组件

本节介绍如何配置 TiDB/TiKV/PD/TiFlash/TiCDC 的配置选项。

配置 TiDB 配置参数

你可以通过 TidbCluster CR 的 spec.tidb.config 来配置 TiDB 配置参数。

  1. spec:
  2. tidb:
  3. config: |
  4. split-table = true
  5. oom-action = "log"

获取所有可以配置的 TiDB 配置参数,请参考 TiDB 配置文档

配置 TiDB 集群 - 图7注意

为了兼容 helm 部署,如果你是通过 CR 文件部署 TiDB 集群,即使你不设置 Config 配置,也需要保证 Config: {} 的设置,从而避免 TiDB 组件无法正常启动。

配置 TiKV 配置参数

你可以通过 TidbCluster CR 的 spec.tikv.config 来配置 TiKV 配置参数。

  1. spec:
  2. tikv:
  3. config: |
  4. [storage]
  5. [storage.block-cache]
  6. capacity = "16GB"

获取所有可以配置的 TiKV 配置参数,请参考 TiKV 配置文档

配置 TiDB 集群 - 图8注意

为了兼容 helm 部署,如果你是通过 CR 文件部署 TiDB 集群,即使你不设置 Config 配置,也需要保证 Config: {} 的设置,从而避免 TiKV 组件无法正常启动。

配置 PD 配置参数

你可以通过 TidbCluster CR 的 spec.pd.config 来配置 PD 配置参数。

  1. spec:
  2. pd:
  3. config: |
  4. lease = 3
  5. enable-prevote = true

获取所有可以配置的 PD 配置参数,请参考 PD 配置文档

配置 TiDB 集群 - 图9注意

  • 为了兼容 helm 部署,如果你是通过 CR 文件部署 TiDB 集群,即使你不设置 Config 配置,也需要保证 Config: {} 的设置,从而避免 PD 组件无法正常启动。
  • PD 部分配置项在首次启动成功后会持久化到 etcd 中且后续将以 etcd 中的配置为准。因此 PD 在首次启动后,这些配置项将无法再通过配置参数来进行修改,而需要使用 SQL、pd-ctl 或 PD server API 来动态进行修改。目前,在线修改 PD 配置文档中所列的配置项中,除 log.level 外,其他配置项在 PD 首次启动之后均不再支持通过配置参数进行修改。

配置 TiFlash 配置参数

你可以通过 TidbCluster CR 的 spec.tiflash.config 来配置 TiFlash 配置参数。

  1. spec:
  2. tiflash:
  3. config:
  4. config: |
  5. [flash]
  6. [flash.flash_cluster]
  7. log = "/data0/logs/flash_cluster_manager.log"
  8. [logger]
  9. count = 10
  10. level = "information"
  11. errorlog = "/data0/logs/error.log"
  12. log = "/data0/logs/server.log"

获取所有可以配置的 TiFlash 配置参数,请参考 TiFlash 配置文档

配置 TiCDC 启动参数

你可以通过 TidbCluster CR 的 spec.ticdc.config 来配置 TiCDC 启动参数。

对于 TiDB Operator v1.2.0-rc.2 及之后版本,请使用 TOML 格式配置:

  1. spec:
  2. ticdc:
  3. config: |
  4. gc-ttl = 86400
  5. log-level = "info"

对于 TiDB Operator v1.2.0-rc.2 之前版本,请使用 YAML 格式配置:

  1. spec:
  2. ticdc:
  3. config:
  4. timezone: UTC
  5. gcTTL: 86400
  6. logLevel: info

获取所有可以配置的 TiCDC 启动参数,请参考 TiCDC 启动参数文档

配置 PD、TiDB、TiKV、TiFlash 故障自动转移阈值

故障自动转移功能在 TiDB Operator 中默认开启。当 PD、TiDB、TiKV、TiFlash 这些组件的 Pod 或者其所在节点发生故障时,TiDB Operator 会触发故障自动转移,通过扩容相应组件补齐 Pod 副本数。

为避免故障自动转移功能创建太多 Pod,可以为每个组件配置故障自动转移时能扩容的 Pod 数量阈值,默认为 3。如果配置为 0,代表关闭这个组件的故障自动转移功能。配置示例如下:

  1. pd:
  2. maxFailoverCount: 3
  3. tidb:
  4. maxFailoverCount: 3
  5. tikv:
  6. maxFailoverCount: 3
  7. tiflash:
  8. maxFailoverCount: 3

配置 TiDB 集群 - 图10注意

对于以下情况,请显式设置 maxFailoverCount: 0

  • 集群中没有足够的资源以供 TiDB Operator 扩容新 Pod。该情况下,扩容出的 Pod 会处于 Pending 状态。
  • 不希望开启故障自动转移功能。

配置 TiDB 平滑升级

滚动更新 TiDB 集群的过程中,在停止 TiDB Pod 之前,Kubernetes 会向 TiDB server 进程发送一个 TERM 信号。在收到 TERM 信号后,TiDB server 会尝试等待所有的连接关闭,不过 15 秒后会强制关闭所有连接并退出进程。

通过配置下面两个属性来实现平滑升级 TiDB 集群:

  • spec.tidb.terminationGracePeriodSeconds:滚动更新的时候,删除旧的 TiDB Pod 最多容忍的时间,即过了这个时间,TiDB Pod 会被强制删除;
  • spec.tidb.lifecycle:设置 TiDB Pod 的 preStop Hook,在 TiDB server 停止之前执行的操作。
  1. spec:
  2. tidb:
  3. ...
  4. terminationGracePeriodSeconds: 60
  5. lifecycle:
  6. preStop:
  7. exec:
  8. command:
  9. - /bin/sh
  10. - -c
  11. - "sleep 10 && kill -QUIT 1"

上述 YAML 文件中:

  • 设置了删除 TiDB Pod 的最多容忍时间为 60 秒,如果 60 秒之内客户端仍然没有关闭连接的话,那么这些连接将会强制关闭。这个时间可根据需要进行调整;
  • 设置 preStop Hook 为 sleep 10 && kill -QUIT 1,这里 Pid 1 为 TiDB Pod 内 TiDB server 进程的 Pid。TiDB server 进程收到这个信号之后,会等待所有连接被客户端关闭之后才会退出。

Kubernetes 在删除 TiDB Pod 的同时,也会把该 TiDB 节点从 Service 的 Endpoints 中移除。这样就可以保证新的连接不会连接到该 TiDB 节点,但是由于此过程是异步的,所以可以在发送 Kill 信号之前 sleep 几秒钟,确保该 TiDB 节点从 Endpoints 中去掉。

配置 TiKV 平滑升级

TiKV 升级过程中,在重启 TiKV Pod 之前,TiDB Operator 会先驱逐 TiKV Pod 上的所有 Region leader。只有当驱逐完成(即 TiKV Pod 上的 Region leader 个数为 0)或者驱逐超时(默认 1500 分钟)后,TiKV Pod 才会重启。如果集群的 TiKV 副本数小于 2,TiDB Operator 不再等待超时,直接触发强制升级。

如果驱逐 Region leader 超时,重启 TiKV Pod 会导致部分请求失败或者延时增加。要避免此问题,你可以将超时时间 spec.tikv.evictLeaderTimeout(默认 1500 分钟)配置为一个更大的值,例如:

  1. spec:
  2. tikv:
  3. evictLeaderTimeout: 10000m

配置 TiDB 集群 - 图11警告

如果使用 TiKV 版本小于 4.0.14,或者小于 5.0.3,由于 TiKV 的 bug,需要将 spec.tikv.evictLeaderTimeout 的值设置的尽可能大(推荐大于 1500m),以保证 TiKV Pod 上所有的 Region Leader 能在设置的时间内驱逐完毕。

配置 TiDB 慢查询日志持久卷

默认配置下,TiDB Operator 会新建名称为 slowlogEmptyDir 卷来存储慢查询日志,slowlog 卷默认挂载到 /var/log/tidb,慢查询日志通过 sidecar 容器打印到标准输出。

配置 TiDB 集群 - 图12警告

默认配置下,使用 EmptyDir 卷存储的慢查询日志会在 Pod 被删除(例如,滚动升级)后丢失。请确保 Kubernetes 集群内已经部署日志收集方案用于收集所有容器的日志。如果没有部署日志收集方案,请务必通过下面配置使用持久卷来存储慢查询日志。

如果想使用单独的持久卷来存储慢查询日志,可以通过配置 spec.tidb.slowLogVolumeName 单独指定存储慢查询日志的持久卷名称,并在 spec.tidb.storageVolumesspec.tidb.additionalVolumes 配置持久卷信息。下面分别演示使用 spec.tidb.storageVolumesspec.tidb.additionalVolumes 配置持久卷。

spec.tidb.storageVolumes 配置

按照如下示例配置 TidbCluster CR,TiDB Operator 将使用持久卷 ${volumeName} 存储慢查询日志,日志文件路径为:${mountPath}/${volumeName}spec.tidb.storageVolumes 字段的具体配置方式可参考多盘挂载

  1. tidb:
  2. ...
  3. separateSlowLog: true # 可省略
  4. slowLogVolumeName: ${volumeName}
  5. storageVolumes:
  6. # name 必须和 slowLogVolumeName 字段的值保持一致
  7. - name: ${volumeName}
  8. storageClassName: ${storageClass}
  9. storageSize: "1Gi"
  10. mountPath: ${mountPath}

spec.tidb.additionalVolumes 配置

下面以 NFS 为例配置 spec.tidb.additionalVolumes。TiDB Operator 将使用持久卷 ${volumeName} 存储慢查询日志,日志文件路径为:${mountPath}/${volumeName}。具体支持的持久卷类型可参考 Persistent Volumes

  1. tidb:
  2. ...
  3. separateSlowLog: true # 可省略
  4. slowLogVolumeName: ${volumeName}
  5. additionalVolumes:
  6. # name 必须和 slowLogVolumeName 字段的值保持一致
  7. - name: ${volumeName}
  8. nfs:
  9. server: 192.168.0.2
  10. path: /nfs
  11. additionalVolumeMounts:
  12. # name 必须和 slowLogVolumeName 字段的值保持一致
  13. - name: ${volumeName}
  14. mountPath: ${mountPath}

配置 TiDB 服务

需要配置 spec.tidb.service,TiDB Operator 才会为 TiDB 创建 Service。Service 可以根据场景配置不同的类型,比如 ClusterIPNodePortLoadBalancer 等。

通用配置

不用类型的 Service 有着部分通用的配置,包括:

  • spec.tidb.service.annotations:添加到 Service 资源的 Annotation。
  • spec.tidb.service.labels:添加到 Service 资源的 Labels。

ClusterIP

ClusterIP 是通过集群的内部 IP 暴露服务,选择该类型的服务时,只能在集群内部访问,使用 ClusterIP 或者 Service 域名(${cluster_name}-tidb.${namespace})访问。

  1. spec:
  2. tidb:
  3. service:
  4. type: ClusterIP

NodePort

在没有 LoadBalancer 时,可选择通过 NodePort 暴露。NodePort 是通过节点的 IP 和静态端口暴露服务。通过请求 NodeIP + NodePort,可以从集群的外部访问一个 NodePort 服务。

  1. spec:
  2. tidb:
  3. service:
  4. type: NodePort
  5. # externalTrafficPolicy: Local

NodePort 有两种模式:

  • externalTrafficPolicy=Cluster:集群所有的机器都会给 TiDB 分配 NodePort 端口,此为默认值

    使用 Cluster 模式时,可以通过任意一台机器的 IP 加 NodePort 访问 TiDB 服务,如果该机器上没有 TiDB Pod,则相应请求会转发到有 TiDB Pod 的机器上。

    配置 TiDB 集群 - 图13注意

    该模式下 TiDB 服务获取到的请求源 IP 是主机 IP,并不是真正的客户端源 IP,所以基于客户端源 IP 的访问权限控制在该模式下不可用。

  • externalTrafficPolicy=Local:只有运行 TiDB 的机器会分配 NodePort 端口,用于访问本地的 TiDB 实例

LoadBalancer

若运行在有 LoadBalancer 的环境,比如 GCP/AWS 平台,建议使用云平台的 LoadBalancer 特性。

  1. spec:
  2. tidb:
  3. service:
  4. annotations:
  5. cloud.google.com/load-balancer-type: "Internal"
  6. externalTrafficPolicy: Local
  7. type: LoadBalancer

访问 Kubernetes Service 文档,了解更多 Service 特性以及云平台 Load Balancer 支持。

高可用配置

配置 TiDB 集群 - 图14注意

TiDB Operator 提供了自定义的调度器,该调度器通过指定的调度算法能在 host 层面保证 TiDB 服务的高可用。目前,TiDB 集群使用该调度器作为默认调度器,可通过 spec.schedulerName 配置项进行设置。本节重点介绍如何配置 TiDB 集群以容忍其他级别的故障,例如机架、可用区或 region。本部分可根据使用需求配置,不是必选。

TiDB 是分布式数据库,它的高可用需要做到在任一个物理拓扑节点发生故障时,不仅服务不受影响,还要保证数据也是完整和可用。下面分别具体说明这两种高可用的配置。

TiDB 服务高可用

通过 nodeSelector 调度实例

通过各组件配置的 nodeSelector 字段,可以约束组件的实例只能调度到特定的节点上。关于 nodeSelector 的更多说明,请参阅 nodeSelector

  1. apiVersion: pingcap.com/v1alpha1
  2. kind: TidbCluster
  3. # ...
  4. spec:
  5. pd:
  6. nodeSelector:
  7. node-role.kubernetes.io/pd: true
  8. # ...
  9. tikv:
  10. nodeSelector:
  11. node-role.kubernetes.io/tikv: true
  12. # ...
  13. tidb:
  14. nodeSelector:
  15. node-role.kubernetes.io/tidb: true
  16. # ...

通过 tolerations 调度实例

通过各组件配置的 tolerations 字段,可以允许组件的实例能够调度到带有与之匹配的污点 (Taint) 的节点上。关于污点与容忍度的更多说明,请参阅 Taints and Tolerations

  1. apiVersion: pingcap.com/v1alpha1
  2. kind: TidbCluster
  3. # ...
  4. spec:
  5. pd:
  6. tolerations:
  7. - effect: NoSchedule
  8. key: dedicated
  9. operator: Equal
  10. value: pd
  11. # ...
  12. tikv:
  13. tolerations:
  14. - effect: NoSchedule
  15. key: dedicated
  16. operator: Equal
  17. value: tikv
  18. # ...
  19. tidb:
  20. tolerations:
  21. - effect: NoSchedule
  22. key: dedicated
  23. operator: Equal
  24. value: tidb
  25. # ...

通过 affinity 调度实例

配置 PodAntiAffinity 能尽量避免同一组件的不同实例部署到同一个物理拓扑节点上,从而达到高可用的目的。关于 Affinity 的使用说明,请参阅 Affinity & AntiAffinity

下面是一个典型的高可用设置例子:

  1. affinity:
  2. podAntiAffinity:
  3. preferredDuringSchedulingIgnoredDuringExecution:
  4. # this term works when the nodes have the label named region
  5. - weight: 10
  6. podAffinityTerm:
  7. labelSelector:
  8. matchLabels:
  9. app.kubernetes.io/instance: ${cluster_name}
  10. app.kubernetes.io/component: "pd"
  11. topologyKey: "region"
  12. namespaces:
  13. - ${namespace}
  14. # this term works when the nodes have the label named zone
  15. - weight: 20
  16. podAffinityTerm:
  17. labelSelector:
  18. matchLabels:
  19. app.kubernetes.io/instance: ${cluster_name}
  20. app.kubernetes.io/component: "pd"
  21. topologyKey: "zone"
  22. namespaces:
  23. - ${namespace}
  24. # this term works when the nodes have the label named rack
  25. - weight: 40
  26. podAffinityTerm:
  27. labelSelector:
  28. matchLabels:
  29. app.kubernetes.io/instance: ${cluster_name}
  30. app.kubernetes.io/component: "pd"
  31. topologyKey: "rack"
  32. namespaces:
  33. - ${namespace}
  34. # this term works when the nodes have the label named kubernetes.io/hostname
  35. - weight: 80
  36. podAffinityTerm:
  37. labelSelector:
  38. matchLabels:
  39. app.kubernetes.io/instance: ${cluster_name}
  40. app.kubernetes.io/component: "pd"
  41. topologyKey: "kubernetes.io/hostname"
  42. namespaces:
  43. - ${namespace}

通过 topologySpreadConstraints 实现 Pod 均匀分布

配置 topologySpreadConstraints 可以实现同一组件的不同实例在拓扑上的均匀分布。具体配置方法请参阅 Pod Topology Spread Constraints

如需使用 topologySpreadConstraints,需要满足以下条件:

  • Kubernetes 集群使用 default-scheduler,而不是 tidb-scheduler。详情可以参考 tidb-scheduler 与 default-scheduler
  • Kubernetes 集群开启 EvenPodsSpread feature gate。如果 Kubernetes 版本低于 v1.16 或集群未开启 EvenPodsSpread feature gate,topologySpreadConstraints 的配置将不会生效。

topologySpreadConstraints 可以设置在整个集群级别 (spec.topologySpreadConstraints) 来配置所有组件或者设置在组件级别 (例如 spec.tidb.topologySpreadConstraints) 来配置特定的组件。

以下是一个配置示例:

  1. topologySpreadConstraints:
  2. - topologyKey: kubernetes.io/hostname
  3. - topologyKey: topology.kubernetes.io/zone

该配置能让同一组件的不同实例均匀分布在不同 zone 和节点上。

当前 topologySpreadConstraints 仅支持 topologyKey 配置。在 Pod spec 中,上述示例配置会自动展开成如下配置:

  1. topologySpreadConstraints:
  2. - topologyKey: kubernetes.io/hostname
  3. maxSkew: 1
  4. whenUnsatisfiable: DoNotSchedule
  5. labelSelector: <object>
  6. - topologyKey: topology.kubernetes.io/zone
  7. maxSkew: 1
  8. whenUnsatisfiable: DoNotSchedule
  9. labelSelector: <object>

数据的高可用

在开始数据高可用配置前,首先请阅读集群拓扑信息配置。该文档描述了 TiDB 集群数据高可用的实现原理。

在 Kubernetes 上支持数据高可用的功能,需要如下操作:

  • 为 PD 设置拓扑位置 Label 集合

    用 Kubernetes 集群 Node 节点上描述拓扑位置的 Label 集合替换 pd.config 配置项中里的 location-labels 信息。

    配置 TiDB 集群 - 图15注意

    • PD 版本 < v3.0.9 不支持名字中带 / 的 Label。
    • 如果在 location-labels 中配置 host,TiDB Operator 会从 Node Label 中的 kubernetes.io/hostname 获取值。
  • 为 TiKV 节点设置所在的 Node 节点的拓扑信息

    TiDB Operator 会自动为 TiKV 获取其所在 Node 节点的拓扑信息,并调用 PD 接口将这些信息设置为 TiKV 的 store labels 信息,这样 TiDB 集群就能基于这些信息来调度数据副本。

    如果当前 Kubernetes 集群的 Node 节点没有表示拓扑位置的 Label,或者已有的拓扑 Label 名字中带有 /,可以通过下面的命令手动给 Node 增加标签:

    1. kubectl label node ${node_name} region=${region_name} zone=${zone_name} rack=${rack_name} kubernetes.io/hostname=${host_name}

    其中 regionzonerackkubernetes.io/hostname 只是举例,要添加的 Label 名字和数量可以任意定义,只要符合规范且和 pd.config 里的 location-labels 设置的 Labels 保持一致即可。