K8S 上 TiDB 集群升级卡住问题探讨
作者: zhuboshuai 原文来源:https://tidb.net/blog/5fa22034
现象
最近把 TiDB Operator 升级到 v1.1.0 后,打算把 tidbcluster 也升级到较高版本。按照常规操作准备了镜像,执行 kubectl edit
命令后开始观察集群升级状态:
watch kubectl -n ${namespace} get pod -o wide
结果发现某个 pd 的 pod 已经处于反复重启状态,于是开始排查。
排查
因为之前在 K8S 上遇到过类似 pd 集群不正常的问题,所以沿用以前思路首先查看 pd 集群的 API 是否正常:
wget -c http://tidb-cluster-prod-pd.tidb-cluster-prod:2379/pd/api/v1/members
使用 ClusterIP 访问以确认底层网络是否正常:
wget -c http://${ClusterIP}:2379/pd/api/v1/members
结果是 pd 集群的 API 可以正常访问。
查看集群 tidbcluster CR 的 yaml 和 pd 的 StatefulSet 的 yaml 没有发现问题。
于是查看相应 pod 的日志:
kubect logs -f ${clustername}-pd-2
日志如下:
2020/06/16 11:03:04.329 log.go:86: [warning] etcdserver: [could not get cluster response from http://${clustername}-pd-4.${clustername}-pd-peer.${clustername}.svc:2380: Get http://${clustername}-pd-4.${clustername}-pd-peer.${clustername}.svc:2380/members: dial tcp: lookup ${clustername}-pd-4.${clustername}-pd-peer.tidbcluster->wuhanwuli.svc on ${ip}:53: no such host]
实际上集群中有 pd-0 到 pd-3 这 4 个 pod,pd-4 不在集群里:
继续查看 pd-2 日志可见 pd-2 已经从集群下线:
但是 pd-2 所在的 pod 仍然在运行。
查看和 pd-2 相关的 PV:
查看为 Released 状态的 PV 存储内容:
查看为 Bound 状态的 PV 存储内容:
发现为 Bound 状态的 PV 文件创建时间比为 Released 状态的 PV 文件创建时间还早。老的 PV 里面的 join 文件的创建时间大概是 2 月 7 日,而新 PV 里面的 join 文件的创建时间大概是 1 月 20 日,比老 join 文件还旧。
于是总结合理的时间序列如下:
pd-2 发生了 failover 之后,TiDB-Operator 将这个 member 从集群中删掉了,并且删掉了 pvc 和 pd-2 的 pod
pd-2 之前使用的 PV 被释放,成为 Released 状态
pd-2 新 pod 和 pvc 创建,绑定了新的 PV,状态为 Bound
由于这个新绑定的 PV 里面有老数据,导致 pd-2 这个节点无法启动
查看 local-volume-provisioner 目前用的版本仍然是 v2.3.2,从 PingCAP 小伙伴那里已经收到了存在 bug 的提醒,从 TiDB DevCon 2020 也看到了相关分享,对应 bug 说明如下:
github.com/kubernetes-sigs/sig-storage-local-static-provisioner
[](https://github.com/yuyulei)
Remove old cleanup status before create new pv
by yuyulei on 01:29PM - 18 Feb 20 UTC
1 commits changed 1 files with 7 additions and 0 deletions.
这个 bug 会导致 PV 对象重建了,但是里面的数据未清理。还没有来得及升级 local-volume-provisioner 就碰到了这个坑。
恢复方法
可以将 pd-2 现在使用的 PV 里面的数据删除,让 /var/lib/pd 目录为空,这样 pd-2 就会作为一个新的 member 启动,重新加入到整个 pd 集群。
kubectl get pv | grep pd-2
找到对应的 Local PV:
kubectl get pv local-pv-xxxx -oyaml
从以上输出中找到对应目录删除所有内容,然后观察所有 pod 状态。
watch kubectl get po -n ${namespace}
可以看到 pd 全部重启并恢复 Running 状态,然后其它组件也相继升级成功:
隐患排查和解决
排查所有目前状态为 Available 的 PV,确认目录为空
kubectl get pv | grep Available | grep local-storage-pd | awk '{print $1}' | xargs kubectl get pv -oyaml | egrep 'kubernetes.io/hostname|path
找到所有目录逐一排查。
备注:本环境中 pd 的 storageclass 为 local-storage-pd
local-volume-provisioner 升级到 2.3.4:
docker pull quay.io/external_storage/local-volume-provisioner:v2.3.4
docker tag quay.io/external_storage/local-volume-provisioner:v2.3.4 ${registry address}/tidb/local-volume-provisioner:2.3.4
docker push ${registry address}/tidb/local-volume-provisioner:2.3.4
编辑 local-volume-provisioner:
kubectl edit ds local-volume-provisioner -oyaml -n kube-system
修改 spec.template.spec.image 保存后观察升级情况:
watch kubectl get po -l app=local-volume-provisioner -n kube-system
可见 local-volume-provisioner 已经升级成功。
后记
截止目前,K8S 上的 TiDB 集群已正常运行两周,没有再发现问题。
同时感谢 PingCAP 小伙伴的大力支持!
版权声明: 本文为 InfoQ 作者【TiDB 社区干货传送门】的原创文章。
原文链接:【http://xie.infoq.cn/article/3a728694dc718cae56936ed89】。文章转载请联系作者。
评论