技术编程|TiDB on Kubernetes 最佳实践( 二 )


那为什么还会推荐大家把 TiDB 放在 K8s 上运行呢?
第一点 , TiDB 本身能够适应动态化的 K8s 环境 。
TiDB 可以多副本做容错 , 当挂掉一个集群当中的小数节点并不会对整个集群的运行产生影响;
TiDB 能够很好的借助 K8s 环境做水平伸缩;
TiDB 提供了开箱自用的可观测性 , 大家基本上把 TiDB 部署起来 , 就可以看到 TiDB 的所有指标 , 即使是在一个动态化混部的环境里面 , 也能很清楚的明白 TiDB 现在的状态是什么 , 即使有副本挂掉 , 也没有问题 。
第二点 , 反回来 , K8s 也能很高效的去撬动 TiDB 的潜力 。
声明式 API 简化集群管理 , 作为一个分布式数据库 , TiDB 的管理会比传统的单机数据库相对复杂一点 , 而在 K8s 上 , 它的声明是 API , 就能把这一点多出来的复杂度很好的消化掉;
弹性资源池简化扩容缩与故障转移 ,TiDB 的故障容忍和无限的水平伸缩都需要额外的资源 , 比如说 , 我们去横向扩张 TiDB 集群时 , 需要申请一部分新的资源进来 , 在故障容错之后 , 要做故障转移把故障副本数补齐 。那么 K8s 的弹性资源池就能很好的把 TiDB 在水平伸缩和故障容忍上的潜力发挥出来 。
因此 ,TiDB 和 K8s 能够非常好的进行一个结合 , 并且释放出更大的潜力达成 1+1 大于 2 的效果的 。这当然不是一个巧合 , 这背后的原因是 , TiDB 和 K8s 都遵循同样的云原生最佳实践原则 。那么假如说我们已经熟悉 TiDB 和 K8s 的知识 , 只要稍微花费一些工夫 , 用 K8s 的云原生对象就可以部署一个 TiDB 集群 , 而且能运行的不错 。
但是 , TiDB 和 Kuberentes 都有大量的最佳实践 , 基本上你想快速看完是有点困难的 。那么 , 我们在 K8s 上部署 TiDB 的时候 , 应该怎样去遵守最佳实践呢?一个基本的办法就是把这些坑都了解清楚 , 并且写非常多的 run book 来告诉 SRE team , 怎么去运维好它们 。run book 需要口口相传 , 需要不断的进行知识的交互、交流 。但其实大家都知道 , 程序员一般不喜欢做这个 。
我们更喜欢把这些知识写成代码 , 做自动化 。那么 , 我们怎么样把这些东西写成代码自动化呢?
TiDB on Kubernetes 运维专家:TiDB Operator
答案就是 TiDB Operator。TiDB Operator 是什么?本质就是利用 K8s 本身的扩展机制 , 把领域性的运维知识编写成代码 , 大家可以把 TiDB Operator 理解为在 K8s 上运行 TiDB 的运维专家 , 把一个专家型人物对 TiDB 和 K8s 的所有知识都编写成了代码 。
TiDB Operator 首先添加了一组自定义类型 , 比如说 TiDB Cluster , 代表一个 TiDB 集群 , 可以在这些类型里描述你想要的 TiDB 长什么样;第二 , TiDB Operator 添加了一组自定义控制器 , 这组自定义控制器就是这些运维知识的集合 , 它会用这些代码化的知识帮助你自动化的运维 K8s 上的 TiDB 集群 。
看一个例子:首先是自定义类型 , 当 TiDB Operator 把自定义类型添加到 K8s 中后 , 作为用户就可以提交资源定义到 K8s 里面 , 比如我们需要一个 TiDB 集群 , 这个集群要的版本是什么 , 要多少 PD , 要多少 KV 。以及我们可以定义一个 TiDBMonitor 对象 , 用来监控 TiDB , 在对象定义里则只需要定义我们要监控哪一个 TiDB 就可以了 。
那么 , 大家可以发现 , 我们在做这些资源定义时是遵循 K8s 本身的声明式定义的 。那这些的理想状态由谁来实现呢?——由自定义控制器 。自定义控制器会把所有的需求和 K8s 集群里的实际状态做一个对比 , 对比之后就能发现两者的不同 , 就需要把实际状态向期望状态转移 。比如说我们把刚刚的 TiDB 集群对象和 TiDB 监控对象提交到 K8s, 那么 TiDB Operator 的控制器就会帮助我们创建很多的容器以及监控 。
当然 , 仅仅只有创建是不够的 , TiDB Operator 中还集成了 TiDB 运维专家的所有的领域知识 , 下面我分享几个运维知识 。


推荐阅读