<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

精通Docker網絡:Bridge驅動深度解析

馬哥Linux運維 ? 來源:cnblogs ? 2024-03-31 15:58 ? 次閱讀

dokcer0 網橋

在 Ubuntn 上安裝 docker 后,宿主機上默認被創建了一個名為 docker0 的網卡,其 IP 為 172.17.0.1/16:

5c788c4e-eea3-11ee-a297-92fbcf53809c.png

有了這個網卡,宿主機還會在內核的路由表中添加一條到達相應網絡的靜態路由記錄:

5c87ca74-eea3-11ee-a297-92fbcf53809c.png

這條路由信息表示所有目的 IP 為 172.17.0.0/16 的數據包都會從 docker0 網卡發出。接下來我們創建一個名為 mycon 的容器,并觀察其網絡配置:

5c960cba-eea3-11ee-a297-92fbcf53809c.png

在 mycon 容器內可以看到兩塊網卡:lo 和 eth0。其中 lo 是容器的回環網卡,eth0 是容器與外界通信的網卡,eth0 的 IP 信息為 172.17.0.2/16,和宿主機上的網卡 bridge0 在同一網段中。查看 mycon 的路由信息:

5ca8cc06-eea3-11ee-a297-92fbcf53809c.png

mycon 容器的默認網關正是宿主機的 docker0 網卡。通過 ping 命令測試與外網的連通性,此時容器 mycon 是可以連通外網的,這就說明 mycon 的 eth0 網卡與宿主機的 docker0 網卡是連通的。

下面我們來查看宿主機的網絡設備:

5cb6c766-eea3-11ee-a297-92fbcf53809c.png

發現多了一個以 "veth" 開頭的網卡,這是一個 veth 設備。而 veth 設備總是成對出現的,那么與 veth7537a16 配對的就應該是 mycon 容器中的 eth0 了。既然 mycon 容器中的 eth0 是與 docker0 連通的,那么 veth7537a16 也應該是與 docker0 連通的。因此docker0 并不是一個簡單的網卡設備,而是一個網橋!下圖展示了 docker bridge 網絡模式的拓撲圖:

5cd3f322-eea3-11ee-a297-92fbcf53809c.png

事實上,docker 創建了 docker0 網橋,并以 veth pair 連接各個容器的網絡,容器中的數據通過 eth0 發送到 docker0 網橋上,并由 docker0 網橋完成轉發。這里網橋的概念等同于交換機,為連在其上的設備轉發數據幀。網橋上的 veth 網卡設備相當于交換機上的端口,可以將多個容器連接在它們上面,這些端口工作在二層,所以是不需要配置 IP 信息的。上圖中的 docker0 網橋就為連在其上的容器轉發數據幀,使得同一臺宿主機上的 docker 容器之間可以相互通信。既然 docker0 是二層設備,那么它為什么還需要 IP 呢?其實,docker0 是一個普通的 linux 網橋,是可以為它配置 IP 的,我們可以認為它的內部有一個可以用于配置 IP 的網卡。Docker0 的 IP 地址作為所連接的容器的默認網關地址!

docker0 網橋是在 docker daemon 啟動時自動創建的,其默認 IP 為 172.17.0.1/16,之后通過 bridge 驅動創建的容器都會在 docker0 的子網范圍內選取一個未占用的 IP 使用,并連接到 docker0 網橋上。Docker daemon 提供了如下參數可以幫助用戶自定義 docker0 的設置。

--bip=CIDR:設置 docker0 的 IP 地址和子網范圍,使用 CIDR 格式,如 192.168.1.0/24。這個參數僅僅是配置 docker0 的,對用戶自定義的網橋無效。

--fixed-cidr=CIDR:限制 docker 容器可以獲取的 IP 地址范圍。Docker 容器默認可以獲取的 IP 范圍為 docker 網橋的整個子網范圍,此參數可以將其縮小到某個子網范圍內,所以這個參數必須在 docker 網橋的子網范圍內。

--mtu=BYTES:指定 docker0 網橋的最大傳輸單元(MTU)。

除了使用 docker0 網橋外,用戶還可以使用自定義的網橋,然后通過 --bridge=BRIDGE 參數傳遞給 docker daemon。比如我們可以創建一個自定義網橋 br0:

$ sudo ip link add name br0 type bridge
$ sudo ifconfig br0 188.18.0.1

5cdf794a-eea3-11ee-a297-92fbcf53809c.png

然后在啟動 docker daemon 時設置參數 --bridge=br0 即可。

iptables 規則

在安裝 docker 時,會默認在宿主機中添加一些 iptables 規則,用于 docker 容器之間已經容器與外界的通信。我們可以通過 iptables-save 命令查看到 nat 表上 POSTROUTING 鏈上的有這么一條規則:

-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
這條規則關系著 docker 容器與外界的通信,其含義是將不是從網卡 docker0 發出的且源地址為 172.17.0.0/16 的數據包(容器中發出的數據包)做 SNAT。這樣一來,從 docker 容器中訪問外網的流量,在外部看來就是從宿主機上發出的,外部感覺不到 docker 容器的存在。

當外界想要訪問 docker 容器運行的服務時該怎么辦呢?接下來我們將啟動一個簡單的 web 服務器:

$ docker run -d -p 3000:3000 --name=myweb ljfpower/nodedemo
然后觀察 iptables 規則的變化:
$ sudo iptables-save
…
*nat
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 3000 -j DNAT --to-destination 172.17.0.3:3000
…
*filter
-A DOCKER -d 172.17.0.3/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 3000 -j ACCEPT
…

可以看到,在 nat 表和 filter 表中的 DOCKER 鏈中分別增加來一條規則,這兩條規則將訪問宿主機 3000 端口的請求轉發到 172.17.0.3 的 3000 端口上(提供服務的 docker 容器的 IP 和端口),所以外界訪問 docker 容器是通過 iptables 做 DNAT 實現的。

Docker 默認的 forward 規則允許所有的外部 IP 訪問容器,我們可以通過在 filter 的 DOCKER 鏈上添加規則來對外部的 IP 訪問做出限制,比如只允許源 IP 為 192.168.21.212(筆者是在局域網內演示的)的數據包訪問容器,添加的規則如下:

$ sudo iptables -I DOCKER -i docker0 ! -s 192.168.21.212 -j DROP

不僅僅是與外界通信,docker 容器之間相互通信也受到 iptables 規則的限制。同一臺宿主機上的 docker 容器默認都連在 docker0 網橋上,它們屬于同一個子網,這是滿足通信的第一步。同時,docker daemon 會在 filter 表的 FORWARD 鏈中增加一條 ACCEPT 的規則(--icc=true):
-A FORWARD -i docker0 -o docker0 -j ACCEPT
這是滿足容器間相互通信的第二步。當 docker daemon 的啟動參數 -icc(icc 參數表示是否允許容器間相互通信) 設置為 false 時,上面的規則被設置為 DROP,容器間的相互通信就被禁止了,這時如果想讓兩個容器通信就需要在 docker run 命令中使用 --link 選項。

在 docker 容器和外界的通信過程中,還涉及了數據包在多個網卡之間的轉發(比如從 docker0 網卡到宿主機 eth0 網卡),這需要內核將 ip forward 功能打開,就是把內核參數 ip_forward 設置為 1。Docker daemon 在啟動的時候會執行這個操作,我們可以通過下面的命令進行檢查:

$ cat /proc/sys/net/ipv4/ip_forward


5cef6170-eea3-11ee-a297-92fbcf53809c.png

返回的結果為 1,表示內核的 ip forward 功能已經打開。

容器的 DNS 和主機名(hostname)

使用同一個 docker 鏡像可以創建很多個 docker 容器,但是這些容器的 hostname 并不相同,也就是說 hostname 并沒有被寫入到鏡像中。實際上容器中的 /etc 目錄下有 3 個文件是在容器啟動后被虛擬文件覆蓋掉的,分別是 /etc/hostname、/etc/hosts 和 /etc/resolv.conf,通過在容器中運行 mount 命令可以看到它們:

# mount
…
/dev/mapper/ubuntu--vg-root on /etc/resolv.conf type ext4 (rw,relatime,errors=remount-ro,data=ordered)
/dev/mapper/ubuntu--vg-root on /etc/hostname type ext4 (rw,relatime,errors=remount-ro,data=ordered)
/dev/mapper/ubuntu--vg-root on /etc/hosts type ext4 (rw,relatime,errors=remount-ro,data=ordered)
…

這種方式既能解決主機名的問題,同時也能讓 DNS 及時更新(改變 resolv.conf)。由于這些文件的維護方法會隨著 docker 版本的升級而不斷變化,所以盡量不要修改這些文件,而是通過 docker 提供的相關參數進行設置,其參數配置方式如下。

-h HOSTNAME 或者 --hostname=HOSTNAME:設置容器的 hostname,此名稱會寫入到 /etc/hostname 和 /etc/hosts 文件中,也可以在容器的 bash 提示符中看到。

--dns=IP_ADDRESS…:為容器配置 DNS,會被寫入到 /etc/resolv.conf 文件中。

這兩個參數都是針對容器的需要在創建容器時進行設置。比如下面的 demo:

$ docker run -it --name mycon -h lion --dns=8.8.8.8 ubuntu:14.04


5cfcecf0-eea3-11ee-a297-92fbcf53809c.png

總結

本文主要通過演示 docker0 網橋相關的功能來探索 docker 網絡中的 bridge 驅動的實現機制。從本文中不難看出,linux 系統中,docker 的 bridge 驅動是依賴于系統的 ip forward 以及 iptables 等核心功能的。因此在學習 docker 的過程中,適當的補充 linux 相關的知識也是十分必要的!

審核編輯:黃飛

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 網橋
    +關注

    關注

    0

    文章

    119

    瀏覽量

    16705
  • 容器
    +關注

    關注

    0

    文章

    481

    瀏覽量

    21914
  • Bridge
    +關注

    關注

    0

    文章

    15

    瀏覽量

    11823
  • Docker
    +關注

    關注

    0

    文章

    439

    瀏覽量

    11640

原文標題:拿捏Docker 網絡 bridge 驅動

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    I2C通信設計深度解析

    I2C通信設計深度解析
    發表于 08-12 21:31

    Docker網絡選型和日志監控選型

    Docker容器化網絡和日志的選型和落地
    發表于 05-06 07:58

    docker的四種網絡模式

    docker網絡模式
    發表于 10-16 08:11

    解析深度學習:卷積神經網絡原理與視覺實踐

    解析深度學習:卷積神經網絡原理與視覺實踐
    發表于 06-14 22:21

    AUTOSAR架構深度解析 精選資料推薦

    AUTOSAR架構深度解析本文轉載于:AUTOSAR架構深度解析目錄AUTOSAR架構深度解析A
    發表于 07-28 07:40

    AUTOSAR架構深度解析 精選資料分享

    AUTOSAR架構深度解析本文轉載于:AUTOSAR架構深度解析AUTOSAR的分層式設計,用于支持完整的軟件和硬件模塊的獨立性(Independence),中間RTE(Runtime
    發表于 07-28 07:02

    ARM64安裝Docker的問題及其解決辦法

    docker0 -j MASQUERADE: iptables: No chain/target/match by that name.【解決2】CONFIG_BRIDGE_NETFILTER=y,以及其他帶
    發表于 10-28 14:47

    C語言深度解析

    C語言深度解析,本資料來源于網絡,對C語言的學習有很大的幫助,有著較為深刻的解析,可能會對讀者有一定的幫助。
    發表于 09-28 07:00

    Docker五種存儲驅動原理詳解

    問題,在Docker 0.7版本中引入了存儲驅動, 目前,Docker支持AUFS、Btrfs、Device mapper、OverlayFS、ZFS五種存儲驅動。
    發表于 05-13 10:33 ?2580次閱讀
    <b class='flag-5'>Docker</b>五種存儲<b class='flag-5'>驅動</b>原理詳解

    docker存儲驅動的工作原理

    Docker的存儲驅動官方有介紹其工作原理,這里只是簡單概括一下。Docker使用了層的概念,docker在構建鏡像的時候,會逐行執行我們的Dockerfile中的每一行,每執行一行的
    的頭像 發表于 06-26 11:49 ?4351次閱讀

    詳解docker的四種網絡模式

    使用none模式,Docker容器擁有自己的Network Namespace,但是,并不為Docker容器進行任何網絡配置。也就是說,這個Docker容器沒有網卡、IP、路由等信息,
    的頭像 發表于 01-21 09:21 ?6355次閱讀

    docker的4種網絡模式

    Docker 使用 Linux 橋接,在宿主機虛擬一個 Docker 容器網橋(docker0),Docker 啟動一個容器時會根據 Docker
    的頭像 發表于 08-14 11:50 ?1326次閱讀

    docker的4種網絡模式配置

    Docker 使用 Linux 橋接,在宿主機虛擬一個 Docker 容器網橋(docker0),Docker 啟動一個容器時會根據 Docker
    的頭像 發表于 10-10 10:37 ?997次閱讀

    Docker容器網絡的數據鏈路是什么

    單主機容器網絡可能存在多個docker,分屬于不同的bridge,它們之間有通信的需求。
    的頭像 發表于 02-15 09:56 ?649次閱讀
    <b class='flag-5'>Docker</b>容器<b class='flag-5'>網絡</b>的數據鏈路是什么

    Docker網絡的基本概念和原理與用法

    橋接網絡Bridge Network):這是 Docker 容器默認使用的網絡類型。每個獨立的容器都會連接到一個內部網絡的私有網橋。
    發表于 03-18 12:26 ?179次閱讀
    <b class='flag-5'>Docker</b><b class='flag-5'>網絡</b>的基本概念和原理與用法
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>