Docker容器網絡-基礎篇

2020-09-16 慧眼人生


Mr_Zack 民工哥技術之路

Docker的技術依賴於Linux內核的虛擬化技術的發展,Docker使用到的網絡技術有Network Namespace、Veth設備對、Iptables/Netfilter、網橋、路由等。接下來,我將以Docker容器網絡實現的基礎技術來分別闡述,在到真正的容器篇章節之前,能形成一個穩固的基礎知識網。

Network Namespace

為了支持網絡協議棧的多個實例,Linux在網絡棧引入了Network Namespace,這些獨立的協議棧被隔離到不同的Namespace中,處於不同Namespace中的網絡棧是完全隔離的,彼此無法通信。具體有關Linux Namespace的介紹,可以另行瀏覽之前寫的《Linux Namespace》。

Linux的網絡協議棧十分複雜,為了支持獨立的協議棧,相關的全局變量都必須修改為協議棧私有。Linux實現Network Namespace的核心就是讓這些全局變量稱為Network Namespace變量的成員,然後為協議棧的函數調用加入一個Namespace參數。與此同時,為了保證已開發程序及內核代碼的兼容性,內核代碼隱式地使用了Namespace空間內的變量。應用程式如果沒有對Namespace有特殊需求,那麼不需要額外的代碼,Network Namespace對應用程式而言是透明的。

在建立了新的Network Namespace,並將某個進程關聯到這個網絡命名空間後,就出現了如下的命名空間下的內核數據結構,所有網絡棧變量都放入了Network Namespace的數據結構中,這個Network Namespace是屬於它進程組私有的,與其他進程組不衝突。

Docker正是利用了Network Namespace特性,實現了不同容器之間的網絡隔離。如果一個容器聲明使用宿主機的網絡棧(-net = host),即不開啟Network Namespace,例如:

docker run –d –net=host --name c_name i_name

這種情況下,這個容器啟動之後監聽的是宿主機的80埠。像這樣直接使用宿主機網絡棧的方式,雖然可以為容器提供良好的網絡性能,但也不可避免的造成埠衝突等網絡資源衝突的問題。

所以在一般情況下,我們都希望程序引入Network Namespace裡的網絡棧,即這個容器擁有自己的IP和埠。但是,這個時候也會帶來一個新的問題,被隔離的容器進程,是怎麼與其它被隔離的進程進行網絡通信的?

Net Bridge

上文說到,Linux 可以支持不同的網絡,他們之間是怎麼支持夠互相通信的呢?如果是兩臺主機,那需要的可能只是一根網線,把它們連接在一臺交換機上。而在Linux當中,網橋(Bridge)就起到相應的作用。本質上來說,這是一個數據鏈路層(data link)的設備,根據Mac地址的信息轉發到網橋的不同埠上。而Docker就是在宿主機上默認創建一個docker0的網橋,凡是連接docker0的網橋,都可以用它來通信。

細述Bridge

網橋是一個二層的虛擬網絡設備,把若干個網絡接口「連接」起來,使得網口之間的報文可以轉發。網橋能夠解析收發的報文,讀取目標的Mac地址信息,和自己的Mac地址表結合,來決策報文轉發的目標網口。為了實現這些功能,網橋會學習源Mac地址。在轉發報文時,網橋只需要向特定的埠轉發,從而避免不必要的網絡交互。如果它遇到了一個自己從未學過的地址,就無法知道這個報文應該向哪個網口轉發,就將報文廣播給除了報文來源之外的所有網口。

在實際網絡中,網絡拓撲不可能永久不變。如果設備移動到另一個埠上,而它沒有發送任何數據,那麼網橋設備就無法感知到這個變化,結果網橋還是向原來的埠發數據包,在這種情況下數據就會丟失。所以網橋還要對學習到的Mac地址表加上超時時間,默認5min。如果網橋收到了對應埠MAC地址回發的包。則重置超時時間,否則過了超時時間後,就認為哪個設備不在那個埠上了,他就會廣播重發。

Linux為了支持越來越多的網卡以及虛擬設備,所以使用網橋去提供這些設備之間轉發數據的二層設備。Linux內核支持網口的橋接(乙太網接口),這與單純的交換機還是不太一樣,交換機僅僅是一個二層設備,對於接受到的報文,要麼轉發,要麼丟棄。運行著Linux內核的機器本身就是一臺主機,有可能是網絡報文的目的地,其收到的報文要麼轉發,要麼丟棄,還可能被送到網絡協議的網絡層,從而被自己主機本身的協議棧消化,所以我們可以把網橋看作一個二層設備,也可以看做是一個三層設備。

Linux中Bridge實現

Linux內核是通過一個虛擬的網橋設備(Net Device)來實現橋接的。這個虛擬設備可以綁定若干個乙太網接口,從而將它們連接起來。Net Device網橋和普通的設備不同,最明顯的是它還可以有一個ip地址。

如上圖所示,網橋設備br0綁定的eth0和eth1。對於網絡協議棧的上層來說,只看到br0。因為橋接是在數據鏈路層實現的,上層不需要關心橋接的細節,於是協議棧上層需要發送的報文被送到br0,網橋設備的處理代碼判斷報文被轉發到eth0還是eth1,或者兩者皆轉發。反之,從eth0或者從eth1接收到的報文被提交給網橋的處理代碼,在這裡判斷報文應該被轉發、丟棄或者提交到協議棧上層。

而有時eth0、eth1也可能會作為報文的源地址或目的地址,直接參與報文的發送和接收,從而繞過網橋。

Bridge常用操作

Docker自動完成了對網橋的創建和維護。如果想要進一步理解網橋,可以看下如下舉的一些常用操作命令。

新增一個網橋:

brctl addbr xxxxx

在新增網橋的基礎上增加網口,在linux中,一個網口其實就是一個物理網卡。將物理網卡和網橋連接起來:

brctl addif xxxx ethx

網橋的物理網卡作為一個網口,由於在鏈路層工作,就不再需要IP位址了,這樣上面的IP位址自然失效:

ipconfig ethx 0.0.0.0

給網橋配置一個IP位址:

ipconfig brxxx xxx.xxx.xxx.xxx

這樣網橋就是一個有了IP位址,而連接在這之上的網卡就是一個純鏈路層設備了。

Veth Pair

上文說到,docker在宿主機上創建docker0網橋後,凡是連接到docker0上的網橋,就可以用它來通信。那麼這裡又有個問題,就是這些容器是如何連接到docker0網橋上的?所以這就是Veth Pair虛擬設備的作用了,Veth Pair就是為了在不同的Network Namespace之間進行通信,利用它,可以將兩個Network Namespace連接起來。

Veth Pair設備的特點是:它被創建出來後,總是以兩張虛擬網卡(Veth Peer)的形式出現。並且,其中一個網卡發出的數據包,可以直接出現在另一張「網卡」上,哪怕這兩張網卡在不同的Network Namespace中。

正是因為這樣的特點,Veth Pair成對出現,很像是一對乙太網卡,常常被看做是不同Network Namespace直連的「網線」。在Veth一端發送數據時,他會將數據發送到另一端並觸發另一端的接收操作。我們可以把Veth Pair其中一端看做另一端的一個Peer。

Veth Pair操作命令

創建Veth Pair:

ip link add veth0 type veth peer name veth1

創建後查看Veth Pair的信息:

ip link show

將其中一個Veth Peer設置到另一個Namespace:

ip link set veth1 netns netns1

在netns1中查看veth1設備:

ip netns exec netns1 ip link show

當然,在docker裡面,除了將Veth放入容器,還改名為eth0。想要通信必須先分配IP位址:

ip netns exec netns1 ip addr add 10.1.1.1/24 dev veth1ip addr add 10.1.1.2/24 dev veth0

啟動它們:

ip netns exec netns1 ip link set dev veth1 upip link set dev veth0 up

測試通信:

ip netns exec netns1 ping 10.1.1.2

Veth Pair查看端對端

在實際操作Veth Pair時,可以使用ethtool便於操作。

在一個Namespace中查看Veth Pair接口在設備列表中的序列號:

ip netns exec netns1 ethtool -S veth1

如果得知另一端的接口設備序列號,假如序列號為6,則可以繼續查看6代表了什麼設備:

ip netns exec netns2 ip link | grep 6

Iptables/Netfilter

Linux協議棧非常高效且複雜。如果我們想要在數據處理過程中對關心的數據進行一些操作,則需要Linux提供一套相應的機制幫助用戶實現自定義的數據包處理過程。

在Linux網絡協議棧有一組網絡回調函數掛接點,通過這些掛接點函數掛接的鉤子函數可以在Linux網絡棧處理數據包的過程中對數據包一些操作,例如過濾、修改、丟棄等。整個掛接點技術叫做Iptables和Netfilter。

Netfilter負責在內核中執行各種各樣的掛接規則,運行在內核模式中。而Iptables是在用戶模式下運行的進程,負責協助維護內核中Netfilter的各種規則表。通過二者的配合來實現整個Linux網絡協議棧中靈活的數據包處理機制。

規則表Table

這些掛載點能掛接的規則也分不同的類型,目前主要支持的Table類型如下:

•RAW•MANGLE•NAT•FILTER

上述4個規則鏈的優先級是RAW最高,FILTER最低。

在實際應用中,不同掛接點需要的規則類型通常不同。例如,在Input的掛接點上明顯不需要FILTER的過濾規則,因為根據目標地址,已經在本機的上層協議棧了,所以無需再掛載FILTER過濾規則。

Route

Linux系統包含了一個完整的路由功能。當IP層在處理數據發送或者轉發時,會使用路由表來決定發往哪裡。通常情況下,如果主機與目的主機直接相連,那麼主機可以直接發送IP報文到目的主機。

路由功能是由IP層維護的一張路由表來實現。當主機收到數據報文時,它用此表來決策接下來應該做什麼操作。當從網絡側接收到數據報文時,IP層首先會檢查報文的IP位址是否與主機自身的地址相同。如果數據報文中的IP位址是自身主機的地址,那麼報文將被發送到傳輸層相應的協議棧中去。如果報文中的IP位址不是主機自身的地址,並且配置了路由功能,那麼報文將被轉發,否則報文將被丟棄。

路由表的數據一般以條目形式存在,一個典型的路由表條目通常包含以下主要的條目項:

•目的IP位址•下一個路由器的IP位址•標誌•網絡接口規範

通過路由錶轉發時,如果任何條目的第一個欄位完全匹配目標條目的IP位址(主機)或部分匹配(網絡),那麼它將指示下一個路由器的IP位址。這些信息將告訴主機數據包該轉發到哪一個「下一個路由器」。而條目中所有其它欄位將提供更多的輔助信息來為路由轉發做決定。

如果沒有一個完全匹配的IP,則繼續搜索網絡ID。找到則轉發數據到指定路由器上。由此可知,網絡上所有主機都是通過這個路由表中的單個條目進行管理。

如果上述兩個條件都不匹配,則將數據報文轉發到一個默認路由器上。

如果上述步驟失敗,默認路由器也不存在,那麼這個數據報文無法轉發。任何無法投遞的數據都會產生一個ICMP主機不可達或者ICMP網絡不可達的錯誤,並將該錯誤返回給生成此數據的應用程式。

Route Table

Linux路由表至少2個,一個是LOCAL,一個是MAIN。

Local表用於供Linux協議棧識別本地地址,以及進行本地各個不同網絡之間的數據轉發。MAIN表用於各類網絡IP的轉發。它的建立既可以使用靜態配置生成,也可以使用動態路由發現協議生成。動態路由發現協議一般使用組播功能來通過發送路由發現數據,動態獲取和交換網絡的路由信息,並更新到路由表中。

通過下列命令查看LOCAL表的內容:

ip route show table local type local

路由表的查看:

ip route list

總結

到此為止,介紹了實現docker容器網絡最核心的基礎部分,包括Network Namespace、Bridge、Veth Pair、Iptables/Netfilter、Route。接下來,將會繼續在這基礎之上闡述Docker容器網絡的具體實現。

連結:https://www.cnblogs.com/sally-zhou/p/13424208.html
作者:Mr_Zack

相關焦點

  • Docker容器網絡-基礎篇
    開源LinuxDocker的技術依賴於Linux內核的虛擬化技術的發展,Docker使用到的網絡技術有Network Namespace、Veth設備對、Iptables/Netfilter、網橋、路由等。接下來,我將以Docker容器網絡實現的基礎技術來分別闡述,在到真正的容器篇章節之前,能形成一個穩固的基礎知識網。
  • IT工程師都需要掌握的容器技術之Docker容器網絡下
    《 》這篇文章我們主要講解了Docker容器網絡基礎,其中網絡的解決方案主要用於解決HOST內的容器通信。本篇文章我們將講解跨主機網絡的容器通信實現,涉及到Docker overlay網絡與MacVlan網絡的解決方案,下面我們就一起來學習吧!
  • docker系列之容器網絡
    眾所周知,當你在創建docker時,會創建默認的三個網絡,可使用docker network ls查看網絡。bridge:默認的docker連接網絡,如果不適用--network=<NETWORK> 則默認會連接到此網絡。可使用ip add show (簡寫 ip a)顯示網橋信息。none:是將容器添加到容器特定的網絡,該容器缺少網卡。進入到一個網絡為none的容器將會有如下的信息。
  • IT工程師都需要掌握的容器技術之Docker容器網絡上
    今天這篇文章我們將講解一下容器原生網絡的幾種類型以及如何創建這些網絡,由於容器網絡的內容比較多我們準備分上下兩個部分來講解,下面我們就一起來學習吧!01 Docker網絡Docker容器在安裝好後會默認的創建三個網絡,我們可以用如下命令進行查看1.
  • Docker 網絡模式詳解及容器間網絡通信
    通過 docker network connect 網絡名稱 容器名稱 為容器連接新的網絡模式。  通過 docker inspect 容器名稱|ID 再次查看容器的網絡信息,多增加了默認的 bridge。
  • Docker 容器編排利器 Docker Compose
    Compose 簡介    通過前面幾篇文章的學習,我們可以通過 dockerfile 文件讓用戶很方便的定義一個單獨的應用容器、參數、依賴等;networkds:定義網絡,可以多個,根據 DNS server 讓相同網絡中的容器可以直接通過容器名稱進行通信;volumes:數據卷,用於實現目錄掛載。
  • Docker 添加容器到一個網絡
    要創建一個安全並且能夠協同運行的 Web 應用程式,你需要創建一個網絡。通過網絡,在默認情況下為容器提供了完全獨立的環境。在你第一次運行一個容器的時候,你可以將容器添加到一個網絡中。例如,我們希望運行一個容器來運行 PostgreSQL 資料庫,並且傳遞 --net=my_bridge 標記來到你新網絡的連接中,可以運行下面的命令:$ docker run -d --net=my_bridge --name db training/postgres如果你檢查你的
  • NetCore微服務入門全紀錄(八)Docker與容器網絡
    那麼本篇將使用Docker Compose來解決以上問題,僅需一個簡單的命令,即可啟動整個環境。my-net: 網絡模式為bridge以上yml文件定義了auth,web,apigateway,productapi1,productapi2,productapi3,orderapi1,orderapi2,orderapi3,consul,postgres,rabbitmq 12個服務(容器),和一個容器網絡
  • 容器微服務和持續集成,(三)微服務docker容器部署
    繼前面兩篇,對Spring Cloud和容器的介紹後,大家應該了解了微服務的基礎。今天整理和介紹Spring Cloud的容器化部署。後面幾篇將介紹持續集成Gitlab和Jenkins,歡迎朋友們關注。
  • 五分鐘安裝docker並啟動第一個docker容器
    /中的鏡像、容器、volumes、網絡配置都會保留。以上命令代表:使用ubuntu鏡像運行docker容器,並在容器中列印'hello world whith docker!'。注釋:-a參數顯示所有docker容器。
  • docker系列學習之容器
    前言上一篇文章說到了docker的鏡像以及常用命令,在docker的使用過程中,一般都是先拉去鏡像,然後在鏡像的基礎上創建並啟動容器來運行我們的項目。故此本篇主要是說下容器的創建和相關命令以及簡單使用。
  • IT工程師都需要掌握的容器技術之Docker容器管理
    上篇文章我們講解了docker的基本用法主要涉及到容器的安裝、容器倉庫鏡像的配置及容器鏡像的管理等。今天這篇文章我們主要了解一下Docker容器管理的一些基礎及其命令的使用方法。    上面命令會創建指定鏡像的容器,但不會運行該容器,其後面常跟的參數如下所示:1)--name 給創建的容器指定一個名字2)--hostname 設置容器主機名3)--network 指定容器網絡類型,目前容器常用的網絡類型有none、host及bridge,如果創建容器不指定網絡類型默認的是使用
  • Docker篇-Docker快速入門
    鏡像列表查看運行容器 docker run -itd --name mg-redis -p 6379:6379 redis,可以查看容器運行情況 docker ps -adocker 容器列表查看redis容器運行日誌 docker logs -f mg-redis
  • docker容器常用命令
    image load -i /opt/nginx.tar.gz啟動容器34;n1& 啟動守護式容器docker run -d -p 8080:80 --name=&34; nginx34;n1& 停止正在運行容器docker stop 容器ID/名稱 重啟容器,不會使容器中已有的修改失效
  • Docker動手教程5.1:容器單機網絡1
    內容摘要none網絡host網絡bridge網絡初步觀察容器網絡安裝網橋管理工具為了便於觀察容器網絡,在容器測試環境中安裝 brctl 命令,命令為:yum install4、docker0 是容器的虛擬網橋。容器在安裝時,自動創建了3種網絡:none,host,bridge,下面分別予以介紹。
  • Docker系列之network命令(容器網絡)
    >com.docker.network.bridge.enable_icc--綁定容器埠時的默認IPcom.docker.network.bridge.host_binding_ipv4--設置容器網絡MTUcom.docker.network.driver.mtu
  • Docker動手教程5.2:容器單機網絡2
    內容摘要容器網絡連接特性Docker DNS容器共享網絡棧在本節開始前,請使用快照恢復容器環境,回到最初的環境。在上一節初步講解了容器的三種自帶網絡,以及自定義bridge網絡,在容器中使用最多的是bridge網絡。下面我們進一步學習bridge網絡。
  • Docker動手教程7:容器跨主機網絡-overlay
    本節講解overlay網絡,它能夠創建基於VxLAN的跨主機網絡。實驗環境初始化本章測試環境構成如下:基於上一章容器多主機構建docker machine,節點名稱分別為:node1,node2,node3。node1安裝容器初始環境,且安裝docker machine軟體。
  • 操作 Docker 容器 | Docker 系列
    與安裝 | Docker 系列使用 Docker 鏡像 | Docker 系列有了鏡像的基礎,下面就開始創建容器吧。還有一種方式,使用 docker create 命令創建容器,然後使用 docker start 來啟動容器,兩條命令相當於 docker run 一條,這種方式不常用,就不做更多介紹了。下面聊聊 docker run 背後的故事,到底這一條命令背後,Docker 都為我們做了哪些操作呢?
  • Docker動手教程5.3:容器單機網絡3
    內容摘要容器訪問外部網絡外部網絡訪問容器本節討論容器與外部網絡的連接特性,外部網絡在這裡是指容器所在主機以外的網絡,比如容器是否可以連接百度等。容器訪問外部網絡容器單機網絡有三種: none host bridge。