2020-04-24-kubectl-debug插件及openshift debug模式

面对 k8s/openshift 的集群或者应用的异常情况,除了通过日志、事件来排查,还会借助各种工具。

本篇介绍 kubectl-debug 插件及 openshift 的debug 模式,来协助我们debug, 提高效率。

kubectl-debug 插件

官方文档见这里,设计思路、配置和使用说明写的很详细。 作者:吴叶磊 aylei https://github.com/aylei/kubectl-debug/blob/master/docs/zh-cn.md

本节以下内容只是记录了我的部分操作。

简述: 在运行中的 Pod 上额外起一个新容器, 并将新容器加入到目标容器的 pid, network, user 以及 ipc namespace 中, 这时我们就可以在新容器中直接用 netstat, tcpdump 这些熟悉的工具来解决问题了, 而旧容器可以保持最小化, 不需要预装任何额外的排障工具。

这就是 kubectl-debug 的出发点: 用工具容器来诊断业务容器 。背后的设计思路和 sidecar 等模式是一致的:每个容器只做一件事情。

具体到实现上,一条 kubectl debug 命令背后是这样的:

kubectl-debug

步骤分别是:

  • 插件查询 ApiServer:demo-pod 是否存在,所在节点是什么

  • ApiServer 返回 demo-pod 所在所在节点

  • 插件请求在目标节点上创建 Debug Agent Pod

  • Kubelet 创建 Debug Agent Pod

  • 插件发现 Debug Agent 已经 Ready,发起 debug 请求(长连接)

  • Debug Agent 收到 debug 请求,创建 Debug 容器并加入目标容器的各个 Namespace 中,创建完成后,与 Debug 容器的 tty 建立连接

  • 接下来,客户端就可以开始通过 5,6 这两个连接开始 debug 操作。操作结束后,Debug Agent 清理 Debug 容器,插件清理 Debug Agent,一次 Debug 完成。

安装与使用

kubectl-debug 使用 nicolaka/netshoot 作为默认镜像. 默认镜像和指令都可以通过命令行参数进行覆盖. 考虑到每次都指定有点麻烦, 也可以通过文件配置的形式进行覆盖, 编辑 ~/.kube/debug-config 文件:

测试 debug command

先运行一个 tomcat ,再使用 debug

这种场景多用于排查网络问题,镜像里也内置了很多网络工具。

这个时候,应用容器还是可以运行的,对于应用容器本身的排查,比如配置挂载、环境变量是否生效,启动参数,启动日志,我们完全可以直接通过容器终端来排查。

诊断 CrashLoopBackoff

这种情况在平时是比较棘手的,因为容器在不停的重启,kubectl exec 不管用。

为了让针对 CrashLoopBackoff 的排查更方便, kubectl-debug 参考 oc debug 命令,添加了一个 --fork 参数。当指定 --fork 时,插件会复制当前的 Pod Spec,做一些小修改, 再创建一个新 Pod:

新 Pod 的所有 Labels 会被删掉,避免 Service 将流量导到 fork 出的 Pod 上 新 Pod 的 ReadinessProbe 和 LivnessProbe 也会被移除,避免 kubelet 杀死 Pod 新 Pod 中目标容器(待排障的容器)的启动命令会被改写,避免新 Pod 继续 Crash

模拟 crash 状态,运行一个 tomcat ,给他一个不正常的启动命令

这和上一个场景的区别是: 上一个场景是启动了一个都是工具的 netshoot pod,和应用pod 处于同样的网络环境,常用于诊断网络环境 这个 --fork 还是启动了一个都是工具的 netshoot pod,不过spec 复制了应用pod,常用于调试启动参数异常导致的反复重启

两种场景都可以在debug 容器中通过 chroot /proc/1/root 进入到应用pod

这个 --fork 参数测试下来和 openshift 还是不太一样,openshift 直接复制了一个应用 pod ,替换掉了启动参数

openshift debug 模式

openshift 内置了 debug 工具,可以在后台 oc debug 命令或者web 页面选择 debug in terminal

差别: web 页面 只有pod 处于异常的状态才会出现 debug 的选项 oc debug 命令没有这个限定

oc debug command

通过 oc debug --help 可以看到介绍,是复制了一个 pod,把启动参数换成了 /bin/sh 以及移除了 readiness 和liveness 方式健康检查导致重启 可以通过参数指定 UID 和所部署 node, 或者选择保留健康检查参数

web 控制台 debug 模式

先运行一个异常的服务,因为 web 页面只有异常的pod 才有debug 选项

进入 web 控制台看下,对比下正常的pod tomcat-1-2h6zf 和异常的 pod tomcat-crash-1-8fd7v

正常的pod debug-pod-ok

异常的pod debug-pod-crash

进入 debug 模式,可以直接在页面进入新启动的 debug pod,不过启动参数是 sleep 3600

这样就可以去手动调试启动参数了

debug-pod-crash

所以,这个的场景主要和 kubectl-debug 插件的第二个场景是一致的,主要应对应用的调试,而且可以在web 控制台操作,是很方便的。

如果要使用调试工具,可以使用上面的 kubectl-debug 插件,或者直接运行这个很多工具的镜像 nicolaka/netshoot

debug 思路

工具终归都是辅助,我们还是要深入理解k8s 原理,有一个清晰的思路,才能更好的排查问题,下文是以前写的故障排查介绍,供参考。

https://github.com/cai11745/k8s-ocp-yaml/blob/master/kubernetes-docs/2019-07-27-openshift-k8s-troubleshooting.md

Last updated