简介
TiDB Operator是 Kubernetes 上的 TiDB 集群自动运维系统,提供包括部署、升级、扩缩容、备份恢复、配置变更的 TiDB 全生命周期管理。借助 TiDB Operator,TiDB 可以无缝运行在公有云或私有部署的 Kubernetes 集群上,目前已开源 pingcap/tidb-operator 。

TiDB Operator 与适用的 TiDB 版本的对应关系如下:
| TiDB 版本 | 适用的 TiDB Operator 版本 |
| dev | dev |
| TiDB >= 5.4 | 1.3 |
| 5.1 <= TiDB < 5.4 | 1.3(推荐),1.2 |
| 3.0 <= TiDB < 5.1 | 1.3(推荐),1.2,1.1 |
| 2.1 <= TiDB < v3.0 | 1.0(停止维护) |
为什么需要TiDB Operator
第一,TiDB Operator提供自动化部署、升级、扩缩容、备份恢复、配置变更的全生命周期管理。
TiDB 的分层架构对于分布式系统是比较常见的,各个组件都可以根据业务需求独立水平伸缩,并且 TiKV 和 TiDB 都可以独立使用。比如,在 TiKV 之上可以构建兼容 Redis 协议的 KV 数据库,而 TiDB 也可以对接 LevelDB 这样的 KV 存储引擎。但是,这种多组件的分布式系统增加了手工部署和运维的成本。一些传统的自动化部署和运维工具如 Puppet/Chef/SaltStack/Ansible,由于缺乏全局状态管理,不能及时对各种异常情况做自动故障转移,并且很难发挥分布式系统的弹性伸缩能力。其中有些还需要写大量的 DSL 甚至与 Shell 脚本一起混合使用,可移植性较差,维护成本比较高。
第二,在云时代容器成为应用分发部署的基本单位,Kubernetes 成为当前容器编排技术上的标准。
如今各大云厂商都开始提供托管的 Kubernetes 集群,部署在 Kubernetes 平台的应用可以不用绑定在特定云平台,轻松实现在各种云平台之间的迁移,其容器化打包和发布方式也解决了对操作系统环境的依赖。
为了在 Kubernetes 上部署和管理 TiDB 这种有状态的服务,我们需要扩展 StatefulSet 的功能。TiDB Operator 正是基于 Kubernetes 内置的 StatefulSet 云原生开发的 TiDB 集群管理和运维工具。官方本地 PV 方案直到最近的 Kubernetes v1.10 才相对稳定地支持调度功能(需要运行在 Kubernetes v1.10 及以上版本),满足用户对本地 PV 的需求。为了降低用户的使用和管理成本并且拥抱 Kubernetes 开源社区。
第三,执行操作需要TiDB相关的知识。
在通过TiDB Operator部署tidb集群时,需要了解tidb集群的架构,各服务组件的关系以及启动都有相关的顺序的,在扩缩容的时候需要按照相应的组件进行操作。
核心亮点
轻松部署TiDB群集
能安全扩展在TiDB的集群的每个组件,TiDB Operator 则通过自定义资源对象(Custom Resource)、自定义控制器(Custom controller)和调度器扩展(Scheduler extender)为 Kubernetes 注入 TiDB 的专业运维知识,允许用户以 Kubernetes 的声明式 API 风格来管理 TiDB 集群。具体来说,用户只需要描述集群规格,TiDB Operator 就会不断调整 Kubernetes 中的资源,驱动实际集群满足该描述。在这种模式下,TiDB 集群会自动完成服务的健康检查、故障转移,而部署、升级、扩缩容等操作则能通过修改集群的规格定义“一键”完成,极大简化了 TiDB 集群的运维管理
滚动更新。
在没有任何停机的情况下,平稳地执行滚动更新,各服务组件在更新的过程中会逐个进行,当完成后才会有其他的pod进行,出现问题便于快速回滚。
多租户支持
用户可以使用TiDB Operator在单个Kubernetes集群上部署和管理多个TiDB集群。
自动故障切换
当节点/Pod发生故障时,TiDB Operator自动执行故障转移切换。
简单监控
TiDB Operator支持安装Prometheus和Grafana进行集群监控
多云支持
1提供了面向 AWS、谷歌云和阿里云的 Terraform 部署脚本。 这些脚本能帮助大家在十几分钟内创建一个 Kubernetes 集群,并在该集群上部署一个或更多生产可用的 TiDB 集群。在后续的管理过程中,Terraform 脚本会在操作 TiDB 集群的同时对相关的云资源进行操作。比如,当扩容一个 TiDB 集群时,Terraform 脚本就会自动创建更多的云服务器来承载集群扩容后的资源需求。
架构

其中,TidbCluster、TidbMonitor、TidbInitializer、Backup、Restore、BackupSchedule、TidbClusterAutoScaler 是由 CRD(CustomResourceDefinition)定义的自定义资源:
TidbCluster用于描述用户期望的 TiDB 集群TidbMonitor用于描述用户期望的 TiDB 集群监控组件TidbInitializer用于描述用户期望的 TiDB 集群初始化 JobBackup用于描述用户期望的 TiDB 集群备份Restore用于描述用户期望的 TiDB 集群恢复BackupSchedule用于描述用户期望的 TiDB 集群周期性备份TidbClusterAutoScaler用于描述用户期望的 TiDB 集群自动伸缩
TiDB 集群的编排和调度逻辑则由下列组件负责:
tidb-controller-manager是一组 Kubernetes 上的自定义控制器。这些控制器会不断对比TidbCluster对象中记录的期望状态与 TiDB 集群的实际状态,并调整 Kubernetes 中的资源以驱动 TiDB 集群满足期望状态,并根据其他 CR 完成相应的控制逻辑;tidb-scheduler是一个 Kubernetes 调度器扩展,它为 Kubernetes 调度器注入 TiDB 集群特有的调度逻辑。tidb-admission-webhook是一个 Kubernetes 动态准入控制器,完成 Pod、StatefulSet 等相关资源的修改、验证与运维。discovery是一个用于组件间发现的服务。每一个 TiDB 集群会对应存在一个 discovery Pod,用于该集群中组件发现其他已经创建的组件。
TiDB Controller Manager
tidb-controller-manager不断持续地调整期望状态和实际状态的差异。如果状态不匹配的话,控制器将触发动作以转换为所期待的状态,具体如下图:


TiDB Scheduler扩展调度器
TiDB Scheduler 是 Kubernetes 调度器扩展 的 TiDB 实现。TiDB Scheduler 用于向 Kubernetes 添加新的调度规则。Kubernetes 集群中默认会部署一个 kube-scheduler,用于 Pod 调度,默认调度器名字为 default-scheduler,具体的调度规则请参考K8S-POD资源和调度 。
TiDB Scheduler 通过实现 Kubernetes 调度器扩展(Scheduler extender)来添加自定义调度规则。
TiDB Scheduler 组件部署为一个或者多个 Pod,但同时只有一个 Pod 在工作。Pod 内部有两个 Container,一个 Container 是原生的 kube-scheduler;另外一个 Container 是 tidb-scheduler,实现为一个 Kubernetes scheduler extender。
如果 TidbCluster 中配置组件使用 tidb-scheduler,TiDB Operator 创建的 PD、TiDB、TiKV Pod 的 .spec.schedulerName 属性会被设置为 tidb-scheduler,即都用 TiDB Scheduler 自定义调度器来调度。
此时,一个 Pod 的调度流程是这样的:
kube-scheduler拉取所有.spec.schedulerName为tidb-scheduler的 Pod,对于每个 Pod 会首先经过 Kubernetes 默认调度规则过滤;- 在这之后,
kube-scheduler会发请求到tidb-scheduler服务,tidb-scheduler会通过一些自定义的调度规则(见上述介绍)对发送过来的节点进行过滤,最终将剩余可调度的节点返回给kube-scheduler; - 最终由
kube-scheduler决定最终调度的节点。
TiDB Operator 准入控制器
Kubernetes 在 1.9 版本引入了 动态准入机制,从而使得拥有对 Kubernetes 中的各类资源进行修改与验证的功能。 在 TiDB Operator 中,我们也同样使用了动态准入机制来帮助我们进行相关资源的修改、验证与运维。
TiDB Operator 准入控制器与大部分 Kubernetes 平台上产品的准入控制器较为不同,TiDB Operator 通过扩展 API-Server 与 WebhookConfiguration 的两个机制组合而成。所以需要 Kubernetes 集群启用聚合层功能,通常情况下这个功能已经默认开启。如需查看是否开启聚合层功能,请参考启用 Kubernetes Apiserver 标志。
原理
Operator 本质上是 Kubernetes 的控制器(Controller),其核心思想是用户给定一个 Spec 描述文件,Controller 根据 Spec 的变化,在 Kubernetes 集群中创建对应资源,并且不断调整资源使其状态满足用户预期的 Spec。

上图是 TiDB Operator 工作流程原理图,其中 TidbCluster 是通过 CRD(Custom Resource Definition)扩展的内置资源类型:
- 用户通过 Helm 往 Kubernetes API Server 创建或更新 TidbCluster 对象。
- TiDB Operator 通过 watch API Server 中的 TidbCluster 对象创建更新或删除,维护 PD/TiKV/TiDB StatefulSet, Service 和 Deployment 对象更新。
- Kubernetes 根据 StatefulSet, Service 和 Deployment 对象创建更新或删除对应的容器和服务。
在第 2 步中,TiDB Operator 在更新 StatefulSet 等对象时会参考 PD API 给出的集群状态来做出 TiDB 集群的运维处理。通过 TiDB Operator 和 Kubernetes 的动态调度处理,创建出符合用户预期的 TiDB 集群。
安装部署TiDB Operator
安装helm
Helm 是一个 Kubernetes 的包管理工具,是查找、分享和使用软件构建 Kubernetes 的最优方式,类似 Linux 的包管理器,如RedHat系的yum、Debian的apt,可以很方便的将之前打包好的 yaml 文件部署到 Kubernetes 上。Helm主要解决以下问题:1、把yaml作为一个整体管理。2、实现yaml的高效复用。3、实现应用级别的版本管理。helm安装比较简单
Helm官方下载地址 (https://github.com/helm/helm/releases )
wget https://get.helm.sh/helm-v3.4.2-linux-amd64.tar.gz
解压Helm
tar zxvf helm-v3.4.2-linux-amd64.tar.gz
移动到主节点 /usr/bin 目录
mv linux-amd64/helm /usr/bin/
验证是否安装成功
helm version
部署TiDB Operator(离线方式)
由于客户大部分都是内网不能上外网,所以本文档以离线的方式部署TiDB Operatro
下载tidb-operator
#下载最新版本的包
wget http://charts.pingcap.org/tidb-operator-v1.4.3.tgz
#解压
tar zxvf tidb-operator.v1.4.3.tgz
下载所需的镜像,打标签并推到私有仓库
#tidb operator所用到的所有镜像
pingcap/tidb-operator:v1.4.3
pingcap/tidb-backup-manager:v1.4.3
bitnami/kubectl:latest
pingcap/advanced-statefulset:v0.3.3
k8s.gcr.io/kube-scheduler:v1.16.9
##镜像拉取并下载
docker pull pingcap/tidb-operator:v1.4.3
docker pull pingcap/tidb-backup-manager:v1.4.3
docker pull bitnami/kubectl:latest
docker pull pingcap/advanced-statefulset:v0.3.3
docker save -o tidb-operator-v1.4.3.tar pingcap/tidb-operator:v1.4.3
docker save -o tidb-backup-manager-v1.4.3.tar pingcap/tidb-backup-manager:v1.4.3
docker save -o bitnami-kubectl.tar bitnami/kubectl:latest
docker save -o advanced-statefulset-v0.3.3.tar pingcap/advanced-statefulset:v0.3.3
##上传镜像
docker load -i tidb-operator-v1.4.3.tar
docker load -i tidb-backup-manager-v1.4.3.tar
docker load -i bitnami-kubectl.tar
docker load -i advanced-statefulset-v0.3.3.tar
##备注,如果推到私有仓库需要给镜像打标签并上传
docker tag pingcap/tidb-operator:v1.4.3 xxx.com:5003/pingcap/tidb-operator:v1.4.3
docker push xxx.com:5003/pingcap/tidb-operator:v1.4.3
配置TiDB Operator
主要配置的镜像名、limits、requests 和 replicas,请根据需要进行修改
vim ./tidb-operator/values.yaml
clusterScoped: true
rbac:
create: true
timezone: UTC
operatorImage: pingcap/tidb-operator:v1.4.3
imagePullPolicy: IfNotPresent
tidbBackupManagerImage: pingcap/tidb-backup-manager:v1.4.3
##启用asts配置
features:
- AdvancedStatefulSet=true
advancedStatefulset:
create: true
appendReleaseSuffix: false
controllerManager:
create: true
serviceAccount: tidb-controller-manager
clusterPermissions:
nodes: true
persistentvolumes: true
storageclasses: true
logLevel: 2
replicas: 1
resources:
requests:
cpu: 80m
memory: 50Mi
autoFailover: true
pdFailoverPeriod: 5m
tikvFailoverPeriod: 5m
tidbFailoverPeriod: 5m
tiflashFailoverPeriod: 5m
dmMasterFailoverPeriod: 5m
dmWorkerFailoverPeriod: 5m
detectNodeFailure: false
affinity: {}
nodeSelector: {}
tolerations: []
selector: []
env: []
securityContext: {}
podAnnotations: {}
scheduler:
create: true
serviceAccount: tidb-scheduler
logLevel: 2
replicas: 1
schedulerName: tidb-scheduler
resources:
limits:
cpu: 250m
memory: 150Mi
requests:
cpu: 80m
memory: 50Mi
kubeSchedulerImageName: k8s.gcr.io/kube-scheduler
affinity: {}
nodeSelector: {}
tolerations: []
securityContext: {}
podAnnotations: {}
configmapAnnotations: {}
advancedStatefulset:
create: true
image: pingcap/advanced-statefulset:v0.4.0
imagePullPolicy: IfNotPresent
serviceAccount: advanced-statefulset-controller
logLevel: 4
replicas: 1
resources:
limits:
cpu: 500m
memory: 300Mi
requests:
cpu: 200m
memory: 50Mi
affinity: {}
nodeSelector: {}
tolerations: []
securityContext: {}
admissionWebhook:
create: false
replicas: 1
serviceAccount: tidb-admission-webhook
logLevel: 2
rbac:
create: true
validation:
statefulSets: false
pingcapResources: false
mutation:
pingcapResources: true
failurePolicy:
validation: Fail
mutation: Fail
apiservice:
insecureSkipTLSVerify: true
tlsSecret: ""
caBundle: ""
cabundle: ""
securityContext: {}
nodeSelector: {}
tolerations: []
安装TiDB Operator
kubectl create ns tidb-admin
helm install tidb-operator ./tidb-operator --namespace=tidb-admin
升级TiDB Operator
helm upgrade tidb-operator ./tidb-operator --namespace=tidb-admin