Docker容器網絡解析

Docker 容器網絡的發展歷史

?

在 Dokcer 發布之初,Docker 是將網絡、管理、安全等集成在一起的,其中網絡模塊可以為容器提供橋接網絡、主機網絡等簡單的網絡功能。

?

從 1.7 版本開始,Docker正是把網絡和存儲這兩部分的功能都以插件化形式剝離出來,允許用戶通過指令來選擇不同的后端實現。剝離出來的獨立容器網絡項目叫 libnetwork。

?

在 1.9 版本時,Docker 又引入了一整套 network 子命令和跨主機網絡支持,這允許用戶可以根據他們應用的拓撲結構創建虛擬網絡并將容器接入其所對應的網絡。

?

什么是 Docker?Libnetwork

?

為了標準化網絡的驅動開發步驟和支持多種網絡驅動,Docker 將網絡部分代碼被抽離成為了單獨的網絡庫(Libnetwork),Libnetwork 提供了可以用于開發多種網絡驅動的標準化接口和組件。

?

Docker daemon 通過調用 Libnetwork 對外提供的 API 完成網絡的創建和管理等功能,Libnetwork 內置了5種驅動來提供不同類型的網絡: bridge driver, host?driver,?null?driver,?overlay?driver,?remote?driver

?

圖片

?

bridge driver

?

此驅動為Docker的默認設置驅動,使用這個驅動的時候,libnetwork將創建出來的Docker容器連接到Docker網橋上。作為最常規的模式,bridge模式已經可以滿足Docker容器最基本的使用需求了。然而其與外界通信使用NAT,增加了通信的復雜性,在復雜場景下使用會有諸多限制。

?

host?driver

?

使用這種驅動的時候,libnetwork將不為Docker容器創建網絡協議棧,即不會創建獨立的network namespace。Docker容器中的進程處于宿主機的網絡環境中,相當于Docker容器和宿主機共同用一個network namespace,使用宿主機的網卡、IP和端口等信息。

?

但是,容器其他方面,如文件系統、進程列表等還是和宿主機隔離的。host模式很好地解決了容器與外界通信的地址轉換問題,可以直接使用宿主機的IP進行通信,不存在虛擬化網絡帶來的額外性能負擔。但是host驅動也降低了容器與容器之間、容器與宿主機之間網絡層面的隔離性,引起網絡資源的競爭與沖突。

?

因此可以認為host驅動適用于對于容器集群規模不大的場景。

?

null driver

?

使用這種驅動的時候,Docker容器擁有自己的network namespace,但是并不為Docker容器進行任何網絡配置。也就是說,這個Docker容器除了network namespace自帶的loopback網卡名,沒有其他任何網卡、IP、路由等信息,需要用戶為Docker容器添加網卡、配置IP等。

?

這種模式如果不進行特定的配置是無法正常使用的,但是優點也非常明顯,它給了用戶最大的自由度來自定義容器的網絡環境。

?

overlay driver

?

此驅動采用IETE標準的VXLAN方式,并且是VXLAN中被普遍認為最適合大規模的云計算虛擬化環境的SDN controller模式。在使用過程中,需要一個額外的配置存儲服務,例如Consul、etcd和zookeeper。還需要在啟動Docker daemon的時候額外添加參數來指定所使用的配置存儲服務地址。

?

remote Driver

?

這個驅動實際上并未做真正的網絡服務實現,而是調用了用戶自行實現的網絡驅動插件,使libnetwork實現了驅動的可插件化,更好地滿足了用戶的多種需求。用戶只需要根據libnetwork提供的協議標準,實現其所要求的各個接口并向Docker daemon進行注冊。

?

什么是 Docker?CNM

?

Docker?Libnetwork 中使用了 CNM 的容器網絡模式概念,CNM定義了構建容器虛擬化網絡的模型,此后容器網絡模式也被抽象變成了統一接口的驅動。

?

CNM 中主要有?sandbox、endpoint 和 network?3 種核心組件CNM 中核心組件的使用模型如下圖:

?

圖片

?

沙盒 (sandbox):一個沙盒包含了一個容器網絡棧的信息。沙盒可以對容器的接口(interface)、路由和 DNS 設置等進行管理,沙盒的實現可以是Linux netns、FreeBSD Jail 或者類似的機制,一個沙盒可以有多個端點和多個網絡。

?

端點 (endpoint):一個端點可以加入一個沙盒和一個網絡。端點的實現可以是 veth pair、ovs 內部端口或者相似的設備,一個端點只屬于一個網絡并且只屬于一個沙盒。

?

網絡 (network):一個網絡是一組可以直接互相聯通的端點。網絡的實現可以是 Linux bridge、VLAN等,一個網絡可以包含多個端點。

?

Libnetwork Remote driver

?

kuryr-libnetwork 是 Libnetwork 框架下的一種 remote driver 實現,現在已經成為Docker 官網推薦的一個 remote driver,kuryr-libnetwork 需要做的就是實現 Libnetwork remote driver 需要實現的接口.?

?

常見的 remote driver 要實現的接口如下,格式:HTTP POST + JSON Body

?

/Plugin.Activate no payload ?????-- Handshake
/NetworkDriver.GetCapabilities ??-- Set capability

/NetworkDriver.DiscoverNew ???-- DiscoverNew Notification

/NetworkDriver.DiscoverDelete ??-- DiscoverDelete Notification

/NetworkDriver.AllocateNetwork ?-- Allocate network specific resources, only called in docker swarm mode

/NetworkDriver.FreeNetwork ????-- Free network specific resources, only called in docker swarm mode

/NetworkDriver.CreateNetwork ??-- Create network

/NetworkDriver.DeleteNetwork ??-- Delete network

/NetworkDriver.CreateEndpoint ??-- Create endpoint

/NetworkDriver.EndpointOperInfo -- Endpoint operational info

/NetworkDriver.DeleteEndpoint ??-- Delete endpoint

/NetworkDriver.Join ???????????-- Join an endpoint to a sandbox

/NetworkDriver.Leave ?????????-- Remove an endpoint from a sandbox

?

IPAM?Driver

?

?在 Libnetwork 中,CNM 模塊通過 IPAM?Driver 管理 IP 地址的分配,Libnetwork 內含有一個默認的IPAM驅動,同時它也允許動態地增加第三方IPAM驅動。

?

在用戶創建網絡時可以指定 Libnetwork 使用的 IPAM 驅動,?Kuryr 項目通過實現了 IPAM 的驅動接口,成為了Docker 的第三方 libnetwork IPAM driver。

?

常見的 IPAM driver 要實現的接口如下,格式:HTTP POST + JSON Body

?

/IpamDriver.GetCapabilities ??-- provides the IPAM driver capabilities. it's called during the registration of the IPAM driver.

/IpamDriver.GetDefaultAddressSpaces ??-- returns the default local and global address space names for this IPAM. it's called after the registration of the IPAM driver

/IpamDriver.RequestPool ????-- registering an address pool with the IPAM driver. multiple identical calls must return the same result.

/IpamDriver.RequestAddress ??-- allocates the IP address

/IpamDriver.ReleaseAddress ??-- deallocates the IP address

/IpamDriver.ReleasePool ?????-- releasing a previously registered address pool

?

Docker 網絡的生命周期

?

Docker 用戶可以通過與 CNM 的 Object 以及 API 的交互來管理對應容器的網絡,下面是一個典型的容器網絡生命周期:

?

1、Driver要向NetworkController注冊。內置的Driver在Libnetwork內注冊,遠程的Driver則通過Plugin mechanism注冊。每一個Driver處理特定的networkType。

?

2、libnetwork.New():NetworkController通過libnetwork.New()創建,用于Network的創建以及通過一些特定的Options配置Driver。

?

3、controller.NewNetwork():Network通過給這個API提供name和networkType來創建,networkType參數用來選擇特定的Driver并且將創建的Network和該Driver相關聯。從此以后,對于Network的任何操作都由Driver處理。controller.NewNetwork() 還有一個可選的options參數,用于提供特定Driver的options和Labels。

?

4、network.CreateEndpoint():可以用于在給定的Network中創建一個新的Endpoint。同時該API還有一個可選的options參數供Driver使用。這個"options"既可以攜帶已知的labels,也可以攜帶和特定Driver相關的labels。之后調用相應的Driver的driver.CreateEndpoint,它可以為在一個Endpoint在Network中被創建時,為它們保留IP地址。Driver會通過driverapi中定義的InterfaceInfo進行這些地址的賦值。IP地址將和endpoint暴露的端口用來完善Endpoint作為Service的定義。事實上,Service endpoint不是其他什么東西,僅僅只是一個網絡地址以及該應用的容器監聽的端口號。

?

5、endpoint.Join():用于將Endpoint與一個容器相連接。Join操作會先創建一個Sandbox如果對應的容器中還沒有的話。Driver可以使用Sandbox Key來識別連接到同一個容器的多個Endpoint。這個API同樣接受可選的options參數供Driver使用。

?

- 雖然這并不是Libnetwork直接的設計要求,但是我們鼓勵像Docker這樣的用戶在執行容器的Start()操作時,即在容器可以操作之前,調用endpoint.Join()。

?

- 另一個關于endpoint.join()這個API經常被提到的問題是,為什么我們需要一個API創建Endpoint和另一個API來join endpoint。事實上Endpoint代表的是一個Service,它可能有,也可能并沒有容器支持。當一個Endpoint被創建的時候,會預留它所需的資源,因此任何容器都能連接該Endpoint并且獲得一個一致的網絡行為。

?

6、endpoint.Leave():會在容器停止的時候被調用。Driver可以清除它在調用Join()時獲取的狀態。Libnetwork會在最后一個Endpoint離開的時候刪除Sandbox。但是只要該Endpoint依舊存在,Libnetwork會依然保有IP地址并且在有新的容器加入的時候進行重用。這保證了容器的資源在停止并重啟的過程中能夠重用。

?

7、endpoint.Delete():用于從一個Network中刪除Endpoint。這將導致Endpoint的刪除以及清空緩存的sandbox.Info。

?

8、network.Delete():用于刪除Network。如果還有Endpoint連接到該網絡,Libnetwork是不允許對它進行刪除的。

?

Docker 網絡命名空間

?

docker 常常使用 linux netns 實現網絡資源隔離,但使用 ip netns 命令卻無法查看,這是因為 docker 默認把創建的網絡命名空間鏈接文件隱藏起來了,導致 ip netns 命令無法讀取,可以通過下面的方法復現 docker 的 ip netns 命名空間。

?

# 創建一個帶有橋接網絡的 docker 容器

$ docker run -it -d --rm --name mytest --network bridge cirros /bin/sh

c093857c756028b4d4f37b16262d017239236bde22a3545f8769fd17366f183a

$ docker ps | grep mytest

c093857c7560 ???cirros ??"/bin/sh" ????6 seconds ago ???Up 2 seconds ??mytest

# 可以通過 inspect 命令查看該容器的 ip 地址和進程號

$ docker inspect mytest |egrep '"IPAddress"|"Pid"'

????????"Pid": 14908,

????????"IPAddress": "172.17.0.2",

?

# 通過進程號參考容器進程 ???????

$ ps -fp 14908

UID ???PID ?PPID ?C STIME ?CMD

root 14889 ?1676 ?0 11:42 ?containerd-shim -namespace moby \

? ? ? ? ? -workdir?

/var/lib/containerd/io.containerd.runtime.v1.linux/moby/c093857c756028b4d4f37b16262d017239236bde22a3545f8769fd17366f183a \

??????????-address /run/containerd/containerd.sock \

??????????-containerd-binary /usr/bin/containerd \

??????????-runtime-root /var/run/docker/runtime-runc

?

# 通過 nsenter 進入容器網絡空間 ?????

$ nsenter --target 14908 --net ip a

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN

????link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

????inet 127.0.0.1/8 scope host lo

???????valid_lft forever preferred_lft forever

54: eth0@if55: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP

????link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0

????inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0

???????valid_lft forever preferred_lft forever

?

# 通過軟連接容器命名空間實現在 ip netns 下顯示

$ ls /proc/14908/ns/net

lrwxrwxrwx 1 root root 0 Jul 25 11:42 /proc/14908/ns/net -> net:[4026532445]

$ ln -s /proc/14908/ns/net /var/run/netns/mytest

?

# 最后檢查一下

$ ip netns

mytest (id: 1)

$ ip netns exec mytest ip a

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN

????link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

????inet 127.0.0.1/8 scope host lo

???????valid_lft forever preferred_lft forever

54: eth0@if55: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP

????link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0

????inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0

???????valid_lft forever preferred_lft forever

?

Docker 主機名與DNS?

?

一個鏡像可以啟動多個容器,但是它們的主機名和網絡信息并不一樣,也即是說主機名和網絡信息并非是被寫入鏡像中的。實際上容器中/etc/目錄下有三個文件是容器啟動后被虛擬文件覆蓋的,分別是/etc/hostname、/etc/hosts、/etc/resolv.conf。對這三個文件的修改不會被docker commit保存,也就是不會保存在鏡像中,重啟容器也會導致修改失效。

?

?

$ docker exec -it mytest mount | grep etc

/dev/mapper/centos-root on /etc/resolv.conf type xfs (rw,relatime,attr2,inode64,noquota)

/dev/mapper/centos-root on /etc/hostname type xfs (rw,relatime,attr2,inode64,noquota)

/dev/mapper/centos-root on /etc/hosts type xfs (rw,relatime,attr2,inode64,noquota)

?

- 這樣能解決主機名的問題,同時也能讓DNS及時更新(改變resolv.conf)。

?

- 由于這些文件的維護方法隨著Docker版本演進而不斷變化,因此盡量不修改這些文件,而是通過Docker提供的參數進行相關設置。

?

參考資料

https://github.com/docker/libnetwork/blob/master/docs/design.md

http://dockone.io/article/1306

https://www.oreilly.com/library/view/learning-docker-networking/9781785280955/

https://feisky.gitbooks.io/sdn/container/cnm/

https://www.nuagenetworks.net/blog/container-networking-standards/

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/535428.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/535428.shtml
英文地址,請注明出處:http://en.pswp.cn/news/535428.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

將指定excel的一列數據提取到另一個excel的指定列

#!/usr/bin/env python import openpyxl bjD:/地市縣公司/西藏臺賬數據分析-設備臺帳分析.xlsx wb openpyxl.load_workbook (bj) get_sheets wb.sheetnames #print(get_sheets) TA01TA01 TA02TA02 TA03TA03 TE01TE01 YG201YG201 YG202YG202 YG203YG203 YG204YG204 YG205YG205…

Docker 數據管理介紹

默認容器的數據是保存在容器的可讀寫層&#xff0c;當容器被刪除時其上的數據也會丟失&#xff0c;所以為了實現數據的持久性則需要選擇一種數據持久技術來保存數據。官方提供了三種存儲方式&#xff1a;Volumes、Bind mounts和tmpfs。前面還介紹了&#xff1a;Docker 服務終端…

Docker 數據持久化的三種方案

容器中的數據可以存儲在容器層。但是將數據存放在容器層存在以下問題&#xff1a; 數據不是持久化。意思是如果容器刪除了&#xff0c;這些數據也就沒了 主機上的其它進程不方便訪問這些數據 對這些數據的I/O會經過存儲驅動&#xff0c;然后到達主機&#xff0c;引入了一層間…

Git 存儲原理及相關實現

Git 是目前最流行的版本控制系統&#xff0c;從本地開發到生產部署&#xff0c;我們每天都在使用 Git 進行我們的版本控制&#xff0c;除了日常使用的命令之外&#xff0c;如果想要對 Git 有更深一步的了解&#xff0c;那么研究下 Git 的底層存儲原理將會對理解 Git 及其使用非…

Git內部原理

Git有什么特點&#xff1f; fast&#xff0c;scalable&#xff0c;distributed revision control system&#xff08;快速&#xff0c;可擴展的分布式版本控制系統&#xff09; 幾乎所有操作都是本地執行 每一個clone都是整個生命周期的完整副本 the stupid content tracker&a…

git存儲原理

四種數據類型 實際上Git基于數據類型的不同&#xff0c;把對象分為四種&#xff1a;數據對象、樹對象、提交對象、標簽對象。Git文件系統的設計思路與linux文件系統相似&#xff0c;即將文件的內容與文件的屬性分開存儲&#xff0c;文件內容以“裝滿字節的袋子”存儲在文件系統…

詳解設計模式:中介者模式

中介者模式&#xff08;Mediator Pattern&#xff09;也被稱為調停者模式&#xff0c;是在 GoF 23 種設計模式中定義了的行為型模式。 中介者模式 是用來降低多個對象和類之間的通信復雜性。這種模式提供了一個中介類&#xff0c;該類通常處理不同類之間的通信&#xff0c;并支…

rebase參數以及注意事項

可以根據需要將pick參數&#xff0c;改變為下面代表不同作用的參數&#xff1b;這樣就可以對節點C和D進行不同的操作了。比如&#xff1a; pick&#xff1a;默認參數&#xff0c;表示不對提交節點進行任何操作&#xff0c;直接應用原提交節點。不創建新提交&#xff1b; rewor…

RPC 服務 與 HTTP 服務的區別

1、什么是RPC RPC&#xff08;Remote Procedure Call&#xff09;—遠程過程調用&#xff0c;它是一種通過網絡從遠程計算機程序上請求服務&#xff0c;而不需要了解底層網絡技術的協議。RPC協議假定某些傳輸協議的存在&#xff0c;如TCP或UDP&#xff0c;為通信程序之間攜帶信…

Docker 網絡命名空間

Docker 用戶可以通過與 CNM 的 Object 以及 API 的交互來管理對應容器的網絡&#xff0c;下面是一個典型的容器網絡生命周期&#xff1a; 1、Driver要向NetworkController注冊。內置的Driver在Libnetwork內注冊&#xff0c;遠程的Driver則通過Plugin mechanism注冊。每一個Driv…

緩存雪崩、擊穿、穿透解決方案

用戶的數據一般都是存儲于數據庫&#xff0c;數據庫的數據是落在磁盤上的&#xff0c;磁盤的讀寫速度可以說是計算機里最慢的硬件了。 當用戶的請求&#xff0c;都訪問數據庫的話&#xff0c;請求數量一上來&#xff0c;數據庫很容易就奔潰的了&#xff0c;所以為了避免用戶直…

Ansible中的playbook詳解

首先簡單說明一下playbook&#xff0c;playbook是什么呢&#xff1f; 根本上說playbook和shell腳本沒有任何的區別&#xff0c;playbook就像shell一樣&#xff0c;也是把一堆的命令組合起來&#xff0c;然后加入對應條件判斷等等&#xff0c;在shell腳本中是一條一條的命令&am…

【Docker】容器鏡像有哪些特性

首先解釋一下什么是Docker鏡像&#xff1f; Docker鏡像它其實是一個模板&#xff0c;擁有這個模板我們才能創建我們的Docker容器&#xff0c;鏡像里含有啟動 docker 容器所需的文件系統結構及其內容&#xff0c;因此是啟動一個 docker 容器的基礎。docker 鏡像的文件內容以及一…

nginx中的location指令

1、location 介紹 location是Nginx中的塊級指令(block directive)&#xff0c;location指令的功能是用來匹配不同的url請求&#xff0c;進而對請求做不同的處理和響應&#xff0c;這其中較難理解的是多個location的匹配順序&#xff0c;本文會作為重點來解釋和說明。 開始之前…

容器底層實現技術Namespace/Cgroup

Docker容器實現原理 Docker容器在實現上是通過namespace技術來進行進程隔離&#xff0c;通過cgroup技術實現容器進程可用資源的限制&#xff0c;當docker啟動一個容器時&#xff0c;實際是創建了多了namespace參數的進程。 Namespace Namespace&#xff1a;命名空間 作用&#…

身體原因 斷更一周

由于眾所周知的原因&#xff0c;博主最近具有發熱、全身乏力、酸痛、干咳等癥狀&#xff0c;已嚴重影響日常的工作學習和博客編寫&#xff0c;所以斷更我將一周&#xff0c;由下周三&#xff08;即2022年12月21日&#xff09;恢復更新 更多往期內容可以參考&#xff1a;全網最…

異方差與多重共線性對回歸問題的影響

異方差的檢驗 1.異方差的畫圖觀察 2.異方差的假設檢驗&#xff0c;假設檢驗有兩種&#xff0c;一般用懷特檢驗使用方法在ppt中&#xff0c;課程中也有實驗&#xff0c;是一段代碼。 異方差的解決辦法 多重共線性 多重共線性可能帶來的影響&#xff1a; 多重共線性的檢驗 多重…

如何修改Docker的鏡像源

改或新增/etc/docker/daemon.json 文件 vi/etc/docker/daemon.json 添加需要修改的國內鏡像源鏡像源 { "registry-mirrors":["http://hub-mirror.c.163.com"] } 重啟Docker服務 Systemctl restart docker.service 方法二 修改或新增 /etc/sysconfig…

nginx 的 rewrite 模塊

ngxhttprewrite_module 模塊用來使用正則表達式&#xff08;PCRE&#xff09;改變請求的 URI&#xff0c;返回重定向&#xff0c;并有條件地選擇配置。 指令執行順序 首先順序執行 server 塊中的 rewrite 模塊指令&#xff0c;得到 rewrite 后的請求 URI 然后循環執行如下指令…

所有的Python庫

庫名稱簡介 Chardet字符編碼探測器&#xff0c;可以自動檢測文本、網頁、xml的編碼。 colorama主要用來給文本添加各種顏色&#xff0c;并且非常簡單易用。 Prettytable主要用于在終端或瀏覽器端構建格式化的輸出。 difflib&#xff0c;[Python]標準庫&#xff0c;計算文本…