ping -c 2 172.18.0.20PING 172.18.0.20 (172.18.0.20) 56(84) bytes of data.From 213.51.1.123 icmp_seq=1 Destination Net UnreachableFrom 213.51.1.123 icmp_seq=2 Destination Net Unreachable--- 172.18.0.20 ping statistics ---2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 3ms为了在根和容器命名空间之间建立连接,需要将IP地址分配给网桥网络接口:
sudo ip addr add 172.18.0.1/16 dev br0
将IP地址分配给网桥接口后,便在主机路由表上获得了一条路由:
ip route172.18.0.0/16 dev br0 proto kernel scope link src 172.18.0.1ping -c 2 172.18.0.10PING 172.18.0.10 (172.18.0.10) 56(84) bytes of data.64 bytes from 172.18.0.10: icmp_seq=1 ttl=64 time=0.036 ms64 bytes from 172.18.0.10: icmp_seq=2 ttl=64 time=0.049 ms--- 172.18.0.10 ping statistics ---2 packets transmitted, 2 received, 0% packet loss, time 11msrtt min/avg/max/mdev = 0.036/0.042/0.049/0.009 msping -c 2 172.18.0.20PING 172.18.0.20 (172.18.0.20) 56(84) bytes of data.64 bytes from 172.18.0.20: icmp_seq=1 ttl=64 time=0.059 ms64 bytes from 172.18.0.20: icmp_seq=2 ttl=64 time=0.056 ms--- 172.18.0.20 ping statistics ---2 packets transmitted, 2 received, 0% packet loss, time 4msrtt min/avg/max/mdev = 0.056/0.057/0.059/0.007 ms容器也具有ping桥接接口的功能,但是仍然无法与主机的接口eth0连接,需要为容器添加默认路由:
sudo nsenter --net=/var/run/netns/netns0ip route add default via 172.18.0.1ping -c 2 10.0.2.15PING 10.0.2.15 (10.0.2.15) 56(84) bytes of data.64 bytes from 10.0.2.15: icmp_seq=1 ttl=64 time=0.036 ms64 bytes from 10.0.2.15: icmp_seq=2 ttl=64 time=0.053 ms--- 10.0.2.15 ping statistics ---2 packets transmitted, 2 received, 0% packet loss, time 14msrtt min/avg/max/mdev = 0.036/0.044/0.053/0.010 ms这配置更改基本上将主机变成了路由器,并且网桥接口成为了容器的默认网关,拓扑图示:

文章插图
容器现在与根命名空间相连,接着我们配置让他们可以对外链接 。默认情况下,在Linux中禁用数据包转发(即路由器功能),我们需要打开它:
sudo bash -c 'echo 1 > /proc/sys/net/ipv4/ip_forward'然后,检查连接性:sudo nsenter --net=/var/run/netns/netns0ping 8.8.8.8好吧,有问题,仍然不通 。由于容器的IP地址是私有的,容器可以数据包发送到外界,但是目标服务器将无法将数据包发送回容器 。为了解决此问题,需要进行网络地址转换(NAT) 。在进入外部网络之前,由容器发起的数据包将其源IP地址替换为主机的外部接口地址 。主机还将跟踪所有现有的映射,并在到达主机时将还原IP地址,然后再将数据包转发回容器 。听起来很复杂,但是做起来不难,可以使用iptables进行转化,只需要一个命令即可实现:sudo iptables -t nat -A POSTROUTING -s 172.18.0.0/16 ! -o br0 -j MASQUERADE该命令非常简单 。在nat表的POSTROUTING链中添加了一条新规则,要求伪装源自172.18.0.0/16网络的所有数据包,但不伪装网桥接口 。再,检查连接性:
sudo nsenter --net=/var/run/netns/netns0ping -c 2 8.8.8.8PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.64 bytes from 8.8.8.8: icmp_seq=1 ttl=61 time=43.2 ms64 bytes from 8.8.8.8: icmp_seq=2 ttl=61 time=36.8 ms--- 8.8.8.8 ping statistics ---2 packets transmitted, 2 received, 0% packet loss, time 2msrtt min/avg/max/mdev = 36.815/40.008/43.202/3.199 ms注意,默认情况会遵循,允许采取策略,请不要实际生产环境中使用,这非常危险 。Docker默认情况下限制所有内容,然后仅对已知路径启用路由 。配置对外访问(端口发布)将容器端口发布到主机的某些(或全部)接口是一种已知的做法 。但是端口发布的真正含义是什么?
假设有一个在容器中运行的服务器:
sudo nsenter --net=/var/run/netns/netns0Python3 -m http.server --bind 172.18.0.10 5000现在用curl尝试从主机向该服务器进程发送HTTP请求:curl 172.18.0.10:5000<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">但是,要从外部访问该服务器,要怎么访问呢?现在对外唯一IP地址是主机的外部接口地址eth0:curl 10.0.2.15:5000curl: (7) Failed to connect to 10.0.2.15 port 5000: Connection refused因此,需要找到一种方法,将到达主机eth0接口上端口5000的所有数据包转发到172.18.0.10:5000目的地 。换句话说,需要在主机的接口上发布容器的端口5000 eth0 。这也可以使用iptables 。sudo iptables -t nat -A PREROUTING -d 10.0.2.15 -p tcp -m tcp --dport 5000 -j DNAT --to-destination 172.18.0.10:5000sudo iptables -t nat -A OUTPUT -d 10.0.2.15 -p tcp -m tcp --dport 5000 -j DNAT --to-destination 172.18.0.10:5000
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- EFK 日志系统收集K8s日志 之 容器标准输出日志
- 使用Python管理网络设备
- 借助工具优化Dockerfile分层
- 网络实用技巧:保护在线账户 谨慎共享信息
- 七类网线相较六类网线有什么区别,凭什么驾驭万兆网络?
- Docker命令大全
- docker下拉取tomcat镜像以及配置,亲测可用
- 无线网络每天不定时出现网速卡顿或无连接,如何处理?
- pc是什么意思网络用语?pc是什么意思材料_2
- 云计算核心技术Docker教程:docker-compose控制服务启动和关闭顺序
