zoukankan      html  css  js  c++  java
  • CNI IPAM插件分析 --- 以hostlocal为示例

    skel.CmdArgs数据结构如下所示:

    type CmdArgs struct {
    
      ContainerID    string
      Netns        string
      IfName        string
      Args         string
      Path         string
      StdinData      []byte
    }
    

      

    // cni/plugins/ipam/host-local/main.go

    1、func cmdAdd(args *skel.CmdArgs) error

    1、调用ipamConf, confVersion, err := allocator.LoadIPAMConfig(args.StdinData, args.Args)加载IPAM的配置和版本号

    2、若ipamConf.ResolvConf不为"",则调用dns, err := parseResolvConf(ipamConf.ResolvConf),并且将result.DNS = *dns

    3、调用store, err := disk.New(ipamConf.Name, ipamConf.DataDir)

    4、调用allocs := []*allocator.IPAllocator{} 获取allocator,保持该结构,当出错的时候,可以将所有IP地址释放

    5、创建requestedIPs := map[string]net.IP{}并将ipamConf.IPArgs中的地址都填入其中

    6、遍历for idx, ipRange := range ipamConf.Ranges,调用allocator := allocator.NewIPAllocator(ipamConf.Name, ipRange, store)

    7、遍历requestedIPs,for k, ip := range requestedIPs,如果ipRange.IPInRange(ip)为nil,则说明请求的ip在可分配的地址范围内,

    设置requestedIP = ip,并调用delete(requestedIPs, k)

    8、调用ipConf, err := allocator.Get(args.ContainerID, requestedIP),并调用allocs = append(allocs, allocator)和result.IPs = append(result.IPs, ipConf)

    9、如果最后len(requestedIPs)不为0,则释放所有的allocator并报错

    10、设置result.Routes = ipamConf.Routes

    11、最后return types.PrintResult(result, confVersion)

    // cni/plugins/ipam/host-local/backend/allocator/config.go

    // NewIPAMConfig creates a NetworkConfig from the given network name.

    2、func LoadIPAMConfig(bytes []byte, envArgs string) (*IPAMConfig, string, error)

    1、首先设置n := Net{},再调用json.Unmarshal(bytes, &n)进行解析

    2、如果envArgs不为"",或者n.Args不为nil,则将他们都添加到n.IPAM.IPArgs中

    3、如果n.IPAM.Range不为nil,说明使用的是老的配置方式,将n.IPAM.Range迁移到n.IPAM.Ranges中

    4、遍历n.IPAM.Ranges,对IPv4或IPv6的range进行计数,若他们的数目大于1,切cni版本小于0.3.0则报错

    5、检测各个range之间是否有重合

    6、将n.IPAM.Name赋值为n.Name

    7、最后return n.IPAM, n.CNIVersion, nil

    Net数据结构如下所示:

    type Net struct {
      Name       string
      CNIVersion    string
      IPAM       *IPAMConfig
      Args       *struct {
        A *IPAMArgs
      }
    }

      

    IPAMConfig数据结构如下所示:

    // IPAMConfig represents the IP related network configuration
    // 保留Range是为了向后兼容 type IPAMConfig struct {
      *Range   Name      string   Type       string   Routes      []*types.Route   DataDir      string   ResolvConf    string
      Ranges       []Range   IPArgs       []net.IP    // Requested IPs from CNI_ARGS and args }

      

    Range结构如下所示:

    type Range struct {
      RangeStart    net.IP
      RangeEnd     net.IP
      Subnet      types.IPNet
      Gateway      net.IP
    }
    

    IPAMArgs结构如下所示:

    type IPAMArgs struct {
      IPs    []net.IP
    }
    

      

    // cni/plugins/ipam/host-local/backend/disk/backend.go

    3、func New(network, dataDir string) (*Store, error)

    1、若dataDir为"",设置defaultDataDir为"/var/lib/cni/networks"

    2、调用dir := filepath.Join(dataDir, network)并且调用os.MkdirAll(dir, 0755)创建目录

    3、调用lk, err := NewFileLock(dir)

    4、最后返回return &Store{*lk, dir}, nil

    Store数据结构如下所示:

    type Store struct {
      FileLock        // FileLock wraps os.File to be used as a lock using flock
      dataDir   string  // 默认为/var/lib/cni/networks/NETWORKNAME
    }
    

      

    // cni/plugins/ipam/host-local/backend/allocator/allocator.go

    4、func NewIPAllocator(netName string, r Range, store backend.Store) *IPAllocator

    1、调用rangeID := base64.URLEncoding.EncodeToString(r.RangeStart)

    2、返回return &IPAllocator{......}

     

    IPAllocator数据结构如下所示:

    type IPAllocator struct {
      netName    string
      ipRange     Range
      store      backend.Store
      rangeID      string    // Used for tracking last reserved ip
    }
    

      

    // cni/plugins/ipam/host-local/backend/allocator/allocator.go

    5、func (a *IPAllocator) Get(id string, requestedIP net.IP) (*current.IPConfig, error)

    1、调用gw := a.ipRange

    2、如果requestedIP 不为nil,首先判断requestedIP和gw不能相等,否则报错

    如果a.ipRange.IPInRange(requestedIP)返回错误,则报错,否则调用reserved, err := a.store.Reserve(id, requestedIP, a.rangeID)将结果保存

    最后,设置reservedIP为requestedIP

    3、如果requestedIP不为nil,先调用iter, err := a.GetIter(),再调用for循环遍历iter,获取下一个可用的IP,之后的动作和2中相同

    4、最后返回return &current.IPConfig{....}, nil

  • 相关阅读:
    Enter passphrase
    laravel扩展包-私有库
    php7中异常
    laravel-admin(自定义表单视图)
    laravel-admin(自定义表单与验证)
    ZJU校赛划水记
    bzoj 4762: 最小集合
    WC2017 颓废记
    bzoj 2337: [HNOI2011]XOR和路径
    bzoj 2870: 最长道路tree
  • 原文地址:https://www.cnblogs.com/YaoDD/p/6418785.html
Copyright © 2011-2022 走看看