docker網絡部分源碼分析

daemon初始化network controller

daemon的配置,網絡部分的內容在cmd/dockerd/config_common_unix.go中指定,默認設置通常都爲空docker

 

// daemon/daemon_unix.goapi

一、func (daemon *Daemon) initNetworkController(config *config.Config, activeSandboxes map[string]interface{}) (libnetwork.NetworkController, error)網絡

  • 調用netOptions, err := daemon.networkOptions(config, daemon.PluginStore, activeSandboxes)初始化netOptions
  • 調用controller, err := libnetwork.New(netOptions...)初始network controller
  • 若是"none"和"host"這兩個network不存在,則分別調用controller.NewNetwork(...)進行建立
  • 若是"bridge"這個network存在,則先將其刪除,最後調用initBridgeDriver()進行建立

 

二、daemon/daemon.go函數

func (daemon *Daemon) networkOptions(dconfig *config.Config, pg plugingetter.PluginGetter, activeSandboxes map[string]interface{}) ([]nwconfig.Option, error)ui

  • 設置默認的network mode和network 
  • 對其它options進行設置

 

三、daemon/daemon_unix.go.net

func initBridgeDriver(controller libnetwork.NetworkController, config *config.Config) errorunix

  • 設置netOptions,其中的內容包括BridgeName,DefaultBridge,DriverMTU等等
  • 調用controller.NewNetwork("bridge", "bridge", ...)建立bridge類型對網絡

 

容器建立過程網絡部分的內容

Container結構與網絡相關的部分以下所示:blog

// container/container.goci

type Container struct {get

  ....

  NetworkSettings  *network.Settings

  HostConfig     *containertypes.HostConfig 

  ...

}

 

network.Setting結構以下所示:

// daemon/network/settings.go

type Settings struct {

  ...

  Networks  map[string]*EndpointSettings   ---> 它只是對docker/api/types/network中的EndpointSettings的封裝

  ...

}

 

EndpointSettings的結構以下所示,其中存儲了network endpoint的細節信息:

// api/types/network/network.go

type EndpointSettings struct {

  // Configurations

  IPAMConfig *EndpointIPAMConfig

  Links    []string

  Aliases    []string

  // Operational data

  NetworkID   string

  EndpointID   string

  Gateway    string

  IPAddress     string

  .....

}

 

// daemon/start.go

一、func (daemon *Daemon) containerStart(container *container.Container, ....) (err error)

  • 調用daemon.initializeNetworking(container)對啓動容器的網絡進行配置

 

// daemon/container_operations.go

二、func (daemon *Daemon) initializeNetworking(container *container.Container) error

  • 調用container.HostConfig.NetworkMode.IsContainer()判斷是否爲container類型的網絡模式
  • 調用container.HostConfig.NetworkMode.IsHost()判斷是否爲host類型的網絡模式
  • 調用daemon.allocateNetwork(container)建立network
  • 最後調用並返回container.BuildHostnameFile()

 

// daemon/container_operations.go

三、func (daemon *Daemon) allocateNetwork(container *container.Container) error

  • 首先經過controller := daemon.netController獲取network controller
  • 作一些前期處理的工做,先調用controller.SandboxDestroy(container.ID)清理可能遺留的sandbox,而且若是網絡模式爲none或者container模式則直接返回
  • 若是len(container.NetworkSettings.Networks)爲0,則調用daemon.updateContainerNetworkSettings(container, nil)
  • 確認container.NetworkSettings.Networks[defaultName]是否存在,存在的話,調用cleanOperationalData以及daemon.connectToNetwork(...)將容器加入網絡
  • 再遍歷container.NetworkSettings.Networks,一樣調用daemon.connectToNetwork()加入
  • 若是network沒有鏈接到任何網絡,則調用daemon.netController.NewSandbox()建立對應的sandbox

 

// daemon/container_operations.go

四、func (daemon *Daemon) updateContainerNetworkSettings(container *container.Container, endpointsConfig map[string]*networktypes.EndpointSettings)

  • 調用networkName := mode.NetworkName()獲取網絡名,若是mode爲default,則調用networkName = daemon.netController.Config().Daemon.DefaultNetwork
  • 若是container.NetworkSettings.Networks爲nil,則建立分配container.NetworkSettings.Networks,並將container.NetworkSettings.Networks[networkName] = &network.EndpointSettings{EndpointSettings: &networktypes.EndpointSettings{},}
  • 若是是默認模式,則將container.NetworkSettings.Networks["default"]轉化爲container.NetworkSettings.Networks["bridge"]

 

// daemon/container_operations.go

五、func (daemon *Daemon) connectToNetwork(container *container.Container,  idOrName string, endpointConfig *networktypes.EndpointSettings, updateSettings bool) (err error)

  •  調用n, config, err := daemon.findAndAttachNetwork(container, idOrName, endpointConfig)找到network
  • 調用sb := daemon.getNetworkSandbox(container)獲取sandbox,若是sb爲空,則調用sb, err = controller.NewSandbox(container.ID, options...)建立sandbox
  • 調用ep, err := n.CreateEndpoint(endpointName, createOptions...)建立endpoint
  • 調用joinOptions, err := container.BuildJoinOptions(n)和ep.Join(sb, joinOptions...)將endpoint加入sandbox

 

 

network命令建立網絡

// api/types/types.go

NetworkCreateRequest結構以下所示:

type NetworkCreateRequest struct {

  NetworkCreate

  Name  string

}

type NetworkCreate struct {

  CheckDuplicate  bool

  Driver      string

  Scope      string

  EnableIPv6    bool

  IPAM        *network.IPAM

  Internal       bool

  Attachable    bool

  Ingress      bool

  ConfigOnly    bool

  ConfigFrom    *network.ConfigReference

  Options     map[string]string

  Labels      map[string]string

}

 

// daemon/network.go

一、func (daemon *Daemon) CreateNetwork(create types.NetworkCreateRequest) (*types.NetworkCreateResponse, error)

  • 該函數僅僅調用resp, err := daemon.createNetwork(create, "", false)

 

// daemon/network.go

二、func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string, agent bool) (*types.NetworkCreateResponse, error)

  • 首先調用runconfig.IsPreDefinedNetwork(create.Name)判斷其是否爲預約義的network
  • 再調用daemon.GetNetworkByName(create.Name)判斷該名字的network是否已存在,若是存在且CheckDuplicate爲true,則報錯
  • 若是driver爲空,獲取controller的DefaultDriver
  • 根據create中的字段建立nwOptions
  • 調用n, err := c.NewNetwork(driver, create.Name, id, nwOptions...)建立network

 

network命令鏈接到網絡

// daemon/network.go

一、func (daemon *Daemon) ConnectToNetwork(container, networkName string, endpointConfig *network.EndpointSettings) error

  • 調用container, err := daemon.GetContainer(containerName)獲取容器信息
  • 調用daemon.ConnectToNetwork(container, networkName, endpointConfig)進行鏈接

 

// daemon/container_operations.go

二、func (daemon *Daemon) ConnectToNetwork(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings) error

  • 若是容器不在運行,則先調用n, err := daemon.FindNetwork(idOrName)找到network,若是n不爲空,則調用daemon.updateNetworkConfig(container, n, endpointConfig, true)進行更新,不然將endpointConfig加入container.NetworkSettings.Networks[idOrName]
  • 若是容器在運行,則調用daemon.connectToNetwork(container, idOrName, endpointConfig, true)加入network

 

// daemon/container_operations.go

三、func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings, updateSettings bool) (err error)

  • 調用n, config, err := daemon.findAndAttachNetwork(container, idOrName, endpointConfig)

 

networktypes.NetworkingConfig結構以下所示

// api/types/network/network.go

// NetworkingConfig represents the container's networking configuration for each of its interfaces
// Carries the networking configs specified in the `docker run` and `docker network connect` commands
type NetworkingConfig struct {
      EndpointsConfig map[string]*EndpointSettings   // Endpoint configs for each connecting network      
}

  

// daemon/container_operations.go

四、func (daemon *Daemon) findAndAttachNetwork(container *container.Container, idOrName string, epConfig *networktypes.EndpointSettings) (libnetwork.Network, *networktypes.NetworkingConfig, error)

  • 首先調用n, err := daemon.FindNetwork(idOrName)找到network
  • 調用err = daemon.updateNetworkConfig(container, n, endpointConfig, updateSettings)
  • 接着獲取sb := daemon.getNetworkSandbox(container),再調用ep, err := n.CreateEndpoint(endpointName, createOptions...)建立endpoint
  • 再調用daemon.updateEndpointNetworkSettings(container, n, ep)
  • 若是sb爲nil,則先調用sb, err = controller.NewSandbox(container.ID, options...)建立sandbox,再調用container.UpdateSandboxNetworkSettings(sb)
  • 最後,調用ep.Join(sb, joinOptions...)加入網絡

// container/container.go

五、func (container *Container) UpdateSandboxNetworkSettings(sb libnetwork.Sandbox) error

  • 設置container.NetworkSettngs.SandboxID = sb.ID()
  • 設置container.NetworkSettings.SandboxKey = sb.Key()
相關文章
相關標籤/搜索