专栏首页云原生生态圈走进Network Namespace学会容器网络调试

走进Network Namespace学会容器网络调试

Linux Network Namespace

Linux的Namespace[1]机制提供了一种资源隔离的解决方案,而目前Linux内核里面实现且支持的Namespace有7种,如下表:

名称

定义

说明

Cgroup

CLONE_NEWCGROUP

Cgroup root directory (since Linux 4.6)

IPC

CLONE_NEWIPC

System V IPC, POSIX message queues (since Linux 2.6.19)

Network

CLONE_NEWNET

Network devices, stacks, ports, etc. (since Linux 2.6.24)

Mount

CLONE_NEWNS

Mount points (since Linux 2.4.19)

PID

CLONE_NEWPID

Process IDs (since Linux 2.6.24)

User

CLONE_NEWUSER

User and group IDs (started in Linux 2.6.23 and completed in Linux 3.8)

UTS

CLONE_NEWUTS

Hostname and NIS domain name (since Linux 2.6.19)

但是今天只分析一下Network NameSpace以及管理,Network NameSpace是实现网络空间隔离或者说网络虚拟化的基础, 不管是Docker还是虚拟机技术上的程序也都是由Linux内核实现的Network NameSpace隔离开的命令空间内运行。ip netns就是管理命令空间的命令,在学习之前,先了解几个命令unsharereadlinknsenter

unshare

运行一些与父级不共享的某些名称空间的程序。

root@node3:~# unshare --help

Usage:
 unshare [options] <program> [<argument>...]

Run a program with some namespaces unshared from the parent.

Options:
-h,--help
显示帮助文本并退出。
-i,-- ipc 取消共享IPC名称空间。
-m,-- mount 取消共享安装名称空间。
-n,-- net 取消共享网络名称空间。
-p,-- pid 取消共享pid名称空间。另请参见--fork和--mount-proc选项。
-u,-- uts 取消共享UTS名称空间。
-U,--user 取消共享用户名称空间。
-f,-将指定程序fork为取消共享的子进程,而不是直接运行它。这在创建新的pid名称空间时很有用。
--mount-proc [=mountpoint]在运行程序之前,将proc文件系统挂载到mountpoint (默认为/ proc)。这在创建新的pid名称空间时很有用。这也意味着创建一个新的挂载名称空间,因为/ proc挂载否则会破坏系统上的现有程序。新的proc文件系统显式安装为私有文件(由MS_PRIVATE | MS_REC)。
-r,-- map-root-user 仅在当前有效的用户和组ID已映射到新创建的用户名称空间中的超级用户UID和GID之后,才运行该程序。这样即使在没有特权的情况下运行,也可以方便地获得管理新创建的名称空间各个方面所需的功能(例如,在网络名称空间中配置接口或在安装名称空间中安装文件系统)。仅作为一项便利功能,它不支持更复杂的用例,例如映射多个范围的UID和GID。

For more details see unshare(1).

readlink是Linux系统中一个常用工具,主要用来找出符号链接所指向的位置

root@node3:/etc# readlink /etc/resolv.conf
../run/resolvconf/resolv.conf

nsenter

一个可以在指定进程的命令空间下运行指定程序的命令。这个命令大家在容器网络调试下可能常用,比如在一些没有网络调试工具(ip addresspingtelnetsstcpdump)的容器内利用宿主机上的命令进行容器内网络连通性的调试等等

root@node3:/etc# nsenter --help
...略
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]:设置工作目录

运行一个Demo演示一下

root@node3:/etc# docker run -d --name test nginx
31095893cbddd999a9f2d9e78cd4c057d4f5b3763fe1b5ecd5d68df4e9ce5943
root@node3:/etc# docker inspect -f {{.State.Pid}} test
26308
root@node3:/etc# nsenter -t 26308 -n
root@node3:/etc# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    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
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
root@node3:/etc# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.17.0.1      0.0.0.0         UG    0      0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth0
root@node3:/etc# netstat -unlpt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      26308/nginx: master
tcp6       0      0 :::80                   :::*                    LISTEN      26308/nginx: master
root@node3:/etc# exit
logout

这样看起来是不是很清楚,以后排查容器网络感觉又方便不少了

前期准备工作做了不少,下面好好说说Network NameSpace如何通过ip netns进行管理

Network NameSpace管理

ip netns命令基本很少使用到,所以先来熟悉一番

root@node3:~# ip netns help
Usage: ip netns list
       ip netns add NAME
       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

ip netns list

Linux系统下默认是没有network namespace,我们可以通过ls或者ip netns查看

root@node3:~# ip netns list
root@node3:~# ls -al /var/run/netns/
total 0
drwxr-xr-x  2 root root   40 Oct  6 05:07 .
drwxr-xr-x 26 root root 1020 Oct  6 04:57 ..

ip netns add

root@node3:~# ip netns add nsdemo1
root@node3:~# ip netns add nsdemo1 # 重复创建会报错
Cannot create namespace file "/var/run/netns/nsdemo1": File exists
root@node3:~# ip netns add nsdemo2
root@node3:~# ip netns list
nsdemo2
nsdemo1
root@node3:~# ls -al /var/run/netns/
total 0
drwxr-xr-x  2 root root   80 Oct  6 05:08 .
drwxr-xr-x 26 root root 1020 Oct  6 04:57 ..
-r--r--r--  1 root root    0 Oct  6 05:08 nsdemo1
-r--r--r--  1 root root    0 Oct  6 05:08 nsdemo2

ip netns add创建的network namespace会在/var/run/netns目录下创建一个同名的文件,

ip netns del

root@node3:~# ip netns add nsdemo1
root@node3:~# ip netns add nsdemo2
root@node3:~# ip netns list
nsdemo2
nsdemo1
root@node3:~# ip -all netns del
root@node3:~# ip netns list
root@node3:~# ip netns add nsdemo3
root@node3:~# ip netns list
nsdemo3
root@node3:~# ip -all netns delete # 可以使用del,也可以使用delete
root@node3:~# ip netns list
root@node3:~#

ip netns exec

在创建了一个新的network namespace之后,很好奇里面究竟包含哪些东西,此时就可以通过exec进去查看,除了网络信息之外与宿主机是没有区别的

root@node3:~# ip netns add nsdemo3
root@node3:~# ip netns exec nsdemo3 ip addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    
root@node3:~# ip netns exec nsdemo3 bash
root@node3:~# ip addr # 每个network namespace都存在一个没有启用的lo本地回环网卡
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
root@node3:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface

# 在进入nsdemo3这个network namespace之前,给nsdemo3的bash指定配置文件,用来修改bash前缀区分shell
root@node3:~# ip netns exec nsdemo3 /bin/bash --rcfile <(echo "PS1=\"namespace nsdemo3> \"")
namespace nsdemo3> ip addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
namespace nsdemo3> exit
exit

启用network namespace中的lo网卡

root@node3:~# ip netns del nsdemo3
root@node3:~# ip netns list
root@node3:~# ip netns add nsdemo4
root@node3:~# ip netns list
nsdemo4
root@node3:~# ip netns exec nsdemo4 /bin/bash --rcfile <(echo "PS1=\"namespace nsdemo4> \"")
namespace nsdemo4> ip addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
namespace nsdemo4> ip link set lo up # 启用网卡lo
namespace nsdemo4> ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    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
namespace nsdemo4> ping 192.168.99.128 # 查看与主机之间的网络状态,发现网络不同
connect: Network is unreachable
namespace nsdemo4> exit
exit
root@node3:~# ip netns exec nsdemo4 /bin/bash --rcfile <(echo "PS1=\"namespace nsdemo4> \"")
namespace nsdemo4> ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    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

默认情况下,隔离的网络命名空间是无法进行通信的,同样可以利用ip的子命令link创建vethbridge类型的网卡实现两个或者多个隔离的Network NameSpace之间相互通信。这样更有助于理解容器网络之间的隔离与通信。

参考资料

[1]

Linux Namespace: https://man7.org/linux/man-pages/man7/namespaces.7.html

本文分享自微信公众号 - 云原生生态圈(CloudNativeEcoSystem),作者:Marionxue

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-10-06

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • tcpdump: 我来帮你过滤和分析系统中的网络数据

    公众号: 云原生生态圈
  • YAPI-高效、易用、功能强大的 api 管理平台

    在前后端分离的架构流行的时下,前后端部门之间交流更多的就是在数据处理和定义前端的接口,但是一边开发一遍维护接口文档,对于开发者来说是一个非常头疼的事情:

    公众号: 云原生生态圈
  • Gitlab持续集成中Dood与Dind应该怎么玩?

    在通过jenkins或Gitlab使用Docker容器化构建服务的时候,我们会遇到两种构建的方式,分别是DIND与DOOD,这两种的构建的方式却有着很大的差异,...

    公众号: 云原生生态圈
  • Echart图表自适应情况下的打印 原

    报表是全屏自适应的,当点击打印按钮时Echart图表设置成固定的宽度以适应打印的页面,img的src是获取变化后的echart数据流

    tianyawhl
  • JS 控制隐藏显示

    问天丶天问
  • 腾讯 AI Lab 2018年度回顾

    ? 2018年是颇具意义的一年,以“Make AI Everywhere”为愿景,我们在医疗、农业和公益等AI应用领域取得不错进展,也正在通过游戏和机器人等实...

    腾讯技术工程官方号
  • 跟肉丝姐学 Frida 之 快速搭建 Frida 安卓逆向环境

    这段时间空闲的时间一直在跟着肉丝姐补课,手残把手机搞崩了,借着这个机会写一篇文章记录下如何从零完成 Frida 安卓逆向环境的搭建。

    咸鱼学Python
  • C++经典算法题-洗扑克牌(乱数排列)

    洗扑克牌的原理其实与乱数排列是相同的,都是将一组数字(例如1~N)打乱重新排列,只不过洗扑克牌多了一个花色判断的动作而已。

    cwl_java
  • 用XPath Helper完成Bing每日壁纸的小爬虫

    为了让搜索变得有趣,谷歌提供了Google doogle, 微软提供了Bing壁纸, 百度直接抄了Google doogle(百度NB!), 作为一名摄影爱好者...

    zhaoolee
  • 技术太多学不过来?教你如何越学越带劲

    一个人要想不断的提升,不断的改变,需要不断的学习,当然如果你想升职加薪,同样需要学习。然而当代知识层出不穷,学的过来吗?只要方法得当,相信可以通过学习达到我们的...

    用户1410343

扫码关注云+社区

领取腾讯云代金券