使用 nsenter 排查容器网络问题
需求
我想进入容器中执行 curl 命令探测某个地址的连通性,但是容器镜像里默认没有 curl 命令。我这里是一个内网环境不太方便使用 yum 或者 apt 安装,怎么办?
这个需求比较典型,这里教大家一个简单的方法,使用 nsenter 进入容器的 net namespace,即可使用宿主机的 curl、ip、ifconfig 等命令,其效果,就跟进入容器中执行是一样的。
原理
容器像是一个轻量级虚拟机,有自己的 IP,宿主机如果已经监听了 8080 端口,容器里的进程仍然可以重复监听 8080 端口。核心就是因为容器有自己的 namespace,和宿主机的 net namespace 互不影响。关于容器的 namespace 相关知识,可以 Google 一下关键字:「容器 namespace 原理」。
nsenter,是个关键工具。其用法如下:
nsenter --help
用法:
nsenter [选项] [<程序> [<参数>...]]
以其他程序的名字空间运行某个程序。
选项:
-a, --all enter all namespaces
-t, --target <pid> 要获取名字空间的目标进程
-m, --mount[=<文件>] 进入 mount 名字空间
-u, --uts[=<文件>] 进入 UTS 名字空间(主机名等)
-i, --ipc[=<文件>] 进入 System V IPC 名字空间
-n, --net[=<文件>] 进入网络名字空间
-p, --pid[=<文件>] 进入 pid 名字空间
-C, --cgroup[=<文件>] 进入 cgroup 名字空间
-U, --user[=<文件>] 进入用户名字空间
-S, --setuid <uid> 设置进入空间中的 uid
-G, --setgid <gid> 设置进入名字空间中的 gid
--preserve-credentials 不干涉 uid 或 gid
-r, --root[=<目录>] 设置根目录
-w, --wd[=<dir>] 设置工作目录
-F, --no-fork 执行 <程序> 前不 fork
-Z, --follow-context 根据 --target PID 设置 SELinux 环境
-h, --help display this help
-V, --version display version
更多信息请参阅 nsenter(1)。
通过 nsenter -t <pid> -n bash 即可进入 pid 指向的进程的 net namespace,并在这个 namespace 执行 bash 命令,之后,在这个 bash session 里执行 curl、ip、ifconfig 等命令,看到的网络信息就都是容器内部的网络信息。
实战
在 Linux 上,通过夜莺的 docker-compose 拉起一套夜莺,使用 bridge 模式,做个演示。
1. 拉起夜莺
[root@aliyun-2c2g40g3m compose-bridge]# docker compose up -d
[+] Running 7/7
Network compose-bridge_nightingale Created 0.1s
Container redis Started 0.1s
Container victoriametrics Started 0.1s
Container mysql Started 0.1s
Container ibex Started 0.1s
Container nightingale Started 0.1s
Container categraf Started
然后,inspect 一下 nightingale 容器,拿到其 Pid:
[root@aliyun-2c2g40g3m compose-bridge]# docker ps |grep nigh
0500a886538e flashcatcloud/nightingale:latest "sh -c /app/n9e" 31 minutes ago Up 31 minutes 0.0.0.0:17000->17000/tcp, :::17000->17000/tcp nightingale
[root@aliyun-2c2g40g3m compose-bridge]# docker inspect 0500a886538e |grep Pid
"Pid": 1619207,
"PidMode": "",
"PidsLimit": null,
2.根据 Pid 进入 net namespace
1619207 就是 Pid,根据此 Pid 进入容器的 net namespace:
[root@aliyun-2c2g40g3m compose-bridge]# nsenter -t 1619207 -n bash
[root@aliyun-2c2g40g3m compose-bridge]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.22.0.6 netmask 255.255.0.0 broadcast 172.22.255.255
ether 02:42:ac:16:00:06 txqueuelen 0 (Ethernet)
RX packets 104463 bytes 33707078 (32.1 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 89615 bytes 10817199 (10.3 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 112 bytes 7096 (6.9 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 112 bytes 7096 (6.9 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
如上,使用 bash 命令进入 net namespace,然后执行 ifconfig,看到 IP:172.22.0.6,显然这就是容器的 IP,说明 nsenter 达成所愿,之后在这个 bash session 内执行 curl、telnet 之类的,就相当于在容器里执行一样的效果。完事执行 exit 命令可以退出这个 net namespace。
补充知识
上面的 1619207 这个 Pid 其实就是容器的一号进程的 Pid,在宿主机上执行下面的命令可以看出:
[root@aliyun-2c2g40g3m compose-bridge]# ps aux|grep n9e
root 1619207 0.0 0.0 2576 888 ? Ss 15:22 0:00 sh -c /app/n9e
root 1619327 0.4 4.0 741264 78720 ? Sl 15:22 0:09 /app/n9e
root 1620612 0.0 0.0 221528 864 pts/0 S+ 16:01 0:00 grep --color=auto n9e
夜莺这个容器,核心执行的命令是 /app/n9e,不过在 docker-compose.yaml 中 command 写的是:
sh -c "/app/n9e"
所以这个容器的一号进程就是 sh 了。1619207 和 1619327 这俩进程是在一个容器里的,也就是在一个 net namespace 中的,这俩 Pid 都可以用于 nsenter,效果是一样的。
补充知识2
除了 nsenter,使用 ip netns exec 也可以达到类似的效果。通过 ip netns help 可以看到相关帮助信息。
[root@aliyun-2c2g40g3m compose-bridge]# ip netns help
Usage: ip netns list
ip netns add NAME
ip netns attach NAME PID
ip netns set NAME NETNSID
ip [-all] netns delete [NAME]
ip netns identify [PID]
ip netns pids NAME
ip [-all] netns exec [NAME] cmd ...
ip netns monitor
ip netns list-id [target-nsid POSITIVE-INT] [nsid POSITIVE-INT]
NETNSID := auto | POSITIVE-INT
从上面的 help 信息可以看出,要执行 ip netns exec,需要知道 net namespace 的 NAME,如何找到容器的 net namespace name 呢?
实际上,在 Linux 中,每个进程只要知道其 Pid 了,根据 Pid 就可以找到 net namespace 了,比如上面的例子,我们知道进程的 Pid 是:1619207,其 net namespace 就是:/proc/1619207/ns/net。
但是,执行 ip netns list 却看不到,这是因为,ip netns list 是罗列的 /var/run/netns/ 下面的内容,而容器的 net namespace 并未挂到这里,此时,我们只需要做个软链挂过去即可:
ln -s /proc/1619207/ns/net /var/run/netns/1619207
如果发现 /var/run/netns 目录不存在,使用 root 账号 mkdir 一下即可。之后,我们就可以使用 ip netns exec 了:
ip netns exec 1619207 ifconfig
看到的输出和 nsenter 方式看到的输出是一样的。
如上,希望这个小知识可以帮到大家。


使用 nsenter 排查容器网络问题的更多相关文章
- 理解Docker(6):若干企业生产环境中的容器网络方案
本系列文章将介绍 Docker的相关知识: (1)Docker 安装及基本用法 (2)Docker 镜像 (3)Docker 容器的隔离性 - 使用 Linux namespace 隔离容器的运行环境 ...
- 容器网络——从CNI到Calico
从容器诞生开始,存储和网络这两个话题就一直为大家津津乐道.我们今天这个环境下讲网络这个问题,其实是因为容器对网络的需求,和传统物理.虚拟环境对网络环境需求是有差别的,主要面临以下两个问题: 过去Iaa ...
- Kubernetes & Docker 容器网络终极之战(十四)
目录 一.单主机 Docker 网络通信 1.1.host 模式 1.2 Bridge 模式 1.3 Container 模式 1.4.None 模式 二.跨主机 Docker 网络通信分类 2.1 ...
- kubernetes/k8s CNI分析-容器网络接口分析
关联博客:kubernetes/k8s CSI分析-容器存储接口分析 kubernetes/k8s CRI分析-容器运行时接口分析 概述 kubernetes的设计初衷是支持可插拔架构,从而利于扩展k ...
- Linux namespace技术应用实践--调用宿主机命令(tcpdump/ip/ps/top)检查docker容器网络、进程状态
背景 最近偶然听了几堂极客时间的云原生免费公开课程,首次接触到了Linux namespace技术,并了解到这正是现在风头正劲的容器技术基石,引起了自己探究一二的兴趣,结合课程+网络搜索+实践操作,也 ...
- Docker的单主机容器网络
作者:杨冬 欢迎转载,也请保留这段声明.谢谢! 出处: https://andyyoung01.github.io/ 或 http://andyyoung01.16mb.com/ 本篇文章主要探索Do ...
- 理解Docker单机容器网络
在” 理解Docker单机容器网络 “一文中,还有一个Docker容器网络的功能尚未提及,那就是Docker容器的端口映射.即将容器的服务端口P’ 绑定到宿主机的端口P上,最终达到一种效果:外部程序通 ...
- 【Networking】容器网络大观 && SDN 资料汇总
SDNLAB技术分享(十五):容器网络大观 SDNLAB君• 16-06-17 •2957 人围观 编者按:本文系SDNLAB技术分享系列,本次分享来自SDN撕X群(群主:大猫猫)群直播,我们希望 ...
- docker1.12在cento7里的跨多主机容器网络
docker1.12在cento7里的跨多主机容器网络
- 从 Kubernetes 谈容器网络
基本概念 在 Kubernetes 中.资源从管理粒度上分为三级:容器.Pod.Service. 容器 即 Docker 或者 Rocket 容器(1.0 中仅支持这两种容器). 容器是最低粒度的资源 ...
随机推荐
- 力扣560(java&python)-和为k的子数组(中等)
题目: 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的连续子数组的个数 . 示例 1: 输入:nums = [1,1,1], k = 2输出:2示例 2: 输入:n ...
- HarmonyOS NEXT应用开发之Axios获取解析网络数据
介绍 本示例介绍使用第三方库的Axios获取GBK格式的网络数据时,通过util实现GBK转换UTF-8格式.该场景多用于需要转换编码格式的应用. 效果图预览 使用说明 直接进入页面就可获取GBK格式 ...
- 开源 Serverless 里程碑:Knative 1.0 来了
简介:近期Knative发布了1.0版本,达到了一个重要的里程碑.Knative自2018年7月首次发布以来, 版本不断的迭代发展,除了无数的错误修复.稳定性和性能增强之外,按时间顺序还进行了一些改 ...
- 快手基于 Flink 构建实时数仓场景化实践
简介: 一文了解快手基于 Flink 构建的实时数仓架构,以及一些难题的解决方案. 本文整理自快手数据技术专家李天朔在 5 月 22 日北京站 Flink Meetup 分享的议题<快手基于 F ...
- [FAQ] MetaMask ALERT: 交易出错. 合约代码执行异常.
首先确认载入的合约地址是否是最新的,比如 web3 载入的 abi 格式的 json 文件名 正不正确. 其次需要检查合约逻辑是否都正确,以及是否是合约抛出的错误,这两点最好是通过写测试用例来保证. ...
- 🎊这个 OpenTiny 开源项目的 CLI 可太牛了,两行命令创建一个美观大气的 Vue Admin 后台管理系统,有手就会,连我的设计师朋友都学会啦啦
大家好,我是 Kagol,OpenTiny 开源社区运营,TinyVue 跨端.跨框架组件库核心贡献者,专注于前端组件库建设和开源社区运营. 近期尝试了下 OpenTiny 的 CLI 工具,不得不说 ...
- 2019-4-29-Roslyn-将这个文件放在你的项目文件夹,无论哪个控制台项目都会输出林德熙是逗比...
title author date CreateTime categories Roslyn 将这个文件放在你的项目文件夹,无论哪个控制台项目都会输出林德熙是逗比 lindexi 2019-4-29 ...
- 圈子社交系统--在线了解前后端,APP小程序H5,三端源码交付-多重玩法,新奇有趣。
圈子论坛社区系统,含完整的后台PHP系统.功能:小程序授权登陆,H5和APP,手机号登陆,发帖,建圈子.发活动.圈主可置顶推荐帖子,关注.点赞.评论.交流等.可作为圈子贴吧等自媒体. 一款全开源支持免 ...
- 简说Python之ipython的pdb调试
目录 简说Python之ipython 1.安装ipython 2.ipython的使用 3.ipython的debug调试. 系统环境:Ubuntu 18.04.1 LTS Python使用的是虚拟 ...
- 网络协议分析与抓包 TCP/IP UDP等
学习地址: https://www.bilibili.com/video/BV1hV411U74y?p=4 https://www.bilibili.com/video/BV1S7411R7kF?p= ...