《容器业务调试多场景--践行版2》

《容器业务调试多场景--践行版2

解决痛点:容器业务调试时内部缺少调试命令工具。

实践场景:k8s容器; k8s受限权限;k8s无受限权限;

主要思路:使用边车(sidecar)容器

可用工具:kubectl debugbusyboxcurl-amd64curlimages/curlAlpinenicolaka/netshoot

已备镜像:reg1.ka.zkj.com/tools/busybox-with-curlreg1.ka.zkj.com/tools/curlimages-curl

reg1.ka.zkj.com/tools/nicolaka-netshoot (在内网harbor私仓均可下载)

--- 学海无涯,文档一直在践行中,如有建议恭请联系,共同提升。

预备知识1

1BusyBox 不基于某个特定的 Linux 发行版,它是一个面向 Linux 的工具集,适用于任何使用 Linux 内核的系统。它的设计目标是为资源有限的环境提供基本的 Unix 命令工具。

2BusyBox 中不支持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(.确定.),可以通过包管理器安装curlapk add curl。缺点工具后安装,无网瞎B

d、其它(例如:如果容器内有python,可以用python内置的 requests 库,模拟curl

3nicolaka/netshoot 是一个专门用于网络调试的容器镜像,集成了大量网络工具(如 tcpdumpnetstatiftop 等)。

   

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

NamespaceDocker三大支柱核心技术(NameSpaceCgroupUnionFS

限于篇幅长话短说,欲达到边车容器调试目标容器的目的,需要边车容器共享目标容器的某些被隔离的NS,那就需要了解Namespace都有哪些类型(old6new2)

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 内的容器共享网络、存储、IPCUTS 等命名空间,以及资源限制、环境变量和安全上下文等资源。
  • 使用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

同时共享网络和进程命名空间(一般情况下共享这2NS即可满足调试需求

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 命令需要单独安装,优点是不用拉起边车容器。

    nsenter 命令用法

       

    场景二:k8s受限权限(不能操作node,没有kubectl操作权限)

    项目中的大部分k8s场景是没有kubectl 操作权限,只有Dashboard用户界面。

    这种场景可以在部署文件中添加一个包含调试工具的Sidecar 容器(例如 busyboxalpine 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-toexit后还可以通过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

https://www.cnblogs.com/sammyliu/p/5878973.html

https://blog.csdn.net/qq_45808700/article/details/130930345

posted @   耿晓芳  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
点击右上角即可分享
微信分享提示