目录
1 容器访问外网
1.1 容器访问外网的原理
在rhel7中,docker访问外网是通过iptables添加地址伪装策略来完成容器网文外网
在rhel7之后的版本中通过nftables添加地址伪装来访问外网
1.2 容器与外网通讯原理解剖
在高版本中可以开启内核中的iptables
[root@rockynode-1 ~]# grubby --update-kernel ALL --args iptables=true
在外网访问内网中 docker-proxy 和 dnat 在容器建立端口映射后都会开启,无论使用哪一个都可以与内网进行通讯。那个传输速录高走那个
[root@node-3 ~]# docker run -d --name webserver -p 80:80 nginx
256689982b91fe7b8dbb9910346653f887efb5fe9e52c656c95513c7f2e276f2
[root@node-3 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
256689982b91 nginx "/docker-entrypoint.…" 14 seconds ago Up 13 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp webserver
# 查看是否走地址伪装,与DNAT
[root@node-3 ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DOCKER 0 -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
DOCKER 0 -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE 0 -- 172.17.0.0/16 0.0.0.0/0
MASQUERADE 6 -- 172.17.0.2 172.17.0.2 tcp dpt:80
Chain DOCKER (2 references)
target prot opt source destination
RETURN 0 -- 0.0.0.0/0 0.0.0.0/0
DNAT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:172.17.0.2:80
# 查看是否走docker-proxy
[root@node-3 ~]# ps ax | grep docker
1297 ? Ssl 0:00 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
2759 ? Sl 0:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 80 -container-ip 172.17.0.2 -container-port 80
2765 ? Sl 0:00 /usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 80 -container-ip 172.17.0.2 -container-port 80
2 docker跨主机网络
2.1 实现docker跨主机通讯方式
在生产环境中,我们的容器不可能都在同一个系统中,所以需要容器具备跨主机通信的能力
跨主机网络解决方案
- docker原生的overlay和macvlan
- 第三方的flannel、weave、calico
众多网络方案是如何与docker集成在一起的
- libnetwork docker容器网络库
- CNM (Container Network Model)这个模型对容器网络进行了抽象
CNM (Container Network Model)
CNM分三类组件
Sandbox:容器网络栈,包含容器接口、dns、路由表。(namespace)
Endpoint:作用是将sandbox接入network (veth pair)
Network:包含一组endpoint,同一 network 的endpoint可以通信
2.2 macvlan网络方式实现跨主机通信
2.2.1 macvlan网络方式
- Linux kernel提供的一种网卡虚拟化技术。
- 无需Linux bridge,直接使用物理接口,性能极好
- 容器的接口直接与主机网卡连接,无需NAT或端口映射。macvlan会独占主机网卡,但可以使用vlan子接口实现多macvlan网络
- vlan可以将物理二层网络划分为4094个逻辑网络,彼此隔离,vlan id取值为1~4094
2.2.2 macvlan网络间的隔离和连通
- macvlan网络在二层上是隔离的,所以不同macvlan网络的容器是不能通信的
- 可以在三层上通过网关将macvlan网络连通起来
- docker本身不做任何限制,像传统vlan网络那样管理即可
2.2.3 实现方法如下:
1.在两台docker主机上各添加一块网卡,打开网卡混杂模式:
#################################### node-3
[root@node-3 ~]# ifconfig eth1
eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
ether 00:0c:29:32:ef:fb txqueuelen 1000 (Ethernet)
RX packets 29 bytes 3539 (3.4 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@node-3 ~]# ip link set eth1 promisc on
[root@node-3 ~]# ip link set up eth1
[root@node-3 ~]# ifconfig eth1
eth1: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST> mtu 1500
ether 00:0c:29:32:ef:fb txqueuelen 1000 (Ethernet)
RX packets 33 bytes 4048 (3.9 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
################################### node-1
[root@rockynode-1 ~]# ifconfig eth1
eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
ether 00:0c:29:76:3c:1a txqueuelen 1000 (Ethernet)
RX packets 34 bytes 4321 (4.2 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@rockynode-1 ~]# ip link set eth1 promisc on
[root@rockynode-1 ~]# ip lin set up eth1
[root@rockynode-1 ~]# ifconfig eth1
eth1: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST> mtu 1500
ether 00:0c:29:76:3c:1a txqueuelen 1000 (Ethernet)
RX packets 34 bytes 4321 (4.2 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth1这款网卡在vmware中要设定为仅主机模式
构建相同network网络环境
[root@rockynode-1 ~]# docker network create \
-d macvlan \
--subnet 1.1.1.0/24 \
--gateway 1.1.1.1 \
-o parent=eth1 macvlan1
7fb93ea03a7017057ecdfeb630488bae93851e804f7a8f049421d9d77334281e
[root@rockynode-1 ~]# docker run -it --name busybox \
--network macvlan1 --ip 1.1.1.100 --rm busybox
[root@node-3 ~]# docker network create \
-d macvlan \
--subnet 1.1.1.0/24 \
--gateway 1.1.1.1 \
-o parent=eth1 macvlan1
5b260b2513194a898badb59b1b77c15e7ee51f65f6690e93670cd83e4a639cb4
[root@node-3 ~]# docker run -it --name busybox \
--network macvlan1 --ip 1.1.1.200 --rm busybox
不同主机 测试容器网络连通性
/ # ping 1.1.1.200
PING 1.1.1.200 (1.1.1.200): 56 data bytes
64 bytes from 1.1.1.200: seq=0 ttl=64 time=0.743 ms
64 bytes from 1.1.1.200: seq=1 ttl=64 time=0.325 ms
^C
--- 1.1.1.200 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.325/0.534/0.743 ms
/ # ping 1.1.1.100
PING 1.1.1.100 (1.1.1.100): 56 data bytes
64 bytes from 1.1.1.100: seq=0 ttl=64 time=0.660 ms
64 bytes from 1.1.1.100: seq=1 ttl=64 time=1.021 ms
^C
--- 1.1.1.100 ping statistics ---