Docker是基于容器的應(yīng)用開發(fā)售貌,部署和運(yùn)行平臺(tái)
- 高性能:相比傳統(tǒng)虛擬機(jī),不需要
hepervisor
的額外負(fù)載,而是直接在主機(jī)內(nèi)核中運(yùn)行,可以在同一硬件上運(yùn)行更多工作負(fù)載 - 持續(xù)交付和部署:通過
container
蜗细,在一個(gè)隔離環(huán)境中打包和運(yùn)行應(yīng)用程序的功能,保證一致的運(yùn)行環(huán)境怒详,非常適合持續(xù)集成和持續(xù)交付(CI Continuous Integration,CD Continuous Delivery )工作流程炉媒,通過利用Docker的方法快速分發(fā),測試和部署代碼昆烁,可以顯著減少編寫代碼和在生產(chǎn)中運(yùn)行代碼之間的延遲 - 易于擴(kuò)展維護(hù)遷移吊骤,基于容器的特性允許高度可移植的工作負(fù)載,可以進(jìn)行集群的自動(dòng)化編排静尼,容器集群管理方案有:Swarm白粉,Kubernetes,Mesos等
docker_practice:github 上一個(gè)Docker的簡介
架構(gòu)
Docker Engine使用client-server架構(gòu)鼠渺,Docker client(docker
鸭巴,是一個(gè)命令行接口,CLI)通過REST API和Docker daemon(dockerd
)交互拦盹,服務(wù)端綁定在一個(gè)Unix socket上
- Docker daemon:監(jiān)聽Docker API請(qǐng)求鹃祖,管理Docker對(duì)象,例如鏡像普舆,容器恬口,網(wǎng)絡(luò)校读,數(shù)據(jù)卷,daemon也可以和其他主機(jī)的daemon通信來管理Docker服務(wù)
- Docker client:用戶與Docker交互的主要方式祖能,客戶端使用Docker API將命令發(fā)送到
dockerd
歉秫,后者將其執(zhí)行,Docker client可以與多個(gè)守護(hù)進(jìn)程通信 - Docker registry:用于存儲(chǔ)Docker鏡像芯杀, Docker Hub和Docker Cloud是公共倉庫端考,Docker默認(rèn)在Docker Hub上查找鏡像,也可以運(yùn)行自己搭建的私有倉庫
容器原理
docker使用go語言編寫揭厚,它基于Linux內(nèi)核的namespace與Cgroups功能
Containers and virtual machines
容器直接運(yùn)行在Linux上却特,并與其他容器共享主機(jī)的內(nèi)核。它運(yùn)行一個(gè)獨(dú)立的進(jìn)程筛圆,不占用其他的內(nèi)存裂明,非常輕量級(jí),是基于操作系統(tǒng)的虛擬化技術(shù)太援,早期的Docker就是基于LXC(Linux Container)項(xiàng)目封裝了一套工具闽晦,后來重新設(shè)計(jì)了自己的虛擬化平臺(tái)并發(fā)布了Libcontainer
項(xiàng)目,擺脫了對(duì)LXC的依賴
虛擬機(jī)(VM)運(yùn)行一個(gè)完整的客戶操作系統(tǒng)Cuest OS
提岔,通過hypervisor
對(duì)主機(jī)資源進(jìn)行虛擬訪問仙蛉,這樣做能夠比較好的實(shí)現(xiàn)虛擬機(jī)與宿主機(jī)操作系統(tǒng)的異構(gòu),例如Linux系統(tǒng)上跑Windows虛擬機(jī)碱蒙,VM需要提供的環(huán)境比大多數(shù)應(yīng)用程序需要的資源更多荠瘪,例如KVM, 全稱是基于內(nèi)核的虛擬機(jī)(Kernel-based Virtual Machine)赛惩,自Linux 2.6.20版本后就整合到內(nèi)核中哀墓,是一個(gè)輕量級(jí)的Hypervisor,依托CPU虛擬化指令集(例如Intel-VT喷兼,Virtualization Technology篮绰、AMD-V)實(shí)現(xiàn)高性能的虛擬化支持
從隔離上來講,虛擬機(jī)是用來對(duì)硬件資源進(jìn)行劃分季惯,屬于硬件虛擬化技術(shù)吠各,通過Hypervisor層來實(shí)現(xiàn)對(duì)資源的徹底隔離,容器是操作系統(tǒng)級(jí)別的虛擬化星瘾,利用內(nèi)核的特性實(shí)現(xiàn)走孽,不需要外部輔助
Namespaces
Docker使用namespaces
技術(shù)來提供容器的隔離工作空間。當(dāng)運(yùn)行容器時(shí)琳状,Docker會(huì)為該容器創(chuàng)建一組名稱空間磕瓷。這些命名空間提供了一層隔離。容器的每個(gè)方面都在一個(gè)單獨(dú)的命名空間中運(yùn)行,其訪問權(quán)限僅限于該命名空間,名稱空間種類如下:
- The cgroup namespace:CGroup isolation(CGoup: Control Group).讓不同進(jìn)程組看到的CGroup規(guī)則各不相同困食,為不同進(jìn)程組采用各自的配額標(biāo)準(zhǔn)提供便利
- The pid namespace: Process isolation (PID: Process ID).基于進(jìn)程的隔離能力边翁,容器中的首個(gè)進(jìn)程成為PID為1的進(jìn)程,是所有進(jìn)程的父進(jìn)程硕盹,以及很多特權(quán)
- The net namespace: Managing network interfaces (NET: Networking).基于網(wǎng)絡(luò)棧的隔離能力符匾,容器中的進(jìn)程和特定的網(wǎng)絡(luò)關(guān)聯(lián)起來
- The ipc namespace: Managing access to IPC resources (IPC: InterProcess Communication).基于System V進(jìn)程信道的隔離能力
- The mnt namespace: Managing filesystem mount points (MNT: Mount).基于磁盤掛載點(diǎn)和文件系統(tǒng)的隔離能力
- The uts namespace: Isolating kernel and version identifiers. (UTS: Unix Timesharing System).基于主機(jī)名的隔離能力
- The user namespace:基于系統(tǒng)用戶的隔離能力,同一用戶在不同namespace中可以擁有不同的UID和GID
# 查看進(jìn)程的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)用程序限制到特定的一組資源啊胶。控制組允許Docker Engine將可用的硬件資源共享給容器垛贤,也可以強(qiáng)制執(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ì)上對(duì)CGroup的所有操作都是對(duì)系統(tǒng)掛載的CGroup目錄進(jìn)行修改某饰,在/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組合到一個(gè)稱為容器格式的包裝器中剂跟。默認(rèn)的容器格式是libcontainer
劳较。將來,Docker可能支持其他容器格式
Docker基本概念
Images
Docker鏡像依照OCI(Open Container Initiative)規(guī)范浩聋,是一個(gè)只讀模板(內(nèi)容在構(gòu)建之后不會(huì)改變),一個(gè)image由manifest
臊恋、image index
(可選)衣洁、filesystem layers
和configuration
四部分組成
鏡像采用分層的結(jié)構(gòu),可以最大化利用磁盤存儲(chǔ)抖仅,因?yàn)榇蠖鄶?shù)的鏡像都會(huì)基于一些標(biāo)準(zhǔn)的基礎(chǔ)鏡像來構(gòu)建坊夫,分層存儲(chǔ)方便重復(fù)利用
最底層bootfs(boot file system)
是一個(gè)引導(dǎo)文件系統(tǒng),Linux在啟動(dòng)后之后撤卢,整個(gè)內(nèi)核都會(huì)被加載進(jìn)內(nèi)环凿,bootfs
會(huì)被卸載掉,之上是rootfs
放吩,即經(jīng)典的目錄結(jié)構(gòu)智听,對(duì)于base image
來說,底層直接用host
的kernel
,自己只需要提供rootfs
就行了到推,對(duì)應(yīng)的所有容器都共用host
的kernel
使用Dockerfile創(chuàng)建image考赛,Dockerfile中的每條指令都在鏡像中創(chuàng)建一個(gè)層,每安裝一個(gè)軟件莉测,就在現(xiàn)有鏡像的基礎(chǔ)上增加一層,鏡像的每一層都可以被共享颜骤,例如多個(gè)鏡像都從相同的base
鏡像構(gòu)建而來,那么主機(jī)只需在磁盤上保存一份base
鏡像捣卤,更改Dockerfile并重建映像時(shí)忍抽,僅重建那些已更改的層,這使鏡像輕量董朝,小巧和快速
當(dāng)容器啟動(dòng)時(shí)鸠项,一個(gè)新的可寫層被加載到鏡像的頂部。這一層通常被稱作容器層 container layer
益涧,“容器層”之下的都叫“鏡像層”锈锤,對(duì)容器的改動(dòng) - 無論添加、刪除闲询、還是修改文件都只會(huì)發(fā)生在容器層中久免,只有容器層是可寫的,容器層具有Copy-on-Write
特性扭弧,下面的所有鏡像層都是只讀的阎姥,當(dāng)需要修改時(shí)才復(fù)制一份數(shù)據(jù)到容器層進(jìn)行修改「肽恚可見呼巴,容器層保存的是鏡像變化的部分,不會(huì)對(duì)鏡像本身進(jìn)行任何修改
docker使用UnionFS文件系統(tǒng)御蒲,它能將多個(gè)文件系統(tǒng)的內(nèi)容合并起來衣赶,形成一個(gè)單一的掛載點(diǎn),掛到同一個(gè)目錄下厚满,底層使用copy on write技術(shù)府瞄,對(duì)文件的修改的會(huì)被向上拷貝到文件系統(tǒng)的一個(gè)臨時(shí)分層里,不會(huì)影響文件系統(tǒng)的原始數(shù)據(jù)碘箍,Docker支持眾多的聯(lián)合文件系統(tǒng)遵馆,可以在啟動(dòng)Docker后臺(tái)服務(wù)時(shí)通過--storage-driver
參數(shù)制定所使用的容器存儲(chǔ)種類,例如aufx丰榴,overlay2货邓,devicemapper等
Containers
容器是鏡像的可運(yùn)行實(shí)例,可以通過Docker API或CLI創(chuàng)建四濒,啟動(dòng)换况,停止职辨,移動(dòng)或刪除容器「绰。可以將容器連接到一個(gè)或多個(gè)網(wǎng)絡(luò)拨匆,并連接上存儲(chǔ),也可以根據(jù)其當(dāng)前狀態(tài)創(chuàng)建新的鏡像挽拂。
默認(rèn)情況下惭每,容器與其他容器以及宿主機(jī)相對(duì)隔離,但是可以自由控制容器的網(wǎng)絡(luò)亏栈,存儲(chǔ)或其他底層子系統(tǒng)與其他容器或宿主機(jī)的隔離程度台腥。容器由其鏡像以及在創(chuàng)建或啟動(dòng)時(shí)為其提供的配置選項(xiàng)定義,容器內(nèi)的文件是和宿主機(jī)隔離開的绒北,如果不進(jìn)行數(shù)據(jù)卷掛載黎侈,容器關(guān)閉以后數(shù)據(jù)就會(huì)丟失
Services
Service允許在多個(gè)Docker daemons中擴(kuò)展容器,一起作為一個(gè)swarm集群工作闷游,內(nèi)部具有多個(gè)manager和worker節(jié)點(diǎn)峻汉。swarm的每個(gè)成員都是Docker daemon,并且都使用Docker API進(jìn)行通信脐往。 可以再服務(wù)中定義所需的狀態(tài)休吠,例如服務(wù)副本數(shù)。默認(rèn)情況下业簿,服務(wù)在所有工作節(jié)點(diǎn)之間進(jìn)行負(fù)載平衡瘤礁。 對(duì)于訪問者來說,Docker服務(wù)似表現(xiàn)的就像一個(gè)單獨(dú)的應(yīng)用程序梅尤。Docker Engine在Docker 1.12及以上版本中支持swarm模式柜思,進(jìn)行集群服務(wù)管理
部署層次
Containers
Docker通過讀取Dockerfile
中的指令自動(dòng)構(gòu)建鏡像,Dockerfile是一個(gè)文本文檔巷燥,定義了容器環(huán)境內(nèi)進(jìn)行的操作赡盘。在容器內(nèi)對(duì)網(wǎng)絡(luò)接口和磁盤等資源的訪問是虛擬化的,與系統(tǒng)的其他部分隔離缰揪,因此需要在dockerfile中將端口映射到宿主機(jī)亡脑,具體說明要“復(fù)制”到哪些文件到容器,掛載數(shù)據(jù)卷等邀跃,然后就可以啟動(dòng)一個(gè)運(yùn)行鏡像的容器
Services
在分布式應(yīng)用程序中,應(yīng)用程序的不同部分稱為“services”蛙紫。例如拍屑,如果一個(gè)視頻共享站點(diǎn),它可能包括一個(gè)用于將應(yīng)用程序數(shù)據(jù)存儲(chǔ)在數(shù)據(jù)庫中的服務(wù)坑傅,一個(gè)用戶上傳內(nèi)容后進(jìn)行視頻轉(zhuǎn)碼的服務(wù)僵驰,前端web服務(wù)等
服務(wù)實(shí)際上只是“工作狀態(tài)的容器”,一個(gè)服務(wù)只運(yùn)行一個(gè)鏡像,但它設(shè)定了鏡像的運(yùn)行方式蒜茴,包括應(yīng)該使用哪些端口星爪,應(yīng)該運(yùn)行多少個(gè)容器副本,以及服務(wù)具有所需的容量粉私,等等顽腾。擴(kuò)展一個(gè)服務(wù)會(huì)改變運(yùn)行該部分程序的容器的數(shù)量,為該服務(wù)分配更多計(jì)算資源诺核,通過YAML文件即可定義抄肖,運(yùn)行和擴(kuò)展服務(wù)
Stacks
stack是一組關(guān)聯(lián)的services,它們共享依賴關(guān)系窖杀,并且可以被一起編排縮放漓摩。堆棧能夠定義和協(xié)調(diào)整個(gè)應(yīng)用程序的功能,對(duì)外體現(xiàn)為多個(gè)容器組合而成的復(fù)雜系統(tǒng)
docker stack deploy -c docker-compose.yml stack_nameXXX
Swarm
Docker Swarm是docker的原生集群入客,用于多個(gè)機(jī)器上創(chuàng)建容器集群服務(wù)管毙,一個(gè)swarm
是運(yùn)行Docker并加入一個(gè)群集的一組計(jì)算機(jī),集群中的機(jī)器被稱為node桌硫。該模塊叫做Swarm Mode
夭咬,早期版本中叫做Swarm standalone
內(nèi)部使用Etcd中的Raft模塊確定Master
節(jié)點(diǎn),raft是分布式一致性協(xié)議鞍泉,用于解決在網(wǎng)絡(luò)集群中進(jìn)行狀態(tài)確認(rèn)的問題
# 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é)點(diǎn)分配任務(wù)
Active
正常
Pause
不能分配新的任務(wù)皱埠,但是已有task可以繼續(xù)運(yùn)行
Drain
不能分配新的任務(wù),調(diào)度器關(guān)閉已有的Task咖驮,在其他節(jié)點(diǎn)上運(yùn)行边器,通常用于對(duì)節(jié)點(diǎn)進(jìn)行維護(hù)升級(jí)
MANAGER STATUS
列顯示節(jié)點(diǎn)在Raft的角色:
- 沒有值表示不參與群組管理的工作節(jié)點(diǎn)
-
Leader
表明節(jié)點(diǎn)是primary manager node
,對(duì)集群進(jìn)行管理和編排 -
Reachable
該節(jié)點(diǎn)是參與Raft共識(shí)仲裁的manager托修。 如果leader節(jié)點(diǎn)變得不可用忘巧,則該節(jié)點(diǎn)有資格被選為新leader -
Unavailable
意味著該manager節(jié)點(diǎn)無法與其他manage通信
Swarm manager是集群中唯一可以執(zhí)行命令的機(jī)器,或授權(quán)其他機(jī)器作為worker加入群集,worker只執(zhí)行工作睦刃,沒有權(quán)力調(diào)度集群
Docker Machine
Docker Machine是一個(gè)工具砚嘴,用于在虛擬機(jī)上安裝Docker Engine
,并使用docker-machine
命令管理這些主機(jī)
數(shù)據(jù)管理
在Docker的使用過程中往往需要對(duì)數(shù)據(jù)進(jìn)行持久化涩拙,或者需要在多個(gè)容器之間進(jìn)行數(shù)據(jù)共享际长,所以這就涉及到Docker容器的數(shù)據(jù)操作
- Volumes方式下:容器內(nèi)的數(shù)據(jù)被存放到宿主機(jī)(linux)一個(gè)特定的目錄下(/var/lib/docker/volumes/)。這個(gè)目錄只有Docker可以管理兴泥,其他進(jìn)程不能修改工育。如果想持久保存容器的應(yīng)用數(shù)據(jù),Volumes是Docker推薦的掛載方式
- Bind mounts方式下:容器內(nèi)的數(shù)據(jù)被存放到宿主機(jī)文件系統(tǒng)的任意位置搓彻,甚至存放到一些重要的系統(tǒng)目錄或文件中如绸。除了Docker之外的進(jìn)程也可以任意對(duì)他們進(jìn)行修改
- tmpfs方式下:容器的數(shù)據(jù)只會(huì)存放到宿主機(jī)的內(nèi)存中嘱朽,不會(huì)被寫到宿主機(jī)的文件系統(tǒng)中,因此不能持久保存容器的應(yīng)用數(shù)據(jù)怔接。
Volumes
由Docker創(chuàng)建和管理搪泳,可以通過命令docker volume create
來現(xiàn)式創(chuàng)建一個(gè)卷,也可以由Docker在創(chuàng)建容器或服務(wù)的過程中來創(chuàng)建
當(dāng)創(chuàng)建一個(gè)volume時(shí)扼脐,它將會(huì)被存儲(chǔ)到宿主機(jī)的一個(gè)目錄下/lib/docker/volumes/<volumn-name>
岸军,當(dāng)掛載這個(gè)volume到一個(gè)容器中時(shí),就是掛載這個(gè)目錄到容器中谎势。這和bind mount的工作機(jī)制很相似凛膏,但是volume是被Docker所管理并與宿主機(jī)其他核心功能隔離
一個(gè)volume可以被同時(shí)掛載到多個(gè)容器中。當(dāng)沒有任何容器在使用這個(gè)volume的時(shí)候脏榆,這個(gè)volume也仍然可以被Docker獲取猖毫,并不會(huì)被自動(dòng)被刪除⌒胛梗可以使用命令刪除不使用的volume:docker volume prune
當(dāng)掛載一個(gè)volume時(shí)吁断,可以選擇為他命名(named),也可以匿名(anonymous). 匿名volume首次被掛載到一個(gè)容器中時(shí)坞生,Docker會(huì)給它一個(gè)隨機(jī)的名字仔役,保證在宿主機(jī)操作系統(tǒng)中這個(gè)volume的名字是唯一的。除了名字之外是己,命名和匿名的volume沒有區(qū)別又兵。
Volume也支持使用volume drivers,用來將數(shù)據(jù)保存到遠(yuǎn)程主機(jī)或云上
Bind mounts
在docker的早期版本中就存在該功能卒废,與volumes相比沛厨,他的功能比較局限。當(dāng)使用bind mounts時(shí)摔认,宿主機(jī)的目錄或文件被掛載到容器中。容器將按照掛載目錄或文件的絕對(duì)路徑來使用或修改宿主機(jī)的中的數(shù)據(jù)参袱。宿主機(jī)中的目錄或文件不需要預(yù)先存在电谣,在需要的時(shí)候會(huì)自動(dòng)創(chuàng)建。使用Bind mounts在性能上是非常好的抹蚀,但這依賴于宿主機(jī)有一個(gè)目錄結(jié)構(gòu)妥善的文件系統(tǒng)剿牺。如果你要?jiǎng)?chuàng)建一個(gè)新的Docker應(yīng)用,推薦使用named volume的方式环壤,因?yàn)槟銦o法通過Docker CLI來管理bind mounts
bind mounts是一把雙刃劍晒来,因?yàn)榭梢栽谕ㄟ^容器內(nèi)部的進(jìn)程對(duì)主機(jī)文件系統(tǒng)進(jìn)行修改,包括創(chuàng)建镐捧,修改和刪除重要的系統(tǒng)文件和目錄潜索,這個(gè)功能雖然很強(qiáng)大,但顯然也會(huì)造成安全方面的影響懂酱,包括影響到宿主機(jī)上Docker以外的進(jìn)程
tmpfs mounts
僅Linux系統(tǒng)支持竹习,容器內(nèi)的應(yīng)用數(shù)據(jù)將不會(huì)被持久的保存到硬盤上,其中的數(shù)據(jù)只能在某個(gè)容器的生存周期內(nèi)被使用列牺,用于保存一些不需要持久存儲(chǔ)整陌,或一些敏感的數(shù)據(jù)信息。比如瞎领,在docker內(nèi)部泌辫,swarm服務(wù)使用tmpfs方式來將secrets掛載到服務(wù)容器中
Bind mounts和volumes都可以通過使用標(biāo)志v
或--volume
來掛載到容器中,只是格式有些許不同九默。tmpfs可以使用標(biāo)志-tmpfs
進(jìn)行掛載震放。在Docker17.06及其以上版本中,推薦使用--mount
來對(duì)容器或服務(wù)進(jìn)行這三種方式的掛載驼修,因?yàn)檫@種格式更加清晰
網(wǎng)絡(luò)
Docker網(wǎng)絡(luò)模塊主要依賴libnetwork
殿遂,依照Container Network Model (CNM) 實(shí)現(xiàn)
網(wǎng)絡(luò)模型
CNM:Container Network Model,容器的標(biāo)準(zhǔn)網(wǎng)絡(luò)模型乙各,只要符合這個(gè)模型的網(wǎng)絡(luò)接口就能被用于容器之間的通信墨礁,通信的細(xì)節(jié)和過程完全由網(wǎng)絡(luò)接口實(shí)現(xiàn),涉及三個(gè)術(shù)語:
- Sandbox:對(duì)應(yīng)一個(gè)網(wǎng)絡(luò)環(huán)境耳峦,包括網(wǎng)卡配置恩静、路由表、DNS配置等
- Endpoint:容器中的虛擬網(wǎng)卡蹲坷,顯示為eth0驶乾、eth1
- Network:能夠相互通信的容器網(wǎng)絡(luò),加入了同一個(gè)網(wǎng)絡(luò)的容器可以直接通過對(duì)方的名字相互連接冠句,實(shí)體是主機(jī)上的虛擬網(wǎng)卡或網(wǎng)橋
CNI標(biāo)準(zhǔn):Container Networking Interface 另一個(gè)輕量級(jí)的應(yīng)用容器網(wǎng)絡(luò)的開放插件化標(biāo)準(zhǔn)轻掩,多數(shù)容器集群架構(gòu)都使用該標(biāo)準(zhǔn),例如Kubernetes懦底、Mesos
- Container:擁有獨(dú)立Network Namespace的運(yùn)行單元唇牧,與CNM的Sandbox概念基本一致
- Network:可以互相連接的一組實(shí)體,實(shí)體擁有各自獨(dú)立的唯一IP地址聚唐,例如容器丐重,物理機(jī)或網(wǎng)關(guān)、路由器等網(wǎng)絡(luò)設(shè)備杆查,相當(dāng)于CNM的Network加Endpoint概念
容器網(wǎng)絡(luò)涉及的其他技術(shù):
- Virtual Bridge:虛擬的網(wǎng)絡(luò)交換單元扮惦,功能相當(dāng)于交換機(jī),為連在其中的設(shè)備轉(zhuǎn)發(fā)數(shù)據(jù)幀亲桦,例如Docker默認(rèn)創(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浊仆,由兩個(gè)虛擬網(wǎng)卡組成的數(shù)據(jù)通道,用于不同network namespace間進(jìn)行通信豫领,例如veth pair 一端連接到容器中作為eth0網(wǎng)卡抡柿,另一端連接到docker0網(wǎng)橋,將容器的數(shù)據(jù)發(fā)往另一個(gè) network namespace
Docker的網(wǎng)絡(luò)實(shí)現(xiàn)
Docker網(wǎng)絡(luò)共有四種模式
- none
容器內(nèi)只有回環(huán)網(wǎng)絡(luò)等恐,容器擁有自己獨(dú)立的network namespace洲劣,但不進(jìn)行配置,通常在容器不需要網(wǎng)絡(luò)或者自定義網(wǎng)絡(luò)時(shí)使用 - host
直接使用host的網(wǎng)絡(luò)课蔬,容器共享宿主機(jī)的network namespace囱稽,使用的是宿主機(jī)的IP、端口等資源 - bridge
docker的默認(rèn)網(wǎng)絡(luò)模式二跋,docker在安裝時(shí)會(huì)創(chuàng)建一個(gè)名為docker0
的Linux bridge战惊,默認(rèn)網(wǎng)段是172.17.0.0/16,在不指定network
的情況下同欠,新建的容器都會(huì)通過veth pair默認(rèn)掛到docker0上样傍,并在該網(wǎng)段內(nèi)獲取一個(gè)IP,在同一個(gè)網(wǎng)橋內(nèi)的容器可以通過IP地址通信铺遂,外部以及不同網(wǎng)絡(luò)之間的通信需要通過映射到主機(jī)的端口衫哥,底層依靠iptables實(shí)現(xiàn)端口轉(zhuǎn)發(fā)功能
容器與宿主機(jī)通信:在橋接模式下,Docker Daemon 將 veth0 附加到 docker0 網(wǎng)橋上襟锐,保證宿主機(jī)的報(bào)文有能力發(fā)往 veth0撤逢。再將 veth1 添加到 Docker 容器所屬的網(wǎng)絡(luò)命名空間,保證宿主機(jī)的網(wǎng)絡(luò)報(bào)文若發(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ū)動(dòng)程序在多個(gè)Docker daemon主機(jī)之間創(chuàng)建分布式的網(wǎng)絡(luò)媳叨。該網(wǎng)絡(luò)(overlap)位于主機(jī)網(wǎng)絡(luò)之上,允許連接到它的容器進(jìn)行通信关顷。它基于VxLAN實(shí)現(xiàn)糊秆,原理就是進(jìn)行額外的裝包、拆包议双,因?yàn)楝F(xiàn)有網(wǎng)絡(luò)只認(rèn)識(shí)節(jié)點(diǎn)到節(jié)點(diǎn)的路由痘番,容器間通信時(shí)將數(shù)據(jù)包加上額外的傳輸協(xié)議包頭(ISO網(wǎng)絡(luò)模型二層或以上協(xié)議),先將數(shù)據(jù)傳輸?shù)侥康墓?jié)點(diǎn),解包后傳輸?shù)侥康娜萜?/li>
初始化swarm或?qū)ocker主機(jī)加入現(xiàn)有swarm時(shí)汞舱,會(huì)在該Docker主機(jī)上創(chuàng)建兩個(gè)新網(wǎng)絡(luò):
- 一個(gè)名為
ingress
的overlay
網(wǎng)絡(luò)伍纫,用于處理與swarm service相關(guān)的控制和數(shù)據(jù)流量。創(chuàng)建swarm service時(shí)昂芜,如果不將其連接到用戶定義的overlay網(wǎng)絡(luò)翻斟,則默認(rèn)下會(huì)連接到ingress網(wǎng)絡(luò) - 一個(gè)名為
docker_gwbridge
的bridge網(wǎng)絡(luò),所有加入swarm的主機(jī)上都有該網(wǎng)橋说铃,且網(wǎng)段是相同的
端口相關(guān):
- TCP 端口 2377 用來進(jìn)行集群管理通信
- TCP UDP 端口 7946 用來節(jié)點(diǎn)之間通信
- UDP 端口 4789 用來進(jìn)行覆蓋網(wǎng)絡(luò)的通信
容器網(wǎng)絡(luò)還有另外一種經(jīng)典模式,Container模式:該模式下啟動(dòng)的容器將和指定的其他容器共享network namespace嘹履,該模式也是Kubernetes使用的網(wǎng)絡(luò)模式
跨結(jié)點(diǎn)網(wǎng)絡(luò)
基本條件
- 對(duì)IP分配進(jìn)行規(guī)劃腻扇,使得每個(gè)容器對(duì)應(yīng)不同的IP地址
- 記錄容器IP和宿主機(jī)IP的映射關(guān)系
解決方案:
集群IP統(tǒng)一分配,通常會(huì)給每個(gè)主機(jī)分配一個(gè)IP段砾嫉,每個(gè)主機(jī)會(huì)知道當(dāng)前節(jié)點(diǎn)所有容器的路由規(guī)則幼苛,以及集群所有IP段到對(duì)應(yīng)主機(jī)的路由規(guī)則,路由過程中首先是源容器將數(shù)據(jù)發(fā)送到目標(biāo)容器所在的主機(jī)節(jié)點(diǎn)焕刮,然后由目標(biāo)主機(jī)的本地路由規(guī)則將數(shù)據(jù)包送到真正的目標(biāo)容器
此外該中心地址分配器需要保證穩(wěn)定性舶沿,例如Flannal和Calico通過Etcd服務(wù)存儲(chǔ)網(wǎng)絡(luò)分配信息,內(nèi)部使用一致性協(xié)議Raft保證消息的可靠性
- 覆蓋網(wǎng)絡(luò):主要是基于VxLAN實(shí)現(xiàn)夸節(jié)點(diǎn)網(wǎng)絡(luò)
- Docker內(nèi)置的overlap網(wǎng)絡(luò)
- Flannel的UDP和VxLAN模式
- 擴(kuò)展路由:讓容器的IP和主機(jī)的IP地址一樣配并,直接進(jìn)行通信括荡,不需要額外的封裝,具體有macvlan溉旋,節(jié)點(diǎn)網(wǎng)關(guān)路由畸冲,節(jié)點(diǎn)BGP路由三種
- Docker的macvlan網(wǎng)絡(luò)模式
- Caliao基于節(jié)點(diǎn)BGP協(xié)議的路由方案,可以直接利用數(shù)據(jù)中心的網(wǎng)絡(luò)結(jié)構(gòu)观腊,不需要額外的NAT邑闲、隧道或者Overlay Network,沒有額外的封包解包梧油,提升網(wǎng)絡(luò)效率
- Flannel的HostGW模式:基于內(nèi)核路由表和Iptable規(guī)則的路由方案
macvlan技術(shù)在主機(jī)網(wǎng)卡上添加多個(gè)MAC地址(需要硬件設(shè)備的支持)苫耸,對(duì)應(yīng)上多個(gè)IP,每個(gè)網(wǎng)卡分配給容器的不同Network Namespace儡陨,就相當(dāng)于把所有容器的網(wǎng)絡(luò)都直接相連到了主機(jī)網(wǎng)卡
節(jié)點(diǎn)網(wǎng)關(guān)路由:每個(gè)節(jié)點(diǎn)上運(yùn)行一個(gè)Agent服務(wù)褪子,監(jiān)聽容器IP段的分配,一旦由變化就將新的路由規(guī)則刷新到內(nèi)核路由表迄委,每個(gè)節(jié)點(diǎn)上的Agent就是一個(gè)控制網(wǎng)絡(luò)聯(lián)通規(guī)則的網(wǎng)關(guān)程序褐筛,這種方法稱為主機(jī)網(wǎng)關(guān)
節(jié)點(diǎn)BGP路由:如果節(jié)點(diǎn)直接隔著一個(gè)路由器,節(jié)點(diǎn)網(wǎng)關(guān)路由就會(huì)失效叙身,路由器沒有相應(yīng)的路由規(guī)則渔扎,此時(shí)需要Agent把自己作為容器所在IP子網(wǎng)段的邊界路由器,利用BGP協(xié)議讓網(wǎng)絡(luò)中的其他三層設(shè)備學(xué)習(xí)到容器網(wǎng)段的路由信息
Flannel容器網(wǎng)絡(luò)方案
Flannel實(shí)現(xiàn)原理
- 每個(gè)主機(jī)上的Docker容器分配互相不沖突的IP地址
- 在這些IP地址之間建立一個(gè)覆蓋網(wǎng)絡(luò)
Flannel會(huì)啟動(dòng)flanneld
進(jìn)程信轿,連接etcd晃痴,管理IP地址段的分配残吩,初始時(shí)獲取一個(gè)未分配的地址段糜俗,然后在Docker的啟動(dòng)參數(shù)中指定docker0網(wǎng)橋的地址蛤虐,flannel之間的底層通信協(xié)議有很多,例如UDP味抖,VxLAN等紧唱,通過在應(yīng)用層進(jìn)行封裝活尊、解包進(jìn)行通信
--bip=172.24.77.1/24
# ifconfig 中的部分?jǐn)?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