1. 程式人生 > >Kubernetes & Docker 容器網絡終極之戰

Kubernetes & Docker 容器網絡終極之戰

無需 轉換 網絡 oot let 1.7 collision ima pac

與 Docker 默認的網絡模型不同,Kubernetes 形成了一套自己的網絡模型,該網絡模型更加適應傳統的網絡模式,應用能夠平滑的從非容器環境遷移到 Kubernetes 環境中。

自從 Docker 容器出現,容器的網絡通信一直是眾人關註的焦點,而容器的網絡方案又可以分為兩大部分:

  • 單主機的容器間通信;
  • 跨主機的容器間通信。

一、單主機 Docker 網絡通信

利用 Net Namespace 可以為 Docker 容器創建隔離的網絡環境,容器具有完全獨立的網絡棧,與宿主機隔離。也可以使 Docker 容器共享主機或者其他容器的網絡命名空間。

我們在使用docker run創建 Docker 容器時,可以使用--network=

選項指定容器的網絡模式,Docker 有以下 4 種網絡模式:

  • 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 容器網絡終極之戰