在 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)。

集群名称

通过更改 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.3.0
  • spec.<pd/tidb/tikv/pump/tiflash/ticdc>.baseImage,格式为 imageName,例如 pingcap/tidb
  • spec.<pd/tidb/tikv/pump/tiflash/ticdc>.version,格式为 imageTag,例如 v5.3.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-ctltikv-ctl

存储

存储类型

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

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

多盘挂载

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

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

相关字段的含义如下:

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

例子:

tikv: ... config: | [rocksdb] wal-dir = "/data_sbi/tikv/wal" [titan] dirname = "/data_sbj/titan/data" storageVolumes: - name: wal storageSize: "2Gi" mountPath: "/data_sbi/tikv/wal" - name: titan storageSize: "2Gi" mountPath: "/data_sbj/titan/data"

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 配置示例:

spec: discovery: limits: cpu: "0.2" requests: cpu: "0.2" ...

集群拓扑

PD/TiKV/TiDB

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

部署 TiFlash

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

pd: config: | ... [replication] enable-placement-rules = true tiflash: baseImage: pingcap/tiflash maxFailoverCount: 0 replicas: 1 storageClaims: - resources: requests: storage: 100Gi storageClassName: local-storage

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

tiflash: baseImage: pingcap/tiflash maxFailoverCount: 0 replicas: 1 storageClaims: - resources: requests: storage: 100Gi storageClassName: local-storage - resources: requests: storage: 100Gi 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 配置参数进行修改。

部署 TiCDC

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

ticdc: baseImage: pingcap/ticdc replicas: 3 config: logLevel: info

配置 TiDB 组件

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

配置 TiDB 配置参数

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

spec: tidb: config: | split-table = true oom-action = "log"

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

配置 TiKV 配置参数

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

spec: tikv: config: | [storage] [storage.block-cache] capacity = "16GB"

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

配置 PD 配置参数

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

spec: pd: config: | lease = 3 enable-prevote = true

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

配置 TiFlash 配置参数

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

spec: tiflash: config: config: | [flash] [flash.flash_cluster] log = "/data0/logs/flash_cluster_manager.log" [logger] count = 10 level = "information" errorlog = "/data0/logs/error.log" log = "/data0/logs/server.log"

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

配置 TiCDC 启动参数

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

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

spec: ticdc: config: | gc-ttl = 86400 log-level = "info"

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

spec: ticdc: config: timezone: UTC gcTTL: 86400 logLevel: info

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

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

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

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

pd: maxFailoverCount: 3 tidb: maxFailoverCount: 3 tikv: maxFailoverCount: 3 tiflash: maxFailoverCount: 3

配置 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 停止之前执行的操作。
spec: tidb: ... terminationGracePeriodSeconds: 60 lifecycle: preStop: exec: command: - /bin/sh - -c - "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)或者驱逐超时(默认 10 分钟)后,TiKV Pod 才会重启。

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

spec: tikv: evictLeaderTimeout: 10000m

配置 TiDB 慢查询日志持久卷

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

如果想使用单独的持久卷来存储慢查询日志,可以通过配置 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 字段的具体配置方式可参考多盘挂载

tidb: ... separateSlowLog: true # 可省略 slowLogVolumeName: ${volumeName} storageVolumes: # name 必须和 slowLogVolumeName 字段的值保持一致 - name: ${volumeName} storageClassName: ${storageClass} storageSize: "1Gi" mountPath: ${mountPath}

spec.tidb.additionalVolumes 配置

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

tidb: ... separateSlowLog: true # 可省略 slowLogVolumeName: ${volumeName} additionalVolumes: # name 必须和 slowLogVolumeName 字段的值保持一致 - name: ${volumeName} nfs: server: 192.168.0.2 path: /nfs additionalVolumeMounts: # name 必须和 slowLogVolumeName 字段的值保持一致 - name: ${volumeName} 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})访问。

spec: tidb: service: type: ClusterIP

NodePort

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

spec: tidb: service: type: NodePort # externalTrafficPolicy: Local

NodePort 有两种模式:

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

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

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

LoadBalancer

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

spec: tidb: service: annotations: cloud.google.com/load-balancer-type: "Internal" externalTrafficPolicy: Local type: LoadBalancer

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

高可用配置

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

TiDB 服务高可用

通过 nodeSelector 调度实例

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

apiVersion: pingcap.com/v1alpha1 kind: TidbCluster # ... spec: pd: nodeSelector: node-role.kubernetes.io/pd: true # ... tikv: nodeSelector: node-role.kubernetes.io/tikv: true # ... tidb: nodeSelector: node-role.kubernetes.io/tidb: true # ...

通过 tolerations 调度实例

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

apiVersion: pingcap.com/v1alpha1 kind: TidbCluster # ... spec: pd: tolerations: - effect: NoSchedule key: dedicated operator: Equal value: pd # ... tikv: tolerations: - effect: NoSchedule key: dedicated operator: Equal value: tikv # ... tidb: tolerations: - effect: NoSchedule key: dedicated operator: Equal value: tidb # ...

通过 affinity 调度实例

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

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

affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: # this term works when the nodes have the label named region - weight: 10 podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/instance: ${cluster_name} app.kubernetes.io/component: "pd" topologyKey: "region" namespaces: - ${namespace} # this term works when the nodes have the label named zone - weight: 20 podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/instance: ${cluster_name} app.kubernetes.io/component: "pd" topologyKey: "zone" namespaces: - ${namespace} # this term works when the nodes have the label named rack - weight: 40 podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/instance: ${cluster_name} app.kubernetes.io/component: "pd" topologyKey: "rack" namespaces: - ${namespace} # this term works when the nodes have the label named kubernetes.io/hostname - weight: 80 podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/instance: ${cluster_name} app.kubernetes.io/component: "pd" topologyKey: "kubernetes.io/hostname" namespaces: - ${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) 来配置特定的组件。

以下是一个配置示例:

topologySpreadConstraints: - topologyKey: kubernetes.io/hostname - topologyKey: topology.kubernetes.io/zone

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

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

topologySpreadConstraints: - topologyKey: kubernetes.io/hostname maxSkew: 1 whenUnsatisfiable: DoNotSchedule labelSelector: <object> - topologyKey: topology.kubernetes.io/zone maxSkew: 1 whenUnsatisfiable: DoNotSchedule labelSelector: <object>

数据的高可用

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

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

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

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

  • 为 TiKV 节点设置所在的 Node 节点的拓扑信息

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

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

    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 保持一致即可。

文档内容是否有帮助?