背景
在云原生时代,容器化技术正逐渐成为软件开发和部署的主流。然而,随着容器化应用的广泛采用,传统镜像可能包含许多不必要的软件包和工具,这些可能成为安全漏洞的来源,占用大量存储空间,并导致容器启动和部署时间过长。此外,不同操作系统版本或发行版之间的差异也可能引发兼容性问题。在这样的背景下,distroless 镜像应运而生,它们是精简的容器镜像,移除了不必要的操作系统组件,仅包含运行应用所需的最小文件集,从而减少了潜在的攻击面并提高了安全性。
distroless 镜像虽然在安全性和性能上具有优势,但它们通常不包含传统的调试工具,这给开发者调试带来了挑战。在容器设计为轻量级且无Shell环境时,传统调试方法可能不适用。为了应对这些挑战,cdebug 工具被开发出来,它为容器环境提供了一种强大而灵活的调试解决方案。
问题
- 如何调试一个没有shell的容器
- 如何访问容器未export的端口
- 如何将容器内的文件导出
cdebug的关键特性
Github 地址: https://github.com/iximiuz/cdebug
关键功能
- 调试 无 Shell 容器: 即使容器内没有 Shell 或调试工具,也能轻松进入并调试。
- 端口转发: 将未公开的端口或 localhost 端口转发到主机系统。
- 反向通道: 将主机系统的端点暴露给容器和 Kubernetes 网络。
- 文件系统导出专家: 轻松将镜像或容器的文件系统导出到本地文件夹。
安装cdebug
|
|
exec: 调试容器
cdebug exec
=docker exec
+kubectl debug
。允许在目标容器中启动一个调试用的 Sidecar 容器,但功能更强:
- 调试容器的根文件系统==目标容器的根文件系统;
- 目标容器不会被重新创建或重启;
- 无需额外的卷或复制调试工具;
- 调试工具在目标容器中随时可用;
参数说明:
-it
交互(STDIN\TTY)-n,--namespace
命名空间,会对应到相应的runtime。比如,调试K8S容器时,为K8S集群命名空间;调试containerd容器时,是containerd的命名空间。--image
进行debug的工具镜像,默认为docker.io/library/busybox:musl
1. 调试 Dockerd 容器
|
|
2. 调试K8S集群中的普通容器
命令:
cdebug exec -it <-n NAMESPACE> pod/{POD_NAME}/{CONTAINER_NAME}
- NAMESPACE : 选填,对应运行时的命名空间,此处为K8S集群中的命名空间
- POD_NAME : 必填,Pod名称
- CONTAINER_NAME:选填,容器名称,可指定特定的容器
|
|
3. 调试 Containerd 容器
3.1 获取容器ID
ctr 参数说明
-n
命名空间,默认k8s集群镜像在k8s.io
命名空间,docker镜像在moby
命名空间,ctr命名空间为default
|
|
3.2 运行调试容器
-n 此处调试containerd容器,指定的命名空间是containerd的命名空间
–image: 进行debug的工具镜像
|
|
4. 调试K8S集群中的静态容器
4.1 调试方式选择
cdebug调试K8S集群容器,是通过
K8S debug
实现的,但由于无法对StaticPod创建临时容器,因此,需要采取宿主机调试containerd容器的方式。下图为报错举例。
|
|
4.2 环境信息
环境为rke2搭建K8S集群,待调试容器为etcd-01(在节点master-1),登录待调试容器所在宿主机,执行以下命令进行ctr客户端设置:
|
|
4.3 获取容器ID
|
|
4.4 运行调试容器
-n,–namespace: 命名空间,会对应到相应的runtime,比如此处是containerd的命名空间
–image: 进行debug的工具镜像,默认为docker.io/library/busybox:musl
|
|
port-forward:端口转发
1. 未发布容器端口:将容器中的端口映射到宿主机本地端口
|
|
2. 容器监听127.0.0.1:将宿主机本地端口映射到容器内的端口
|
|
结论
cdebug 作为一款专为容器环境设计的调试工具,它通过提供一系列高级功能,极大地简化了容器化应用的调试流程。无论是面对无 Shell 容器、需要端口转发的场景,还是需要导出文件系统,cdebug 都能提供有效的解决方案,是云原生开发者的得力助手。