Docker源碼分析(六):Docker Daemon網絡


http://www.infoq.com/cn/articles/docker-source-code-analysis-part6

1. 前言

Docker作為一個開源的輕量級虛擬化容器引擎技術,已然給雲計算領域帶來了新的發展模式。Docker借助容器技術徹底釋放了輕量級虛擬化技術的威力,讓容器的伸縮、應用的運行都變得前所未有的方便與高效。同時,Docker借助強大的鏡像技術,讓應用的分發、部署與管理變得史無前例的便捷。然而,Docker畢竟是一項較為新穎的技術,在Docker的世界中,用戶並非一勞永逸,其中最為典型的便是Docker的網絡問題。

毋庸置疑,對於Docker管理者和開發者而言,如何有效、高效的管理Docker容器之間的交互以及Docker容器的網絡一直是一個巨大的挑戰。目前,雲計算領域中,絕大多數系統都采取分布式技術來設計並實現。然而,在原生態的Docker世界中,Docker的網絡卻是不具備跨宿主機能力的,這也或多或少滯后了Docker在雲計算領域的高速發展。

工業界中,Docker的網絡問題的解決勢在必行,在此環境下,很多IT企業都開發了各自的新產品來幫助完善Docker的網絡。這些企業中不乏像Google一樣的互聯網翹楚企業,同時也有不少初創企業率先出擊,在最前沿不懈探索。這些新產品中有,Google推出的容器管理和編排開源項目Kubernetes,Zett.io公司開發的通過虛擬網絡連接跨宿主機容器的工具Weave,CoreOS團隊針對Kubernetes設計的網絡覆蓋工具Flannel,Docker官方的工程師Jérôme Petazzoni自己設計的SDN網絡解決方案Pipework,以及SocketPlane項目等。

對於Docker管理者與開發者而言,Docker的跨宿主機通信能力固然重要,但Docker自身的網絡架構也同樣重要。只有深入了解Docker自身的網絡設計與實現,才能在這基礎上擴展Docker的跨宿主機能力。

Docker自身的網絡主要包含兩部分:Docker Daemon的網絡配置,Docker Container的網絡配置。本文主要分析Docker Daemon的網絡。

2. Docker Daemon網絡分析內容安排

本文從源碼的角度,分析Docker Daemon在啟動過程中,為Docker配置的網絡環境,章節安排如下:

 

(1) Docker Daemon網絡配置;

(2) 運行Docker Daemon網絡初始化任務;

(3) 創建Docker網橋。

本文為《Docker源碼分析》系列第六篇——Docker Daemon網絡篇,第七篇將安排Docker Container網絡篇。

3. Docker Daemon網絡配置

Docker環境中,Docker管理員完全有權限配置Docker Daemon運行過程中的網絡模式。 關於Docker的網絡模式,大家最熟知的應該就是“橋接”的模式。下圖為橋接模式下,Docker的網絡環境拓撲圖(包括Docker Daemon網絡環境和Docker Container網絡環境):

圖3.1 Docker網絡橋接示意圖

然而,“橋接”是Docker網絡模式中最為常用的模式。除此之外,Docker還為用戶提供了更多的可選項,下文將對此一一說來。

3.1 Docker Daemon網絡配置接口

Docker Daemon每次啟動的過程中,都會初始化自身的網絡環境,這樣的網絡環境最終為Docker Container提供網絡通信服務。

Docker管理員配置Docker的網絡環境,可以在Docker Daemon啟動時,通過Docker提供的接口來完成。換言之,可以使用docker二進制可執行文件,運行docker -d並添加相應的flag參數來完成。

其中涉及的flag參數有EnableIptables、EnableIpForward、BridgeIface、BridgeIP以及InterContainerCommunication。該五個參數的定義位於./docker/daemon/config.go,具體代碼如下:

flag.BoolVar(&config.EnableIptables, []string{"#iptables", "-iptables"}, true, "Enable Docker's addition of iptables rules")
flag.BoolVar(&config.EnableIpForward, []string{"#ip-forward", "-ip-forward"}, true, "Enable net.ipv4.ip_forward")
flag.StringVar(&config.BridgeIP, []string{"#bip", "-bip"}, "", "Use this CIDR notation address for the network bridge's IP, not compatible with -b")
flag.StringVar(&config.BridgeIface, []string{"b", "-bridge"}, "", "Attach containers to a pre-existing network bridge\nuse 'none' to disable container networking")
flag.BoolVar(&config.InterContainerCommunication, []string{"#icc", "-icc"}, true, "Enable inter-container communication")

以下介紹這5個flag的作用:

  • EnableIptables:確保Docker對於宿主機上的iptables規則擁有添加權限;
  • EnableIpForward:確保net.ipv4.ip_forward可以使用,使得多網絡接口設備模式下,數據報可以在網絡設備之間轉發;
  • BridgeIP:在Docker Daemon啟動過程中,為網絡環境中的網橋配置CIDR網絡地址;
  • BridgeIface:為Docker網絡環境指定具體的通信網橋,若BridgeIface的值為”none”,則說明不需要為Docker Container創建網橋服務,關閉Docker Container的網絡能力;
  • InterContainerCommunication:確保Docker容器之間可以完成通信。

除了Docker會使用到的5個flag參數之外,Docker在創建網絡環境時,還使用一個DefaultIP變量,如下:

opts.IPVar(&config.DefaultIp, []string{"#ip", "-ip"}, "0.0.0.0", "Default IP address to use when binding container ports")

該變量的作用是:當綁定容器的端口時,將DefaultIp作為默認使用的IP地址。

具備了以上Docker Daemon的網絡背景知識,以下着重舉例分析使用BridgeIP和BridgeIface,在啟動Docker Daemon時進行網絡配置:

啟動Docker Daemon使用命令

用途注釋

docker -d

啟動Docker Daemon,使用默認網橋docker0,不指定CIDR網絡地址

docker -d -b=”xxx”

啟動Docker Daemon,使用

網橋xxx,不指定CIDR網絡地址

docker -d --bip=”172.17.42.1”

啟動Docker Daemon,使用默認網橋docker0,使用指定CIDR網絡地址”172.17.42.1”

docker -d --bridge=”xxx” --bip=”10.0.42.1”

報錯,出現兼容性問題,不能同時指定”BridgeIP”和”BridgeIface”

docker -d --bridge=”none”

啟動Docker Daemon,

不創建Docker網絡環境

深入理解BridgeIface與BridgeIP,並熟練使用相應的flag參數,即做到了如何配置Docker Daemon的網絡環境。需要特別注意的是,Docker Daemon的網絡與Docker Container的網絡存在很大的區別。Docker Daemon為Docker Container創建網絡的大環境,Docker Container的網絡需要Docker Daemon的網絡提供支持,但不唯一。舉一個形象的例子,Docker Daemon可以創建docker0網橋,為之后Docker Container的橋接模式提供支持,然而Docker Container仍然可以根據用戶需求創建自身網絡,其中Docker Container的網絡可以是橋接模式的網絡,同時也可以直接共享使用宿主機的網絡接口,另外還有其他模式,會在《Docker源碼分析》系列的第七篇——Docker Container網絡篇中詳細介紹。

3.2 Docker Daemon網絡初始化

正如上一節所言,Docker管理員可以通過與網絡相關的flag參數BridgeIface與BridgeIP,來為Docker Daemon創建網路環境。最簡單的,Docker管理員通過執行”docker -d”就已經完成了運行Docker Daemon,而Docker Daemon在啟動的時候,根據以上兩個flag參數的值,創建相應的網絡環境。

Docker Daemon網絡初始化流程圖如下:

圖 3.2 Docker Daemon網絡初始化流程圖

Docker Daemon網絡初始化的流程總體而言,主要是根據解析flag參數來決定到底建立哪種類型的網絡環境。從流程圖中可知,Docker Daemon創建網絡環境時有兩個分支,不難發現分支代表的分別是:為Docker創建一個網絡驅動、以及對Docker的網絡不做任何的操作。

以下參照Docker Daemon網絡初始化流程圖具體分析實現步驟。

3.2.1 啟動Docker Daemon傳遞flag參數

用戶啟動Docker Daemon,並在命令行中選擇性的傳入所需要的flag參數。

3.2.2 解析網絡flag參數

flag包對命令行中的flag參數進行解析,其中和Docker Daemon網絡配置相關的flag參數有5個,分別是:EnableIptables、EnableIpForward、BridgeIP、BridgeIface以及InterContanierCommunication,各個flag參數的作用上文已有介紹。

3.2.3 預處理flag參數

預處理與網絡配置相關的flag參數信息,包括檢測配置信息的兼容性、以及判斷是否創建Docker網絡環境。

首先檢驗是否會出現彼此不兼容的配置信息,源碼位於./docker/daemon/daemon.go#L679-L685

這部分的兼容信息有兩種。第一種是BridgeIP和BridgeIface配置信息的兼容性,具體表現為用戶啟動Docker Daemon時,若同時指定了BridgeIP和BridgIface的值,則出現兼容問題。原因為這兩者屬於互斥對,換言之,若用戶指定了新建網橋的設備名,那么該網橋已經存在,無需指定網橋的IP地址BridgeIP;若用戶指定了新建網橋的網絡IP地址BridgeIP,那么該網橋肯定還沒有新建成功,則Docker Daemon在新建網橋時使用默認網橋名“docker0”。具體如下:

// Check for mutually incompatible config options
if config.BridgeIface != "" && config.BridgeIP != "" {
	return nil, fmt.Errorf("You specified -b & --bip, mutually exclusive options. Please specify only one.")
}

第二種是EnableIptables和InterContainerCommunication配置的兼容性,具體是指不能同時指定這兩個flag參數為false。原因很簡單,如果指定InterContainerCommunication為false,則說明Docker Daemon不允許創建的Docker容器之間互相進行通信。但是為了達到以上目的,Docker正是使用iptables過濾規則。因此,再次設定EnableIptables為false,關閉iptables的使用,即出現了自相矛盾的結果。代碼如下:

if !config.EnableIptables && !config.InterContainerCommunication {
	return nil, fmt.Errorf("You specified --iptables=false with --icc=false. ICC uses iptables to function. Please set --icc or --iptables to true.")
	}

檢驗完系統配置信息的兼容性問題,Docker Daemon接着會判斷是否需要為Docker Daemon配置網絡環境。判斷的依據為BridgeIface的值是否與DisableNetworkBridge的值相等,DisableNetworkBridge在./docker/daemon/config.go#L13中被定義為const量,值為字符串”none”。因此,若BridgeIface為”none”,則DisableNetwork為true,最終Docker Daemon不會創建網絡環境;若BridgeIface不為”none”,則DisableNetwork為false,最終Docker Daemon需要創建網絡環境(橋接模式)。

3.2.4 確定Docker網絡模式

Docker網絡模式由配置信息DisableNetwork決定。由於在上一環節已經得出DisableNetwork的值,故這一環節可以確定Docker網絡模式。該部分的源碼實現位於./docker/daemon/daemon.go#L792-L805,如下:

if !config.DisableNetwork {
	job := eng.Job("init_networkdriver")

	job.SetenvBool("EnableIptables", config.EnableIptables)
	job.SetenvBool("InterContainerCommunication", config.InterContainerCommunication)
	job.SetenvBool("EnableIpForward", config.EnableIpForward)
	job.Setenv("BridgeIface", config.BridgeIface)
	job.Setenv("BridgeIP", config.BridgeIP)
	job.Setenv("DefaultBindingIP", config.DefaultIp.String())

	if err := job.Run(); err != nil {
		return nil, err
	}
}

若DisableNetwork為false,則說明需要創建網絡環境,具體的模式為創建Docker網橋模式。創建網絡環境的步驟為:

(1) 創建名為”init_networkdriver”的job;

(2) 為該job配置環境變量,設置的環境變量有EnableIptables、InterContainerCommunication、EnableIpForward、BridgeIface、BridgeIP以及DefaultBindingIP;

(3) 運行job。

運行”init_network”即為創建Docker網橋,這部分內容將會在下一節詳細分析。

若DisableNetwork為true。則說明不需要創建網絡環境,網絡模式屬於none模式。

以上便是Docker Daemon網絡初始化的所有流程。

3.3 創建Docker網橋

Docker的網絡往往是Docker開發者最常提起的話題。而Docker網絡中最常使用的模式為bridge橋接模式。本小節將詳細分析創建Docker網橋的創建流程。

創建Docker網橋的實現通過”init_network”這個job的運行來完成。”init_network”的實現為InitDriver函數,位於./docker/daemon/networkdriver/bridge/driver.go#L79,運行流程如下:

圖3.3 Docker Daemon創建網橋流程圖

3.3.1 提取環境變量

在InitDriver函數的實現過程中,Docker首先提取”init_networkdriver”這個job的環境變量。這樣的環境變量共有6個,各自的作用在上文已經詳細說明。具體的實現代碼為:

var (
	network        *net.IPNet
	enableIPTables = job.GetenvBool("EnableIptables")
	icc            = job.GetenvBool("InterContainerCommunication")
	ipForward      = job.GetenvBool("EnableIpForward")
	bridgeIP       = job.Getenv("BridgeIP")
)

if defaultIP := job.Getenv("DefaultBindingIP"); defaultIP != "" {
	defaultBindingIP = net.ParseIP(defaultIP)
}

bridgeIface = job.Getenv("BridgeIface")

3.3.2 確定Docker網橋設備名

提取job的環境變量之后,Docker隨即確定最終使用網橋設備的名稱。為此,Docker首先創建了一個名為usingDefaultBridge的bool變量,含義為是否使用默認的網橋設備,默認值為false。接着,若環境變量中bridgeIface的值為空,則說明用戶啟動Docker時,沒有指定特定的網橋設備名,因此Docker首先將usingDefaultBridge置為true,然后使用默認的網橋設備名DefaultNetworkBridge,即docker0;若bridgeIface的值不為空,則判斷條件不成立,繼續往下執行。這部分的代碼實現為:

usingDefaultBridge := false
if bridgeIface == "" {
	usingDefaultBridge = true
	bridgeIface = DefaultNetworkBridge
}

3.3.3 查找bridgeIface網橋設備

確定Docker網橋設備名bridgeIface之后,Docker首先通過bridgeIface設備名在宿主機上查找該設備是否真實存在。若存在,則返回該網橋設備的IP地址,若不存在,則返回nil。實現代碼位於./docker/daemon/networkdriver/bridge/driver.go#L99,如下:

addr, err := networkdriver.GetIfaceAddr(bridgeIface)

GetIfaceAddr的實現位於./docker/daemon/networkdriver/utils.go,實現步驟為:首先通過Golang中net包的InterfaceByName方法獲取名為bridgeIface的網橋設備,會得出以下結果:

  • 若名為bridgeIface的網橋設備不存在,直接返回error;
  • 若名為bridgeIface的網橋設備存在,返回該網橋設備的IP地址。

需要強調的是:GetIfaceAddr函數返回error,說明當前宿主機上不存在名為bridgeIface的網橋設備。而這樣的結果會有兩種不同的情況:第一,用戶指定了bridgeIface,那么usingDefaultBridge為false,而該bridgeIface網橋設備在宿主機上不存在;第二,用戶沒有指定bridgeIface,那么usingDefaultBridge為true,bridgeIface名為docker0,而docker0網橋在宿主機上也不存在。

當然,若GetIfaceAddr函數返回的是一個IP地址,則說明當前宿主機上存在名為bridgeIface的網橋設備。這樣的結果同樣會有兩種不同的情況:第一,用戶指定了bridgeIface,那么usingDefaultBridge為false,而該bridgeIface網橋設備在宿主機上已經存在;第二,用戶沒有指定bridgeIface,那么usingDefaultBridge為true,bridgeIface名為docker0,而docker0網橋在宿主機上也已經存在。第二種情況一般是:用戶在宿主機上第一次啟動Docker Daemon時,創建了默認網橋設備docker0,而后docker0網橋設備一直存在於宿主機上,故之后在不指定網橋設備的情況下,重啟Docker Daemon,會出現docker0已經存在的情況。

以下兩小節將分別從bridgeIface已創建與bridgeIface未創建兩種不同的情況分析。

3.3.4 bridgeIface已創建的情況

Docker Daemon所在宿主機上bridgeIface的網橋設備存在時,Docker Daemon仍然需要驗證用戶在配置信息中是否為網橋設備指定了IP地址。

用戶啟動Docker Daemon時,假如沒有指定bridgeIP參數信息,則Docker Daemon使用名為bridgeIface的原有的IP地址。

當用戶指定了bridgeIP參數信息時,則需要驗證:指定的bridgeIP參數信息與bridgeIface網橋設備原有的IP地址信息是否匹配。若兩者匹配,則驗證通過,繼續往下執行;若兩者不匹配,則驗證不通過,拋出錯誤,顯示“bridgeIP與已有網橋配置信息不匹配”。該部分內容位於./docker/daemon/networkdriver/bridge/driver.go#L119-L129,代碼如下:

network = addr.(*net.IPNet)
// validate that the bridge ip matches the ip specified by BridgeIP
if bridgeIP != "" {
	bip, _, err := net.ParseCIDR(bridgeIP)
	if err != nil {
		return job.Error(err)
	}
	if !network.IP.Equal(bip) {
		return job.Errorf("bridge ip (%s) does not match existing bridge configuration %s", network.IP, bip)
	}
}

3.3.5 bridgeIface未創建的情況

Docker Daemon所在宿主機上bridgeIface的網橋設備未創建時,上文已經介紹將存在兩種情況:

l 用戶指定的bridgeIface未創建;

l 用戶未指定bridgeIface,而docker0暫未創建。

當用戶指定的bridgeIface不存在於宿主機時,即沒有使用Docker的默認網橋設備名docker0,Docker打印日志信息“指定網橋設備未找到”,並返回網橋未找到的錯誤信息。代碼實現如下:

if !usingDefaultBridge {
	job.Logf("bridge not found: %s", bridgeIface)
	return job.Error(err)
}

當使用的默認網橋設備名,而docker0網橋設備還未創建時,Docker Daemon則立即實現創建網橋的操作,並返回該docker0網橋設備的IP地址。代碼如下:

// If the iface is not found, try to create it
job.Logf("creating new bridge for %s", bridgeIface)
if err := createBridge(bridgeIP); err != nil {
	return job.Error(err)
}

job.Logf("getting iface addr")
addr, err = networkdriver.GetIfaceAddr(bridgeIface)
if err != nil {
	return job.Error(err)
}
network = addr.(*net.IPNet)

創建Docker Daemon網橋設備docker0的實現,全部由createBridge(bridgeIP)來實現,createBridge的實現位於./docker/daemon/networkdriver/bridge/driver.go#L245

createBridge函數實現過程的主要步驟為:

(1) 確定網橋設備docker0的IP地址;

(2) 通過createBridgeIface函數創建docker0網橋設備,並為網橋設備分配隨機的MAC地址;

(3) 將第一步中已經確定的IP地址,添加給新創建的docker0網橋設備;

(4) 啟動docker0網橋設備。

以下詳細分析4個步驟的具體實現。

首先Docker Daemon確定docker0的IP地址,實現方式為判斷用戶是否指定bridgeIP。若用戶未指定bridgeIP,則從Docker預先准備的IP網段列表addrs中查找合適的網段。具體的代碼實現位於./docker/daemon/networkdriver/bridge/driver.go#L257-L278,如下:

if len(bridgeIP) != 0 {
	_, _, err := net.ParseCIDR(bridgeIP)
	if err != nil {
		return err
	}
	ifaceAddr = bridgeIP
} else {
	for _, addr := range addrs {
		_, dockerNetwork, err := net.ParseCIDR(addr)
		if err != nil {
			return err
		}
		if err := networkdriver.CheckNameserverOverlaps(nameservers, dockerNetwork); err == nil {
			if err := networkdriver.CheckRouteOverlaps(dockerNetwork); err == nil {
				ifaceAddr = addr
				break
			} else {
				log.Debugf("%s %s", addr, err)
			}
		}
	}
}

其中為網橋設備准備的候選網段地址addrs為:

addrs = []string{
		"172.17.42.1/16", // Don't use 172.16.0.0/16, it conflicts with EC2 DNS 172.16.0.23
		"10.0.42.1/16",   // Don't even try using the entire /8, that's too intrusive
		"10.1.42.1/16",
		"10.42.42.1/16",
		"172.16.42.1/24",
		"172.16.43.1/24",
		"172.16.44.1/24",
		"10.0.42.1/24",
		"10.0.43.1/24",
		"192.168.42.1/24",
		"192.168.43.1/24",
		"192.168.44.1/24",
}

通過以上的流程的執行,可以確定找到一個可用的IP網段地址,為ifaceAddr;若沒有找到,則返回錯誤日志,表明沒有合適的IP地址賦予docker0網橋設備。

第二個步驟通過createBridgeIface函數創建docker0網橋設備。createBridgeIface函數的實現如下:

func createBridgeIface(name string) error {
	kv, err := kernel.GetKernelVersion()
	// only set the bridge's mac address if the kernel version is > 3.3
	// before that it was not supported
	setBridgeMacAddr := err == nil && (kv.Kernel >= 3 && kv.Major >= 3)
	log.Debugf("setting bridge mac address = %v", setBridgeMacAddr)
	return netlink.CreateBridge(name, setBridgeMacAddr)
}

以上代碼通過宿主機Linux內核信息,確定是否支持設定網橋設備的MAC地址。若Linux內核版本大於3.3,則支持配置MAC地址,否則則不支持。而Docker在不小於3.8的內核版本上運行才穩定,故可以認為內核支持配置MAC地址。最后通過netlink的CreateBridge函數實現創建docker0網橋。

Netlink是Linux中一種較為特殊的socket通信方式,提供了用戶應用間和內核進行雙向數據傳輸的途徑。在這種模式下,用戶態可以使用標准的socket API來使用netlink強大的功能,而內核態需要使用專門的內核API才能使用netlink。

Libcontainer的netlink包中CreateBridge實現了創建實際的網橋設備,具體使用系統調用的代碼如下:

syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), SIOC_BRADDBR, uintptr(unsafe.Pointer(nameBytePtr)))

創建完網橋設備之后,為docker0網橋設備配置MAC地址,實現函數為setBridgeMacAddress。

第三個步驟是為創建docker0網橋設備綁定IP地址。上一步驟僅完成了創建名為docker0的網橋設備,之后仍需要為docker0網橋設備綁定IP地址。具體代碼實現為:

if netlink.NetworkLinkAddIp(iface, ipAddr, ipNet); err != nil {
		return fmt.Errorf("Unable to add private network: %s", err)
}

NetworkLinkAddIP的實現同樣位於libcontainer中的netlink包,主要的功能為:通過netlink機制為一個網絡接口設備綁定一個IP地址。

第四個步驟是啟動docker0網橋設備。具體實現代碼為:

if err := netlink.NetworkLinkUp(iface); err != nil {
		return fmt.Errorf("Unable to start network bridge: %s", err)
	}

NetworkLinkUp的實現同樣位於libcontainer中的netlink包,功能為啟動docker網橋設備。

至此,docker0網橋歷經確定IP、創建、綁定IP、啟動四個環節,createBridge關於docker0網橋設備的工作全部完成。

3.3.6 獲取網橋設備的網絡地址

創建完網橋設備之后,網橋設備必然會存在一個網絡地址。網橋網絡地址的作用為:Docker Daemon在創建Docker Container時,使用該網絡地址為Docker Container分配IP地址。

Docker使用代碼network = addr.(*net.IPNet)獲取網橋設備的網絡地址。

3.3.7 配置Docker Daemon的iptables

創建完網橋之后,Docker Daemon為容器以及宿主機配置iptables,包括為container之間所需要的link操作提供支持,為host主機上所有的對外對內流量制定傳輸規則等。該部分詳情可以參看《Docker源碼分析(四):Docker Daemon之NewDaemon實現》。代碼位於./docker/daemon/networkdriver/bridge/driver/driver.go#L133,如下:

// Configure iptables for link support
if enableIPTables {
		if err := setupIPTables(addr, icc); err != nil {
			return job.Error(err)
		}
}

// We can always try removing the iptables
if err := iptables.RemoveExistingChain("DOCKER"); err != nil {
		return job.Error(err)
}

if enableIPTables {
		chain, err := iptables.NewChain("DOCKER", bridgeIface)
		if err != nil {
			return job.Error(err)
		}
		portmapper.SetIptablesChain(chain)
}

3.3.8 配置網絡設備間數據報轉發功能

在Linux系統上,數據包轉發功能是被默認禁止的。數據包轉發,就是當host主機存在多個網絡設備時,如果其中一個接收到數據包,並需要將其轉發給另外的網絡設備。通過修改/proc/sys/net/ipv4/ip_forward的值,將其置為1,則可以保證系統內數據包可以實現轉發功能,代碼如下:

if ipForward {
		// Enable IPv4 forwarding
		if err := ioutil.WriteFile("/proc/sys/net/ipv4/ip_forward", []byte{'1', '\n'}, 0644); err != nil {
			job.Logf("WARNING: unable to enable IPv4 forwarding: %s\n", err)
		}
}

3.3.9 注冊網絡Handler

創建Docker Daemon網絡環境的最后一個步驟是:注冊4個與網絡相關的Handler。這4個Handler分別是allocate_interface、release_interface、allocate_port和link,作用分別是為Docker Container分配網絡設備,回收Docker Container網絡設備、為Docker Container分配端口資源、以及為Docker Container間執行link操作。

至此,Docker Daemon的網絡環境初始化工作全部完成。

4 總結

在工業界,Docker的網絡問題備受關注。Docker的網絡環境可以分為Docker Daemon網絡和Docker Container網絡。本文從Docker Daemon的網絡入手,分析了大家熟知的Docker 橋接模式。

Docker的容器技術以及鏡像技術,已經給Docker實踐者帶來了諸多效益。然而Docker網絡的發展依然具有很大的潛力。下一篇Docker Container網絡篇,將會帶來更為靈活的Docker網絡配置。

5 作者介紹

孫宏亮,DaoCloud初創團隊成員,軟件工程師,浙江大學VLIS實驗室應屆研究生。讀研期間活躍在PaaS和Docker開源社區,對Cloud Foundry有深入研究和豐富實踐,擅長底層平台代碼分析,對分布式平台的架構有一定經驗,撰寫了大量有深度的技術博客。2014年末以合伙人身份加入DaoCloud團隊,致力於傳播以Docker為主的容器的技術,推動互聯網應用的容器化步伐。郵箱:allen.sun@daocloud.io

6 參考文獻

http://www.cnblogs.com/iceocean/articles/1594195.html

http://docs.studygolang.com/pkg/net/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM