kubectl-debug
是一个简单的 kubectl 插件, 能够帮助你便捷地进行 Kubernetes 上的 Pod 排障诊断. 背后做的事情很简单: 在运行中的 Pod 上额外起一个新容器, 并将新容器加入到目标容器的 pid
, network
, user
以及 ipc
namespace 中, 这时我们就可以在新容器中直接用 netstat
, tcpdump
这些熟悉的工具来解决问题了, 而旧容器可以保持最小化, 不需要预装任何额外的排障工具.
kubectl-debug 包含两部分:
kubectl-debug:命令行工具;
debug-agent:部署在K8s的node上,用于启动关联排错工具容器
我们先不着急进入 Quick Start 环节。 kubectl-debug
本身非常简单,因此只要理解了它的工作原理,你就能完全掌握这个工具,并且还能用它做 debug 之外的事情。
我们知道,容器本质上是带有 cgroup 资源限制和 namespace 隔离的一组进程。因此,我们只要启动一个进程,并且让这个进程加入到目标容器的各种 namespace 中,这个进程就能 “进入容器内部”(注意引号),与容器中的进程”看到”相同的根文件系统、虚拟网卡、进程空间了——这也正是 docker exec
和 kubectl exec
等命令的运行方式。
现在的状况是,我们不仅要 “进入容器内部”,还希望带一套工具集进去帮忙排查问题。那么,想要高效管理一套工具集,又要可以跨平台,最好的办法就是把工具本身都打包在一个容器镜像当中。 接下来,我们只需要通过这个”工具镜像”启动容器,再指定这个容器加入目标容器的的各种 namespace,自然就实现了 “携带一套工具集进入容器内部”。事实上,使用 docker-cli 就可以实现这个操作:
export TARGET_ID=666666666
# 加入目标容器的 network, pid 以及 ipc namespace
docker run -it --network=container:$TARGET_ID --pid=container:$TARGET_ID --ipc=container:$TARGET_ID busybox
这就是 kubectl-debug 的出发点: 用工具容器来诊断业务容器 。背后的设计思路和 sidecar 等模式是一致的:每个容器只做一件事情。
具体到实现上,一条 kubectl debug <target-pod>
命令背后是这样的:
步骤分别是:
- 插件查询 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 完成。效果如下图
安装相应的工具
export PLUGIN_VERSION=0.1.1
curl -Lo kubectl-debug.tar.gz https://github.com/aylei/kubectl-debug/releases/download/v${PLUGIN_VERSION}/kubectl-debug_${PLUGIN_VERSION}_linux_amd64.tar.gz
下载完之后就可以开始使用 debug 插件:
简单使用(K8s v1.15.0):
kubectl 1.12.0 或更高的版本, 可以直接使用:
kubectl debug -h
kubectl 从 1.12 版本之后开始支持从 PATH 中自动发现插件。1.12 版本之前的 kubectl 不支持这种插件机制,但也可以通过命令名 kubectl-debug 直接调用。
假如安装了 debug-agent 的 daemonset, 可以略去 --agentless 来加快启动速度
之后的命令里会略去 --agentless
kubectl debug POD_NAME --agentless
debug-agent 两种运行方式:
daemon-set模式,agent pod预先部署在所有node上,会始终占用资源,对于排错调试频率不高的环境造成资源浪费;
kubectl apply -f https://raw.githubusercontent.com/aylei/kubectl-debug/master/scripts/agent_daemonset.yml
agentless模式,kubectl-debug执行命令后,才创建agent pod和排错工具容器,并在退出后删除工具容器和agent pod。由于每次执行都要重新拉起agent,启动会比daemon-set模式稍慢。
使用-a, --agentless开启agentless模式:
假如 Pod 处于 CrashLookBackoff 状态无法连接, 可以复制一个完全相同的 Pod 来进行诊断
kubectl debug POD_NAME --fork
假如 Node 没有公网 IP 或无法直接访问(防火墙等原因), 请使用 port-forward 模式
kubectl debug POD_NAME --port-forward --daemonset-ns=kube-system --daemonset-name=debug-agent
进阶使用:
排错init-container:
kubectl debug demo-pod --container=init-pod
排错crash pod:
kubectl debug POD_NAME --fork
离线配置:
--image:可自定义排错工具容器镜像,改为私有镜像仓库,默认为nicolaka/netshoot:latest
--agent-image:在agentless模式下,自定义debug-agent镜像,默认为aylei/debug-agent:latest。在daemon-set模式下,直接将debug-agent daemonset pod template修改为私有仓库镜像即可
配置文件:
~/.kube/debug-config,通过配置文件修改默认参数,免去使用命令时设置flag。
# debug agent listening port(outside container)
default to 10027
agentPort: 10027
whether using agentless mode
default to false
agentless: true
namespace of debug-agent pod, used in agentless mode
default to 'default'
agentPodNamespace: default
prefix of debug-agent pod, used in agentless mode
default to 'debug-agent-pod'
agentPodNamePrefix: debug-agent-pod
image of debug-agent pod, used in agentless mode
default to 'aylei/debug-agent:latest'
agentImage: aylei/debug-agent:latest
daemonset name of the debug-agent, used in port-forward
default to 'debug-agent'
debugAgentDaemonset: debug-agent
daemonset namespace of the debug-agent, used in port-forwad
default to 'default'
debugAgentNamespace: kube-system
whether using port-forward when connecting debug-agent
default false
portForward: true
image of the debug container
default as showed
image: nicolaka/netshoot:latest
start command of the debug container
default ['bash']
command:
- '/bin/bash'
- '-l'
对于没有安装yum ,apt-get 的镜像可以挂载 centos 的sidecar 镜像, 再进行操作, 如安装 redis 命令, 再使用redis-cli 命令
kubectl-debug POD_NAME --image centos --port-forward --daemonset-ns=default --daemonset-name=debug-agent
[root@mall-order-provider-6b8665fd67-w74lb /]# yum install -y redis