不用CNI插件,打通容器网络
传统模式下单节点容器网络
在不同ns中创建网卡并对接公共网桥
1 # centos8 安装brctl命令 2 rpm -ivh http://mirror.centos.org/centos/7/os/x86_64/Packages/bridge-utils-1.5-9.el7.x86_64.rpm 3 4 # 创建ns 5 ip netns add ns1 6 ip netns add ns2 7 8 # 创建br3 9 brctl addbr br3 10 ip addr add 170.19.0.3/24 dev br3 11 ip link set dev br3 up 12 13 # 创建veth00和veth01这个veth对并设置 14 ip link add veth00 type veth peer name veth01 15 brctl addif br3 veth01 16 ip link set veth00 netns ns1 17 ip netns exec ns1 ip addr add 170.19.0.1/24 dev veth00 18 ip netns exec ns1 ip link set dev veth00 up 19 ip link set dev veth01 up 20 21 # 创建veth10和veth11这个veth对并设置 22 ip link add veth10 type veth peer name veth11 23 brctl addif br3 veth11 24 ip link set veth10 netns ns2 25 ip netns exec ns2 ip addr add 170.19.0.2/24 dev veth10 26 ip netns exec ns2 ip link set dev veth10 up 27 ip link set dev veth11 up 28 29 # ns1中的veth00和ns2中的veth10互通 30 ip netns exec ns1 ping 170.19.0.2
1 # 查看ns1内自动添加的路由 2 ip netns exec ns1 route -n
1 # 查看虚拟机上自动添加的路由 2 route -n
解决问题1:ns内无法ping通veth自己(启动回环设备)
1 ip netns exec ns1 ip a
1 ip netns exec ns1 ping 170.19.0.1
1 # 启动回环设备 2 ip netns exec ns1 ip link set lo up 3 ip netns exec ns1 ping 170.19.0.1
解决问题2:ns内无法ping通宿主机网卡IP(ns内添加默认路由)
1 ip netns exec ns1 ping 10.0.4.13
1 # 在ns1内添加默认路由(从veth到网卡) 2 ip netns exec ns1 route add default gw 170.19.0.3 dev veth00 3 ip netns exec ns1 ping 10.0.4.13
解决问题3:ns内无法ping通外部(SNAT)
1 # 开启转发 2 sysctl -w net.ipv4.conf.all.forwarding=1 3 # 添加SNAT规则 4 iptables -t nat -A POSTROUTING -s 170.19.0.0/24 -o eth0 -j MASQUERADE
1 ip netns exec ns1 ping 180.76.76.76
请求路径
从容器内veth00出发 -> 根据容器内路由到达docker0网桥 -> 根据宿主机路由到达宿主机的eth0网卡 -> iptables的SNAT转换 -> 到达外部主机
响应路径
响应来到宿主机的eth0网卡 -> 源地址由Linux的NAT表转换成原容器IP -> 开启FORWARD转发后,根据容器网段路由到达docker0 -> 通过veth进入容器
解决问题4:外部无法访问容器端口(DNAT)
1 # 启动nginx容器 2 docker pull nginx 3 docker run -d --rm --name test nginx:latest 4 5 # 进入Nginx容器,安装ping和ip以及netstat命令 6 docker exec -it test bash 7 apt-get update 8 apt-get install -y inetutils-ping 9 apt-get install -y iproute2 10 apt-get install -y net-tools 11 12 # 查看容器IP 13 ip a s eth0
1 # 查看端口 2 netstat -tunlp
1 # 宿主机上直接访问该容器IP+80端口 2 curl 172.17.0.2:80
1 # 外部无法访问到该端口,因为IP ping不通 2 curl 172.17.0.2:80
1 ping 172.17.0.2
1 # 在Nginx容器所在的宿主机上,开启转发并添加DNAT规则 2 sysctl -w net.ipv4.ip_forward=1 3 iptables -t nat -A PREROUTING -p tcp -m tcp --dport 90 -j DNAT --to-destination 172.17.0.2:80 4 # 外部虚拟机可以curl通当前虚拟机的90端口,从而访问到Nginx服务 5 curl 192.168.0.103:90
请求路径
请求的主机向容器所在的宿主机发送请求 -> 宿主机上iptables的DNAT转换 -> 开启FORWARD转发后,根据容器网段路由到达docker0 -> 通过veth进入容器
响应路径
响应来到宿主机的eth0网卡 -> 源地址和端口由Linux的NAT表转换成宿主机网卡地址和端口 -> 通过宿主机eth0网卡把响应返回给请求的主机
使用ovs来打通容器网络
同节点容器互通
docker run -itd --name c1 --net=none busybox:1.36 sh
docker run -itd --name c2 --net=none busybox:1.36 sh
ovs-vsctl add-br br1
# 使用ovs-docker给容器添加网卡,并挂到网桥上
ovs-docker add-port br1 eth0 c1 --ipaddress=100.1.1.6/24
ovs-docker add-port br1 eth0 c2 --ipaddress=100.1.1.7/24
查看网桥
容器同节点互通
vxlan跨节点通信
# host1
docker run -itd --name c1 --net=none busybox:1.36 sh
ovs-vsctl add-br br1
ovs-docker add-port br1 eth0 c1 --ipaddress=100.1.1.1/24
ovs-vsctl add-port br1 vxlan1 -- set interface vxlan1 type=vxlan options:remote_ip=192.168.1.10 options:key=flow
# host2
docker run -itd --name c1 --net=none busybox:1.36 sh
ovs-vsctl add-br br1
ovs-docker add-port br1 eth0 c1 --ipaddress=100.1.1.2/24
ovs-vsctl add-port br1 vxlan1 -- set interface vxlan1 type=vxlan options:remote_ip=192.168.1.9 options:key=flow
docker run -itd --name c2 --net=none busybox:1.36 sh
ovs-docker add-port br1 eth0 c2 --ipaddress=100.1.2.1/24
容器同网段跨节点互通
host1 c1增加路由
host2 c2增加路由
容器跨网段跨节点互通
参考资料
单节点容器网络参考:《自己动手写Docker》
ovs参考:ovs实践--openFlow跨网段组网