Docker是基于容器的應(yīng)用開發(fā),部署和運行平臺
- 高性能:相比傳統(tǒng)虛擬機,不需要
hepervisor的額外負載,而是直接在主機內(nèi)核中運行,可以在同一硬件上運行更多工作負載 - 持續(xù)交付和部署:通過
container,在一個隔離環(huán)境中打包和運行應(yīng)用程序的功能,保證一致的運行環(huán)境,非常適合持續(xù)集成和持續(xù)交付(CI Continuous Integration,CD Continuous Delivery )工作流程,通過利用Docker的方法快速分發(fā),測試和部署代碼,可以顯著減少編寫代碼和在生產(chǎn)中運行代碼之間的延遲 - 易于擴展維護遷移,基于容器的特性允許高度可移植的工作負載,可以進行集群的自動化編排,容器集群管理方案有:Swarm,Kubernetes,Mesos等
docker_practice:github 上一個Docker的簡介
架構(gòu)
Docker Engine使用client-server架構(gòu),Docker client(docker,是一個命令行接口,CLI)通過REST API和Docker daemon(dockerd)交互,服務(wù)端綁定在一個Unix socket上
- Docker daemon:監(jiān)聽Docker API請求,管理Docker對象,例如鏡像,容器,網(wǎng)絡(luò),數(shù)據(jù)卷,daemon也可以和其他主機的daemon通信來管理Docker服務(wù)
- Docker client:用戶與Docker交互的主要方式,客戶端使用Docker API將命令發(fā)送到
dockerd,后者將其執(zhí)行,Docker client可以與多個守護進程通信 - Docker registry:用于存儲Docker鏡像, Docker Hub和Docker Cloud是公共倉庫,Docker默認在Docker Hub上查找鏡像,也可以運行自己搭建的私有倉庫


容器原理
docker使用go語言編寫,它基于Linux內(nèi)核的namespace與Cgroups功能
Containers and virtual machines
容器直接運行在Linux上,并與其他容器共享主機的內(nèi)核。它運行一個獨立的進程,不占用其他的內(nèi)存,非常輕量級,是基于操作系統(tǒng)的虛擬化技術(shù),早期的Docker就是基于LXC(Linux Container)項目封裝了一套工具,后來重新設(shè)計了自己的虛擬化平臺并發(fā)布了Libcontainer項目,擺脫了對LXC的依賴
虛擬機(VM)運行一個完整的客戶操作系統(tǒng)Cuest OS,通過hypervisor對主機資源進行虛擬訪問,這樣做能夠比較好的實現(xiàn)虛擬機與宿主機操作系統(tǒng)的異構(gòu),例如Linux系統(tǒng)上跑Windows虛擬機,VM需要提供的環(huán)境比大多數(shù)應(yīng)用程序需要的資源更多,例如KVM, 全稱是基于內(nèi)核的虛擬機(Kernel-based Virtual Machine),自Linux 2.6.20版本后就整合到內(nèi)核中,是一個輕量級的Hypervisor,依托CPU虛擬化指令集(例如Intel-VT,Virtualization Technology、AMD-V)實現(xiàn)高性能的虛擬化支持
從隔離上來講,虛擬機是用來對硬件資源進行劃分,屬于硬件虛擬化技術(shù),通過Hypervisor層來實現(xiàn)對資源的徹底隔離,容器是操作系統(tǒng)級別的虛擬化,利用內(nèi)核的特性實現(xiàn),不需要外部輔助

Namespaces
Docker使用namespaces技術(shù)來提供容器的隔離工作空間。當(dāng)運行容器時,Docker會為該容器創(chuàng)建一組名稱空間。這些命名空間提供了一層隔離。容器的每個方面都在一個單獨的命名空間中運行,其訪問權(quán)限僅限于該命名空間,名稱空間種類如下:
- The cgroup namespace:CGroup isolation(CGoup: Control Group).讓不同進程組看到的CGroup規(guī)則各不相同,為不同進程組采用各自的配額標(biāo)準(zhǔn)提供便利
- The pid namespace: Process isolation (PID: Process ID).基于進程的隔離能力,容器中的首個進程成為PID為1的進程,是所有進程的父進程,以及很多特權(quán)
- The net namespace: Managing network interfaces (NET: Networking).基于網(wǎng)絡(luò)棧的隔離能力,容器中的進程和特定的網(wǎng)絡(luò)關(guān)聯(lián)起來
- The ipc namespace: Managing access to IPC resources (IPC: InterProcess Communication).基于System V進程信道的隔離能力
- The mnt namespace: Managing filesystem mount points (MNT: Mount).基于磁盤掛載點和文件系統(tǒng)的隔離能力
- The uts namespace: Isolating kernel and version identifiers. (UTS: Unix Timesharing System).基于主機名的隔離能力
- The user namespace:基于系統(tǒng)用戶的隔離能力,同一用戶在不同namespace中可以擁有不同的UID和GID
# 查看進程的namespace
$ ls -l /proc/$$/ns
總用量 0
lrwxrwxrwx 1 wdy wdy 0 9月 17 15:08 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 wdy wdy 0 9月 17 15:08 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 wdy wdy 0 9月 17 15:08 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 wdy wdy 0 9月 17 15:08 net -> net:[4026531957]
lrwxrwxrwx 1 wdy wdy 0 9月 17 15:08 pid -> pid:[4026531836]
lrwxrwxrwx 1 wdy wdy 0 9月 17 15:08 user -> user:[4026531837]
lrwxrwxrwx 1 wdy wdy 0 9月 17 15:08 uts -> uts:[4026531838]
Control groups
Linux上的Docker Engine還依賴于另一種稱為控制組(cgroups)的技術(shù)。cgroup將應(yīng)用程序限制到特定的一組資源??刂平M允許Docker Engine將可用的硬件資源共享給容器,也可以強制執(zhí)行限制和約束。例如限制特定容器的CPU,內(nèi)存,磁盤IO等
$ cat /proc/$$/cgroup
11:cpuset:/
10:net_cls,net_prio:/
9:devices:/user.slice
8:perf_event:/
7:freezer:/
6:pids:/user.slice/user-1000.slice
5:cpu,cpuacct:/user.slice
4:memory:/user.slice
3:blkio:/user.slice
2:hugetlb:/
1:name=systemd:/user.slice/user-1000.slice/session-c2.scope
本質(zhì)上對CGroup的所有操作都是對系統(tǒng)掛載的CGroup目錄進行修改,在/sys/fs/cgroup/<controller>目錄下創(chuàng)建新的目錄
Union file systems
聯(lián)合文件系統(tǒng)或UnionFS是通過創(chuàng)建layer來操作的文件系統(tǒng),使它們非常輕量和快速。Docker Engine使用UnionFS為容器提供構(gòu)建塊。Docker Engine可以使用多種UnionFS,包括AUFS,btrfs,vfs和DeviceMapper
Container format
Docker Engine將命名空間,控制組和UnionFS組合到一個稱為容器格式的包裝器中。默認的容器格式是libcontainer。將來,Docker可能支持其他容器格式
Docker基本概念
Images
Docker鏡像依照OCI(Open Container Initiative)規(guī)范,是一個只讀模板(內(nèi)容在構(gòu)建之后不會改變),一個image由manifest、image index(可選)、filesystem layers和configuration四部分組成
鏡像采用分層的結(jié)構(gòu),可以最大化利用磁盤存儲,因為大多數(shù)的鏡像都會基于一些標(biāo)準(zhǔn)的基礎(chǔ)鏡像來構(gòu)建,分層存儲方便重復(fù)利用

最底層bootfs(boot file system)是一個引導(dǎo)文件系統(tǒng),Linux在啟動后之后,整個內(nèi)核都會被加載進內(nèi),bootfs會被卸載掉,之上是rootfs,即經(jīng)典的目錄結(jié)構(gòu),對于base image來說,底層直接用host的kernel,自己只需要提供rootfs就行了,對應(yīng)的所有容器都共用host的kernel
使用Dockerfile創(chuàng)建image,Dockerfile中的每條指令都在鏡像中創(chuàng)建一個層,每安裝一個軟件,就在現(xiàn)有鏡像的基礎(chǔ)上增加一層,鏡像的每一層都可以被共享,例如多個鏡像都從相同的base鏡像構(gòu)建而來,那么主機只需在磁盤上保存一份base鏡像,更改Dockerfile并重建映像時,僅重建那些已更改的層,這使鏡像輕量,小巧和快速
當(dāng)容器啟動時,一個新的可寫層被加載到鏡像的頂部。這一層通常被稱作容器層 container layer,“容器層”之下的都叫“鏡像層”,對容器的改動 - 無論添加、刪除、還是修改文件都只會發(fā)生在容器層中,只有容器層是可寫的,容器層具有Copy-on-Write特性,下面的所有鏡像層都是只讀的,當(dāng)需要修改時才復(fù)制一份數(shù)據(jù)到容器層進行修改??梢姡萜鲗颖4娴氖晴R像變化的部分,不會對鏡像本身進行任何修改

docker使用UnionFS文件系統(tǒng),它能將多個文件系統(tǒng)的內(nèi)容合并起來,形成一個單一的掛載點,掛到同一個目錄下,底層使用copy on write技術(shù),對文件的修改的會被向上拷貝到文件系統(tǒng)的一個臨時分層里,不會影響文件系統(tǒng)的原始數(shù)據(jù),Docker支持眾多的聯(lián)合文件系統(tǒng),可以在啟動Docker后臺服務(wù)時通過--storage-driver參數(shù)制定所使用的容器存儲種類,例如aufx,overlay2,devicemapper等
Containers
容器是鏡像的可運行實例,可以通過Docker API或CLI創(chuàng)建,啟動,停止,移動或刪除容器??梢詫⑷萜鬟B接到一個或多個網(wǎng)絡(luò),并連接上存儲,也可以根據(jù)其當(dāng)前狀態(tài)創(chuàng)建新的鏡像。
默認情況下,容器與其他容器以及宿主機相對隔離,但是可以自由控制容器的網(wǎng)絡(luò),存儲或其他底層子系統(tǒng)與其他容器或宿主機的隔離程度。容器由其鏡像以及在創(chuàng)建或啟動時為其提供的配置選項定義,容器內(nèi)的文件是和宿主機隔離開的,如果不進行數(shù)據(jù)卷掛載,容器關(guān)閉以后數(shù)據(jù)就會丟失
Services
Service允許在多個Docker daemons中擴展容器,一起作為一個swarm集群工作,內(nèi)部具有多個manager和worker節(jié)點。swarm的每個成員都是Docker daemon,并且都使用Docker API進行通信。 可以再服務(wù)中定義所需的狀態(tài),例如服務(wù)副本數(shù)。默認情況下,服務(wù)在所有工作節(jié)點之間進行負載平衡。 對于訪問者來說,Docker服務(wù)似表現(xiàn)的就像一個單獨的應(yīng)用程序。Docker Engine在Docker 1.12及以上版本中支持swarm模式,進行集群服務(wù)管理
部署層次
Containers
Docker通過讀取Dockerfile中的指令自動構(gòu)建鏡像,Dockerfile是一個文本文檔,定義了容器環(huán)境內(nèi)進行的操作。在容器內(nèi)對網(wǎng)絡(luò)接口和磁盤等資源的訪問是虛擬化的,與系統(tǒng)的其他部分隔離,因此需要在dockerfile中將端口映射到宿主機,具體說明要“復(fù)制”到哪些文件到容器,掛載數(shù)據(jù)卷等,然后就可以啟動一個運行鏡像的容器
Services
在分布式應(yīng)用程序中,應(yīng)用程序的不同部分稱為“services”。例如,如果一個視頻共享站點,它可能包括一個用于將應(yīng)用程序數(shù)據(jù)存儲在數(shù)據(jù)庫中的服務(wù),一個用戶上傳內(nèi)容后進行視頻轉(zhuǎn)碼的服務(wù),前端web服務(wù)等
服務(wù)實際上只是“工作狀態(tài)的容器”,一個服務(wù)只運行一個鏡像,但它設(shè)定了鏡像的運行方式,包括應(yīng)該使用哪些端口,應(yīng)該運行多少個容器副本,以及服務(wù)具有所需的容量,等等。擴展一個服務(wù)會改變運行該部分程序的容器的數(shù)量,為該服務(wù)分配更多計算資源,通過YAML文件即可定義,運行和擴展服務(wù)
Stacks
stack是一組關(guān)聯(lián)的services,它們共享依賴關(guān)系,并且可以被一起編排縮放。堆棧能夠定義和協(xié)調(diào)整個應(yīng)用程序的功能,對外體現(xiàn)為多個容器組合而成的復(fù)雜系統(tǒng)
docker stack deploy -c docker-compose.yml stack_nameXXX
Swarm
Docker Swarm是docker的原生集群,用于多個機器上創(chuàng)建容器集群服務(wù),一個swarm是運行Docker并加入一個群集的一組計算機,集群中的機器被稱為node。該模塊叫做Swarm Mode,早期版本中叫做Swarm standalone
內(nèi)部使用Etcd中的Raft模塊確定Master節(jié)點,raft是分布式一致性協(xié)議,用于解決在網(wǎng)絡(luò)集群中進行狀態(tài)確認的問題
# Manage nodes in a swarm
docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
4zrcf6u6gfwvpgw7ygcj2rrt5 * gpu-server5 Ready Active Leader 18.06.1-ce
wyndarmh11o1qpt6yqy8717xs gpu-server7 Ready Active 18.06.1-ce
AVAILABILITY 列表示調(diào)度器是否可以向該節(jié)點分配任務(wù)
Active 正常
Pause不能分配新的任務(wù),但是已有task可以繼續(xù)運行
Drain 不能分配新的任務(wù),調(diào)度器關(guān)閉已有的Task,在其他節(jié)點上運行,通常用于對節(jié)點進行維護升級
MANAGER STATUS列顯示節(jié)點在Raft的角色:
- 沒有值表示不參與群組管理的工作節(jié)點
-
Leader表明節(jié)點是primary manager node,對集群進行管理和編排 -
Reachable該節(jié)點是參與Raft共識仲裁的manager。 如果leader節(jié)點變得不可用,則該節(jié)點有資格被選為新leader -
Unavailable意味著該manager節(jié)點無法與其他manage通信
Swarm manager是集群中唯一可以執(zhí)行命令的機器,或授權(quán)其他機器作為worker加入群集,worker只執(zhí)行工作,沒有權(quán)力調(diào)度集群
Docker Machine
Docker Machine是一個工具,用于在虛擬機上安裝Docker Engine,并使用docker-machine命令管理這些主機
數(shù)據(jù)管理
在Docker的使用過程中往往需要對數(shù)據(jù)進行持久化,或者需要在多個容器之間進行數(shù)據(jù)共享,所以這就涉及到Docker容器的數(shù)據(jù)操作

- Volumes方式下:容器內(nèi)的數(shù)據(jù)被存放到宿主機(linux)一個特定的目錄下(/var/lib/docker/volumes/)。這個目錄只有Docker可以管理,其他進程不能修改。如果想持久保存容器的應(yīng)用數(shù)據(jù),Volumes是Docker推薦的掛載方式
- Bind mounts方式下:容器內(nèi)的數(shù)據(jù)被存放到宿主機文件系統(tǒng)的任意位置,甚至存放到一些重要的系統(tǒng)目錄或文件中。除了Docker之外的進程也可以任意對他們進行修改
- tmpfs方式下:容器的數(shù)據(jù)只會存放到宿主機的內(nèi)存中,不會被寫到宿主機的文件系統(tǒng)中,因此不能持久保存容器的應(yīng)用數(shù)據(jù)。
Volumes
由Docker創(chuàng)建和管理,可以通過命令docker volume create來現(xiàn)式創(chuàng)建一個卷,也可以由Docker在創(chuàng)建容器或服務(wù)的過程中來創(chuàng)建
當(dāng)創(chuàng)建一個volume時,它將會被存儲到宿主機的一個目錄下/lib/docker/volumes/<volumn-name>,當(dāng)掛載這個volume到一個容器中時,就是掛載這個目錄到容器中。這和bind mount的工作機制很相似,但是volume是被Docker所管理并與宿主機其他核心功能隔離
一個volume可以被同時掛載到多個容器中。當(dāng)沒有任何容器在使用這個volume的時候,這個volume也仍然可以被Docker獲取,并不會被自動被刪除。可以使用命令刪除不使用的volume:docker volume prune
當(dāng)掛載一個volume時,可以選擇為他命名(named),也可以匿名(anonymous). 匿名volume首次被掛載到一個容器中時,Docker會給它一個隨機的名字,保證在宿主機操作系統(tǒng)中這個volume的名字是唯一的。除了名字之外,命名和匿名的volume沒有區(qū)別。
Volume也支持使用volume drivers,用來將數(shù)據(jù)保存到遠程主機或云上
Bind mounts
在docker的早期版本中就存在該功能,與volumes相比,他的功能比較局限。當(dāng)使用bind mounts時,宿主機的目錄或文件被掛載到容器中。容器將按照掛載目錄或文件的絕對路徑來使用或修改宿主機的中的數(shù)據(jù)。宿主機中的目錄或文件不需要預(yù)先存在,在需要的時候會自動創(chuàng)建。使用Bind mounts在性能上是非常好的,但這依賴于宿主機有一個目錄結(jié)構(gòu)妥善的文件系統(tǒng)。如果你要創(chuàng)建一個新的Docker應(yīng)用,推薦使用named volume的方式,因為你無法通過Docker CLI來管理bind mounts
bind mounts是一把雙刃劍,因為可以在通過容器內(nèi)部的進程對主機文件系統(tǒng)進行修改,包括創(chuàng)建,修改和刪除重要的系統(tǒng)文件和目錄,這個功能雖然很強大,但顯然也會造成安全方面的影響,包括影響到宿主機上Docker以外的進程
tmpfs mounts
僅Linux系統(tǒng)支持,容器內(nèi)的應(yīng)用數(shù)據(jù)將不會被持久的保存到硬盤上,其中的數(shù)據(jù)只能在某個容器的生存周期內(nèi)被使用,用于保存一些不需要持久存儲,或一些敏感的數(shù)據(jù)信息。比如,在docker內(nèi)部,swarm服務(wù)使用tmpfs方式來將secrets掛載到服務(wù)容器中
Bind mounts和volumes都可以通過使用標(biāo)志v或--volume來掛載到容器中,只是格式有些許不同。tmpfs可以使用標(biāo)志-tmpfs進行掛載。在Docker17.06及其以上版本中,推薦使用--mount來對容器或服務(wù)進行這三種方式的掛載,因為這種格式更加清晰
網(wǎng)絡(luò)
Docker網(wǎng)絡(luò)模塊主要依賴libnetwork,依照Container Network Model (CNM) 實現(xiàn)
網(wǎng)絡(luò)模型
CNM:Container Network Model,容器的標(biāo)準(zhǔn)網(wǎng)絡(luò)模型,只要符合這個模型的網(wǎng)絡(luò)接口就能被用于容器之間的通信,通信的細節(jié)和過程完全由網(wǎng)絡(luò)接口實現(xiàn),涉及三個術(shù)語:
- Sandbox:對應(yīng)一個網(wǎng)絡(luò)環(huán)境,包括網(wǎng)卡配置、路由表、DNS配置等
- Endpoint:容器中的虛擬網(wǎng)卡,顯示為eth0、eth1
- Network:能夠相互通信的容器網(wǎng)絡(luò),加入了同一個網(wǎng)絡(luò)的容器可以直接通過對方的名字相互連接,實體是主機上的虛擬網(wǎng)卡或網(wǎng)橋

CNI標(biāo)準(zhǔn):Container Networking Interface 另一個輕量級的應(yīng)用容器網(wǎng)絡(luò)的開放插件化標(biāo)準(zhǔn),多數(shù)容器集群架構(gòu)都使用該標(biāo)準(zhǔn),例如Kubernetes、Mesos
- Container:擁有獨立Network Namespace的運行單元,與CNM的Sandbox概念基本一致
- Network:可以互相連接的一組實體,實體擁有各自獨立的唯一IP地址,例如容器,物理機或網(wǎng)關(guān)、路由器等網(wǎng)絡(luò)設(shè)備,相當(dāng)于CNM的Network加Endpoint概念

容器網(wǎng)絡(luò)涉及的其他技術(shù):
- Virtual Bridge:虛擬的網(wǎng)絡(luò)交換單元,功能相當(dāng)于交換機,為連在其中的設(shè)備轉(zhuǎn)發(fā)數(shù)據(jù)幀,例如Docker默認創(chuàng)建的docker0網(wǎng)橋
- iptable:內(nèi)置在內(nèi)核中的基于規(guī)則的網(wǎng)絡(luò)防火墻和包轉(zhuǎn)發(fā)服務(wù),為容器提供于NAT和網(wǎng)絡(luò)安全相關(guān)的特性
- Veth(Virtual Ethernet Device) Pair,由兩個虛擬網(wǎng)卡組成的數(shù)據(jù)通道,用于不同network namespace間進行通信,例如veth pair 一端連接到容器中作為eth0網(wǎng)卡,另一端連接到docker0網(wǎng)橋,將容器的數(shù)據(jù)發(fā)往另一個 network namespace
Docker的網(wǎng)絡(luò)實現(xiàn)
Docker網(wǎng)絡(luò)共有四種模式

- none
容器內(nèi)只有回環(huán)網(wǎng)絡(luò),容器擁有自己獨立的network namespace,但不進行配置,通常在容器不需要網(wǎng)絡(luò)或者自定義網(wǎng)絡(luò)時使用 - host
直接使用host的網(wǎng)絡(luò),容器共享宿主機的network namespace,使用的是宿主機的IP、端口等資源 - bridge
docker的默認網(wǎng)絡(luò)模式,docker在安裝時會創(chuàng)建一個名為docker0的Linux bridge,默認網(wǎng)段是172.17.0.0/16,在不指定network的情況下,新建的容器都會通過veth pair默認掛到docker0上,并在該網(wǎng)段內(nèi)獲取一個IP,在同一個網(wǎng)橋內(nèi)的容器可以通過IP地址通信,外部以及不同網(wǎng)絡(luò)之間的通信需要通過映射到主機的端口,底層依靠iptables實現(xiàn)端口轉(zhuǎn)發(fā)功能
容器與宿主機通信:在橋接模式下,Docker Daemon 將 veth0 附加到 docker0 網(wǎng)橋上,保證宿主機的報文有能力發(fā)往 veth0。再將 veth1 添加到 Docker 容器所屬的網(wǎng)絡(luò)命名空間,保證宿主機的網(wǎng)絡(luò)報文若發(fā)往 veth0 可以立即被 veth1 收到
容器與外界通信:容器如果需要聯(lián)網(wǎng),則需要采用 NAT方式。準(zhǔn)確的說,是 NATP (網(wǎng)絡(luò)地址端口轉(zhuǎn)換) 方式。NATP 包含兩種轉(zhuǎn)換方式:SNAT 和 DNAT
-
目的 NAT (Destination Network Address Translation,DNAT): 修改數(shù)據(jù)包的目的地址。
-
源 NAT (Source Network Address Translation,SNAT): 修改數(shù)據(jù)包的源地址
- overlap
overlap網(wǎng)絡(luò)驅(qū)動程序在多個Docker daemon主機之間創(chuàng)建分布式的網(wǎng)絡(luò)。該網(wǎng)絡(luò)(overlap)位于主機網(wǎng)絡(luò)之上,允許連接到它的容器進行通信。它基于VxLAN實現(xiàn),原理就是進行額外的裝包、拆包,因為現(xiàn)有網(wǎng)絡(luò)只認識節(jié)點到節(jié)點的路由,容器間通信時將數(shù)據(jù)包加上額外的傳輸協(xié)議包頭(ISO網(wǎng)絡(luò)模型二層或以上協(xié)議),先將數(shù)據(jù)傳輸?shù)侥康墓?jié)點,解包后傳輸?shù)侥康娜萜?/li>
初始化swarm或?qū)ocker主機加入現(xiàn)有swarm時,會在該Docker主機上創(chuàng)建兩個新網(wǎng)絡(luò):
- 一個名為
ingress的overlay網(wǎng)絡(luò),用于處理與swarm service相關(guān)的控制和數(shù)據(jù)流量。創(chuàng)建swarm service時,如果不將其連接到用戶定義的overlay網(wǎng)絡(luò),則默認下會連接到ingress網(wǎng)絡(luò) - 一個名為
docker_gwbridge的bridge網(wǎng)絡(luò),所有加入swarm的主機上都有該網(wǎng)橋,且網(wǎng)段是相同的
端口相關(guān):
- TCP 端口 2377 用來進行集群管理通信
- TCP UDP 端口 7946 用來節(jié)點之間通信
- UDP 端口 4789 用來進行覆蓋網(wǎng)絡(luò)的通信

容器網(wǎng)絡(luò)還有另外一種經(jīng)典模式,Container模式:該模式下啟動的容器將和指定的其他容器共享network namespace,該模式也是Kubernetes使用的網(wǎng)絡(luò)模式
跨結(jié)點網(wǎng)絡(luò)
基本條件
- 對IP分配進行規(guī)劃,使得每個容器對應(yīng)不同的IP地址
- 記錄容器IP和宿主機IP的映射關(guān)系
解決方案:
集群IP統(tǒng)一分配,通常會給每個主機分配一個IP段,每個主機會知道當(dāng)前節(jié)點所有容器的路由規(guī)則,以及集群所有IP段到對應(yīng)主機的路由規(guī)則,路由過程中首先是源容器將數(shù)據(jù)發(fā)送到目標(biāo)容器所在的主機節(jié)點,然后由目標(biāo)主機的本地路由規(guī)則將數(shù)據(jù)包送到真正的目標(biāo)容器
此外該中心地址分配器需要保證穩(wěn)定性,例如Flannal和Calico通過Etcd服務(wù)存儲網(wǎng)絡(luò)分配信息,內(nèi)部使用一致性協(xié)議Raft保證消息的可靠性
- 覆蓋網(wǎng)絡(luò):主要是基于VxLAN實現(xiàn)夸節(jié)點網(wǎng)絡(luò)
- Docker內(nèi)置的overlap網(wǎng)絡(luò)
- Flannel的UDP和VxLAN模式
- 擴展路由:讓容器的IP和主機的IP地址一樣,直接進行通信,不需要額外的封裝,具體有macvlan,節(jié)點網(wǎng)關(guān)路由,節(jié)點BGP路由三種
- Docker的macvlan網(wǎng)絡(luò)模式
- Caliao基于節(jié)點BGP協(xié)議的路由方案,可以直接利用數(shù)據(jù)中心的網(wǎng)絡(luò)結(jié)構(gòu),不需要額外的NAT、隧道或者Overlay Network,沒有額外的封包解包,提升網(wǎng)絡(luò)效率
- Flannel的HostGW模式:基于內(nèi)核路由表和Iptable規(guī)則的路由方案
macvlan技術(shù)在主機網(wǎng)卡上添加多個MAC地址(需要硬件設(shè)備的支持),對應(yīng)上多個IP,每個網(wǎng)卡分配給容器的不同Network Namespace,就相當(dāng)于把所有容器的網(wǎng)絡(luò)都直接相連到了主機網(wǎng)卡
節(jié)點網(wǎng)關(guān)路由:每個節(jié)點上運行一個Agent服務(wù),監(jiān)聽容器IP段的分配,一旦由變化就將新的路由規(guī)則刷新到內(nèi)核路由表,每個節(jié)點上的Agent就是一個控制網(wǎng)絡(luò)聯(lián)通規(guī)則的網(wǎng)關(guān)程序,這種方法稱為主機網(wǎng)關(guān)
節(jié)點BGP路由:如果節(jié)點直接隔著一個路由器,節(jié)點網(wǎng)關(guān)路由就會失效,路由器沒有相應(yīng)的路由規(guī)則,此時需要Agent把自己作為容器所在IP子網(wǎng)段的邊界路由器,利用BGP協(xié)議讓網(wǎng)絡(luò)中的其他三層設(shè)備學(xué)習(xí)到容器網(wǎng)段的路由信息
Flannel容器網(wǎng)絡(luò)方案
Flannel實現(xiàn)原理
- 每個主機上的Docker容器分配互相不沖突的IP地址
- 在這些IP地址之間建立一個覆蓋網(wǎng)絡(luò)
Flannel會啟動flanneld進程,連接etcd,管理IP地址段的分配,初始時獲取一個未分配的地址段,然后在Docker的啟動參數(shù)中指定docker0網(wǎng)橋的地址,flannel之間的底層通信協(xié)議有很多,例如UDP,VxLAN等,通過在應(yīng)用層進行封裝、解包進行通信
--bip=172.24.77.1/24
# ifconfig 中的部分數(shù)據(jù)
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.24.77.1 netmask 255.255.255.0 broadcast 172.24.77.255
flannel.1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450
inet 172.24.77.0 netmask 255.255.255.255 broadcast 0.0.0.0

