• docker网络部分源码分析


    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()
  • 相关阅读:
    idea 代码提交到gitee
    flink+nacos实现参数化配置
    循环依赖的学习
    protobuf学习
    idea重置试用期插件
    Idea git 指定回滚版本
    Tomcat8下的Redis会话共享
    建造者设计模式
    Servlet中跨域问题详解
    gRPC
  • 原文地址:https://www.cnblogs.com/YaoDD/p/7908055.html
Copyright © 2020-2023  润新知