超好用的k8s中pod诊断工具:kubectl-debug

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 超好用的k8s中pod诊断工具:kubectl-debug

背景


容器技术的一个最佳实践是构建尽可能精简的容器镜像。但这一实践却会给排查问题带来麻烦:精简后的容器中普遍缺失常用的排障工具,部分容器里甚至没有 shell (比如 FROM scratch )。 在这种状况下,我们只能通过日志或者到宿主机上通过 docker-cli 或 nsenter 来排查问题,效率很低,在K8s环境部署应用后,经常遇到需要进入pod进行排错。除了查看pod logs和describe方式之外,传统的解决方式是在业务pod基础镜像中提前安装好procps、net-tools、tcpdump、vim等工具。但这样既不符合最小化镜像原则,又徒增Pod安全漏洞风险。


今天为大家推荐一款K8s pod诊断工具,kubectl-debug是一个简单、易用、强大的 kubectl 插件, 能够帮助你便捷地进行 Kubernetes 上的 Pod 排障诊断。它通过启动一个排错工具容器,并将其加入到目标业务容器的pid, network, user 以及 ipc namespace 中,这时我们就可以在新容器中直接用 netstat, tcpdump 这些熟悉的工具来解决问题了, 而业务容器可以保持最小化, 不需要预装任何额外的排障工具。 kubectl-debug 主要包含以下两部分:


  • kubectl-debug:命令行工具
  • debug-agent:部署在K8s的node上,用于启动关联排错工具容器


工作原理


我们知道,容器本质上是带有 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命令背后逻辑流程是这样的:


640.png


步骤分别是:


  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 完成


安装


github地址:https://github.com/aylei/kubectl-debug


  • Mac 可以直接使用 brew 安装


brew install aylei/tap/kubectl-debug


  • 通过下载二进制文件安装


export PLUGIN_VERSION=0.1.1
# linux x86_64
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
# macos
curl -Lo kubectl-debug.tar.gz https://github.com/aylei/kubectl-debug/releases/download/v${PLUGIN_VERSION}/kubectl-debug_${PLUGIN_VERSION}_darwin_amd64.tar.gz
tar -zxvf kubectl-debug.tar.gz kubectl-debug
sudo mv kubectl-debug /usr/local/bin/


Windows 用户可以在Release 页面选择进行下载windows版本,加入环境变量使用

其中github上有提供debug agent以DaemonSet的方式安装在集群中,但是daemonset模式,agent pod预先部署在所有node上,会始终占用资源,对于排错调试频率不高的环境造成资源浪费


日常用法说明


简单使用


1、kubectl 1.12.0 或更高的版本, 可以直接使用


#查看常用命令参数
kubectl debug -h


kubectl 从 1.12 版本之后开始支持从 PATH 中自动发现插件。1.12 版本之前的 kubectl 不支持这种插件机制,但也可以通过命令名 kubectl-debug 直接调用。


2、假如安装了 debug-agent 的 daemonset, 可以略去 --agentless 来加快启动速度,之后的命令里会略去 --agentless


kubectl debug POD_NAME --daemonset-ns=default --daemonset-name=debug-agent


其中github上有提供debug agent以DaemonSet的方式安装在集群中,但是daemonset模式,agent pod预先部署在所有node上,会始终占用资源,对于排错调试频率不高的环境造成资源浪费,部署方式:kubectl apply -f

https://raw.githubusercontent.com/aylei/kubectl-debug/master/scripts/agent_daemonset.yml


3、agentless模式,kubectl-debug执行命令后,才创建agent pod和排错工具容器,并在退出后删除工具容器和agent pod。由于每次执行都要重新拉起agent,启动会比daemon-set模式稍慢。使用-a, --agentless开启agentless模式:


kubectl debug POD_NAME --agentless --port-forward


4、假如 Node 没有公网 IP 或无法直接访问(防火墙等原因), 请使用 port-forward 模式


kubectl debug POD_NAME --agentless --port-forward


进阶使用


1、排错init-container


kubectl debug POD_NAME --container=init-pod


2、假如 Pod 处于 CrashLookBackoff 状态无法连接, 可以复制一个完全相同的 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'


典型案例


使用 iftop查看pod的网络流量


比如查看POD_NAME是kube-flannel-ds-amd64-2xwqp的网络流量:


~  kubectl debug kube-flannel-ds-amd64-2xwqp -n kube-system
Agent Pod info: [Name:debug-agent-pod-b14bd868-61a9-11ec-bc72-acbc328370f3, Namespace:default, Image:registry.cn-hangzhou.aliyuncs.com/querycapimages/kubectl-debug-agent:latest, HostPort:10027, ContainerPort:10027]
Waiting for pod debug-agent-pod-b14bd868-61a9-11ec-bc72-acbc328370f3 to run...
Forwarding from 127.0.0.1:10027 -> 10027
Forwarding from [::1]:10027 -> 10027
Handling connection for 10027
                             set container procfs correct false ..
pulling image registry.cn-hangzhou.aliyuncs.com/querycapimages/netshoot:latest, skip TLS false...
latest: Pulling from querycapimages/netshoot
Digest: sha256:f0eba49c9bf66600788d58779e57c2d7334708e12cb292ff8ccc9414c1b6730c
Status: Image is up to date for registry.cn-hangzhou.aliyuncs.com/querycapimages/netshoot:latest
starting debug container...
container created, open tty...
bash-5.0# iftop -i eth0
interface: eth0
IP address is: 172.17.3.3
MAC address is: 52:54:be:83:3a:e4


使用 drill 诊断 DNS 解析


比如查看POD_NAME是kube-flannel-ds-amd64-2xwqp的网络流量:


bash-5.0# drill any www.baidu.com
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 3214
;; flags: qr rd ra ; QUERY: 1, ANSWER: 1, AUTHORITY: 5, ADDITIONAL: 3
;; QUESTION SECTION:
;; www.baidu.com. IN ANY
;; ANSWER SECTION:
www.baidu.com. 803 IN CNAME www.a.shifen.com.
;; AUTHORITY SECTION:
baidu.com. 38993 IN NS ns4.baidu.com.
baidu.com. 38993 IN NS ns3.baidu.com.
baidu.com. 38993 IN NS ns7.baidu.com.
baidu.com. 38993 IN NS dns.baidu.com.
baidu.com. 38993 IN NS ns2.baidu.com.
;; ADDITIONAL SECTION:
ns2.baidu.com. 19348 IN A 220.181.33.31
ns3.baidu.com. 23022 IN A 112.80.248.64
ns7.baidu.com. 20697 IN A 180.76.76.92
;; Query time: 1 msec
;; SERVER: 100.64.9.5
;; WHEN: Mon Dec 20 15:37:35 2021
;; MSG SIZE  rcvd: 196


drill 命令详解:https://commandnotfound.cn/linux/1/533/drill-%E5%91%BD%E4%BB%A4


使用 tcpdump 抓包


比如查看POD_NAME是kube-flannel-ds-amd64-2xwqp的网络流量:


bash-5.0# tcpdump -i eth0 -c 1 -Xvv
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
15:39:27.577342 IP (tos 0x0, ttl 63, id 41476, offset 0, flags [DF], proto TCP (6), length 89)
    198.19.116.60.16710 > 172.17.3.3.6443: Flags [P.], cksum 0xf831 (correct), seq 677521811:677521848, ack 1388710574, win 1037, options [nop,nop,TS val 2849535414 ecr 1924260089], length 37
 0x0000:  4500 0059 a204 4000 3f06 b036 c613 743c  E..Y..@.?..6..t<
 0x0010:  ac11 0303 4146 192b 2862 2993 52c6 0aae  ....AF.+(b).R...
 0x0020:  8018 040d f831 0000 0101 080a a9d8 75b6  .....1........u.
 0x0030:  72b1 e0f9 1703 0300 2047 49f1 8fbb 2835  r........GI...(5
 0x0040:  059a 5e82 0746 afaf bd2d 5af3 c797 16b5  ..^..F...-Z.....
 0x0050:  8709 4666 7e61 6f5a 0b                   ..Ff~aoZ.
1 packet captured
18 packets received by filter
0 packets dropped by kernel
bash-5.0# tcpdump -n -vvv -w /tmp/kube-flannel-ds-amd64-2xwqp.pcap
tcpdump: listening on veth19416cac, link-type EN10MB (Ethernet), capture size 262144 bytes
50 packets captured
50 packets received by filter
0 packets dropped by kernel


这里需要注意,如果是想拿到-w抓包保存的文件用wireshark工具分析,则需要去POD_NAME对应的宿主机上拷贝出来进行分析


[root@k8s-demo-master-01-2 ~]# docker ps |grep netshoot
58b918b67b3f        registry.cn-hangzhou.aliyuncs.com/querycapimages/netshoot:latest       "bash"                   15 minutes ago      Up 15 minutes                           unruffled_fermat
[root@k8s-demo-master-01-2 ~]# docker cp 58b918b67b3f:/tmp/kube-flannel-ds-amd64-2xwqp.pcap .
[root@k8s-demo-master-01-2 ~]# ll |grep kube-flannel-ds-amd64-2xwqp.pcap
-rw-r--r--  1 root root 5404 12月 20 23:41 kube-flannel-ds-amd64-2xwqp.pcap


诊断 CrashLoopBackoff


排查 CrashLoopBackoff 是一个很麻烦的问题,Pod 可能会不断重启, kubectl exec 和 kubectl debug 都没法稳定进行排查问题,基本上只能寄希望于 Pod 的日志中打印出了有用的信息。 为了让针对 CrashLoopBackoff 的排查更方便, kubectl-debug 参考 oc debug 命令,添加了一个 --fork 参数。当指定 --fork 时,插件会复制当前的 Pod

Spec,做一些小修改, 再创建一个新 Pod:


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


接下来,我们就可以在新 Pod 中尝试复现旧 Pod 中导致 Crash 的问题,示例pod_name为srv-es-driver-7445f6cf48-ff7bq的go服务。为了保证操作的一致性,可以先 chroot 到目标容器的根文件系统中:


~  kubectl-debug srv-es-driver-7445f6cf48-ff7bq -n devops --agentless --port-forward
Agent Pod info: [Name:debug-agent-pod-177482f4-61ad-11ec-b297-acbc328370f3, Namespace:default, Image:registry.cn-hangzhou.aliyuncs.com/querycapimages/kubectl-debug-agent:latest, HostPort:10027, ContainerPort:10027]
Waiting for pod debug-agent-pod-177482f4-61ad-11ec-b297-acbc328370f3 to run...
Forwarding from 127.0.0.1:10027 -> 10027
Forwarding from [::1]:10027 -> 10027
Handling connection for 10027
                             set container procfs correct false ..
pulling image registry.cn-hangzhou.aliyuncs.com/querycapimages/netshoot:latest, skip TLS false...
latest: Pulling from querycapimages/netshoot
Digest: sha256:f0eba49c9bf66600788d58779e57c2d7334708e12cb292ff8ccc9414c1b6730c
Status: Image is up to date for registry.cn-hangzhou.aliyuncs.com/querycapimages/netshoot:latest
starting debug container...
container created, open tty...
bash-5.0# ls
bin                        mnt                        sys
dev                        opt                        termshark_2.1.1_linux_x64
etc                        proc                       tmp
home                       root                       usr
lib                        run                        var
lib64                      sbin
media                      srv
bash-5.0# chroot /proc/1/root
root@srv-es-driver-7445f6cf48-ff7bq:/# ls
bin   dev  go  lib media  opt   root  sbin  sys  usr
boot  etc  home  lib64 mnt    proc  run   srv  tmp  var
root@srv-es-driver-7445f6cf48-ff7bq:/# cd /go/bin/
root@srv-es-driver-7445f6cf48-ff7bq:/go/bin# ls
openapi.json  srv-es-driver
root@srv-es-driver-7445f6cf48-ff7bq:/go/bin# ./srv-es-driver
 # 观察执行启动脚本时的信息并根据信息进一步排障


自定义image作为sidercar安装命令行调试


对于没有安装yum,apt-get 的镜像可以挂载 centos或者ubuntu的sidercar镜像, 再进行操作, 如安装 redis 命令, 再使用redis-cli 命令


~  kubectl-debug srv-es-driver-7445f6cf48-ff7bq -n devops --agentless --port-forward --image centos
Agent Pod info: [Name:debug-agent-pod-f5077b08-61ad-11ec-8728-acbc328370f3, Namespace:default, Image:registry.cn-hangzhou.aliyuncs.com/querycapimages/kubectl-debug-agent:latest, HostPort:10027, ContainerPort:10027]
Waiting for pod debug-agent-pod-f5077b08-61ad-11ec-8728-acbc328370f3 to run...
Forwarding from 127.0.0.1:10027 -> 10027
Forwarding from [::1]:10027 -> 10027
Handling connection for 10027
                             set container procfs correct false ..
pulling image centos, skip TLS false...
latest: Pulling from library/centos
a1d0c7532777: Pull complete
Digest: sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177
Status: Downloaded newer image for centos:latest
starting debug container...
container created, open tty...
[root@srv-es-driver-7445f6cf48-ff7bq /]# yum install -y redis


相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。 &nbsp; &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
8月前
|
Kubernetes Docker 容器
Kubernetes与Docker参数对照:理解Pod中的command、args与Dockerfile中的CMD、ENTRYPOINT。
需要明确的是,理解这些都需要对Docker和Kubernetes有一定深度的理解,才能把握二者的区别和联系。虽然它们都是容器技术的二个重要组成部分,但各有其特性和适用场景,理解它们的本质和工作方式,才能更好的使用这些工具,将各自的优点整合到生产环境中,实现软件的快速开发和部署。
313 25
|
Prometheus Kubernetes 监控
深入探索Kubernetes中的Pod自动扩展(Horizontal Pod Autoscaler, HPA)
深入探索Kubernetes中的Pod自动扩展(Horizontal Pod Autoscaler, HPA)
|
8月前
|
Kubernetes Shell Windows
【Azure K8S | AKS】在AKS的节点中抓取目标POD的网络包方法分享
在AKS中遇到复杂网络问题时,可通过以下步骤进入特定POD抓取网络包进行分析:1. 使用`kubectl get pods`确认Pod所在Node;2. 通过`kubectl node-shell`登录Node;3. 使用`crictl ps`找到Pod的Container ID;4. 获取PID并使用`nsenter`进入Pod的网络空间;5. 在`/var/tmp`目录下使用`tcpdump`抓包。完成后按Ctrl+C停止抓包。
310 12
|
存储 Kubernetes Docker
【赵渝强老师】Kubernetes中Pod的基础容器
Pod 是 Kubernetes 中的基本单位,代表集群上运行的一个进程。它由一个或多个容器组成,包括业务容器、基础容器、初始化容器和临时容器。基础容器负责维护 Pod 的网络空间,对用户透明。文中附有图片和视频讲解,详细介绍了 Pod 的组成结构及其在网络配置中的作用。
211 1
【赵渝强老师】Kubernetes中Pod的基础容器
|
运维 Kubernetes Shell
【赵渝强老师】K8s中Pod的临时容器
Pod 是 Kubernetes 中的基本调度单位,由一个或多个容器组成,包括业务容器、基础容器、初始化容器和临时容器。临时容器用于故障排查和性能诊断,不适用于构建应用程序。当 Pod 中的容器异常退出或容器镜像不包含调试工具时,临时容器非常有用。文中通过示例展示了如何使用 `kubectl debug` 命令创建临时容器进行调试。
222 1
|
Kubernetes 调度 容器
【赵渝强老师】K8s中Pod中的业务容器
Pod 是 Kubernetes 中的基本调度单元,由一个或多个容器组成。除了业务容器,Pod 还包括基础容器、初始化容器和临时容器。本文通过示例介绍如何创建包含业务容器的 Pod,并提供了一个视频讲解。示例中创建了一个名为 &quot;busybox-container&quot; 的业务容器,并使用 `kubectl create -f firstpod.yaml` 命令部署 Pod。
177 1
|
Kubernetes 容器 Perl
【赵渝强老师】K8s中Pod中的初始化容器
Kubernetes的Pod包含业务容器、基础容器、初始化容器和临时容器。初始化容器在业务容器前运行,用于执行必要的初始化任务。本文介绍了初始化容器的作用、配置方法及优势,并提供了一个示例。
235 1
|
1月前
|
人工智能 算法 调度
阿里云ACK托管集群Pro版共享GPU调度操作指南
本文介绍在阿里云ACK托管集群Pro版中,如何通过共享GPU调度实现显存与算力的精细化分配,涵盖前提条件、使用限制、节点池配置及任务部署全流程,提升GPU资源利用率,适用于AI训练与推理场景。
223 1
|
1月前
|
弹性计算 监控 调度
ACK One 注册集群云端节点池升级:IDC 集群一键接入云端 GPU 算力,接入效率提升 80%
ACK One注册集群节点池实现“一键接入”,免去手动编写脚本与GPU驱动安装,支持自动扩缩容与多场景调度,大幅提升K8s集群管理效率。
223 89
|
6月前
|
资源调度 Kubernetes 调度
从单集群到多集群的快速无损转型:ACK One 多集群应用分发
ACK One 的多集群应用分发,可以最小成本地结合您已有的单集群 CD 系统,无需对原先应用资源 YAML 进行修改,即可快速构建成多集群的 CD 系统,并同时获得强大的多集群资源调度和分发的能力。
272 9

推荐镜像

更多
下一篇
oss云网关配置