1袜刷、Docker Client 配置容器網(wǎng)絡(luò)模式
Docker 目前支持 4 種網(wǎng)絡(luò)模式,分別是 bridge莺丑、host著蟹、container、none
配置 Docker Container 網(wǎng)絡(luò)環(huán)境與創(chuàng)建 Docker Container 網(wǎng)絡(luò)環(huán)境有一些區(qū)別
- 配置網(wǎng)絡(luò)環(huán)境指用戶通過向 Docker Client 傳遞網(wǎng)絡(luò)參數(shù)梢莽,實現(xiàn) Docker Container 網(wǎng)絡(luò)環(huán)境參數(shù)的配置萧豆,這部分配置由 Docker Client 傳遞至 Docker Daemon,并由 Docker Daemon 保存
- 創(chuàng)建網(wǎng)絡(luò)環(huán)境指昏名,用戶通過 Docker Client 向 Docker Daemon 發(fā)送容器啟動命令之后涮雷,Docker Daemon 根據(jù)之前保存的網(wǎng)絡(luò)參數(shù),實現(xiàn) Docker Container 的啟動轻局,并在啟動過程中完成 Docker Container 網(wǎng)絡(luò)環(huán)境的創(chuàng)建洪鸭。
1.1、Docker Client 使用
Docker 架構(gòu)中仑扑,用戶可以通過 Docker Client 來配置 Docker Container 的網(wǎng)絡(luò)模式览爵。配置過程主要通過 docker run 命令來完成,實現(xiàn)配置的方式是在 docker run 命令中添加網(wǎng)絡(luò)參數(shù)镇饮。
Docker Client 解析出 run 命令之后蜓竹,立即調(diào)用相應(yīng)的處理函數(shù) CmdRun 進行處理關(guān)于 run 請求的具體內(nèi)容。CmdRun 的作用主要可以歸納為三點:
*解析 Docker Client 傳入的參數(shù)盒让,解析出 config、hostconfig 和 cmd 對象等司蔬;
*發(fā)送請求至 Docker Daemon邑茄,創(chuàng)建一個 container 對象,完成 Docker Container 啟動前的準備工作俊啼;
*發(fā)送請求至 Docker Daemon肺缕,啟動相應(yīng)的 Docker Container(包含創(chuàng)建 Docker Container 網(wǎng)絡(luò)環(huán)境創(chuàng)建)。
1.2授帕、runconfig 包解析
config 的類型為 Config 結(jié)構(gòu)體同木,hostConfig 的類型為 HostConfig 結(jié)構(gòu)體,兩種類型的定義均位于 runconfig 包跛十。Config 與 HostConfig 類型同用以描述 Docker Container 的配置信息彤路,然而兩者之間又有著本質(zhì)的區(qū)別,最大的區(qū)別在于兩者各自的作用范疇:
*Config 結(jié)構(gòu)體:描述 Docker Container 獨立的配置信息芥映。獨立的含義是:Config 這部分信息描述的是容器本身洲尊,而不會與容器所在 host 宿主機相關(guān)远豺;
*HostConfig 結(jié)構(gòu)體:描述 Docker Container 與宿主機相關(guān)的配置信息。
1.2.1坞嘀、Config 結(jié)構(gòu)體
結(jié)構(gòu)體的定義如下:
type Config struct {
Hostname string //容器主機名
Domainname string //域名名稱
User string //用戶名
Memory int64 // Memory limit (in bytes)容器內(nèi)存使用上限(單位:字節(jié))
MemorySwap int64 // Total memory usage (memory + swap); set `-1' to disable swap 容器所有的內(nèi)存使用上限(物理內(nèi)存 + 交互區(qū))躯护,關(guān)閉交互區(qū)支持置為 -1
CpuShares int64 // CPU shares (relative weight vs. other containers)容器 CPU 使用 share 值,其他容器的相對值
Cpuset string // Cpuset 0-2, 0,1CPU 核的使用集合
AttachStdin bool //是否附加標準輸入
AttachStdout bool //是否附加標準輸出
AttachStderr bool //是否附加標準錯誤輸出
PortSpecs []string // Deprecated - Can be in the format of 8080/tcp 目前已被遺棄
ExposedPorts map[nat.Port]struct{} //容器內(nèi)部暴露的端口號
Tty bool // Attach standard streams to a tty, including stdin if it is not closed.是否分配一個偽終端 tty
OpenStdin bool // Open stdin 在沒有附加標準輸入時丽涩,是否依然打開標準輸入
StdinOnce bool // If true, close stdin after the 1 attached client disconnects.若為真棺滞,表示第一個客戶關(guān)閉標準輸入后關(guān)閉標準輸入功能
Env []string //容器進程運行的環(huán)境變量
Cmd []string //容器內(nèi)通過 ENTRYPOINT 運行的指令
Image string // Name of the image as it was passed by 容器 rootfs 所依賴的鏡像名稱
the operator (eg. could be symbolic)
Volumes map[string]struct{} //容器需要從 host 宿主機上掛載的目錄
WorkingDir string //容器內(nèi)部的指定工作目錄
Entrypoint []string //覆蓋鏡像屬性中默認的 ENTRYPOINT
NetworkDisabled bool //是否關(guān)閉容器網(wǎng)絡(luò)功能
OnBuild []string
}
1.2.2、HostConfig 結(jié)構(gòu)體
結(jié)構(gòu)體的定義如下:
type HostConfig struct {
Binds []string //從宿主機上綁定到容器的 volumes
ContainerIDFile string //文件名矢渊,文件用以寫入容器的 ID
LxcConf []utils.KeyValuePair //添加自定義的 lxc 選項
Privileged bool //是否賦予該容器擴展權(quán)限
PortBindings nat.PortMap //容器綁定到 host 宿主機的端口
Links []string //添加其他容器的鏈接到該容器
PublishAllPorts bool //是否向宿主機暴露所有端口信息
Dns []string //自定義的 DNS 服務(wù)器地址
DnsSearch []string //自定義的 DNS 查找服務(wù)器地址
VolumesFrom []string //從指定的容器中掛載到該容器的 volumes
Devices []DeviceMapping //為容器添加一個或多個宿主機設(shè)備
NetworkMode NetworkMode //為容器設(shè)置的網(wǎng)絡(luò)模式
CapAdd []string //為容器用戶添加一個或多個 Linux Capabilities
CapDrop []string //為容器用戶禁用一個或多個 Linux Capabilities
RestartPolicy RestartPolicy //當(dāng)一個容器異常退出時采取的重啟策略
}
1.2.3继准、runconfig 解析網(wǎng)絡(luò)模式
runconfig 包中的 ParseSubcommand 函數(shù)調(diào)用 parseRun 函數(shù)完成命令請求的分析,該函數(shù)完成了四方面的工作:
*定義與容器配置信息相關(guān)的 flag 參數(shù)昆淡;
*解析 docker run 命令后緊跟的請求內(nèi)容锰瘸,將請求內(nèi)容全部保存至 flag 參數(shù)中,余下的內(nèi)容一個為鏡像 image 名昂灵,另一個為需要在容器內(nèi)執(zhí)行的 cmd 命令避凝;
*通過 flag 參數(shù)驗證參數(shù)的有效性,并處理得到 Config 結(jié)構(gòu)體與 HostConfig 結(jié)構(gòu)體需要的屬性值眨补;
*創(chuàng)建并初始化 Config 類型實例 config管削、HostConfig 類型實例 hostConfig,最總返回 config撑螺、hostConfig 與 cmd含思。
1.3、CmdRun 執(zhí)行
CmdRun 后續(xù)主要工作是:利用 Docker Daemon 暴露的 RESTful API 接口甘晤,將 docker run 的請求發(fā)送至 Docker Daemon含潘。
CmdRun 執(zhí)行過程中 Docker Client 與 Docker Daemon 的簡易交互圖如下:
2、Docker Daemon 創(chuàng)建容器網(wǎng)絡(luò)流程
Docker Daemon 接收到 Docker Client 的請求大致可以分為兩次线婚,第一次為 create container遏弱,第二次為 start container
2.1、創(chuàng)建容器并配置網(wǎng)絡(luò)參數(shù)
Docker Daemon 首先接收并處理 create container 請求塞弊。需要注意的是:create container 并非創(chuàng)建了一個運行的容器漱逸,而是完成了以下三個主要的工作:
*通過 runconfig 包解析出 create container 請求中與 Docker Container 息息相關(guān)的 config 對象;
*在 Docker Daemon 內(nèi)部創(chuàng)建了與 Docker Container 對應(yīng)的 container 對象游沿;
*完成 Docker Container 啟動前的準備化工作饰抒,如準備所需鏡像、創(chuàng)建 rootfs 等诀黍。
與 Docker Container 網(wǎng)絡(luò)模式配置相關(guān)的內(nèi)容主要位于創(chuàng)建 container 對象中
container := &Container{
ID: id,
Created: time.Now().UTC(),
Path: entrypoint,
Args: args, //FIXME: de-duplicate from config
Config: config,
hostConfig: &runconfig.HostConfig{},
Image: img.ID, // Always use the resolved image id
NetworkSettings: &NetworkSettings{},
Name: name,
Driver: daemon.driver.String(),
ExecDriver: daemon.execDriver.Name(),
State: NewState(),
}
其中 hostConfig 對象將在 start container 請求執(zhí)行過程中被賦值袋坑,NetworkSettings 類型的作用是描述容器的網(wǎng)絡(luò)具體信息
type NetworkSettings struct {
IPAddress string //IP 網(wǎng)絡(luò)地址
IPPrefixLen int //網(wǎng)絡(luò)標識位長度
Gateway string //網(wǎng)關(guān)地址
Bridge string //網(wǎng)橋地址
PortMapping map[string]PortMapping // Deprecated 端口映射
Ports nat.PortMap //端口號
}
2.2、啟動容器之網(wǎng)絡(luò)配置
啟動容器過程中眯勾,Docker Daemon 首先通過 runconfig 包中 ContainerHostConfigFromJob 函數(shù)咒彤,解析出請求中的 hostConfig 對象
Start 函數(shù)執(zhí)行過程中疆柔,與 Docker Container 網(wǎng)絡(luò)模式相關(guān)的部分主要有三部分:
*initializeNetwork(),初始化 container 對象中與網(wǎng)絡(luò)相關(guān)的屬性镶柱;
*populateCommand蜈漓,填充 Docker Container 內(nèi)部需要執(zhí)行的命令聘芜,Command 中含有進程啟動命令迈倍,還含有容器環(huán)境的配置信息追城,也包括網(wǎng)絡(luò)配置;
*container.waitForStart()故觅,實現(xiàn) Docker Container 內(nèi)部進程的啟動厂庇,進程啟動之后,為進程創(chuàng)建網(wǎng)絡(luò)環(huán)境等输吏。
3权旷、execdriver 網(wǎng)絡(luò)執(zhí)行流程
在 Docker Daemon 啟動容器的最后一步,即調(diào)用了 execdriver 的 Run 函數(shù)來執(zhí)行贯溅。通過分析 Run 函數(shù)的具體實現(xiàn)拄氯,關(guān)于 Docker Container 的網(wǎng)絡(luò)執(zhí)行流程主要包括兩個環(huán)節(jié):
(1) 創(chuàng)建 libcontainer 的 Config 對象
(2) 通過 libcontainer 中的 namespaces 包執(zhí)行啟動容器
Docker Container 網(wǎng)絡(luò)相關(guān)的流程,可以得到以下示意圖:
3.1它浅、 創(chuàng)建 libcontainer 的 Config 對象
libcontainer.Config 的作用是译柏,定義在一個容器化的環(huán)境中執(zhí)行一個進程所需要的所有配置項。createContainer 函數(shù)的存在姐霍,使用 Docker Daemon 層創(chuàng)建的 execdriver.Command鄙麦,創(chuàng)建更下層 libcontainer 所需要的 Config 對象。這個角度來看镊折,execdriver 更像是封裝了 libcontainer 對外的接口胯府,實現(xiàn)了將 Docker Daemon 認識的容器啟動信息轉(zhuǎn)換為底層 libcontainer 能真正使用的容器啟動配置選項。libcontainer.Config 類型與其內(nèi)部對象的關(guān)聯(lián)圖如下:
3.2恨胚、 調(diào)用 libcontainer 的 namespaces 啟動容器
創(chuàng)建完 libcontainer.Config 實例 container骂因,經(jīng)過一系列其他方面的處理之后,最終 execdriver 執(zhí)行 namespaces.Exec 函數(shù)實現(xiàn)啟動容器与纽,container 對象依然是 namespace.Exec 函數(shù)中一個非常重要的參數(shù)
4侣签、libcontainer 實現(xiàn)內(nèi)核態(tài)網(wǎng)絡(luò)配置
當(dāng) execdriver 調(diào)用 libcontainer 中 namespaces 包的 Exec 函數(shù)時塘装,libcontainer 開始發(fā)揮其實現(xiàn)容器功能的作用急迂。Docker Container 的網(wǎng)絡(luò)創(chuàng)建,因此從這個角度來看Exec 的實現(xiàn)可以分為三個步驟:
(1) 通過 createCommand 創(chuàng)建一個 Golang 語言內(nèi)的 exec.Cmd 對象蹦肴;
(2) 啟動命令 exec.Cmd僚碎,執(zhí)行容器內(nèi)第一個進程;
(3) 通過 InitializeNetworking 函數(shù)為容器進程初始化網(wǎng)絡(luò)環(huán)境阴幌。