《容器业务调试多场景--践行版2》
《容器业务调试多场景--践行版2》
解决痛点:容器业务调试时内部缺少调试命令工具。
实践场景:非k8s容器; k8s受限权限;k8s无受限权限;
主要思路:使用边车(sidecar)容器
可用工具:kubectl debug;busybox、curl-amd64、curlimages/curl、Alpine、nicolaka/netshoot
已备镜像:reg1.ka.zkj.com/tools/busybox-with-curl、reg1.ka.zkj.com/tools/curlimages-curl、
reg1.ka.zkj.com/tools/nicolaka-netshoot (在内网harbor私仓均可下载)
--- 学海无涯,文档一直在践行中,如有建议恭请联系,共同提升。
预备知识1:
1、BusyBox 不基于某个特定的 Linux 发行版,它是一个面向 Linux 的工具集,适用于任何使用 Linux 内核的系统。它的设计目标是为资源有限的环境提供基本的 Unix 命令工具。
2、BusyBox 中不支持curl,如果必须要用到curl命令解决方法如下:
2.1:强制busybox拥有curl:
a、编译busybox并启用curl功能,需要下载busybox源码,进行编译,较复杂代价大。
b、下载独立的curl二进制文件,放置到系统中。(推荐)
2.2:脱离busybox使用专门的curl调试镜像
a、使用curlimages/curl (推荐)--image=curlimages/curl 镜像是由官方的curl项目维护的,是基于Alpine Linux。
b、使用nicolaka/netshoot (推荐),缺点体积稍大(约542MB)。
c、使用Alpine Linux, Alpine Linux 是一个轻量级的Linux发行版,基于BusyBox(.确定.),可以通过包管理器安装curl:apk add curl。缺点工具后安装,无网瞎B。
d、其它(例如:如果容器内有python,可以用python内置的 requests 库,模拟curl)
3、nicolaka/netshoot 是一个专门用于网络调试的容器镜像,集成了大量网络工具(如 tcpdump、netstat、iftop 等)。
Bash ---上面 2.1.b 做法:
静态二进制文件下载网站: https://github.com/moparisthebest/static-curl/releasesy 以v8.4.0版本为例操作: # wget https://github.com/moparisthebest/static-curl/releases/tag/v8.4.0 # 下载 # cat Dockerfile FROM busybox COPY curl-amd64 /usr/local/bin/curl RUN chmod +x /usr/local/bin/curl # docker build -t="busybox-with-curl" . # 构建 # docker run -ti --rm --name box-curl busybox-with-curl curl --version # 验证 curl 8.4.0 (x86_64-pc-linux-musl) libcurl/8.4.0 OpenSSL/3.1.3 zlib/1.2.13 libssh2/1.10.0 nghttp2/1.57.0 Release-Date: 2023-10-11 Protocols: dict file ftp ftps gopher gophers http https imap imaps mqtt pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp Features: alt-svc AsynchDNS HSTS HTTP2 HTTPS-proxy IPv6 Largefile libz NTLM SSL threadsafe TLS-SRP UnixSockets
# docker tag busybox-with-curl reg1.ka.zkj.com/tools/busybox-with-curl # 打tag # docker push reg1.ka.zkj.com/tools/busybox-with-curl # 推仓 |
预备知识2:
Namespace是Docker三大支柱核心技术(NameSpace、Cgroup、UnionFS)
限于篇幅长话短说,欲达到边车容器调试目标容器的目的,需要边车容器共享目标容器的某些被隔离的NS,那就需要了解Namespace都有哪些类型(old的6种new的2种):
Bash NET NS 隔离"网络接口、IP地址和端口"。 共享用法:--net=container:existing_container PID NS 隔离不同用户的"进程ID"。 共享用法:--pid=container:existing_container IPC NS 隔离"进程间通信(如信号量、共享内存)"。 共享用法:--ipc=container:existing_container UTS NS 隔离"主机名和域名"。 目前docker run命令中支持与宿主机共享UTS命名空间,不支持容器间共享。共享用法:--uts=host User NS 隔离"用户和组id"。 目前docker run命令中支持与宿主机共享User命名空间,不支持容器间共享。共享用法:--userns=host Mount NS 隔离"文件系统挂载点" 目前docker run命令中并未直接提供Mount NS的参数。可以采用其它方法如:--volum-from <目标容器> 把目标容器的卷挂载到新容器中。
---内核Linux 4.6及以后 Cgroup NS 隔离"Cgroup层级的视图",使得容器能看到自己的Cgroup树结构。 Time NS 隔离"系统时间" 使容器与宿主机拥有不同的时间视图。 |
预备知识3:
- 在 K8s 中,Pod 是调度的最小单位,一个 Pod 可以包含一个或多个容器。Pod 内的容器共享网络、存储、IPC、UTS 等命名空间,以及资源限制、环境变量和安全上下文等资源。
- 使用kubectl debug,只需要拥有一个体积较小的边车镜像(debug-agent),就能够调试。
- kubectl debug 命令本质是添加一个边车容器(和被调试容器在一个pod中)并将其挂接到该容器,这个调试容器会共享目标容器的命名空间(如PID、网络、IPC等)。
- Debug agent有两种运行方式:
daemon-set模式,agent pod预先部署在所有node上,会始终占用资源;daemon-set方式在实际场景中个人觉得不实用,此文不赘述。( 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模式稍慢。
- 常用参数说明
Bash --image参数就是用于指定使用哪个镜像来debug,这个镜像包含我们需要使用的工具即可。 --image-pull-policy=IfNotPresent 使用debug镜像的下载策略(IfNotPresent本地有就不再下载),默认是Always(始终联网下载)。 --target参数,这个参数主要用于指定debug Pod中的哪个容器(一个pod中可能会有多个容器),在k8s中可以用以下命令得知 # kubectl describe pod poweragent-tq-portal-58b546b46f-52gtc | grep -iA2 ^Containers: --copy-to=xxx 为前面指定pod建立一个名为xxx的副本用来调试。 --share-processes 允许在此pod的其它容器中查看该容器的进程。 |
场景一:非k8s的 docker && docker-compose 的调试
如果目标容器没有调试工具,可以使用docker run启动一个包含调试工具的新容器,用指定参数共享目标容器的命名空间(如网络、进程等)。
Bash 共享网络命名空间: docker run -it --network container:<target-container-id-or-name> busybox 共享进程命名空间 docker run -it --pid container:<target-container-id-or-name> busybox 同时共享网络和进程命名空间(一般情况下共享这2个NS即可满足调试需求) docker run -it --network container:<target-container-id-or-name> --pid container:<target-container-id-or-name> busybox
共享ipc命名空间注意: 共享ipc命名空间要求被调试容器已经加载--ipc shareable参数,否则使用--ipc=container:existing_container 后会报:can't join IPC of container。 例如: # docker run -tid --name nginx --ipc shareable reg1.ka.zkj.com/tools/nginx # docker run -it --net="container:nginx" --pid="container:nginx" --ipc="container:nginx" reg1.ka.zkj.com/tools/nicolaka-netshoot |
示例:
Bash 启动一个nginx容器 # docker run -tid --name nginx reg1.ka.zkj.com/tools/nginx 启动netshoot容器调试它 # docker run -it --network container:nginx --pid container:nginx reg1.ka.zkj.com/tools/nicolaka-netshoot
9ebdde76f8e1 ~ ps -ef PID USER TIME COMMAND 1 root 0:00 nginx: master process nginx -g daemon off; 29 bird 0:00 nginx: worker process ......
9ebdde76f8e1 ~ top Mem: 64716340K used, 1087476K free, 3313008K shrd, 603760K buff, 12438520K cached CPU: 60% usr 0% sys 0% nic 37% idle 0% io 0% irq 0% sirq Load average: 24.45 21.24 20.80 26/6177 152 PID PPID USER STAT VSZ %VSZ CPU %CPU COMMAND 30 1 bird S 11820 0% 14 0% nginx: worker process 29 1 bird S 11820 0% 31 0% nginx: worker process 32 1 bird S 11820 0% 27 0% nginx: worker process 31 1 bird S 11820 0% 4 0% nginx: worker process 36 1 bird S 11820 0% 4 0% nginx: worker process ......
9ebdde76f8e1 ~ chroot /proc/1/root # 使用--pid后,文件系统同样适用:chroot /proc/1/root 机制。 root@9ebdde76f8e1:/# ls /etc/nginx conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params
9ebdde76f8e1 ~ exit |
- nsenter命令:以上使用sidecar container debug思路和使用linux nsenter命令有异曲同工之妙,但nsenter 命令需要单独安装,优点是不用拉起边车容器。
场景二:k8s受限权限(不能操作node,没有kubectl操作权限)
项目中的大部分k8s场景是没有kubectl 操作权限,只有Dashboard用户界面。
这种场景可以在部署文件中添加一个包含调试工具的Sidecar 容器(例如 busybox、alpine 或 netshoot;实际上是一个变相的kubectl debug 的 agentless模式)
Sidecar 容器与主容器共享相同的网络命名空间、存储卷和其他资源,通过Sidecar中工具调试主容器。
示例:
Bash ```yaml apiVersion: v1 kind: Pod metadata: name: debug-pod spec: shareProcessNamespace: true # 共享 PID 命名空间,看到被调容器进程需要配置此项。 containers: # 主容器(假设没有调试工具) - name: main-container image: nginx ports: - containerPort: 80 # Sidecar 容器(提供调试工具) - name: debug-container image: reg1.ka.zkj.com/tools/busybox-with-curl # 或者 alpine 或者 nicolaka/netshoot command: ["sleep", "infinity"] # 保持容器永久运行,infinity表示无限大,永远不会超时。 ``` |
运行后进入sidecar容器调试,没有命令行,可以通过客户提供的dashboard进入终端调试。
如果工程处于调试阶段,验证比较频繁,建议部署的时候直接部署边车容器,调试正常后再去掉。
场景三:k8s无受限权限(可以执行kubectl等);pod状态running
使用--target:直接进入目标container执行debug
语法:kubectl debug -it {pod name} --image={image name} --target={container name}
实例:
Bash # kubectl debug -ti poweragent-tq-portal-58b546b46f-52gtc --image=reg1.ka.zkj.com/tools/busybox-with-curl --target=tq-portal
Targeting container "tq-portal". If you don't see processes from this container it may be because the container runtime doesn't support this feature. Defaulting debug container name to debugger-l6sjh. If you don't see a command prompt, try pressing enter.
/ # curl -I http://127.0.0.1:8080/readiness/health HTTP/1.1 200 OK Server: nginx Date: Thu, 06 Feb 2025 03:54:02 GMT Content-Type: application/octet-stream Content-Length: 0 Connection: close
使用exit退出,debug container 会自动删除。 |
其它技巧:
- 也可以在外直接执行命令,效果相同:
Bash # kubectl debug -ti poweragent-tq-portal-58b546b46f-52gtc --image=reg1.ka.zkj.com/tools/busybox-with-curl --target=tq-portal -- /bin/sh -c "curl -I http://127.0.0.1:8080/readiness/health" |
- 使用target参数后,临时debug容器会将目标容器的文件系统挂载到/proc/<pid>/root (pid通常为1,因为它是容器内的第一个进程);在临时容器中通过 chroot /proc/1/root 访问被调试容器的文件系统。exit退出chroot。
Bash <...示例承上...> / # chroot /proc/1/root/ root@poweragent-tq-portal-58b546b46f-52gtc:/# ls bin boot dev docker-entrypoint.d docker-entrypoint.sh etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var root@poweragent-tq-portal-58b546b46f-52gtc:/# cat /etc/issue Debian GNU/Linux 10 \n \l # 示例可以看到poweragent-tq-portal容器是基于Debian 10的。 root@poweragent-tq-portal-58b546b46f-52gtc:/# exit exit / # |
- 关于参数--image-pull-policy=xxx 用法:
Bash --- debug镜像能够从互联网或私仓获取 # kubectl debug -ti poweragent-tq-portal-58b546b46f-52gtc --image=reg1.ka.zkj.com/tools/curl --target=tq-portal -- /bin/sh -c "curl -I http://127.0.0.1:8080" --- debug镜像不能从互联网或私仓获取 debug镜像获取的策略默认是Always;如果指定从本地获取需要添加参数"--image-pull-policy=IfNotPresent"(必须在debug镜像后添加) # kubectl debug -ti poweragent-tq-portal-58b546b46f-52gtc --image=curlimages/curl --image-pull-policy=IfNotPresent --target=tq-portal -- /bin/sh -c "curl -I http://127.0.0.1:8080/readiness/health |
场景四:k8s无受限权限(可以执行kubectl等);pod无法正确启动。
使用--copy-to:复制目标container并进入新的container执行debug
语法:kubectl debug -it {pod name} --image={image name} --share-processes --copy-to={new container name}
实例:
Bash 首先运行一个失败的pod # kubectl run --image=reg1.ka.zkj.com/tools/ubuntu ubuntu -- false
查看状态 # kubectl get pod NAME READY STATUS RESTARTS AGE ubuntu 0/1 CrashLoopBackOff 1 (3s ago) 5s
启动debug模式,利用nicolaka-netshoot镜像容器对ubuntu容器进行调试,复制的pod命名为ubuntu-debug。--share-processes 允许在此pod的其它容器中查看该容器的进程。 # kubectl debug -ti ubuntu --image=reg1.ka.zkj.com/tools/nicolaka-netshoot --share-processes --copy-to='ubuntu-debug'
进入后执行top ubuntu-debug ~ top Mem: 65201328K used, 602480K free, 3421404K shrd, 94624K buff, 4463660K cached CPU: 1% usr 0% sys 0% nic 96% idle 0% io 0% irq 0% sirq Load average: 0.19 0.25 0.29 2/10647 93 PID PPID USER STAT VSZ %VSZ CPU %CPU COMMAND 13 0 root S 5012 0% 27 0% zsh 93 13 root R 1608 0% 29 0% top 1 0 65535 S 956 0% 19 0% /pause
再查看状态 # kubectl get pod NAME READY STATUS RESTARTS AGE ubuntu 0/1 Error 4 (62s ago) 114s ubuntu-debug 1/2 Error 2 (20s ago) 23s
--copy-to的exit后还可以通过attach再进入,这就意味着容器调试完后不会像target一样自动退出,需要手动清理。 # kubectl attach nginx-debug -c debugger-n2k5p -i -t
清理 # kubectl delete pod ubuntu ubuntu-debug |
其它技巧:
Bash 以上模式只能使用边车容器的调试命令,并不能和--target一样通过 chroot /proc/1/root 访问被调试容器的文件系统。只能如下方式查看:
# kubectl debug nginx -ti --copy-to=nginx-filesystem --container=nginx -- sh # 在该副本中命令改变为交互式shell If you don't see a command prompt, try pressing enter.(再敲回车!) # cat /etc/issue Debian GNU/Linux 12 \n \l # ls /etc/nginx conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params |
参考:
https://blog.yowko.com/kubernetes-pod-debug/
https://www.cnblogs.com/sealio/p/17893829.html
https://www.cnblogs.com/gongzb/p/18309316
https://www.bookstack.cn/read/kubernetes-1.32-zh/19b80188008460b9.md
https://www.cnblogs.com/weifeng1463/p/11214266.html
https://blog.csdn.net/IOT_AI/article/details/131958896
https://blog.csdn.net/songguangfan/article/details/121727435
https://yeasy.gitbook.io/docker_practice/underly/namespace
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本