文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Kubernetes 应用问题的通用排查思路

2024-12-02 19:16

关注

本文转载自微信公众号「明哥的IT随笔」,作者IT明哥。转载本文请联系明哥的IT随笔公众号。

大家好,我是明哥!

本片文章介绍下 Kubernetes 应用问题的通用排查思路,分享一个线上此类问题的排查案例,总结下背后的相关知识,以飨读者,大家共勉!

1 技术趋势大背景

我们知道,大数据进一步发展的一个趋势,就是大数据和云计算进一步融合(包括在底层更加青睐存储计算分离的架构,在底层更加青睐对象存储),在部署架构上支持混合云和多云场景,拥抱云计算走向云原生化。

对应到底层具体技术堆栈上,体现在各个主流大数据平台和底层的大数据组件,纷纷开始支持以 Kubernetes 和 Docker 为代表的容器系列技术栈。

所以大数据从业者,需要不断扩展自己的技能包,掌握 Kubernetes 和 Docker 的基础知识和常见命令,才能在排查大数据相关问题时不至于捉襟见肘,因技能储备短缺,无从下手。

从技术视角看大数据行业的发展趋势

在此分享一个大数据平台中 docker 容器相关故障的排查案列,并介绍下此类问题的背后知识和排查思路,以飨读者,大家共勉!

2 问题现象

星环大数据平台 TDH 中, zookeeper 服务无法正常启动。我们知道 TDH 中,各个服务其实是在 k8s 的管控下运行于 docker 容器中,通过 kubectl get pods -owide |grep -i zoo 可以发现,对应的 pod 的状态是CrashLoopBackOff,如下图所示:

pod-CrashLoopBackOff

3 背后知识:什么是 CrashLoopBackOff?

某个 pod 处于 CrashloopBackOff, 意味着该 pod 中的容器被启动了,然后崩溃了,接下来又被自动启动了,但又崩溃了,如此周而复始,陷入了(starting, crashing, starting,crashing)的循坏.

注意:pod 中的容器之所以会被自动重启,其实是通过 PodSpec 中的 restartPolicy 指定的,该配置项默认是 Always,即失败后会自动重启:

4 背后知识:为什么会发生 CrashLoopBackOff 错误?

pod 的 CrashLoopBackOff 错误还是挺常见的,该错误可能会因为多种原因被触发,几个主要的上层原因有:

5 背后知识:如何排查 pod 容器底层的应用程序的故障?

当 pod 容器底层的应用程序运行出现故障时,通用的排查思路,一般是:

有的小伙伴可能会有疑问,上述步骤二和步骤三都是查看 pod 容器底层的应用程序的日志,有什么区别呢?

其实步骤二和步骤三在底层查看的是应用程序的不同的日志文件,其底层细节跟 kubernetes 的日志机制,以及该 pod 底层的应用程序将日志写向何处有关:

ps. 我们这里讨论的是运行在 k8s 容器中的应用程序的日志,除了应用程序的日志,其实整个k8s 集群中还有很多系统组件的日志,如:docker,kubelet,kube-proxy,kube-apiserver,kube-scheduler,etcd等。

6 问题排查复盘

按照上述通用问题排查思路,我们复盘回顾下该 CrashLoopBackOff 问题的排查经过。

6.1:问题排查复盘:通过命令 kubeclt describe pod xxx 获取 pod 详细信息

该命令输出的部分截图如下,通过输出中 Events 部分,我们可以获取如下信息:该 pod 被成功地分配到了某个节点上,然后镜像拉取成功,然后 contaier 创建和启动成功,但随后 contaier 中程序运行失败,最后 pod 进入到了 BackOff 状态:

kubectl-describe-pod

该命令的详细输出如下:

  1. kubectl describe pod zookeeper-server-license-7fbfc544fc-h8nn9 
  2. Name:               zookeeper-server-license-7fbfc544fc-h8nn9 
  3. Namespace:          default 
  4. Priority:           0 
  5. PriorityClassName:   
  6. Node:               uf30-tdh3-regression/10.20.159.115 
  7. Start Time:         Mon, 11 Oct 2021 16:56:30 +0800 
  8. Labels:             name=zookeeper-server-license 
  9.                     pod-template-hash=3969710097 
  10.                     podConflictName=zookeeper-server-license 
  11. Annotations:         
  12. Status:             Running 
  13. IP:                 10.20.159.115 
  14. Controlled By:      ReplicaSet/zookeeper-server-license-7fbfc544fc 
  15. Containers: 
  16.   zookeeper-server-license: 
  17.     Container ID:  docker://0887c97ab185f1b004759e8c85b48631f511cb43088424190c3f27c715bb8414 
  18.     Image:         transwarp/zookeeper:transwarp-6.0.2-final 
  19.     Image ID:      docker-pullable://transwarp/zookeeper@sha256:19bf952dedc70a1d82ba9dd9217a2b7e34fc018561c2741d8f6065c0d87f8a10 
  20.     Port:           
  21.     Args: 
  22.       boot.sh 
  23.       LICENSE_NODE 
  24.     State:          Terminated 
  25.       Reason:       Error 
  26.       Exit Code:    1 
  27.       Started:      Mon, 11 Oct 2021 17:12:09 +0800 
  28.       Finished:     Mon, 11 Oct 2021 17:12:10 +0800 
  29.     Last State:     Terminated 
  30.       Reason:       Error 
  31.       Exit Code:    1 
  32.       Started:      Mon, 11 Oct 2021 17:07:07 +0800 
  33.       Finished:     Mon, 11 Oct 2021 17:07:08 +0800 
  34.     Ready:          False 
  35.     Restart Count:  8 
  36.     Environment: 
  37.       ZOOKEEPER_CONF_DIR:  /etc/license/conf 
  38.     Mounts: 
  39.       /etc/license/conf from conf (rw) 
  40.       /etc/localtime from timezone (rw) 
  41.       /etc/tos/conf from tos (rw) 
  42.       /etc/transwarp/conf from transwarphosts (rw) 
  43.       /usr/lib/transwarp/plugins from plugin (rw) 
  44.       /var/license from data (rw) 
  45.       /var/log/license/ from log (rw) 
  46.       /var/run/secrets/kubernetes.io/serviceaccount from default-token-g42jt (ro) 
  47.       /vdir from mountbind (rw) 
  48. Conditions: 
  49.   Type           Status 
  50.   Initialized    True  
  51.   Ready          False  
  52.   PodScheduled   True  
  53. Volumes: 
  54.   data: 
  55.     Type:          HostPath (bare host directory volume) 
  56.     Path:          /var/license 
  57.     HostPathType:   
  58.   conf: 
  59.     Type:          HostPath (bare host directory volume) 
  60.     Path:          /etc/license/conf 
  61.     HostPathType:   
  62.   log: 
  63.     Type:          HostPath (bare host directory volume) 
  64.     Path:          /var/log/license/ 
  65.     HostPathType:   
  66.   mountbind: 
  67.     Type:          HostPath (bare host directory volume) 
  68.     Path:          /transwarp/mounts/license 
  69.     HostPathType:   
  70.   plugin: 
  71.     Type:          HostPath (bare host directory volume) 
  72.     Path:          /usr/lib/transwarp/plugins 
  73.     HostPathType:   
  74.   timezone: 
  75.     Type:          HostPath (bare host directory volume) 
  76.     Path:          /etc/localtime 
  77.     HostPathType:   
  78.   transwarphosts: 
  79.     Type:          HostPath (bare host directory volume) 
  80.     Path:          /etc/transwarp/conf 
  81.     HostPathType:   
  82.   tos: 
  83.     Type:          HostPath (bare host directory volume) 
  84.     Path:          /etc/tos/conf 
  85.     HostPathType:   
  86.   default-token-g42jt: 
  87.     Type:        Secret (a volume populated by a Secret) 
  88.     SecretName:  default-token-g42jt 
  89.     Optional:    false 
  90. QoS Class:       BestEffort 
  91. Node-Selectors:  zookeeper-server-license=true 
  92. Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s 
  93.                  node.kubernetes.io/unreachable:NoExecute for 300s 
  94. Events: 
  95.   Type     Reason                 Age                 From                           Message 
  96.   ----     ------                 ----                ----                           ------- 
  97.   Normal   SuccessfulMountVolume  15m                 kubelet, uf30-tdh3-regression  MountVolume.SetUp succeeded for volume "default-token-g42jt" 
  98.   Normal   SuccessfulMountVolume  15m                 kubelet, uf30-tdh3-regression  MountVolume.SetUp succeeded for volume "conf" 
  99.   Normal   SuccessfulMountVolume  15m                 kubelet, uf30-tdh3-regression  MountVolume.SetUp succeeded for volume "tos" 
  100.   Normal   SuccessfulMountVolume  15m                 kubelet, uf30-tdh3-regression  MountVolume.SetUp succeeded for volume "mountbind" 
  101.   Normal   SuccessfulMountVolume  15m                 kubelet, uf30-tdh3-regression  MountVolume.SetUp succeeded for volume "transwarphosts" 
  102.   Normal   SuccessfulMountVolume  15m                 kubelet, uf30-tdh3-regression  MountVolume.SetUp succeeded for volume "log" 
  103.   Normal   SuccessfulMountVolume  15m                 kubelet, uf30-tdh3-regression  MountVolume.SetUp succeeded for volume "plugin" 
  104.   Normal   SuccessfulMountVolume  15m                 kubelet, uf30-tdh3-regression  MountVolume.SetUp succeeded for volume "data" 
  105.   Normal   SuccessfulMountVolume  15m                 kubelet, uf30-tdh3-regression  MountVolume.SetUp succeeded for volume "timezone" 
  106.   Normal   Scheduled              15m                 default-scheduler              Successfully assigned zookeeper-server-license-7fbfc544fc-h8nn9 to uf30-tdh3-regression 
  107.   Normal   Pulled                 15m (x3 over 15m)   kubelet, uf30-tdh3-regression  Successfully pulled image "transwarp/zookeeper:transwarp-6.0.2-final" 
  108.   Normal   Created                15m (x3 over 15m)   kubelet, uf30-tdh3-regression  Created container 
  109.   Normal   Started                15m (x3 over 15m)   kubelet, uf30-tdh3-regression  Started container 
  110.   Normal   Pulling                15m (x4 over 15m)   kubelet, uf30-tdh3-regression  pulling image "transwarp/zookeeper:transwarp-6.0.2-final" 
  111.   Warning  BackOff                44s (x70 over 15m)  kubelet, uf30-tdh3-regression  Back-off restarting failed container 

6.2 问题排查复盘:通过命令 kubectl logs xxx 查看 pod 容器底层的应用程序的日志

接下来我们尝试通过命令 kubectl logs xxx 查看 pod 容器底层的应用程序的日志,以期找到问题的原因,该命令的输出部分截图如下所示:图片

如上图所见,不幸的是,该命令的输出,没有展示出问题的根本原因。

在底层日志机制上,应该是星环 tdh 中该 zk 应用没有将日志打印到标准输出 stdout 和标准错误 stderr, 所以 kubectl logs xxx 查看不到对应的日志。

我们需要进一步排查。

6.3 问题排查复盘:进一步获取并查看 pod 容器底层的应用程序的其它日志文件,深挖问题原因

进一步排查问题,我们首先需要获取 pod 容器底层的应用程序的其它日志文件的路径。

由于 tdh 是闭源的,我们查看不到应用程序的源码,在没有联络官方客户的情况下,我们可以通过命令 kubectl describe pod xxx 查看该 pod 挂载了哪些 volume,然后猜测并验证获得具体的日志文件的路劲给,(排查问题就是要,大胆猜想,小心求证!)

该命令输出的部分截图如下,我们看到其中挂载了路径 /var/log/license:

接下来我们查看这些日志文件/var/log/license,尝试深挖问题原因,注意,该文件是本地文件系统的文件,需要登录到对应的节点上去查看,该日志文件部分关键截图如下:

通过日志,问题原因找到了:zk 底层存储在本地文件系统中的文件 /var/license/version-2/snapshot.70000007a 损坏了,所以无法启动:

  1. 2021-10-11 17:07:08,330 ERROR org.apache.zookeeper.server.persistence.Util: [myid:16] - [main:Util@239] - Last transaction was partial
  2. 2021-10-11 17:07:08,331 ERROR org.apache.zookeeper.server.quorum.QuorumPeer: [myid:16] - [main:QuorumPeer@453] - Unable to load database on disk 
  3. java.io.EOFException at java.io.DataInputStream.readInt(DataInputStream.java:392) 

该日志文件详细内容如下:

  1. tail -50 /var/log/license/zookeeper.log 
  2. 2021-10-11 17:07:08,203 INFO  org.apache.zookeeper.server.DatadirCleanupManager: [myid:16] - [main:DatadirCleanupManager@101] - Purge task is not scheduled. 
  3. 2021-10-11 17:07:08,212 INFO  org.apache.zookeeper.server.quorum.QuorumPeerMain: [myid:16] - [main:QuorumPeerMain@127] - Starting quorum peer 
  4. 2021-10-11 17:07:08,221 INFO  org.apache.zookeeper.server.NIOServerCnxnFactory: [myid:16] - [main:NIOServerCnxnFactory@94] - binding to port 0.0.0.0/0.0.0.0:2291 
  5. 2021-10-11 17:07:08,235 INFO  org.apache.zookeeper.server.quorum.QuorumPeer: [myid:16] - [main:QuorumPeer@913] - tickTime set to 9000 
  6. 2021-10-11 17:07:08,235 INFO  org.apache.zookeeper.server.quorum.QuorumPeer: [myid:16] - [main:QuorumPeer@933] - minSessionTimeout set to -1 
  7. 2021-10-11 17:07:08,235 INFO  org.apache.zookeeper.server.quorum.QuorumPeer: [myid:16] - [main:QuorumPeer@944] - maxSessionTimeout set to -1 
  8. 2021-10-11 17:07:08,236 INFO  org.apache.zookeeper.server.quorum.QuorumPeer: [myid:16] - [main:QuorumPeer@959] - initLimit set to 10 
  9. 2021-10-11 17:07:08,285 INFO  org.apache.zookeeper.server.persistence.FileSnap: [myid:16] - [main:FileSnap@83] - Reading snapshot /var/license/version-2/snapshot.70000007a 
  10. 2021-10-11 17:07:08,330 ERROR org.apache.zookeeper.server.persistence.Util: [myid:16] - [main:Util@239] - Last transaction was partial
  11. 2021-10-11 17:07:08,331 ERROR org.apache.zookeeper.server.quorum.QuorumPeer: [myid:16] - [main:QuorumPeer@453] - Unable to load database on disk 
  12. java.io.EOFException 
  13.         at java.io.DataInputStream.readInt(DataInputStream.java:392) 
  14.         at org.apache.jute.BinaryInputArchive.readInt(BinaryInputArchive.java:63) 
  15.         at org.apache.zookeeper.server.persistence.FileHeader.deserialize(FileHeader.java:64) 
  16.         at org.apache.zookeeper.server.persistence.FileTxnLog$FileTxnIterator.inStreamCreated(FileTxnLog.java:558) 
  17.         at org.apache.zookeeper.server.persistence.FileTxnLog$FileTxnIterator.createInputArchive(FileTxnLog.java:577) 
  18.         at org.apache.zookeeper.server.persistence.FileTxnLog$FileTxnIterator.goToNextLog(FileTxnLog.java:543) 
  19.         at org.apache.zookeeper.server.persistence.FileTxnLog$FileTxnIterator.next(FileTxnLog.java:625) 
  20.         at org.apache.zookeeper.server.persistence.FileTxnLog$FileTxnIterator.init(FileTxnLog.java:529) 
  21.         at org.apache.zookeeper.server.persistence.FileTxnLog$FileTxnIterator.(FileTxnLog.java:504) 
  22.         at org.apache.zookeeper.server.persistence.FileTxnLog.read(FileTxnLog.java:341) 
  23.         at org.apache.zookeeper.server.persistence.FileTxnSnapLog.restore(FileTxnSnapLog.java:132) 
  24.         at org.apache.zookeeper.server.ZKDatabase.loadDataBase(ZKDatabase.java:223) 
  25.         at org.apache.zookeeper.server.quorum.QuorumPeer.loadDataBase(QuorumPeer.java:417) 
  26.         at org.apache.zookeeper.server.quorum.QuorumPeer.start(QuorumPeer.java:409) 
  27.         at org.apache.zookeeper.server.quorum.QuorumPeerMain.runFromConfig(QuorumPeerMain.java:151) 
  28.         at org.apache.zookeeper.server.quorum.QuorumPeerMain.initializeAndRun(QuorumPeerMain.java:111) 
  29.         at org.apache.zookeeper.server.quorum.QuorumPeerMain.main(QuorumPeerMain.java:78) 
  30. 2021-10-11 17:07:08,332 ERROR org.apache.zookeeper.server.quorum.QuorumPeerMain: [myid:16] - [main:QuorumPeerMain@89] - Unexpected exception, exiting abnormally 
  31. java.lang.RuntimeException: Unable to run quorum server  
  32.         at org.apache.zookeeper.server.quorum.QuorumPeer.loadDataBase(QuorumPeer.java:454) 
  33.         at org.apache.zookeeper.server.quorum.QuorumPeer.start(QuorumPeer.java:409) 
  34.         at org.apache.zookeeper.server.quorum.QuorumPeerMain.runFromConfig(QuorumPeerMain.java:151) 
  35.         at org.apache.zookeeper.server.quorum.QuorumPeerMain.initializeAndRun(QuorumPeerMain.java:111) 
  36.         at org.apache.zookeeper.server.quorum.QuorumPeerMain.main(QuorumPeerMain.java:78) 
  37. Caused by: java.io.EOFException 
  38.         at java.io.DataInputStream.readInt(DataInputStream.java:392) 
  39.         at org.apache.jute.BinaryInputArchive.readInt(BinaryInputArchive.java:63) 
  40.         at org.apache.zookeeper.server.persistence.FileHeader.deserialize(FileHeader.java:64) 
  41.         at org.apache.zookeeper.server.persistence.FileTxnLog$FileTxnIterator.inStreamCreated(FileTxnLog.java:558) 
  42.         at org.apache.zookeeper.server.persistence.FileTxnLog$FileTxnIterator.createInputArchive(FileTxnLog.java:577) 
  43.         at org.apache.zookeeper.server.persistence.FileTxnLog$FileTxnIterator.goToNextLog(FileTxnLog.java:543) 
  44.         at org.apache.zookeeper.server.persistence.FileTxnLog$FileTxnIterator.next(FileTxnLog.java:625) 
  45.         at org.apache.zookeeper.server.persistence.FileTxnLog$FileTxnIterator.init(FileTxnLog.java:529) 
  46.         at org.apache.zookeeper.server.persistence.FileTxnLog$FileTxnIterator.(FileTxnLog.java:504) 
  47.         at org.apache.zookeeper.server.persistence.FileTxnLog.read(FileTxnLog.java:341) 
  48.         at org.apache.zookeeper.server.persistence.FileTxnSnapLog.restore(FileTxnSnapLog.java:132) 
  49.         at org.apache.zookeeper.server.ZKDatabase.loadDataBase(ZKDatabase.java:223) 
  50.         at org.apache.zookeeper.server.quorum.QuorumPeer.loadDataBase(QuorumPeer.java:417) 
  51.         ... 4 more 

7 问题解决

通过以上通用问题排查思路,我们查看日志找到了问题原因:zk 底层存储在本地文件系统中的文件 /var/license/version-2/snapshot.70000007a 损坏了,所以无法启动。由于集群中 zk 是有多个节点的,且其它节点的 zk 启动是成功的,所以我们 可以删除该问题节点上述目录下的数据文件,然后重启该节点的 zk, 重启后该节点的 zk 就可以从其它节点复制数据到本地,就可以正常对外提供服务了!

zk 底层存储在本地文件系统中的文件,在正常节点于问题节点,对比截图如下:

zk data on good node

zk data on bad node

按照上述方法,清空目录重启zk后,kubectl get pods 查看服务正常,截图如下:

kubectl-get-pods-after-fix

注意:其实 zk 也提供了系统工具 zkCleanup.sh 来清理本地数据文件,笔者没有使用该工具,而是手工备份和清空了问题节点的本地文件。大家可以自行尝试该工具。

zkCleanup.sh

8 知识总结

步骤一:通过命令 kubectl describe pod xxx 获取 pod 详细信息;

步骤二:通过命令 kubectl logs xxx 查看 pod 容器底层的应用程序的日志;

步骤三:进一步获取并查看 pod 容器底层的应用程序的其它日志文件,深挖问题原因;

 

来源: 明哥的IT随笔内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯