k8s网络详解(一)

浅谈容器网络

直接使用宿主机网络

启动一个 nginx, 直接使用宿主机网络

1
[root@k8s01 service]#  docker run -d --net=host --name nginx-host nginx

这个容器启动后,直接监听的就是宿主机的 80 端口。像这样直接使用宿主机网络栈的方式,虽然可以为容器提供良好的网络性能,但也会不可避免地引入共享网络资源的问题,比如端口冲突。所以,在大多数情况下,我们都希望容器进程能使用自己 Network Namespace 里的网络栈,即:拥有属于自己的 IP 地址和 Port

可以看到实际使用的宿主机 ip+port
nginx-host

使用 docker0 网桥

宿主机

1
2
3
4
5
6
7
8
9
10
[root@k8s01 service]# ifconfig
## 省略 docker0 为 172.17.0.1
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:87ff:fe56:a7bb prefixlen 64 scopeid 0x20<link>
ether 02:42:87:56:a7:bb txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 5 bytes 446 (446.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

启动两个 busybox 容器

1
2
docker run -d -it  --name busybox1 busybox
docker run -d -it --name busybox2 busybox

查看 ip:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
[root@k8s01 service]# docker exec -it busybox1 /bin/sh  # 节选
/ # ifconfig # 172.17.0.2
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:03
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:656 (656.0 B) TX bytes:0 (0.0 B)


[root@k8s01 service]# docker exec -it busybox2 /bin/sh
/ # ifconfig # 172.17.0.3
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:04
inet addr:172.17.0.3 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:656 (656.0 B) TX bytes:0 (0.0 B)
/ # route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.17.0.1 0.0.0.0 UG 0 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0

/ # ping 172.17.0.2 # 可以 ping 通, busybox2内eth0 → vethdf30199 → docker0 → veth1f4b2a8 → busybox1内eth0

/ # ping 192.168.43.101 # 宿主机可以 ping 通, busybox2内eth0 → vethdf30199 → docker0 → 宿主机 eth0

/ # ping 192.168.43.102 # 另一台主机 可以 ping 通 busybox2内eth0 → vethdf30199 → docker0 → 宿主机 eth0 → 另一台宿主机 eth0

图的 node_ip 不重要,盗的图,意思差不多
veth

docker里 这个 eth0 网卡,是一个 Veth Pair,它的一端在这个 busybox 容器的 Network Namespace 里,而另一端则位于宿主机上(Host Namespace)(veth1f4b2a8),并且被“插”在了宿主机的 docker0 网桥上,另一个 busybox2 也是“插”在了宿主机的 docker0 网桥上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
veth1f4b2a8: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
inet6 fe80::a802:c6ff:fe6c:13c5 prefixlen 64 scopeid 0x20<link>
ether aa:02:c6:6c:13:c5 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 8 bytes 656 (656.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

vethdf30199: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::d438:c7ff:fe9d:3cf9 prefixlen 64 scopeid 0x20<link>
ether d6:38:c7:9d:3c:f9 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 13 bytes 1102 (1.0 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

[root@hdp03 ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242a434516d no veth1f4b2a8
vethdf30199

veth2

宿主机 ping 容器也能 ping 通

1
2
3
4
[root@k8s01 service]# ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.099 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.079 ms

veth3

在默认情况下,被限制在 Network Namespace 里的容器进程,实际上是通过 Veth Pair 设备 + 宿主机网桥的方式,实现了跟同其他容器的数据交换。

宿主机上,访问该宿主机上的容器的 IP 地址时,这个请求的数据包,也是先根据路由规则到达 docker0 网桥,然后被转发到对应的 Veth Pair 设备,最后出现在容器里

在 192.168.43.102 上启动一个 busybox3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@k8s02 ~]# docker run -d -it  --name busybox3 busybox
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
d60bca25ef07: Pull complete
Digest: sha256:49dae530fd5fee674a6b0d3da89a380fc93746095e7eca0f1b70188a95fd5d71
Status: Downloaded newer image for busybox:latest
f3864007cb0742ee8641ca19f8320be55d0f35b7a5714b47cff4a554f5f819fb

[root@k8s02 ~]# docker exec -it busybox3 /bin/sh
/ # ifconfig # 172.17.0.2
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:13 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:1102 (1.0 KiB) TX bytes:0 (0.0 B)

在 Docker 的默认配置下,不同宿主机上的容器通过 IP 地址进行互相访问是根本做不到的。

192.168.43.101 上的容器 无法 ping 通 192.168.43.102 上的容器。

Overlay Network

flannel Vxlan, Calico BGP, Calico Vxlan

通过软件的方式,创建一个整个集群“公用”的网桥,然后把集群里的所有容器都连接到这个网桥上

需要在已有的宿主机网络上,再通过软件构建一个覆盖在已有宿主机网络之上的、可以把所有容器连通在一起的虚拟网络。所以,这种技术就被称为:Overlay Network(覆盖网络)。

就是将 pod 地址信封装在宿主机地址信息以内,实现跨主机且跨 node 子网的通信报文。性能较差

OverlayNetwork

直接路由

flannel Host-gw, flannel Vxlan directrouting, Calico Directrouting

基于主机路由,实现报文从源主机到目的主机的直接转发,不需要进行报文的叠加封装。性能好

underlay

为 pod 启用单独的虚拟机网络,直接使用宿主机物理网络。pod 甚至可以在 k8s 环境之外的节点直接访问。相当于把 pod 当桥接模式的虚拟机使用(pod 和 宿主机在同一子网)。比较方便 k8s环境之外访问 k8s 环境之内的 pod 中的服务。性能最好