Kubernetes & Docker 容器網絡終極之戰
自從 Docker 容器出現,容器的網絡通信一直是眾人關註的焦點,而容器的網絡方案又可以分為兩大部分:
- 單主機的容器間通信;
- 跨主機的容器間通信。
一、單主機 Docker 網絡通信
利用 Net Namespace 可以為 Docker 容器創建隔離的網絡環境,容器具有完全獨立的網絡棧,與宿主機隔離。也可以使 Docker 容器共享主機或者其他容器的網絡命名空間。
我們在使用docker run
創建 Docker 容器時,可以使用--network=
- host 模式,使用
--network=host
指定,不支持多主機; - bridge 模式,使用
--network=bridge
指定,默認設置,不支持多主機; - container 模式,使用
--network=container:NAME_or_ID
指定,即joiner 容器
,不支持多主機; - none 模式,使用
--network=none
指定,不支持多主機。
1.1、host 模式
連接到 host 網絡的容器共享 Docker host 的網絡棧,容器的網絡配置與 host 完全一樣。
我們先查看一下主機的網絡。
[root@datanode03 ~]# ifconfig docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255 ether 02:42:44:8d:48:70 txqueuelen 0 (Ethernet) RX packets 0 bytes 0 (0.0 B) 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 enp1s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.1.203 netmask 255.255.255.0 broadcast 192.168.1.255 inet6 fe80::2e0:70ff:fe92:4779 prefixlen 64 scopeid 0x20<link> ether 00:e0:70:92:47:79 txqueuelen 1000 (Ethernet) RX packets 46093 bytes 66816291 (63.7 MiB) RX errors 0 dropped 1 overruns 0 frame 0 TX packets 24071 bytes 1814769 (1.7 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 0 (Local Loopback) RX packets 170 bytes 107720 (105.1 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 170 bytes 107720 (105.1 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
然後創建 host 網絡的容器,再查看容器的網絡信息。
[root@datanode03 ~]# docker run -it --network=host busybox Unable to find image ‘busybox:latest‘ locally latest: Pulling from library/busybox 90e01955edcd: Pull complete Digest: sha256:2a03a6059f21e150ae84b0973863609494aad70f0a80eaeb64bddd8d92465812 Status: Downloaded newer image for busybox:latest / # ifconfig docker0 Link encap:Ethernet HWaddr 02:42:44:8D:48:70 inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0 UP BROADCAST MULTICAST MTU:1500 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:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) enp1s0 Link encap:Ethernet HWaddr 00:E0:70:92:47:79 inet addr:192.168.1.203 Bcast:192.168.1.255 Mask:255.255.255.0 inet6 addr: fe80::2e0:70ff:fe92:4779/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:45850 errors:0 dropped:1 overruns:0 frame:0 TX packets:23921 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:66794758 (63.7 MiB) TX bytes:1783655 (1.7 MiB) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:170 errors:0 dropped:0 overruns:0 frame:0 TX packets:170 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:107720 (105.1 KiB) TX bytes:107720 (105.1 KiB)
在容器中可以看到 host 的所有網卡,並且連 hostname 也是 host 的,可以直接使用宿主機 IP 地址與外界通信,無需額外進行 NAT 轉換。由於容器通信時,不再需要通過 Linux Bridge 等方式轉發或者數據包的封裝,性能上有很大的優勢。
當然,Host 模式有利也有弊,主要包括以下缺點:
容器沒有隔離、獨立的網絡棧:容器因與宿主機共用網絡棧而爭搶網絡資源,並且容器崩潰也可能導致主機崩潰,這再生產環境中是不允許發生的。
端口資源:Docker host 上已經使用的端口就不能再用了。
1.2 Bridge 模式
Bridge 模式是 Docker 默認的網絡模式,也是開發者最常用的網絡模式。在這種模式下,Docker 為容器創建獨立的網絡棧,保證容器內的進行使用獨立的網絡環境,實現容器之間,容器與宿主機之間的網絡棧隔離。同時,通過宿主機上的 Docker0 網橋,容器可以與宿主機乃至外界進行網絡通信。
從上圖可以看出,容器是可以與宿主機以及外界的其他機器通信的,同一宿主機上,容器之間都是橋接在 Docker0 這個網橋上,Docker0 作為虛擬交換機使容器間互相通信。但是,由於宿主機的 IP 地址與容器 veth pair 的 IP 地址均不在同一個網段,故僅僅依靠 veth pair 和 NameSpace 的技術並不足以使宿主機以外的網絡主動發現容器的存在。Docker 采用了端口綁定的方式(通過 iptables 的 NAT),將宿主機上的端口流量轉發到容器內的端口上,這樣一來,外界就可以與容器中的進程進行通信。
1.3 Container 模式
Container 模式是一種特殊的網絡模式。該模式下的容器使用其他容器的網絡命名空間,網絡隔離性會處於 Bridge 模式與 Host 模式之間。也就是說,當容器與其他容器共享網絡命名空間時,這兩個容器間不存在網絡隔離,但他們與宿主機機器其他容器又存在網絡隔離。
Container 模式的容器可以通過 localhost 來與同一網絡命名空間下的其他容器通信,傳輸效率高。這種模式節約了一定數量的網絡資源,但並沒有改變容器與外界的通信方式。在 Kubernetes 體系架構下引入 Pod 概念,Kubernetes 為 Pod 創建一個基礎設施容器,同一 Pod 下的其他容器都以 Container 模式共享這個基礎設施容器的網絡命名空間,相互之間以 localhost 訪問,構成一個統一的整體。
1.4、None 模式
與前幾種不同,None 模式的 Docker 容器擁有自己的 Network Namespace,但並不為 Docker 容器進行網絡配置。也就是說,該 Docker 容器沒有網卡、IP、路由等信息。需要用戶為 Docker容器添加網卡、配置 IP 等。
Kubernetes & Docker 容器網絡終極之戰