16 | 容器网络配置(1):容器网络不通了要怎么调试?

你好,我是程远。

在上一讲,我们讲了Network Namespace隔离了网络设备,IP协议栈和路由表,以及防火墙规则,那容器Network Namespace里的参数怎么去配置,我们现在已经很清楚了。

其实对于网络配置的问题,我们还有一个最需要关心的内容,那就是容器和外面的容器或者节点是怎么通讯的,这就涉及到了容器网络接口配置的问题了。

所以这一讲呢,我们就来聊一聊,容器Network Namespace里如何配置网络接口,还有当容器网络不通的时候,我们应该怎么去做一个简单调试。

问题再现

在前面的课程里,我们一直是用 docker run 这个命令来启动容器的。容器启动了之后,我们也可以看到,在容器里面有一个"eth0"的网络接口,接口上也配置了一个IP地址。

不过呢,如果我们想从容器里访问外面的一个IP地址,比如说39.106.233.176(这个是极客时间网址对应的IP),结果就发现是不能ping通的。

这时我们可能会想到,到底是不是容器内出了问题,在容器里无法访问,会不会宿主机也一样不行呢?

所以我们需要验证一下,首先我们退出容器,然后在宿主机的Network Namespace下,再运行 ping 39.106.233.176,结果就会发现在宿主机上,却是可以连通这个地址的。

# docker run -d --name if-test centos:8.1.1911 sleep 36000
244d44f94dc2931626194c6fd3f99cec7b7c4bf61aafc6c702551e2c5ca2a371
# docker exec -it if-test bash
 
[root@244d44f94dc2 /]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    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
808: eth0@if809: <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@244d44f94dc2 /]# ping 39.106.233.176       ### 容器中无法ping通
PING 39.106.233.176 (39.106.233.176) 56(84) bytes of data.
^C
--- 39.106.233.176 ping statistics ---
9 packets transmitted, 0 received, 100% packet loss, time 185ms
 
[root@244d44f94dc2 /]# exit             ###退出容器
exit
 
# ping 39.106.233.176                        ### 宿主机上可以ping通
PING 39.106.233.176 (39.106.233.176) 56(84) bytes of data.
64 bytes from 39.106.233.176: icmp_seq=1 ttl=78 time=296 ms
64 bytes from 39.106.233.176: icmp_seq=2 ttl=78 time=306 ms
64 bytes from 39.106.233.176: icmp_seq=3 ttl=78 time=303 ms
^C
--- 39.106.233.176 ping statistics ---
4 packets transmitted, 3 received, 25% packet loss, time 7ms
rtt min/avg/max/mdev = 296.059/301.449/305.580/4.037 ms

那么碰到这种容器内网络不通的问题,我们应该怎么分析调试呢?我们还是需要先来理解一下,容器Network Namespace里的网络接口是怎么配置的。

基本概念

在讲解容器的网络接口配置之前,我们需要先建立一个整体的认识,搞清楚容器网络接口在系统架构中处于哪个位置。

你可以看一下我给你画的这张图,图里展示的是容器有自己的Network Namespace,eth0 是这个Network Namespace里的网络接口。而宿主机上也有自己的eth0,宿主机上的eth0对应着真正的物理网卡,可以和外面通讯。

那你可以先想想,我们要让容器Network Namespace中的数据包最终发送到物理网卡上,需要完成哪些步骤呢?从图上看,我们大致可以知道应该包括这两步。

第一步,就是要让数据包从容器的Network Namespace发送到Host Network Namespace上。

第二步,数据包发到了Host Network Namespace之后,还要解决数据包怎么从宿主机上的eth0发送出去的问题。

好,整体的思路已经理清楚了,接下来我们做具体分析。我们先来看第一步,怎么让数据包从容器的Network Namespace发送到Host Network Namespace上面。

你可以查看一下Docker 网络的文档或者Kubernetes网络的文档,这些文档里面介绍了很多种容器网络配置的方式。

不过对于容器从自己的Network Namespace连接到Host Network Namespace的方法,一般来说就只有两类设备接口:一类是veth,另外一类是macvlan/ipvlan。

在这些方法中,我们使用最多的就是veth的方式,用Docker启动的容器缺省的网络接口用的也是这个veth。既然它这么常见,所以我们就用veth作为例子来详细讲解。至于另外一类macvlan/ipvlan的方式,我们在下一讲里会讲到。

那什么是veth呢?为了方便你更好地理解,我们先来模拟一下Docker为容器建立eth0网络接口的过程,动手操作一下,这样呢,你就可以很快明白什么是veth了。

对于这个模拟操作呢,我们主要用到的是ip netns 这个命令,通过它来对Network Namespace做操作。

首先,我们先启动一个不带网络配置的容器,和我们之前的命令比较,主要是多加上了"--network none"参数。我们可以看到,这样在启动的容器中,Network Namespace里就只有loopback一个网络设备,而没有了eth0网络设备了。

# docker run -d --name if-test --network none centos:8.1.1911 sleep 36000
cf3d3105b11512658a025f5b401a09c888ed3495205f31e0a0d78a2036729472
# docker exec -it if-test ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    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

完成刚才的设置以后,我们就在这个容器的Network Namespace里建立veth,你可以执行一下后面的这个脚本。

pid=$(ps -ef | grep "sleep 36000" | grep -v grep | awk '{print $2}')
echo $pid
ln -s /proc/$pid/ns/net /var/run/netns/$pid
 
# Create a pair of veth interfaces
ip link add name veth_host type veth peer name veth_container
# Put one of them in the new net ns
ip link set veth_container netns $pid
 
# In the container, setup veth_container
ip netns exec $pid ip link set veth_container name eth0
ip netns exec $pid ip addr add 172.17.1.2/16 dev eth0
ip netns exec $pid ip link set eth0 up
ip netns exec $pid ip route add default via 172.17.0.1
 
# In the host, set veth_host up
ip link set veth_host up

我在这里解释一下,这个veth的建立过程是什么样的。

首先呢,我们先找到这个容器里运行的进程"sleep 36000"的pid,通过 "/proc/$pid/ns/net"这个文件得到Network Namespace的ID,这个Network Namespace ID既是这个进程的,也同时属于这个容器。

然后我们在"/var/run/netns/"的目录下建立一个符号链接,指向这个容器的Network Namespace。完成这步操作之后,在后面的"ip netns"操作里,就可以用pid的值作为这个容器的Network Namesapce的标识了。

接下来呢,我们用 ip link 命令来建立一对veth的虚拟设备接口,分别是veth_container和veth_host。从名字就可以看出来,veth_container这个接口会被放在容器Network Namespace里,而veth_host会放在宿主机的Host Network Namespace。

所以我们后面的命令也很好理解了,就是用 ip link set veth_container netns $pid 把veth_container这个接口放入到容器的Network Namespace中。

再然后我们要把veth_container重新命名为eth0,因为这时候接口已经在容器的Network Namesapce里了,eth0就不会和宿主机上的eth0冲突了。

最后对容器内的eht0,我们还要做基本的网络IP和缺省路由配置。因为veth_host已经在宿主机的Host Network Namespace了,就不需要我们做什么了,这时我们只需要up一下这个接口就可以了。

那刚才这些操作完成以后,我们就建立了一对veth虚拟设备接口。我给你画了一张示意图,图里直观展示了这对接口在容器和宿主机上的位置。

现在,我们再来看看veth的定义了,其实它也很简单。veth就是一个虚拟的网络设备,一般都是成对创建,而且这对设备是相互连接的。当每个设备在不同的Network Namespaces的时候,Namespace之间就可以用这对veth设备来进行网络通讯了。

比如说,你可以执行下面的这段代码,试试在veth_host上加上一个IP,172.17.1.1/16,然后从容器里就可以ping通这个IP了。这也证明了从容器到宿主机可以利用这对veth接口来通讯了。

# ip addr add 172.17.1.1/16 dev veth_host
# docker exec -it if-test ping 172.17.1.1
PING 172.17.1.1 (172.17.1.1) 56(84) bytes of data.
64 bytes from 172.17.1.1: icmp_seq=1 ttl=64 time=0.073 ms
64 bytes from 172.17.1.1: icmp_seq=2 ttl=64 time=0.092 ms
^C
--- 172.17.1.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 30ms
rtt min/avg/max/mdev = 0.073/0.082/0.092/0.013 ms

好了,这样我们完成了第一步,通过一对veth虚拟设备,可以让数据包从容器的 Network Namespace发送到Host Network Namespace上。

那下面我们再来看第二步, 数据包到了Host Network Namespace之后呢,怎么把它从宿主机上的eth0发送出去?

其实这一步呢,就是一个普通Linux节点上数据包转发的问题了。这里我们解决问题的方法有很多种,比如说用nat来做个转发,或者建立Overlay网络发送,也可以通过配置proxy arp加路由的方法来实现。

因为考虑到网络环境的配置,同时Docker缺省使用的是 bridge + nat的转发方式, 那我们就在刚才讲的第一步基础上,再手动实现一下bridge+nat的转发方式。对于其他的配置方法,你可以看一下Docker或者Kubernetes相关的文档。

Docker程序在节点上安装完之后,就会自动建立了一个docker0的bridge interface。所以我们只需要把第一步中建立的veth_host这个设备,接入到docker0这个bridge上。

这里我要提醒你注意一下,如果之前你在veth_host上设置了IP的,就需先运行一下"ip addr delete 172.17.1.1/16 dev veth_host",把IP从veth_host上删除。

# ip addr delete 172.17.1.1/16 dev veth_host 
ip link set veth_host master docker0

这个命令执行完之后,容器和宿主机的网络配置就会发生变化,这种配置是什么样呢?你可以参考一下面这张图的描述。

从这张示意图中,我们可以看出来,容器和docker0组成了一个子网,docker0上的IP就是这个子网的网关IP。

如果我们要让子网通过宿主机上eth0去访问外网的话,那么加上iptables的规则就可以了,也就是下面这条规则。

iptables -P FORWARD ACCEPT

好了,进行到这里,我们通过bridge+nat的配置,似乎已经完成了第二步——让数据从宿主机的eth0发送出去。

那么我们这样配置,真的可以让容器里发送数据包到外网了吗?这需要我们做个测试,再重新尝试下这一讲开始的操作,从容器里ping外网的IP,这时候,你会发现还是ping不通。

其实呢,做到这一步,我们通过自己的逐步操作呢,重现了这一讲了最开始的问题。

解决问题

既然现在我们清楚了,在这个节点上容器和宿主机上的网络配置是怎么一回事。那么要调试这个问题呢,也有了思路,关键就是找到数据包传到哪个环节时发生了中断。

那最直接的方法呢,就是在容器中继续ping外网的IP 39.106.233.176,然后在容器的eth0 (veth_container),容器外的veth_host,docker0,宿主机的eth0这一条数据包的路径上运行tcpdump。

这样就可以查到,到底在哪个设备接口上没有收到ping的icmp包。我把tcpdump运行的结果我列到了下面。

容器的eth0:

# ip netns exec $pid tcpdump -i eth0 host 39.106.233.176 -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
00:47:29.934294 IP 172.17.1.2 > 39.106.233.176: ICMP echo request, id 71, seq 1, length 64
00:47:30.934766 IP 172.17.1.2 > 39.106.233.176: ICMP echo request, id 71, seq 2, length 64
00:47:31.958875 IP 172.17.1.2 > 39.106.233.176: ICMP echo request, id 71, seq 3, length 64

veth_host:

# tcpdump -i veth_host host 39.106.233.176 -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth_host, link-type EN10MB (Ethernet), capture size 262144 bytes
00:48:01.654720 IP 172.17.1.2 > 39.106.233.176: ICMP echo request, id 71, seq 32, length 64
00:48:02.678752 IP 172.17.1.2 > 39.106.233.176: ICMP echo request, id 71, seq 33, length 64
00:48:03.702827 IP 172.17.1.2 > 39.106.233.176: ICMP echo request, id 71, seq 34, length 64

docker0:

# tcpdump -i docker0 host 39.106.233.176 -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes
00:48:20.086841 IP 172.17.1.2 > 39.106.233.176: ICMP echo request, id 71, seq 50, length 64
00:48:21.110765 IP 172.17.1.2 > 39.106.233.176: ICMP echo request, id 71, seq 51, length 64
00:48:22.134839 IP 172.17.1.2 > 39.106.233.176: ICMP echo request, id 71, seq 52, length 64

host eth0:

# tcpdump -i eth0 host 39.106.233.176 -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
^C
0 packets captured
0 packets received by filter
0 packets dropped by kernel

通过上面的输出结果,我们发现icmp包到达了docker0,但是没有到达宿主机上的eth0。

因为我们已经配置了iptables nat的转发,这个也可以通过查看iptables的nat表确认一下,是没有问题的,具体的操作命令如下:

# iptables -L  -t nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
DOCKER     all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL
 
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
 
Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  172.17.0.0/16        anywhere
 
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
DOCKER     all  --  anywhere            !127.0.0.0/8          ADDRTYPE match dst-type LOCAL
 
Chain DOCKER (2 references)
target     prot opt source               destination
RETURN     all  --  anywhere             anywhere

那么会是什么问题呢?因为这里需要做两个网络设备接口之间的数据包转发,也就是从docker0把数据包转发到eth0上,你可能想到了Linux协议栈里的一个常用参数ip_forward。

我们可以看一下,它的值是0,当我们把它改成1之后,那么我们就可以从容器中ping通外网39.106.233.176这个IP了!

# cat /proc/sys/net/ipv4/ip_forward
0
# echo 1 > /proc/sys/net/ipv4/ip_forward
 
# docker exec -it if-test ping 39.106.233.176
PING 39.106.233.176 (39.106.233.176) 56(84) bytes of data.
64 bytes from 39.106.233.176: icmp_seq=1 ttl=77 time=359 ms
64 bytes from 39.106.233.176: icmp_seq=2 ttl=77 time=346 ms
^C
--- 39.106.233.176 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1ms
rtt min/avg/max/mdev = 345.889/352.482/359.075/6.593 ms

重点小结

这一讲,我们主要解决的问题是如何给容器配置网络接口,让容器可以和外面通讯;同时我们还学习了当容器网络不通的时候,我们应该怎么来做一个简单调试。

解决容器与外界通讯的问题呢,一共需要完成两步。第一步是,怎么让数据包从容器的Network Namespace发送到Host Network Namespace上;第二步,数据包到了Host Network Namespace之后,还需要让它可以从宿主机的eth0发送出去。

我们想让数据从容器Netowrk Namespace发送到Host Network Namespace,可以用配置一对veth虚拟网络设备的方法实现。而让数据包从宿主机的eth0发送出去,就用可bridge+nat的方式完成。

这里我讲的是最基本的一种配置,但它也是很常用的一个网络配置。针对其他不同需要,容器网络还有很多种。那你学习完这一讲,了解了基本的概念和操作之后呢,还可以查看更多的网上资料,学习不同的网络配置。

遇到容器中网络不通的情况,我们先要理解自己的容器以及容器在宿主机上的配置,通过对主要设备上做tcpdump可以找到具体在哪一步数据包停止了转发。

然后我们结合内核网络配置参数,路由表信息,防火墙规则,一般都可以定位出根本原因,最终解决这种网络完全不通的问题。

但是如果是网络偶尔丢包的问题,这个就需要用到其他的一些工具来做分析了,这个我们会在之后的章节做讲解。

思考题

我们这一讲的例子呢,实现了从容器访问外面的IP。那么如果要实现节点外的程序来访问容器的IP,我们应该怎么配置网络呢?

欢迎你在留言区分享你的思考和问题。如果这篇文章对你有启发,也欢迎分享给你的朋友,一起学习进步。

精选留言

  • 良凯尔

    2020-12-21 08:43:48

    实现节点外的程序来访问容器:

    iptables -t nat -A PREROUTING -d 【宿主机ip】 -p tcp -m tcp --dport 【宿主机映射端口】 -j DNAT --to-destination 【容器ip】:【容器端口】

    利用DNAT,访问宿主机ip+宿主机映射端口,即可访问容器
  • 我来也

    2021-01-05 00:00:24

    老师一路tcpdump的操作很犀利,特别是抓容器中的数据包的那个操作:

    ip netns exec $pid tcpdump -i eth0 host 39.106.233.176 -nn

    以前为了在容器中抓包,还要在容器中安装tcpdump,从国外的源拉数据又慢,即使换了国内的源,但每次重建容器后又得再来一次。
    搞的我专门准备了一个调试用的基础容器,把各种常用的工具都给装上,包括我的vim。😄
    作者回复

    @我来也
    把调试工具都放到一个基础容器中也挺好的。

    2021-01-06 21:32:02

  • 陈斯佳

    2021-02-04 17:11:42

    这篇网络调试太硬核了!!一直觉得,容器就是Linux的高级知识,容器通了,Linux的内容你就所向披靡了
    作者回复

    @陈斯佳
    是这样的!

    2021-02-06 22:12:41

  • 争光 Alan

    2020-12-27 00:15:28

    你好,老师,我网络比较弱,看了文章有两个地方没看懂
    1.docker0 和veth连接,是可以理解为docker0是个交换机,所有连接docker0的网卡可以二层通信?

    2.为什么连接到docker0,开启forward就通了?能讲一下原理吗? 是到达docker0的包会经过postrouting链,然后经过本地路由后,需要走forward链出去,所以需要开forward为accept并且开启forward吗?
    作者回复

    > 1
    对的你可以理解为docker0是一个L2交换机。

    > 2
    ip_forward就是打开Linux类似路由器的功能,允许数据包从一个接口进入,根据路由从另外一个接口出去。这个和你说的iptables里的postrouting/forward链没有关系

    2020-12-28 12:37:32

  • Geek_c2089d

    2021-03-09 17:27:29

    老师有个问题想咨询一下你,我有个FTP的容器,ftp的配置是配置了127.0.0.1地址,而我宿主机是192.168.1.21的ip,我连接ftp服务的时候用宿主机的ip去连接会有问题???我现在有一个问题是被动模式连接上去但LIST命令数据没返回,但是主动模式可以,想问下和上面配置有关系??如果没关系我上面的配置会引起什么问题??
    作者回复

    127.0.0.1 是 localhost IP, 每个namespace里都有一个。如果从宿主机的host network namespace里去访问127.0.0.1只是 host network namespace里的,不会访问到容器 network namespace的127.0.0.1

    2021-03-13 20:54:47

  • 谢哈哈

    2020-12-21 21:06:01

    1,宿主机上配置容器网段的路由
    2,DNAT,在nat表的PREROUTING链做好包伪装到达容器
  • JianXu

    2022-08-14 09:24:42

    以我们设计的system diagnostics 为例子,我们是怎么自动推算出 数据路径是 container veth—> host veth —> docker 0 —> host eth0 呢?从而在这条路径上做消息提取呢?
    作者回复

    我们用bpf trace 主要的内核stack的收发函数,dump出network namespace id和device name, 就可以看出这条路径了。

    2022-08-21 20:26:24

  • kissingers

    2021-06-20 17:24:40

    如果eth0 也加到docker0 bridge,那么这个时候是通过二层转发或者洪泛的方式连通外网。如果eth0不加到docker0的话那么利用的是host 的路由转发了。这样理解对吗?
  • 徐喆

    2021-12-11 12:43:26

    老师,我做实验的时候跟着做发现ping不通外网,后来把veth_host桥接到docker0网络通了,是老师在课程里没写上还是其他原因,求教一下
  • moonberry

    2021-03-01 17:12:24

    老师您好,请问iptables 列出的NAT表是docker默认配置的吗?
    作者回复

    需要自己加一条 “iptables -P FORWARD ACCEPT”, 其它的是默认的配置。

    2021-03-06 21:55:54

  • Geek_ba556d

    2021-01-04 07:24:28

    老师,能帮忙解决一下,我在两台vmwarework虚拟机安装centos7.6,分别创建物理网卡子接口,并关联了macvlan,但是ARP传输一直出问题,绑定静态就可以ping通,不知是什么原因,能帮忙解答一下吗?
    作者回复

    @Geek_ba556d
    不好意思,这个需要看到现场环境才能进一步分析。不过,你说arp出问题,那么可以先在主要接口dump一下arp request 或者 arp reply的包。

    2021-01-06 22:00:27

  • PageNotFound

    2022-05-14 22:47:48

    外部网络访问容器内服务:
    sudo iptables -t nat -A DOCKER ! -i docker0 -p tcp -m tcp --dport [hostPort] -j DNAT --to-destination [containerIP]:[containerPort]
  • 超级芒果冰

    2021-09-11 16:16:21

    老师,veth是怎么配对的,创建之后自动配对吗。如果建了4个veth,配对规则是怎么样的
  • Demon.Lee

    2021-08-04 20:23:56

    请教老师和小伙伴们一个问题,不知道你们是否遇到过:
    一个简单的 k8s 集群(1个 master ,2个 worker) ,master 的 ip 为 10.5.xx.xx,2 个 worker 的 ip 为 192.168.100.xx。

    有一个 pod 暴露了一个 https 端口(比如443),然后 通过 curl https://xxx:443/apis/xxx 访问(调用是会带上token),如果这个 pod 不在 master 节点上,那么在 master 节点上发起请求后一直没反应,直到超时。而在 2 个 worker 节点发起请求,则可以正常返回。
    如果将这个 pod 强制调度到 master 节点上,那么在 master 节点上发起请求,可以正常返回,但在 2 个 worker 节点发起请求,会超时无响应。
    作者回复

    @Demon.Lee
    你描述了k8s 集群节点,不过没有描述pod网络配置方式。在分析这个问题前,你可以把集群的网络拓扑和pod在节点上的网络拓扑分析一遍,然后再分析具体的问题。

    2021-08-10 20:34:39

  • 徐少文

    2021-07-07 10:16:44

    老师的思路我看明白了。我已经自己实现了一个容器沙箱,用net namespace进行了网络的隔离,现在想配置它的网络功能。宿主机已经可以连通外网,我在host上创建了一个网桥,然后在host和沙箱里放置了veth0和veth1。但是还没有设置host上的SNAT和DNAT。现在沙箱和host已经可以ping通,也可以通过tcp通信。但是沙箱内还是无法访问外网,但是不知道具体如何设置SNAT和DNAT,老师能给点指导吗?
    作者回复

    @徐少文
    可以找一些iptables相关的文档看一下。

    2021-08-12 21:15:30

  • 百里英骐

    2021-05-20 11:20:25

    节点外访问容器内ip:
    1. 前提是正常启动容器和宿主机可以通过VETH和docker0网桥互通,两个节点之间互通
    2. 在外部的节点配置iptables(DNAT)规则:
    sudo iptables -t nat -A PREROUTING -d 172.17.0.10(容器的真实ip) -j DNAT --to-destination 172.31.27.61(节点的真实ip)
    3.之后即可从外部机器直接与container内ip交互

    反过来需要,容器节点本地做SNAT,否则数据包只能过去回不来
  • Geek_c2089d

    2021-04-24 10:46:39

    老师,这段时间遇到这样一个问题,想问下遇到这种问题应该怎么找原因:什么日志都看不了

    adding interface vethbad9e82 to bridge docker0 failed: could not find bridge docker0: no such network interface"
    作者回复

    用"ip link show type bridge"命令看一下 docker0 interface是不是存在。

    2021-04-24 21:05:18

  • Roy Liang

    2021-03-30 16:40:35

    用tcpdump抓包排查问题的思路值得参考,同时理解了示意图上的数据链路中每一个节点的作用
    作者回复

    赞!

    2021-04-10 20:42:27

  • Geek_41a96e

    2021-03-03 17:31:15

    [root@tyy-node06 ~]# ln -s /proc/$pid/ns/net /var/run/netns/$pid
    ln: failed to create symbolic link ‘/var/run/netns/24847’: No such file or directory,目录/var/run/netns/不存在要手动创建吗?
    作者回复

    是的,如果/var/run/netns 不存在,事先建一下。 `mkdir -p /var/run/netns`

    2021-03-06 21:16:50

  • 争光 Alan

    2020-12-27 00:29:55

    我的理解
    外部访问容器,一个包在主机上的处理大概是
    经过postrouting链,本地路由,input/forword。。。

    所以如果需要主机访问容器
    方案一
    1.可以在postrouting链增加目的地是docker0的网络接收
    2.经过路由的时候,存在docker0直通路由,会接收处理
    但这样只能是本主机访问,如果是其他主机,还需要在其他主机配置,把到该docker0的包发过来(比如借助overlay等)

    方案二
    做nat,访问主机某端口的流量转给容器的某个端口,则
    1.在postrouting链增加dnat即可

    老师对吗?