天天看點

Docker的none網絡模式下建立一個點到點的連接配接(及4種docker網絡模式)

預設情況下,Docker 會将所有容器連接配接到由  docker0  提供的虛拟子網中。

使用者有時候需要兩個容器之間可以直連通信,而不用通過主機網橋進行橋接。

解決辦法很簡單:建立一對  peer  接口,分别放到兩個容器中,配置成點到點鍊路類型即可。

首先啟動 2 個容器:

[root@jeff ~]# docker run -i -d -t --name=centos1  --net=none centos /bin/bash

e2191877bb274031f6d966e81f7927271a438b5d446549797d145a691290f957

[root@jeff ~]# docker run -i -d -t --name=centos2  --net=none centos /bin/bash

90c1314f44e33a42a74a13e8c12f9d221f8bd23c7439150e523fd03caa6dc54c

找到程序号,然後建立網絡名字空間的跟蹤檔案。

[root@jeff ~]# docker inspect -f '{{.State.Pid}}' 90c1

15171

[root@jeff ~]# docker inspect -f '{{.State.Pid}}' e219

14813

[root@jeff ~]# mkdir -p /var/run/netns

[root@jeff ~]# ln -s /proc/15171/ns/net /var/run/netns/15171

[root@jeff ~]# ln -s /proc/14813/ns/net /var/run/netns/14813

建立一對 peer 接口,然後配置路由

[root@jeff ~]# ip link add A type veth peer name B

[root@jeff ~]# ip link set A netns 15171

[root@jeff ~]# ip netns exec 15171 ip addr add 10.1.1.1/32 dev A

[root@jeff ~]# ip netns exec 15171 ip link set A up

[root@jeff ~]# ip netns exec 15171 ip route add 10.1.1.2/32 dev A

[root@jeff ~]# ip link set B netns 14813

[root@jeff ~]# ip netns exec 14813 ip addr add 10.1.1.2/32 dev B

[root@jeff ~]# ip netns exec 14813 ip link set B up

[root@jeff ~]# ip netns exec 14813 ip route add 10.1.1.1/32 dev B

現在這 2 個容器就可以互相 ping 通,并成功建立連接配接。點到點鍊路不需要子網和子網路遮罩。

[root@jeff ~]# docker exec -it e219 bash

[root@e2191877bb27 /]# ping 10.1.1.1

PING 10.1.1.1 (10.1.1.1) 56(84) bytes of data.

64 bytes from 10.1.1.1: icmp_seq=1 ttl=64 time=0.125 ms

[root@e2191877bb27 /]# ping 10.1.1.2

PING 10.1.1.2 (10.1.1.2) 56(84) bytes of data.

64 bytes from 10.1.1.2: icmp_seq=1 ttl=64 time=0.043 ms

此外,也可以不指定  --net=none  來建立點到點鍊路。這樣容器還可以通過原先的網絡來通信。

利用類似的辦法,可以建立一個隻跟主機通信的容器。但是一般情況下,更推薦使用  --icc=false  來關閉容器之間的通信。

4種docker網絡模式

我們在使用docker run建立Docker容器時,可以用--net選項指定容器的網絡模式,Docker有以下4種網絡模式:

· host模式,使用--net=host指定。

· container模式,使用--net=container:NAME_or_ID指定。

· none模式,使用--net=none指定。

· bridge模式,使用--net=bridge指定,預設設定。

下面分别介紹一下Docker的各個網絡模式。

1 host模式

衆所周知,Docker使用了Linux的Namespaces技術來進行資源隔離,如PID Namespace隔離程序,Mount Namespace隔離檔案系統,Network Namespace隔離網絡等。一個Network Namespace提供了一份獨立的網絡環境,包括網卡、路由、Iptable規則等都與其他的Network Namespace隔離。一個Docker容器一般會配置設定一個獨立的Network Namespace。但如果啟動容器的時候使用host模式,那麼這個容器将不會獲得一個獨立的Network Namespace,而是和主控端共用一個Network Namespace。容器将不會虛拟出自己的網卡,配置自己的IP等,而是使用主控端的IP和端口。

例如,我們在10.10.101.105/24的機器上用host模式啟動一個含有web應用的Docker容器,監聽tcp80端口。當我們在容器中執行任何類似ifconfig指令檢視網絡環境時,看到的都是主控端上的資訊。而外界通路容器中的應用,則直接使用10.10.101.105:80即可,不用任何NAT轉換,就如直接跑在主控端中一樣。但是,容器的其他方面,如檔案系統、程序清單等還是和主控端隔離的。

2 container模式

在了解了host模式後,這個模式也就好了解了。這個模式指定新建立的容器和已經存在的一個容器共享一個Network Namespace,而不是和主控端共享。新建立的容器不會建立自己的網卡,配置自己的IP,而是和一個指定的容器共享IP、端口範圍等。同樣,兩個容器除了網絡方面,其他的如檔案系統、程序清單等還是隔離的。兩個容器的程序可以通過lo網卡裝置通信。

3 none模式

這個模式和前兩個不同。在這種模式下,Docker容器擁有自己的Network Namespace,但是,并不為Docker容器進行任何網絡配置。也就是說,這個Docker容器沒有網卡、IP、路由等資訊。需要我們自己為Docker容器添加網卡、配置IP等。

4 bridge模式

bridge模式是Docker預設的網絡設定,此模式會為每一個容器配置設定Network Namespace、設定IP等,并将一個主機上的Docker容器連接配接到一個虛拟網橋上。下面着重介紹一下此模式。

4.1 bridge模式的拓撲

Docker的none網絡模式下建立一個點到點的連接配接(及4種docker網絡模式)
Docker的none網絡模式下建立一個點到點的連接配接(及4種docker網絡模式)

Docker完成以上網絡配置的過程大緻是這樣的:

1. 在主機上建立一對虛拟網卡veth pair裝置。veth裝置總是成對出現的,它們組成了一個資料的通道,資料從一個裝置進入,就會從另一個裝置出來。是以,veth裝置常用來連接配接兩個網絡裝置。

2. Docker将veth pair裝置的一端放在新建立的容器中,并命名為eth0。另一端放在主機中,以veth65f9這樣類似的名字命名,并将這個網絡裝置加入到docker0網橋中,可以通過brctl show指令檢視。

Docker的none網絡模式下建立一個點到點的連接配接(及4種docker網絡模式)

3. 從docker0子網中配置設定一個IP給容器使用,并設定docker0的IP位址為容器的預設網關。

網絡拓撲介紹完後,接着介紹一下bridge模式下容器是如何通信的。

4.2 bridge模式下容器的通信

在bridge模式下,連在同一網橋上的容器可以互相通信(若出于安全考慮,也可以禁止它們之間通信,方法是在DOCKER_OPTS變量中設定--icc=false,這樣隻有使用--link才能使兩個容器通信)。

容器也可以與外部通信,我們看一下主機上的Iptable規則,可以看到這麼一條

-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE

這條規則會将源位址為172.17.0.0/16的包(也就是從Docker容器産生的包),并且不是從docker0網卡發出的,進行源位址轉換,轉換成主機網卡的位址。這麼說可能不太好了解,舉一個例子說明一下。假設主機有一塊網卡為eth0,IP位址為10.10.101.105/24,網關為10.10.101.254。從主機上一個IP為172.17.0.1/16的容器中ping百度(180.76.3.151)。IP包首先從容器發往自己的預設網關docker0,包到達docker0後,也就到達了主機上。然後會查詢主機的路由表,發現包應該從主機的eth0發往主機的網關10.10.105.254/24。接着包會轉發給eth0,并從eth0發出去(主機的ip_forward轉發應該已經打開)。這時候,上面的Iptable規則就會起作用,對包做SNAT轉換,将源位址換為eth0的位址。這樣,在外界看來,這個包就是從10.10.101.105上發出來的,Docker容器對外是不可見的。

那麼,外面的機器是如何通路Docker容器的服務呢?我們首先用下面指令建立一個含有web應用的容器,将容器的80端口映射到主機的80端口。

docker run -d --name web -p 80:80 fmzhen/simpleweb

然後檢視Iptable規則的變化,發現多了這樣一條規則:

-A DOCKER ! -i docker0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.17.0.5:80

此條規則就是對主機eth0收到的目的端口為80的tcp流量進行DNAT轉換,将流量發往172.17.0.5:80,也就是我們上面建立的Docker容器。是以,外界隻需通路10.10.101.105:80就可以通路到容器中得服務。

除此之外,我們還可以自定義Docker使用的IP位址、DNS等資訊,甚至使用自己定義的網橋,但是其工作方式還是一樣的。

本文轉自 326647452 51CTO部落格,原文連結:http://blog.51cto.com/svsky/2046110,如需轉載請自行聯系原作者