daemon初始化network controller
daemon的配置,网络部分的内容在cmd/dockerd/config_common_unix.go中指定,默认设置一般都为空
// daemon/daemon_unix.go
1、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()进行创建
2、daemon/daemon.go
func (daemon *Daemon) networkOptions(dconfig *config.Config, pg plugingetter.PluginGetter, activeSandboxes map[string]interface{}) ([]nwconfig.Option, error)
- 设置默认的network mode和network
- 对其它options进行设置
3、daemon/daemon_unix.go
func initBridgeDriver(controller libnetwork.NetworkController, config *config.Config) error
- 设置netOptions,其中的内容包括BridgeName,DefaultBridge,DriverMTU等等
- 调用controller.NewNetwork("bridge", "bridge", ...)创建bridge类型对网络
容器创建过程网络部分的内容
Container结构与网络相关的部分如下所示:
// container/container.go
type Container struct {
....
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
1、func (daemon *Daemon) containerStart(container *container.Container, ....) (err error)
- 调用daemon.initializeNetworking(container)对启动容器的网络进行配置
// daemon/container_operations.go
2、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
3、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
4、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
5、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
1、func (daemon *Daemon) CreateNetwork(create types.NetworkCreateRequest) (*types.NetworkCreateResponse, error)
- 该函数仅仅调用resp, err := daemon.createNetwork(create, "", false)
// daemon/network.go
2、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
1、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
2、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
3、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
4、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
5、func (container *Container) UpdateSandboxNetworkSettings(sb libnetwork.Sandbox) error
- 设置container.NetworkSettngs.SandboxID = sb.ID()
- 设置container.NetworkSettings.SandboxKey = sb.Key()