腾讯云TKE-网络: 如何在Node节点对容器内抓包快速定位网络问题

2020-11-13 18:03:19 浏览数 (1)

背景

k8s的网络比较复杂, 可能会遇到一些网络问题。当 我们通过检查一些配置和日志仍然无法定位问题

这时候我们需要进行网络抓包,但是Pod 内一般不会按照tcpdump,甚至都不会安装bash , sh等工具

那有没有什么办法可以直接通过宿主机抓取Pod网络数据包?

方案

一 . 手动进入

先查到pod所在节点 kubectl get po -n namespace podname -o wide 获取到主机ip后登陆到主机

执行以下操作:

代码语言:txt复制
docker ps |grep podname
例如:

 docker ps |grep nginx-66b87767fd-2jww9

 1. 获取到docker id 之后
 docker inspect -f '{{.State.Pid}}' contaienrid

 2. 获取到pid之后进入到容器的网络命名空间
 nsenter  -n -t pid

 3. 验证是否已经进入到了容器的网络命名空间
  ip a 
    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
3: eth0@if60: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 62:47:5f:ef:62:d5 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.16.2.12/26 brd 172.16.2.191 scope global eth0
       valid_lft forever preferred_lft forever

二. 使用脚本

脚本内容如下

代码语言:txt复制
#!/usr/bin/env bash

function debug_net() {
  set -eu
  pod=`kubectl get pod ${pod_name} -n ${namespace} -o template --template='{{range .status.containerStatuses}}{{.containerID}}{{end}}' | sed 's/docker://(.*)$/1/'`
  pid=`docker inspect -f {{.State.Pid}} $pod`
  echo -e "33[32m Entering pod netns for ${namespace}/${pod_name} 33[0mn"
  cmd="nsenter -n -t ${pid}"
  echo -e "33[32m Execute the command: ${cmd} 33[0m"
  ${cmd}
}

# 运行函数
pod_name=$1
namespace=${2-"default"}
debug_net

使用方式如下:

代码语言:txt复制
# ./debug.sh podName nameSpace
./debug.sh wordpress-5c9d88868c-6lz2n default

## 验证是否进入到了pod的namespace空间
ip a 
##  查看IP
image.pngimage.png

注意 如果 pod 为特权模式 会看到宿主机的上的所有ip, 进入之后就可以执行tcpdump命令了

使用 tcpdump 抓取 eth0 网卡上 80 端口 数据包

image.pngimage.png

原理

本质上是使用nsenter 进入命名空间, 先看下参数

代码语言:txt复制
nsenter [options] [program [arguments]]

options:
-t, --target pid:指定被进入命名空间的目标进程的pid
-m, --mount[=file]:进入mount命名空间。如果指定了file,则进入file的命名空间
-u, --uts[=file]:进入uts命名空间。如果指定了file,则进入file的命名空间
-i, --ipc[=file]:进入ipc命名空间。如果指定了file,则进入file的命名空间
-n, --net[=file]:进入net命名空间。如果指定了file,则进入file的命名空间
-p, --pid[=file]:进入pid命名空间。如果指定了file,则进入file的命名空间
-U, --user[=file]:进入user命名空间。如果指定了file,则进入file的命名空间
-G, --setgid gid:设置运行程序的gid
-S, --setuid uid:设置运行程序的uid
-r, --root[=directory]:设置根目录
-w, --wd[=directory]:设置工作目录

如果没有给出program,则默认执行 $SHELL。

除了进入 net 命名空间,nsenter 还可以进入 mnt, uts, ipc, pid, user 命名空间,以及指定根目录和工作目录。

0 人点赞