1 个月前 TIDB 官方展开了一个 TiDB 6.0 Book Rush 活动, 作为2年前参与过:TiDB in action 的我来说,还是比较熟悉的,之前电子书编写采用了比较极客的方式,有个 36 小时的实现,大家都编写自己领取的文章模块后,在 github 上提交自己的文章,本次 TiDB 6.0 Book Rush 则主要针对 6.0 新提出的 14 个新特性展开,这样大家试用+写文章时也能体现出重点,顺带帮官方测测BUG。哈哈。
本文主要涉及到 TiDB 6.0 的新特性 Clinic。
一、传统的故障排查
谈 Clinic 这个工具之前,不得不讲讲之前遇到故障时,找官方排查的血泪史。遇到bug时,官方技术支持一般要求提供:TiDB集群信息(版本,display ),grafana 监控、各个组件(TiDB/PD/TIKV/TiCDC/DM)日志、系统参数配置等。从 asktug 的帖子说明就可以看出需要用户提供的一些清单,主要包括 TiDB 集群节点信息、配置信息、集群监控、对应出问题组件的日志:
【 TiDB 使用环境】
【概述】 场景 + 问题概述
【背景】 做过哪些操作
【现象】 业务和数据库现象
【问题】 当前遇到的问题
【业务影响】
【TiDB 版本】
【应用软件及版本】
【附件】 相关日志及配置信息
* TiUP Cluster Display 信息
* TiUP CLuster Edit config 信息
监控(https://metricstool.pingcap.com/)
* TiDB-Overview Grafana监控
* TiDB Grafana 监控
* TiKV Grafana 监控
* PD Grafana 监控
* 对应模块日志(包含问题前后 1 小时日志)
1、提供监控
先聊 grafana 监控,下面的各个阶段都是我之前经历和使用过的提供监控的方式方法,大家用的过麻烦点赞。
(1)手动截图,刚开始技术支持会按照排除法给用户来定位问题。比如一个 oom 问题可能有几种导致的原因,技术支持同学会一个个让你截图来排除。这时的问题如下:
混乱繁杂(技术支持只能靠一点点猜想找你要截图,而且需要看看多个截图,光截图和问题判断的相互配合就需要大家的一上午或者下午的时间)
时间跨度不好定(比如:看详情需要 30 分钟内,如果要对比昨天的数据则需要看 2 天,同一个图可能需要截图不同时间段)
拿 tikv detail 这个dashboard来讲,上百个监控指标,光打开就分钟级别,再找就需要半分钟。
效率低下,刚开始还担心数据安全,截图后,自己还需要加“马赛克”,再加上排除法的来来回回的反馈,半天的时间很快就过去了,问题还没有及时的定位。
(2) 后来 PingCAP 官方提供了一个“脚本”,脚本的好处就是避免手工截图,可以以 json 的方式导出 grafana 监控,然后发送给官方技术支持,他们收到这个 json 可以自己 load 到本地的 grafana 查看,避免了截图的效率低下,这个脚本也可以自己保存 json 数据。
脚本如下
/* Copyright 2020 PingCAP, Inc. Licensed under MIT. */
"use strict"
var t={t:"Script failed to run. Please ensure it is running on the Grafana v6.x.x dashboard page.",
i:"Going to export snapshot of the current dashboard: ",s:"Note: Only metrics from visible panels can be exported",
o:"Number of panels",l:"Loading panels",h:"Expand all rows",p:"Export",u:"Export immediately",cancel:"Cancel"}
try{
var e=angular.element,i=document.styleSheets[0],a=[".__dexport_hint{z-index:2222;position:fixed;background:#fff;color:#000;padding:1em;font-size:18px;border-left:3px solid #faad14;right:0;top:5em;opacity:.8;min-width:30em}",".__dexport_hint:hover{opacity:1}",".__dexport_hint button{margin:0 1em}",".__dexport_hint button[disabled]{opacity:.5}",".__dexport_hint progress{margin-right:1em;vertical-align:middle;width:18em}"]
new(function(){function n(){var n=this,s=e(document).injector()
this.m=s.get("timeSrv")
var o=this.m.dashboard
a.forEach(t=>i.insertRule(t,0)),this.v=e("<span>"),this.g=e('<progress value="0">'),
this._=e('<button style="font-weight:bold">').text(t.p).one("click",()=>n.k()),
this.P=e("<button>").text(t.h).on("click",()=>{o.expandRows(),n.S(()=>{n.T()})})
var r=/^(Mac|iP)/.test(navigator.platform)?"flex-direction:row-reverse":"justify-content:center"
this.j=e('<div class="__dexport_hint">').append(e("<p>").text(t.i).append(e("<strong>").text(o.title)),e("<p>").text(t.s).append(this.P),e('<p style="font-size:.8em">').append(this.g,this.v),e('<p style="display:flex;'+r+'">').append(this._,e("<button>").text(t.cancel).on("click",()=>n.I()))),
this.L=0,e(document.body).append(this.j),this.N=setInterval(()=>n.T(),500)}return n.prototype.T=function(){
var i=this,a=e(".panel-container"),n=a.length
if(0===this.L)this.v.text(t.o+": "+n),this._.prop("disabled",0===n)
else{var s=n-a.find(".panel-loading:visible").length,o=(100*s/n||0).toFixed(1)
this.v.text(t.l+": "+o+"% ("+s+"/"+n+")"),this.g.prop({value:s,max:n}),n>s?2!==this.L&&(this.L=2,
this._.prop("disabled",!1).text(t.u).one("click",()=>i.O())):this.O()}},n.prototype.k=function(){
var t=this,i=this.m.dashboard
this.B=i.refresh,this.m.setAutoRefresh(),e(".panel-loading").removeClass("ng-hide"),this.S(()=>{t.L=1,
t._.prop("disabled",!0),i.snapshot={timestamp:new Date},i.startRefresh()})},n.prototype.S=function(t){var i=e(".layout")
i.hide(),this.m.dashboard.removePanel(null),setTimeout(()=>{t(),i.show()},100)},n.prototype.O=function(){
var t=this.m.dashboard,i=t.snapshot.timestamp.toISOString(),a=t.getSaveModelClone(),n=a.title
a.time=this.m.timeRange(),a.id=null,a.uid=null,a.title=n+" (exported at "+i+")"
var s={meta:{isSnapshot:!0,type:"snapshot",expires:"9999-12-31T23:59:59Z",created:i,
grafana:grafanaBootData.settings.buildInfo},dashboard:a,overwrite:!0}
this.I()
var o=new Blob([JSON.stringify(s)],{type:"application/json"}),r=URL.createObjectURL(o),l=e("<a>")
l.prop({href:r,download:n+"_"+i+".json",target:"_blank"}),e(document.body).append(l),l[0].click(),setTimeout(()=>{
URL.revokeObjectURL(r),l.remove()},0)},n.prototype.I=function(){var t=this.m.dashboard
delete t.snapshot,t.forEachPanel(t=>delete t.snapshotData),t.annotations.list.forEach(t=>delete t.snapshotData),
this.B&&this.m.setAutoRefresh(this.B),clearInterval(this.N),this.j.remove(),a.forEach(()=>i.deleteRule(0))},n}())
}catch(e){console.error(e),alert(t.t)}
PS:脚本的主要问题,像tikv detail存储的时间比较长,另外grafana版本的变更/chrome的升级也可能带来兼容性的问题,需要频繁的调整脚本。另外你可能还需要具备“前端工程师”的能力。
2、提供日志
有时监控不能完全确认问题,还需要有日志的辅助,这时就需要提供各个组件的日志,就拿一个慢日志造成的tikv oom 举例,需要提供的日志:
(1)TiDB server 的日志,找“Welcome”关键词(代表重启)的附近 [expensive_query] 相关日志。
(2)TiDB 的 slow log,找 query-time,total-keys,process-keys 等指标,来找出导致问题的 SQL。
(3)Tikv 的日志,看是否读写有热点。
(4)如果涉及到统计信息不更新导致慢查询的问题,可能也需要查看 PD Leader 相关的日志。
提供日志时问题如下:
(1)有时需要提供所有 TIKV 组件的日志,假如你的 TiKV 节点比较多,又没有 ELK 这种日志收集平台的话,一台台的远程登录,找对应时间段的日志(可能因为日志切分放到了不同的文件),折腾一遭非常的痛苦。
(2)有时需要提供较长时间的日志文件过大,发送给官方人员的还需要各种渠道。
3、涉及的安全问题
很多小伙伴把自己业务的 grafana 监控放到 asktug 这个公共平台,对于大量的监控截图虽说是可以抹除敏感信息,但是光加马赛克就各种折腾和大量时间消耗。另外日志等信息放 asktug 这个平台就不好弄了,因为 asktug 是注册就可以看到大家发的帖子,包括各种截图以及日志信息。所以不免导致上传者担心的自己 TIDB 集群信息安全。
二、PingCAP Clinic
我想告诉大家的是,救星终于来了,以后 asktug 提故障帖子,不需要各种截图还打马赛克,也不需要脚本导json,各种苦哈哈的提供各种组件的日志。Pingcap 公司的技术人员,根据多年来问题排查的经验,提供了 Clinic 这个诊断服务来统一收集集群的各个指标(下面会有详细的指标收集说明)、统一上传到 Pingcap 公司的Clinic Server上,在 asktug 上,你只需要提供给官方技术一个上传完毕的链接即可,不要担心,你上传的数据首先只能官方人员查看,并且在 case 解决并关闭后的 90 天内删除,所以再也不用担心 asktug自 己公司集群信息暴露的安全问题。
所以通过上面的说明可以了解到,Clinic 这个解决方案提供了2个组件。
Clinic 数据采集端 Diag ,用来采集各种数据。
Clinic Server 用于接收用户上传的各种采样数据。
1、Diag 都采集什么数据
(1)集群信息
包括集群基本信息,集群节点的硬件配置、内核参数等。
tiup cluster audit/display/edit-config获取集群的信息。
tiup exec --command可以执行 Insight 等命令获取系统信息,包括内核日志、内核参数、系统和硬件的基础信息。
(2)TiDB 组件配置和日志
tidb/pd/tikv/tiflash/ticdc/dm 的配置和日志,底层使用 SCP 直接从目标组件的节点采集日志文件和配置文件
(3) 监控
通过 Prometheus 提供的 HTTP API,数据收集组件可获取 Alert 和 metric 监控指标
另外 TiDB 的各个组件本身就暴露了 HTTP 接口,数据收集组件可以实时收集采样信息和进行性能采样。
PS:这些不就是我们之前苦哈哈的手动需要提供的么?以后可以通过 Diag 数据收集工具几个命令搞定。
2、使用 Diag 采集集群数据
(1)安装 Diag 诊断客户端:部署在集群侧的工具,用于采集集群的诊断数据 (collect)、上传诊断数据到 Clinic Server、对集群进行本地快速健康检查 (check)。
在tiup中控机上使用下面的命令安装,看到安装应该是 v0.7.1 版本:
tiup install diag
download https://tiup-mirrors.pingcap.com/diag-v0.7.1-linux-amd64.tar.gz 17.57 MiB / 17.57 MiB 100.00% 10.74 MiB/s
(2)采集近2小时的诊断数据。
tiup diag collect ${cluster-name}
#执行命令过程不会马上收集,会大概展示要收集的内容、数据的大小,数据的路径:以diag开头的文件夹,确认后开始收集,收集完毕,进入路径发现以下内容:
cluster_audit #集群的audit信息,执行tiup cluster audit|grep 集群得到
cluster.json #集群的display信息,执行tiup cluster display的结果
fTLypmPrm8j_diag_audit.log #tiup diag的执行日志,通过该日志可以看出详细的收集流程
meta.yaml #集群的meta信息,执行tiup cluster edit-config可以得到
monitor/ #集群的大量的详细的grafana监控dashboard的json文件
test1.xxxx.com/ #各个tidb组件的详细日志+系统配置
..........
test10.xxxx.com/ #进入该目录
datax/ #TiDB集群组件配置和日志
dmesg.log #系统内核日志,记录了操作系统硬件故障/oom kill等信息
insight.json #系统和硬件的基础信息
limits.conf #系统limit.conf的信息
ss.txt #系统网络情况
sysctl.conf #操作系统内核参数配置sysctl.conf
PS:默认 diag 会采集近2小时数据,如果要采集更早的某个时间段,可以通过 --from/--to来指定,详见 tiup diag collect --help
(3) 上传数据到 Clinic Server 给PingCAP官方技术人员查看。
tiup diag upload ${filepath}
完成上传后,Diag 会提示诊断数据的下载路径 Download URL,以后只需要提供该 URL 给官方支持人员就OK了,然后就是等反馈了。
PS:早期我使用的时候,上传还是统一的用户名和密码,新的版本已经需要
3、Clinic 还能干啥?
(1)集群抖动现场保留
当集群出现问题,但无法马上进行问题分析时,你可以先使用 Diag 采集数据,并将其数据保存下来,用于自己后期进行问题分析。
(2)日常巡检:预测可出现的集群的配置问题
Clinic 设计之初应该就是以后做日常 TIDB 巡检的工具,不过当前的 Technical Preview 版本只提供对配置项检查,用于发现不合理的配置,并提供修改建议。
#执行收集当前集群配置
tiup diag collect ${cluster-name} --include="config"
# 执行完毕后会生成一个数据目录
tiup diag check ${subdir-in-output-data}
#查看结果发现提示了几个Rule name tidb-max-days/backups、pdconfig-max-days/backups的warning,每个报警都有个链接可以知道具体的报警原因,比如下面就是TiDB 的日志大保留的天数设置为0(保存)导致的警告
#### Rule Name: tidb-max-days
- RuleID: 100
- Variation: TidbConfig.log.file.max-days
- For more information, please visit: https://s.tidb.io/msmo6awg
- Check Result:
TidbConfig_xxxx.com:4000 TidbConfig.log.file.max-days:0 warning
TidbConfig_xxxx.com:4000 TidbConfig.log.file.max-days:0 warning
(3)收集DM集群的诊断数据
主要采集DM集群信息,dm-master/worker的日志和配置,以及DM的监控,DM集群各个节点的硬件信息。
tiup diag collectdm ${cluster-name}
注意:这里跟上面的TiDB集群收集的命令不同主要在diag后面的collectdm参数上,别写错了。
后要想更多了解 Clinic 可以查看官方链接:
https://docs.pingcap.com/zh/tidb/v6.0/clinic-data-instruction-for-tiup