kubectl-debug 是一个简单的 kubectl 插件, 能够帮助你便捷地进行 Kubernetes 上的 Pod 排障诊断. 背后做的事情很简单: 在运行中的 Pod 上额外起一个新容器, 并将新容器加入到目标容器的 pidnetworkuser 以及 ipc namespace 中, 这时我们就可以在新容器中直接用 netstattcpdump 这些熟悉的工具来解决问题了, 而旧容器可以保持最小化, 不需要预装任何额外的排障工具.

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> 命令背后是这样的:

kubernetes常用维护命令 kubernetes debug_sed

 

 

步骤分别是:

  1. 插件查询 ApiServer:demo-pod 是否存在,所在节点是什么
  2. ApiServer 返回 demo-pod 所在所在节点
  3. 插件请求在目标节点上创建 Debug Agent Pod
  4. Kubelet 创建 Debug Agent Pod
  5. 插件发现 Debug Agent 已经 Ready,发起 debug 请求(长连接)
  6. 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