从网络命令空间netns,来说明docker brige模式的通信原理

两个netns之间的通信

① netns的概念:
netns是linux中一个独立的网络栈,每个ns都有自己的网卡、loopback设备、路由表、iptables。有了这些,一个进程就可以和外部进行通信

② netns之间通信需要用到的设备:

  • vethpair设备:是一种必须成对出现设备,两张虚拟网卡,分别置于两端,一端发包,另一端会收包;
  • 网桥:交换机的角色

③ 具体方式:

  • 两个netns之间通信,可以在两个netns下分别放一个vethpair设备;
  • 多个netns之间通信,借助网桥来做交换机,将成对的vethpair设备分别放在netns和网桥上,此时,在网桥上的vethpair会从一个网卡,降级成交换机的端口,所有的流量都会被交换机,网桥劫持,并进行相关的转发。

④ 举个栗子:
下面会操作两个netns,借助网桥的方式来通信。

//创建net ns   
ip  netns  add  net1

//创建网桥
ip link  add br0 type bridge

//创建vethpair设备
ip  link  add type veth 
or
ip link add veth0 type  veth peer name veth1

//将vethpair的veth1添加在net1 ns中,并配置ip,启动设备,配置ip的时候会默认配置路由规则
ip link set dev veth1 netns net1 
ip netns exec net1 ip link set dev veth1 name eth0 
ip netns exec net1 ip addr  add 10.0.1.1/24 dev eth0
ip netns exec net1 ip link set dev eth0 up

//将vethpair的veth0添加在网桥br0上,并启动
ip link set dev veth0 master br0
ip link set dev veth0 up

另一个ns和上面操作相同,至此,配置已经完毕:我们可以测试一下:
1.bridge命令可以查看bridge的信息

[root@localhost ~]# bridge  link
20: veth0 state UP @(null): <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br0 state disabled priority 32 cost 2 
22: veth2 state UP @(null): <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br0 state disabled priority 32 cost 2 

[root@localhost ~]# brctl show 
bridge name     bridge id               STP enabled     interfaces
br0             8000.1af19dd61e02       no              veth0
                                                        veth2
  1. 进入net2中ping net1:
[root@localhost ~]# ip netns  exec  net2  ping -c 1   10.0.1.1
PING 10.0.1.1 (10.0.1.1) 56(84) bytes of data.
64 bytes from 10.0.1.1: icmp_seq=1 ttl=64 time=0.069 ms

--- 10.0.1.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.069/0.069/0.069/0.000 ms

查看当前的网络情况:
此时,可以看到,并没有给br0配置ip,在这里br0只是充当交换机的角色。

[root@localhost ~]# ifconfig 
br0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::18f1:9dff:fed6:1e02  prefixlen 64  scopeid 0x20<link>
        ether 1a:f1:9d:d6:1e:02  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 6  bytes 508 (508.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.6.213  netmask 255.255.255.0  broadcast 192.168.6.255
        inet6 fe80::3979:3ddc:8722:3685  prefixlen 64  scopeid 0x20<link>
        ether b6:41:48:9f:44:31  txqueuelen 1000  (Ethernet)
        RX packets 25520  bytes 4561658 (4.3 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 15907  bytes 2560284 (2.4 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
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 944  bytes 94296 (92.0 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 944  bytes 94296 (92.0 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::f0ab:b1ff:fe72:ddec  prefixlen 64  scopeid 0x20<link>
        ether f2:ab:b1:72:dd:ec  txqueuelen 1000  (Ethernet)
        RX packets 11  bytes 774 (774.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 14  bytes 1156 (1.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::18f1:9dff:fed6:1e02  prefixlen 64  scopeid 0x20<link>
        ether 1a:f1:9d:d6:1e:02  txqueuelen 1000  (Ethernet)
        RX packets 14  bytes 900 (900.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 14  bytes 1156 (1.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

遗留的问题:
1.此时我们在net2中,不能ping通自己的ip,为什么呢?
因为lo网卡还没有启动,默认情况下访问本机ip,会走lo网卡。
上面的网络拓扑图如下所示:
在这里插入图片描述

ns内部和宿主机的通信

1.进入netns1中ping 宿主机ip,发现不能通

[root@localhost ~]# ip netns  exec  net2    ping 192.168.6.213
connect: Network is unreachable

此时需要查看net2 ns的路由规则:

[root@localhost ~]# ip netns  exec  net2    route -n 
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.0.1.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0

路由规则不满足,无法到达指定的网络,故添加默认路由:使所有的流量都从ns中的eth0网卡发出。

ip route add default  dev eth0

查看路由规则:

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         0.0.0.0         0.0.0.0         U     0      0        0 eth0
10.0.1.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0

问题:其实添加路由后,包应该是可以发到br0网络了。但是抓br0包,发现并没有收到。为什么呢?
答:抓eth0包,发现它发的arp请求,获取192.168.6.2的mac地址,不能成功,故包不能组装成功,所以不能从网卡eth0发出。

[root@localhost ~]# tcpdump   -i  eth0 
22:15:41.125393 ARP, Request who-has 192.168.6.2 tell localhost.localdomain, length 28
22:15:42.126989 ARP, Request who-has 192.168.6.213 tell localhost.localdomain, length 28

其实此时,交换机只是连接了两个ns,其实是相当于他创建了一个封闭的局域网,此时的交换机就是纯粹的交换机,即二层交换机,只工作在链路层。想要将交换机和宿主机连通网络,就需要三层交换机,三层交换机就是即做路由转发,又做交换机。工作在三层,当有arp请求,三层交换机会看mac是不是自己,是自己,判断ip是不是自己,ip是自己就不转发了。不是自己就进行转发策略。向上转发。

  1. 给br0网桥添加ip,此命令会默认添加路由:
ip  addr  add 10.0.1.1/24 dev br0

此时就可以ping 通宿主机的ip,如下:

[root@localhost ~]# ip netns  exec  net2     ping  192.168.6.213
PING 192.168.6.213 (192.168.6.213) 56(84) bytes of data.
64 bytes from 192.168.6.213: icmp_seq=1 ttl=64 time=0.068 ms

这里有一个问题,之前看到的,一台物理机上有多个网卡。当网卡之间需要访问时,需要打开ip_foward,但是,此处却不用打开,因为交换机会根据主机的路由表走 “直连路由”。 故不用宿主机进行转发。

另我困惑的是,我们可以通过在netns中使用arp -a 看到宿主机ip的mac映射是br0的mac,而不是宿主机的真实网卡ens33的mac。进行抓包的时候,也只能在br0上抓到包,不能在ens33上抓到包。

ns内部和宿主机外的通信

1.完成了ping宿主机ip,我们尝试ping 8.8.8.8,却发现不能ping通,其实当前ns中的包可以正常的发到宿主机,且宿主机可以访问到8.8.8.8。为什么呢?

答:我想可能是因为没有打开宿主机的Ipforward,打开,如下:

echo 1 > /proc/sys/net/ipv4/ip_forward
cat /proc/sys/net/ipv4/ip_forward
  1. 但是还是不能ping通,为什么呢?
    抓netns内的网卡eth0的包,发现还是不能获取到mac地址,所以包不能完成组装,故不能发送。那怎么办呢?

解决:
因为广播原因,所以往其他宿主机的网络发包,需要先到网关,之后怎么去,是由网关来决定的。
而之前配置的默认路由是从eth0发出,并没有指向发到那里,此时网桥br0上因为veth pair设备的存在会收到包,但并不会继续广播。故我们需要在net ns中配置发往网关的路由。

  1. 修改路由规则改为发往br0网关:
[root@localhost ~]\# ip netns exec net2 route -n 

Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.0.1.1 0.0.0.0 UG 0 0 0 eth0

10.0.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0

再次ping 8.8.8.8,发现可以ping通:

[root@localhost ~]\# ip netns exec net2 ping -c 1 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.

From 10.0.1.1 icmp\_seq=1 Destination Host Prohibited

--- 8.8.8.8 ping statistics ---

1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用: Docker是一个图像化界面管理工具,它提供了一个后台面板供我们操作。你可以使用以下命令来运行Docker: "docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer"。 引用: 如果你想编写一个Dockerfile文件,可以按照以下步骤进行:首先,使用"Docker build"命令将其构建成为一个镜像;然后,使用"Docker run"命令运行该镜像;最后,使用"Docker push"命令发布镜像到DockerHub或阿里云镜像仓库(私有/共有)。 引用: 如果你想使用Dockerfile创建一个镜像,可以按照以下步骤进行:首先,将Dockerfile和你的jar文件放在同一个目录下;然后,执行命令"Docker build -t helloworld:1.0 ."来创建镜像。 关于"docker bridge -v"的问题,它是一个无效的命令Docker Bridge是Docker网络驱动程序,它为容器提供了网络连接。而"-v"是用来挂载卷(Volume)的命令,用于将宿主机的目录或文件挂载到容器中。所以,"docker bridge -v"不是一个有效的Docker命令,请确认你的命令是否正确。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [docker快速入门](https://blog.csdn.net/chongcilingjian/article/details/119640314)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值