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

Kubernetes & Docker 容器網路終極之戰

與 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 完全一樣。

我們先檢視一下主機的網路。

[[email protected] ~]# 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 網路的容器,再檢視容器的網路資訊。

[[email protected] ~]# 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 等方式轉發或者資料包的封裝,效能上有很大的優勢。

Kubernetes & Docker 容器網路終極之戰

當然,Host 模式有利也有弊,主要包括以下缺點:

容器沒有隔離、獨立的網路棧:容器因與宿主機共用網路棧而爭搶網路資源,並且容器崩潰也可能導致主機崩潰,這再生產環境中是不允許發生的。
埠資源:Docker host 上已經使用的埠就不能再用了。

1.2 Bridge 模式

Bridge 模式是 Docker 預設的網路模式,也是開發者最常用的網路模式。在這種模式下,Docker 為容器建立獨立的網路棧,保證容器內的進行使用獨立的網路環境,實現容器之間,容器與宿主機之間的網路棧隔離。同時,通過宿主機上的 Docker0 網橋,容器可以與宿主機乃至外界進行網路通訊。

Kubernetes & Docker 容器網路終極之戰

從上圖可以看出,容器是可以與宿主機以及外界的其他機器通訊的,同一宿主機上,容器之間都是橋接在 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 訪問,構成一個統一的整體。

Kubernetes & Docker 容器網路終極之戰

1.4、None 模式

與前幾種不同,None 模式的 Docker 容器擁有自己的 Network Namespace,但並不為 Docker 容器進行網路配置。也就是說,該 Docker 容器沒有網絡卡、IP、路由等資訊。需要使用者為 Docker容器新增網絡卡、配置 IP 等。

Kubernetes & Docker 容器網路終極之戰