前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >走进Network Namespace学会容器网络调试

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

作者头像
公众号: 云原生生态圈
发布2020-10-10 10:36:50
5790
发布2020-10-10 10:36:50
举报
文章被收录于专栏:云原生生态圈云原生生态圈

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

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

代码语言:javascript
复制
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

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

代码语言:javascript
复制
root@node3:/etc# readlink /etc/resolv.conf
../run/resolvconf/resolv.conf

nsenter

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

代码语言:javascript
复制
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演示一下

代码语言:javascript
复制
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命令基本很少使用到,所以先来熟悉一番

代码语言:javascript
复制
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查看

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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进去查看,除了网络信息之外与宿主机是没有区别的

代码语言:javascript
复制
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网卡

代码语言:javascript
复制
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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-10-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 云原生生态圈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • unshare
  • readLink
  • nsenter
  • Network NameSpace管理
    • ip netns list
      • ip netns add
        • ip netns del
          • ip netns exec
            • 参考资料
            相关产品与服务
            容器服务
            腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档