目录

nsenter调试docker-k8s

目录

本文介绍了如何使用nsenter工具在k8s中调试容器

需求:

我想进入容器中执行 curl 命令探测某个地址的连通性,但是容器镜像里默认没有 curl 命令。我这里是一个内网环境不太方便使用 yum 或者 apt 安装,怎么办? 这个需求比较典型,这里教大家一个简单的方法,使用 nsenter 进入容器的 net namespace,即可使用宿主机的 curl、ip、ifconfig 等命令,其效果,就跟进入容器中执行是一样的。

原理:

容器像是一个轻量级虚拟机,有自己的 IP,宿主机如果已经监听了 8080 端口,容器里的进程仍然可以重复监听 8080 端口。核心就是因为容器有自己的 namespace,和宿主机的 net namespace 互不影响。

https://pic4.zhimg.com/80/v2-caf72a3ceee97d3d899223f54b037943_1440w.webp

通过 nsenter -t -n bash 即可进入 pid 指向的进程的 net namespace,并在这个 namespace 执行 bash 命令,之后,在这个 bash session 里执行 curl、ip、ifconfig 等命令,看到的网络信息就都是容器内部的网络信息。

找到容器的pid

然后使用 nsenter 进入容器

1
2
3
4
5
6
7
crictl ps |grep console

crictl inspect ${containerid} |grep pid

nsenter -t ${pid} -n bash

# nsenter -t 62298 -n bash

例如查看console容器,能够看到已经进入容器空间,ip是pod容器的ip地址:10.230.96.236

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
[root@arm-master1 ~]# crictl ps |grep console
f7f790ca4093a       9c910f17dc73b       3 weeks ago         Running             ks-console                      0                   887ac0301a553       ks-console-6c45c8578b-7hqnd
[root@arm-master1 ~]#
[root@arm-master1 ~]#
[root@arm-master1 ~]# crictl inspect f7f790ca4093a |grep pid
    "pid": 62298,
            "pid": 1
            "type": "pid"
[root@arm-master1 ~]#

[root@arm-master1 ~]# nsenter -t 62298 -n bash


Welcome to 5.10.0-136.12.0.86.ctl3.aarch64

System information as of time:  Tue Mar 12 09:19:31 AM CST 2024

System load:    3.01
Processes:      462
Memory used:    65.3%
Swap used:      0.0%
Usage On:       83%
IP address:     10.230.96.236
Users online:   3

[root@arm-master1 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
4: eth0@if980: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1480 qdisc noqueue state UP group default qlen 1000
    link/ether 36:da:f3:ec:b6:24 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.230.96.236/32 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::34da:f3ff:feec:b624/64 scope link
       valid_lft forever preferred_lft forever
[root@arm-master1 ~]#



https://pic3.zhimg.com/80/v2-68932a5e97ac590c2abbf0138393c616_1440w.webp

如上,使用 bash 命令进入 net namespace,然后执行 ifconfig,看到 IP:172.22.0.6,显然这就是容器的 IP,说明 nsenter 达成所愿,之后在这个 bash session 内执行 curl、telnet 之类的,就相当于在容器里执行一样的效果。完事执行 exit 命令可以退出这个 net namespace。