防偽碼:不經一番寒徹骨,怎得梅花撲鼻香。
docker技術剖析--docker網絡
一、 Docker 中的網絡功能介紹
默認情況下,容器可以建立到外部網絡的連接,但是外部網絡無法連接到容器。
Docker 允許通過外部訪問容器或容器互聯的方式來提供網絡服務
外部訪問容器:
容器中可以運行一些網絡應用,要讓外部也可以訪問這些應用,可以通過 -P 或 -p 參數來指定端口映射。
練習環(huán)境:運行一個容器,提供web服務和ssh服務
宿主機啟用路由轉發(fā)(net.ipv4.ip_forward=1)
通過docker commit或dockerfile生成一個web應用的鏡像,這里我通過docker dockerfile構建鏡像模板
1) 創(chuàng)建一個sshd_dockerfile工作目錄
編輯run.sh文件
#!/bin/sh
/usr/sbin/httpd -D DFOREGROUND
/usr/sbin/sshd -D
在主機上生成ssh秘鑰對,并創(chuàng)建authorized_keys文件
在sshd_dockerfile目錄下,使用docker build命令來創(chuàng)建鏡像,注意:在最后還有一個”.”,表示使用當前目錄中的dockerfile
執(zhí)行docker images查看新生成的鏡像
當使用–P(大寫)標記時,Docker 會隨機映射一個隨機的端口到內部容器開放的網絡端口。
注:-P使用時需要指定--expose選項或dockerfile中用expose指令容器要暴露的端口,指定需要對外提供服務的端口
使用 docker ps 可以看到,本地主機的32770被映射到了容器的22端口,本地主機的32769被映射到了容器的80端口,本地主機的32768被映射到了容器的443 端口。
此時訪問本機的 32770端口即可訪問容器內 ssh 應用。
注:192.168.12.128是宿主主機地址。
查看容器運行的httpd進程
此時訪問本機的 32769端口即可訪問容器內 web 應用
-p(小寫)則可以指定要映射的端口,并且,在一個指定端口上只可以綁定一個容器。支持的格式有
ip:hostPort:containerPort
ip::containerPort
hostPort:containerPort
注意:
容器有自己的內部網絡和 ip 地址(使用 docker inspect 可以獲取所有的變量。)
-p 標記可以多次使用來綁定多個端口
映射所有接口地址:
使用 hostPort:containerPort 格式,將本地的10111端口映射到容器的 22 端口,本地的801端口映射到容器的80端口可以執(zhí)行
測試訪問:
1) ssh測試:
使用xshell工具:
測試web訪問
映射到指定地址的指定端口
可以使用 ip:hostPort:containerPort 格式,指定映射使用一個特定地址,比如宿主機網卡配置的一個地址192.168.12.128
映射到指定地址的任意端口
使用 ip::containerPort 綁定192.168.12.128的任意端口到容器的80端口,本地主機會自動分配一個口。--name為啟動的容器指定一個容器名。
注:還可以使用 udp 標記來指定 udp 端口
# docker run -d -p 127.0.0.1:5000:5000/udp –name db4 commit:v1
查看映射端口配置
使用 docker port 來查看當前映射的端口配置,也可以查看到綁定的地址
Docker NAT iptables實現
默認情況下,容器可以主動訪問到外部網絡的連接,但是外部網絡無法訪問到容器
容器訪問外部實現
容器所有到外部網絡的連接,源地址都會被 NAT 成本地系統(tǒng)的 IP 地址(即docker0地址)。這是使用 iptables 的源地址偽裝操作實現的
查看主機的 NAT 規(guī)則
其中,上述規(guī)則將所有源地址在 172.17.0.0/16 網段,目標地址為其他網段(外部網絡)的流量動態(tài)偽裝為從系統(tǒng)網卡發(fā)出。MASQUERADE 跟傳統(tǒng) SNAT 的好處是它能動態(tài)從網卡獲取地址。
外部訪問容器實現
容器允許外部訪問,可以在 docker run 時候通過 -p 或 -P 參數來啟用,不管用那種辦法,其實也是在本地的 iptable 的 nat 表中添加相應的規(guī)則
使用 -P 時:
# iptables -t nat –nvL
使用 -p 80:80 時:
# iptables -t nat –nvL
docker0 網橋
Docker服務默認會創(chuàng)建一個 docker0 網橋(其上有一個 docker0 內部接口),它在內核層連通了其他的物理或虛擬網卡,這就將所有容器和本地主機都放到同一個物理網絡。
Docker 默認指定了 docker0 接口的 IP 地址和子網掩碼,讓主機和容器之間可以通過網橋相互通信
由于目前 Docker 網橋是 Linux 網橋,用戶可以使用 brctl show 來查看網橋和端口連接信息。
注:brctl 命令在centos中可以使用yum install bridge-utils 來安裝
每次創(chuàng)建一個新容器的時候,Docker 從可用的地址段中選擇一個空閑的 IP 地址分配給容器的eth0端口。使用本地主機上 docker0 接口的 IP 作為所有容器的默認網關。
Docker 網絡配置
Docker 四種網絡模式
docker run 創(chuàng)建 Docker 容器時,可以用 --net 選項指定容器的網絡模式,Docker 有以下 4 種網絡模式:
host 模式,使用 --net=host 指定。
container 模式,使用 --net=container:NAMEorID 指定。
none 模式,使用 --net=none 指定。
bridge 模式,使用 --net=bridge 指定,默認設置。
如果啟動容器的時候使用 host 模式,那么這個容器將不會獲得一個獨立的 Network Namespace,而是和宿主機共用一個 Network Namespace。容器將不會虛擬出自己的網卡,配置自己的 IP 等,而是使用宿主機的 IP 和端口。
例如,我們在192.168.1.102/24 的機器上用 host 模式啟動一個含有 web 應用的 Docker 容器,監(jiān)聽 tcp 80 端口。當我們在容器中執(zhí)行任何類似 ifconfig 命令查看網絡環(huán)境時,看到的都是宿主機上的信息。而外界訪問容器中的應用,則直接使用192.168.1.102:80 即可,不用任何 NAT 轉換,就如直接跑在宿主機中一樣。但是,容器的其他方面,如文件系統(tǒng)、進程列表等還是和宿主機隔離的。
啟動容器前,執(zhí)行pgrep http查看宿主機httpd進程
上面顯示結果說明宿主機沒有httpd進程運行
用 host 模式啟動一個含有 web 應用的 Docker 容器
用瀏覽器訪問宿主機地址的80端口
注意防火墻:
container 模式
這個模式指定新創(chuàng)建的容器和已經存在的一個容器共享一個 Network Namespace,而不是和宿主機共享。新創(chuàng)建的容器不會創(chuàng)建自己的網卡,配置自己的 IP,而是和一個指定的容器共享 IP、端口范圍等。同樣,兩個容器除了網絡方面,其他的如文件系統(tǒng)、進程列表等還是隔離的。兩個容器的進程可以通過 lo 網卡設備通信。
運行一個容器:查看容器的IP
將容器切換到后臺運行:ctrl+p ctrl+q
在運行一個容器使用container模式:查看新容器的地址
bridge模式
當 docker 啟動時,會在主機上創(chuàng)建一個 docker0 的虛擬網卡。他隨機挑選 RFC1918 私有網絡中的一段地址給 docker0 。比如 172.17.0.1/16,16 位掩碼的網段可以擁有 65534 個地址可以使用,這對主機和容器來說應該足夠了。
docker0 不是普通的網卡,他是橋接到其他網卡的虛擬網卡,容器使用它來和主機相互通信。當創(chuàng)建一個 docker 容器的時候,它就創(chuàng)建了一個對接口,當數據包發(fā)送到一個接口時,另外一個接口也可以收到相同的數據包,它們是綁在一起的一對孿生接口。這對接口在容器中那一端的的名字是 eth0 ,宿主主機端的會指定一個唯一的名字,比如 vethAQI2QT 這樣的名字。
所有的 veth* 的接口都會橋接到 docker0 ,這樣 docker 就創(chuàng)建了在主機和所有容器之間一個虛擬共享網
bridge 模式是 Docker 默認的網絡設置,此模式會為每一個容器分配 Network Namespace、設置 IP 等,并將一個主機上的 Docker 容器連接到一個虛擬網橋上。當 Docker server 啟動時,會在主機上創(chuàng)建一個名為 docker0 的虛擬網橋,此主機上啟動的 Docker 容器會連接到這個虛擬網橋上。虛擬網橋的工作方式和物理交換機類似,這樣主機上的所有容器就通過交換機連在了一個二層網絡中。接下來就要為容器分配 IP 了,Docker 會從 RFC1918 所定義的私有 IP 網段中,選擇一個和宿主機不同的IP地址和子網分配給 docker0,連接到 docker0 的容器就從這個子網中選擇一個未占用的 IP 使用。如一般 Docker 會使用 172.17.0.0/16 這個網段,并將 172.17.0.1/16 分配給 docker0 網橋(在主機上使用 ifconfig 命令是可以看到 docker0 的,可以認為它是網橋的管理接口,在宿主機上作為一塊虛擬網卡使用)
Docker完成以上網絡配置的過程大致是這樣的:
1.在主機上創(chuàng)建一對虛擬網卡veth pair設備。veth設備總是成對出現的,它們組成了一個數據的通道,數據從一個設備進入,就會從另一個設備出來。因此,veth設備常用來連接兩個網絡設備。
2.Docker將veth pair設備的一端放在新創(chuàng)建的容器中,并命名為eth0。另一端放在主機中,以veth65f9這樣類似的名字命名,并將這個網絡設備加入到docker0網橋中,可以通過brctl show命令查看。
注:brctl 工具依賴 bridge-utils 軟件包
3.從docker0子網中分配一個IP給容器使用,并設置docker0的IP地址為容器的默認網關。
容器內部訪問外網以及容器和主機之間的端口映射都是通過Iptables實現的,可以查看Iptables表分析。
查看當前 docker0地址
在容器運行時,每個容器都會分配一個特定的虛擬機口并橋接到 docker0。每個容器都會配置同 docker0 ip 相同網段的專用 ip 地址,docker0 的 IP 地址被用于所有容器的默認網關。
運行一個容器:
查看當前運行的容器:
通過brctl show命令查看
以上, docker0 扮演著veth986582c容器的虛擬接口 vethxx interface 橋接的角色。
執(zhí)行docker network inspect bridge查看橋接網絡的詳細信息
自定義網橋
除了默認的 docker0 網橋,用戶也可以指定網橋來連接各個容器。在啟動 Docker 服務的時候,使用 -b BRIDGE 或 --bridge=BRIDGE 來指定使用的網橋。
Docker 允許你管理 docker0 橋接或者通過-b選項自定義橋接網卡,需要安裝bridge-utils軟件包。
基本步驟如下:
1.確保 docker 的進程是停止的
2.創(chuàng)建自定義網橋
3.給網橋分配特定的 ip
4.以 -b 的方式指定網橋
具體操作步驟:
如果服務已經運行,那需要先停止服務,并刪除舊的網橋
然后創(chuàng)建一個網橋 bridge0,給網橋分配特定的 ip
查看確認網橋創(chuàng)建并啟動
或
修改/etc/sysconfig/docker文件
修改前:
修改后:添加前面所新建的網橋
啟動 Docker 服務。
新建一個容器,可以看到它已經橋接到了 bridge0 上。
進入容器,查看容器的IP
docker 服務啟動成功并綁定容器到新的網橋,新建一個容器,你會看到它的 ip 是我們的設置的新 ip段, docker 會自動檢測到它。用 brctl show 可以看到容器啟動或則停止后網橋的配置變化,在容器中使用 ip a 和 ip r 來查看 ip 地址配置和路由信息。
讓我們回顧一些基礎知識:
機器需要一個網絡接口來發(fā)送和接受數據包,路由表來定義如何到達哪些地址段。這里的網絡接口可以不是物理接口。事實上,每個 linux 機器上的 lo 環(huán)回接口( docker 容器中也有)就是一個完全的linux 內核虛擬接口,它直接復制發(fā)送緩存中的數據包到接收緩存中。 docker 讓宿主主機和容器使用特殊的虛擬接口來通信 -- 通信的 2 端叫“ peers“,他們在主機內核中連接在一起,所以能夠相互通信。創(chuàng)建他們很簡單,前面介紹過了。
docker 創(chuàng)建容器的步驟如下:
創(chuàng)建一對虛擬接口
其中宿主主機一端使用一個名字比如 veth65f9 ,他是唯一的 , 另外一端橋接到默認的 docker0, 或其它你指定的橋接網卡。
主機上的 veth65f9 這種接口映射到新的新容器中的名稱通常是eth0, 在容器這個隔離的 networknamespace 中,它是唯一的,不會有其他接口名字和它沖突。
從主機橋接網卡的地址段中獲取一個空閑地址給eth0使用,并設定默認路由到橋接網卡。
完成這些之后,容器就可以使用這eth0虛擬網卡來連接其他容器和其他網絡。
你也可以為特殊的容器設定特定的參數,在 docker run 的時候使用 --net ,它有 4 個可選參數:
--net=bridge :默認連接到 docker0 網橋。
--net=host :告訴 docker 不要將容器放到隔離的網絡堆棧中。盡管容器還是有自己的文件系統(tǒng)、進程列表和資源限制。但使用 ip addr 命令這樣命令就可以知道實際上此時的的容器處于和 docker 宿主主機的一樣的網絡級別,它擁有完全的宿主主機接口訪問權限。雖然它不允許容器重新配置主機的網絡堆棧,除非 --privileged=true,—但是容器進程可以跟其他 root 進程一樣可以打開低數字的端口,可以訪問本地網絡服務比如 D-bus ,還可以讓容器做一些意想不到的事情,比如重啟主機,使用這個選項的時候要非常小心!
--net=container:NAME_or_ID :告訴 docker 將新容器的進程放到一個已經存在的容器的網絡堆棧中,新容器進程有它自己的文件系統(tǒng)、進程列表和資源限制,但它會和那個已經存在的容器共享 ip 地址和端口,他們之間來可以通過環(huán)回接口通信。
--net=none :告訴 docker 將新容器放到自己的網絡堆棧中,但是不要配置它的網絡。
下面通過配置一個以 --net=none 啟動的容器,使他達到跟平常一樣具有訪問網絡的權限。來介紹docker 是如何連接到容器中的。
啟動一個運行 /bin/bash的容器,并指定 --net=none
再開啟一個新的終端,查找這個容器的進程 id ,然后創(chuàng)建它的命名空間,后面的 ip netns會用到
檢查橋接網卡的 ip 和子網掩碼
創(chuàng)建一對” peer“接口 A 和 B ,綁定 A 到網橋,并啟用它
將 B 放到容器的網絡命名空間,命名為eth0, 配置一個空閑的 ip
自此,你又可以像平常一樣使用網絡了
當你退出容器后, docker 清空容器,容器的eth0隨網絡命名空間一起被摧毀, A 接口也被自動從docker0 取消注冊。不用其他命令,所有東西都被清理掉了!
注意 ip netns exec 命令,它可以讓我們像 root 一樣配置網絡命名空間。但在容器內部無法使用,因為統(tǒng)一的安全策略, docker 限制容器進程配置自己的網絡。使用 ip netns exec 可以讓我們不用設置 --privileged=true 就可以完成一些可能帶來危險的操作。
DNS/HOSTNAME自定義
Docker 沒有為每個容器專門定制鏡像,那么怎么自定義配置容器的主機名和 DNS 配置呢?秘訣就是它利用虛擬文件來掛載到來容器的 3 個相關配置文件。
在容器中使用 mount 命令可以看到掛載信息:注(mount命令軟件包util-linux)
# mount
...
這種機制可以讓宿主主機 DNS 信息發(fā)生更新后,所有 Docker 容器的 dns 配置通過 /etc/resolv.conf文件立刻得到更新。
如果用戶想要手動指定容器的配置,可以利用下面的選項。
-h HOSTNAME or --hostname=HOSTNAME 設定容器的主機名,它會被寫到容器內的/etc/hostname 和 /etc/hosts。但它在容器外部看不到,既不會在 docker ps 中顯示,也不會在其他的容器的 /etc/hosts 看到。
--link=CONTAINER_NAME:ALIAS 選項會在創(chuàng)建容器的時候,添加一個其他容器的主機名到
/etc/hosts 文件中,讓新容器的進程可以使用主機名 ALIAS 就可以連接它。
--dns=IP_ADDRESS 添加 DNS 服務器到容器的 /etc/resolv.conf 中,讓容器用這個服務器來解析所有不在 /etc/hosts 中的主機名。
--dns-search=DOMAIN 設定容器的搜索域,當設定搜索域為 .example.com 時,在搜索一個名為 host的主機時, DNS 不僅搜索 host,還會搜索 host.example.com。注意:如果沒有上述最后 2 個選項,Docker 會默認用主機上的 /etc/resolv.conf 來配置容器。
具體其他選項可以查看docker run --help幫助
docker中的容器互聯--linking 系統(tǒng)
docker 有一個 linking 系統(tǒng)可以連接多個容器。它會創(chuàng)建一對父子關系,父容器可以看到所選擇的子容器的信息。該系統(tǒng)會在源和接收容器之間創(chuàng)建一個隧道,接收容器可以看到源容器指定的信息
自定義容器的命名
linking系統(tǒng)依據容器的名稱來執(zhí)行,因此,首先需要自定義一個好記的容器命名。當我們創(chuàng)建容器的時候,系統(tǒng)會隨機分配一個名字。當然我們也可以自己來命名容器,這樣做有 2 個好處:
當我們自己指定名稱的時候,比較好記,比如一個 web 應用我們可以給它起名叫 web
當我們要連接其他容器時候,可以作為一個有用的參考點,比如連接 web 容器到 db 容器
使用 --name 標記可以為容器自定義命名。使用 docker ps 來驗證設定的命名,也可以使用 docker inspect 來查看容器的名字docker inspect -f "{{ .Name }}" 容器id
注意:容器的名稱是唯一的。如果已經命名了一個叫 web 的容器,當你要再次使用 web 這個名稱的時候,需要先用 docker rm 來刪除之前創(chuàng)建的同名容器。
在執(zhí)行 docker run 的時候如果添加 --rm 標記,則容器在終止后會立刻刪除。注意, --rm 和 -d 參數不能同時使用。
容器互聯
使用--link參數可以讓容器之間安全的進行交互。
下面先創(chuàng)建一個新的數據庫容器。
docker run -dit --name dbserver鏡像id
然后創(chuàng)建一個新的 web 容器,并將它連接到 db 容器
--link 標記的格式: --link name:alias , name 是我們要鏈接的容器的名稱, alias 是這個鏈接的別名。
使用docker ps來查看容器的連接
我們可以看到我們命名的容器, dbserver 和 web , dbserver 容器的 names 列有 dbserver 也有 web/dbserver 。這表示 web 容器鏈接到 db 容器,他們是一個父子關系。在這個 link 中, 2 個容器中有一對父子關系。 docker 在 2 個容器之間創(chuàng)建了一個安全的連接,而且不用映射dbserver容器的端口到宿主主機上。所以在啟動 db 容器的時候也不用 -p 和 -P 標記。使用 link 之后我們就可以不用暴露數據庫端口到網絡上。
注意:你可以鏈接多個子容器到父容器,比如我們可以鏈接多個 web 到 db 容器上。
Docker 會添加子容器的 host 信息到父容器的 /etc/hosts 的文件。
下面是父容器 web 的 hosts 文件
這里有 2 個 hosts,第一個是 web 容器,web 容器用 id 作為他的主機名,第二個是 dbserver 容器的 ip 和主機名??梢栽?web 容器中安裝 ping 命令來測試跟dbserver容器的連通。
注意:官方的鏡像默認沒有安裝 ping,需要自行安裝,軟件包名iputils
用 ping 來測試db容器,
附:在bridge模式下,連在同一網橋上的容器可以相互通信(若出于安全考慮,也可以禁止它們之間通信,方法是在DOCKER_OPTS變量中設置--icc=false,這樣只有使用--link才能使兩個容器通信)。
多臺物理主機之間的容器互聯(暴露容器到真實網絡中)
docker 默認的橋接網卡是 docker0 。它只會在本機橋接所有的容器網卡,舉例來說容器的虛擬網卡在主機上看一般叫做 vethxxx,而 docker 只是把所有這些網卡橋接在一起,如下:
這樣就可以把這個網絡看成是一個私有的網絡,通過 nat 連接外網,如果要讓外網連接到容器中,就需要做端口映射,即 -p 參數。
如果在企業(yè)內部應用,或則做多個物理主機的集群,可能需要將多個物理主機的容器組到一個物理網絡中來,那么就需要將這個網橋橋接到我們指定的網卡上。
主機 A 和主機 B 的網卡一都連著物理交換機的同一個 vlan 101, 這樣網橋一和網橋三就相當于在同一個物理網絡中了,而容器一、容器三、容器四也在同一物理網絡中了,他們之間可以相互通信,而且可以跟同一 vlan 中的其他物理機器互聯。
這樣就直接把容器暴露到物理網絡上了,多臺物理主機的容器也可以相互聯網了。需要注意的是,這樣就需要自己來保證容器的網絡安全了。
不同容器之間的通信可以借助于 pipework 這個工具
pipework是由Docker的工程師Jérôme Petazzoni開發(fā)的一個Docker網絡配置工具,由200多行shell實現,方便易用。
下載地址:wget https://github.com/jpetazzo/pipework.git
unzip pipework-master.zip
cp -p /root/pipework-master/pipework /usr/local/bin/
安裝相應依賴軟件
yum install bridge-utils -y
配置橋接網絡
重啟network服務并查看IP地址
把 docker 的橋接指定為 br0,這樣跨主機不同容器之間通過 pipework 新建 docker 容器的網卡橋接到 br0,這樣跨主機容器之間就可以通信了。
CentOS 7/RHEL 7系統(tǒng)
#systemctl stop docker
修改/etc/sysconfig/docker
#systemctl start docker
pipework
把 docker 默認橋接指定到了 br0,則最好在創(chuàng)建容器的時候加上--net=none,防止自動分配的 IP 在局域網中有沖突。
使用鏡像運行一個容器
注:默認不指定網卡設備名,則默認添加為 eth1
注:另外 pipework 不能添加靜態(tài)路由,如果有需求則可以在 run 的時候加上 --privileged=true 權限在容器中手動添加,但這種安全性有缺陷,可以通過 ip netns 操作
route -n
訪問容器提供的web服務:
pipework可以在下面用三個場景來使用和工作原理。
1、將Docker容器配置到本地網絡環(huán)境中
為了使本地網絡中的機器和Docker容器更方便的通信,我們經常會有將Docker容器配置到和主機同一網段的需求。這個需求其實很容易實現,我們只要將Docker容器和主機的網卡橋接起來,再給Docker容器配上IP就可以了。
下面我們來操作一下,我主機A地址為192.168.1.102/24,網關為192.168.1.1,需要給Docker容器的地址配置為192.168.1.150/24。在主機A上做如下操作:
安裝pipework
下載地址:wget https://github.com/jpetazzo/pipework.git
unzip pipework-master.zip
cp -p /root/pipework-master/pipework /usr/local/bin/
啟動Docker容器。
docker run -itd --name test1 鏡像 /bin/bash
配置容器網絡,并連到網橋br0上。網關在IP地址后面加@指定。
pipework
br0 test1 192.168.1.150/24@192.168.1.1
將主機enp0s3橋接到br0上,并把enp0s3的IP配置在br0上。
ip addr add 192.168.1.102/24 dev br0
ip addr del 192.168.1.102/24 dev enp0s3
brctl addif br0 enp0s3
ip route del default
ip route add default via192.168.1.1 dev br0
注:如果是遠程操作,中間網絡會斷掉,所以放在一條命令中執(zhí)行。
ip addr add 192.168.1.102/24 dev br0; \ ip addr del 192.168.1.102/24 dev enp0s3; \ brctl addif br0 enp0s3; \
ip route del default; \ ip route add default via192.168.1.1 dev br0
完成上述步驟后,我們發(fā)現Docker容器已經可以使用新的IP和主機網絡里的機器相互通信了。
進入容器內部查看容器的地址:
pipework工作原理分析
那么容器到底發(fā)生了哪些變化呢?我們docker attach到test1上,發(fā)現容器中多了一塊eth1的網卡,并且配置了192.168.1.150/24的IP,而且默認路由也改為了192.168.1.1。這些都是pipework幫我們配置的。
首先pipework檢查是否存在br0網橋,若不存在,就自己創(chuàng)建。
創(chuàng)建veth pair設備,用于為容器提供網卡并連接到br0網橋。
使用docker inspect找到容器在主機中的PID,然后通過PID將容器的網絡命名空間鏈接到/var/run/netns/目錄下。這么做的目的是,方便在主機上使用ip netns命令配置容器的網絡。因為,在Docker容器中,我們沒有權限配置網絡環(huán)境。
將之前創(chuàng)建的veth pair設備分別加入容器和網橋中。在容器中的名稱默認為eth1,可以通過pipework的-i參數修改該名稱。
然后就是配置新網卡的IP。若在IP地址的后面加上網關地址,那么pipework會重新配置默認路由。這樣容器通往外網的流量會經由新配置的eth1出去,而不是通過eth0和docker0。(若想完全拋棄自帶的網絡設置,在啟動容器的時候可以指定--net=none)
以上就是pipework配置Docker網絡的過程,這和Docker的bridge模式有著相似的步驟。事實上,Docker在實現上也采用了相同的底層機制。
通過源代碼,可以看出,pipework通過封裝Linux上的ip、brctl等命令,簡化了在復雜場景下對容器連接的操作命令,為我們配置復雜的網絡拓撲提供了一個強有力的工具。當然,如果想了解底層的操作,我們也可以直接使用這些Linux命令來完成工作,甚至可以根據自己的需求,添加額外的功能。
2、單主機Docker容器VLAN劃分
pipework不僅可以使用Linux bridge連接Docker容器,還可以與OpenVswitch結合,實現Docker容器的VLAN劃分。下面,就來簡單演示一下,在單機環(huán)境下,如何實現Docker容器間的二層隔離。
為了演示隔離效果,我們將4個容器放在了同一個IP網段中。但實際他們是二層隔離的兩個網絡,有不同的廣播域。
安裝openvswitch
安裝基礎環(huán)境
yum install gcc make python-devel openssl-devel kernel-devel graphviz \
kernel-debug-devel autoconf automake rpm-build redhat-rpm-config \
libtool
下載openvswitch的包
wget http://openvswitch.org/releases/openvswitch-2.3.1.tar.gz
解壓與打包
之后會在~/rpmbuild/RPMS/x86_64/里有2個文件
安裝第一個就行
啟動
或
systemctl start openvswitch
查看狀態(tài)
或
可以看到是正常運行狀態(tài)
安裝pipework過程略,參考前面的操作
創(chuàng)建交換機,把物理網卡加入ovs1
在主機A上創(chuàng)建4個Docker容器,test1、test2、test3、test4
將test1,test2劃分到一個vlan中,
將test3,test4劃分到另一個vlan中
vlan在mac地址后加@指定,此處mac地址省略。(注:有空格)
完成上述操作后,使用docker attach連到容器中,然后用ping命令測試連通性,發(fā)現test1和test2可以相互通信,但與test3和test4隔離。這樣,一個簡單的VLAN隔離容器網絡就已經完成。
驗證:
由于Openvwitch本身支持VLAN功能,所以這里pipework所做的工作和之前介紹的基本一樣,只不過將Linux bridge替換成了OpenVswitch,在將veth pair的一端加入ovs0網橋時,指定了tag。底層操作如下:
ovs-vsctl add-port ovs0 veth* tag=100
3 、多主機Docker容器的VLAN劃分
上面介紹完了單主機上VLAN的隔離,下面我們將情況延伸到多主機的情況。有了前面兩個例子做鋪墊,這個也就不難了。為了實現這個目的,我們把宿主機上的網卡橋接到各自的OVS網橋上,然后再為容器配置IP和VLAN就可以了。我們實驗環(huán)境如下,主機A和B各有一塊網卡enp0s3,IP地址分別為10.10.101.105/24、10.10.101.106/24。在主機A上創(chuàng)建兩個容器test1、test2,分別在VLAN
100和VLAN 200上。在主機B上創(chuàng)建test3、test4,分別在VLAN 100和VLAN 200 上。最終,test1可以和test3通信,test2可以和test4通信。
拓撲圖如下所示
在主機A上
創(chuàng)建Docker容器
docker run -itd --name test1 ubuntu /bin/bash
docker run -itd --name test2 ubuntu /bin/bash
劃分VLAN
pipework ovs0 test1 192.168.0.1/24 @100
pipework ovs0 test2 192.168.0.2/24 @200
將eth0橋接到ovs0上
ip addr add 10.10.101.105/24 dev ovs0
ip addr del 10.10.101.105/24 dev eth0;
ovs-vsctl add-port ovs0 eth0
ip route del default
ip route add default gw 10.10.101.254 dev ovs0
在主機B上
創(chuàng)建Docker容器
docker run -itd --name
test3 ubuntu /bin/bash
docker run -itd --name test4 ubuntu /bin/bash
劃分VLAN
pipework ovs0 test1 192.168.0.3/24 @100
pipework ovs0 test2 192.168.0.4/24 @200
將eth0橋接到ovs0上
ip addr add 10.10.101.106/24 dev ovs0
ip addr del 10.10.101.106/24 dev eth0;
ovs-vsctl add-port ovs0 eth0
ip route del default
ip route add default gw 10.10.101.254 dev ovs0
完成上面的步驟后,主機A上的test1和主機B上的test3容器就劃分到了一個VLAN中,并且與主機A上的test2和主機B上的test4隔離(主機eth0網卡需要設置為混雜模式,連接主機的交換機端口應設置為trunk模式,即允許VLAN
100和VLAN 200的包通過)。
注:除此之外,pipework還支持使用macvlan設備、設置網卡MAC地址等功能。不過,pipework有一個缺陷,就是配置的容器在關掉重啟后,之前的設置會丟失。
其中promisc表示網卡混雜模式
其他參數的含義:
UP: 表示網卡開啟狀態(tài);
BROADCAST: 表示支持廣播;
promisc: 表示網卡混雜模式;
RUNNING: 表示網卡的網線被接上;
MULTICAST: 表示支持組播;
MTU: 表示MaximumTrasmission Unit 最大傳輸單元(字節(jié)),即此接口一次所能傳輸的最大封包;
RX: 表示網絡由激活到目前為止接收的數據包;
TX: 表示網絡由激活到目前為止發(fā)送的數據包;
collisions: 表示網絡信號沖突的情況;
txqueuelen: 表示傳輸緩沖區(qū)長度大??;
設置網卡工作模式
#ifconfig 網卡名 promisc 設置混雜
#ifconfig 網卡名 -promisc 取消混雜
網卡工作模式有4種,分別是:
廣播(Broadcast)模式
多播(Multicast)模式
單播模式(Unicast)
混雜模式(Promiscuous)
在混雜模式下的網卡能夠接收一切通過它的數據,而不管該數據目的地址是否是它。如果通過程序將網卡的工作模式設置為
“混雜模式”,那么網卡將接受所有流經它的數據幀,這實際上就是Sniffer工作的基本原理:讓網卡接收一切他所能接收的數據。Sniffer就是一種 能將本地網卡狀態(tài)設成混雜(promiscuous)狀態(tài)的軟件,當網卡處于這種"混雜"方式時,它對所有遇到的每一個數據幀都
產生一個硬件中斷以便提醒操作系統(tǒng)處理流經該物理媒體上的每一個報文包??梢姡琒niffer工作在網絡環(huán)境中的底層,它會攔截所有的正在網絡上傳送的數據,并且通過相應的軟件處理,可以實時分析這些數據的內容,進而分析所處的網絡狀態(tài)和整體布局。
謝謝觀看,真心的希望能幫到您!
本文出自 “一盞燭光” 博客,謝絕轉載!
更多建議: