前言
- 最近在搭建 k8s 过程中,网络方案使用了 flannel 网络,遇到了 master 节点无法 ping 通 pod ip 的问题。为了解这个问题,先系统性学习一下容器网络相关的知识,会分成两个阶段,第一阶段是单机容器网络,第二阶段是跨主机容器网络。本篇主要先介绍单机容器网络。
实验环境
- virtualbox 搭建4台 VM(ubuntu-18.04.5-live-server-amd64.iso),每台 VM 配置双网卡
- 网卡1
NAT桥接(使用 nat 会出现 k8s master 无法 ping 通 pod 等问题),用于连接外网,混杂模式选全部允许 - 网卡2 Host-Only,用于提供宿主机到虚拟机的连接以及虚拟机直接的访问,混杂模式选全部允许。参考virtualbox 虚拟机组网一顿操作后配置结果如下
- 网卡1
ip | hostname |
---|---|
192.168.99.13 | linyouquan-master |
192.168.99.14 | linyouquan-worker1 |
192.168.99.15 | linyouquan-worker2 |
192.168.99.16 | linyouquan-test |
docker 网络
原生网络
docker 安装时会自动在 host 上创建三个网络
linyouquan@linyouquan-master:~$ docker network ls
NETWORK ID NAME DRIVER SCOPE
98835cd9ea52 bridge bridge local
9be4ce0db265 host host local
dee007fac16c none null local
none 网络
linyouquan@linyouquan-master:~$ docker run -it --network=none busybox
/ # ifconfig
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ # ping www.baidu.com
ping: bad address 'www.baidu.com'
/ # ping 192.168.99.13
PING 192.168.99.13 (192.168.99.13): 56 data bytes
ping: sendto: Network is unreachable
host 网络
连接到 host 网络的容器共享 docker host 的网络栈,容器的网络配置和 host 完全一样
docker run -it --network=host busybox
bridge 网络
Docker 安装时会创建一个命名为如果不指定--network
,创建的容器会默认挂到 docker0 上。
linyouquan@linyouquan-master:~$ docker run -it busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:8 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:696 (696.0 B) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ #
linyouquan@linyouquan-master:~$ brctl show
bridge name bridge id STP enabled interfaces
cni0 8000.2adc05803c00 no veth757262fe
vethc8bd6ed9
docker0 8000.0242391693b6 no veth146cb3d
ip address
docker network inspect bridge
自定义网络
docker 提供了三种 user-defined 网络(bridge/overlay/macvlan),本篇文章只先讲 bridg 网络。
docker network create --driver bridge --subnet 172.22.16.0/24 --gateway 172.22.16.1 my_net
docker run -it --network=my_net --ip 172.22.16.18 busybox /bin/sh
docker run -it --network=my_net --ip 172.22.16.19 busybox /bin/sh
同一网络中的容器是可以通信的,不同网络中的容器不能相互通信
如何让第一个 busybox 容器能访问第二第三个 busybox 呢?答案是给第一个 busybox 增加 my_net 网卡
docker network connect my_net dc5464853a0f
容器间通信
ip 通信
- 直接 ping ip
docker dns server
从 Docker 1.10 版本开始,docker daemon 实现了一个内嵌的 DNS server,使容器可以直接通过“容器名”通信。方法很简单,只要在启动时用 --name 为容器命名就可以了。使用 docker DNS 有个限制:只能在 user-defined 网络中使用。也就是说,默认的 bridge 网络是无法使用 DNS 的。
joined 容器
joined 容器非常特别,它可以使两个或多个容器共享一个网络栈,共享网卡和配置信息,joined 容器之间可以通过 127.0.0.1 直接通信。
docker run -d -it --name=web1 httpd
docker run -it --network=container:web1 busybox
/ # wget localhost
Connecting to localhost (127.0.0.1:80)
saving to 'index.html'
index.html 100% |**************************************************************************************************************************************************************************************************************| 45 0:00:00 ETA
'index.html' saved
/ # cat index.html
<html><body><h1>It works!</h1></body></html>
/ #
joined 容器非常适合以下场景:
- 不同容器中的程序希望通过 loopback 高效快速地通信,比如 web server 与 app server。
- 希望监控其他容器的网络流量,比如运行在独立容器中的网络监控程序。
容器与外部世界连接
容器访问外部世界
容器默认就能访问外网。在上面的例子中,busybox 位于 docker0 这个私有 bridge 网络中(172.17.0.0/16),当 busybox 从容器向外 ping 时,docker host 上的网桥 docker0 收到来自 172.17.0.0/16 网段的外出包,把它交给 MASQUERADE 处理。而 MASQUERADE 的处理方式是将包的源地址替换成 host 的地址发送出去,即做了一次网络地址转换(NAT)。
外部世界访问容器
docker 可将容器对外提供服务的端口映射到 host 的某个端口,外网通过该端口访问容器。每一个映射的端口,host 都会启动一个 docker-proxy 进程来处理访问容器的流量。
docker run -d -p 80 httpd
linyouquan@linyouquan-master:~$ docker ps | grep -v k8s
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5f285be7fb67 httpd "httpd-foreground" 55 minutes ago Up 55 minutes 0.0.0.0:49153->80/tcp, :::49153->80/tcp upbeat_lewin
linyouquan@linyouquan-master:~$ ps aux | grep -i proxy
root 5271 0.0 0.1 1152912 3788 ? Sl 18:18 0:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 49153 -container-ip 172.17.0.2 -container-port 80
root 5277 0.0 0.1 1152912 4016 ? Sl 18:18 0:00 /usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 49153 -container-ip 172.17.0.2 -container-port 80
linyouq+ 14629 0.0 0.0 13144 1048 pts/0 S+ 18:43 0:00 grep --color=auto -i proxy