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)和allocator, err := allocator.NewIPAllocator(ipamConf, store)获取allocator

4、调用ipConf, routes, err := allocator.Get(args.ContainerID)获取IP和路由配置

5、最后result.IPs = []*current.IPConfig{ipConf}和result.Routes = routes,并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, args string) (*IPAMConfig, string, error)

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

2、若args不为nil,调用types.LoadArgs(args, n.IPAM.Args)

3、最后调用n.IPAM.Name = n.Name ---> Copy net name into IPAM so not to drag Net struct around

Net数据结构如下所示:

type Net struct {

  Name      string
  CNIVersion    string
  IPAM      *IPAMConfig
}

  

IPAMConfig数据结构如下所示:

// IPAMConfig represents the IP related network configuration

type IPAMConfig struct {
  Name        string
  Type        string
  RangeStart    net.IP
  RangeEnd     net.IP
  Subnet       types.IPNet
  Gateway      net.IP
  Routes      []types.Route
  DataDir      string
  ResolvConf    string
  Args        *IPAMArgs
}

  

// 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)并且调用lk, err := NewFileLock(dir)

3、最后返回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(conf *IPAMConfig, store backend.Store) (*IPAllocator, error)

1、对子网的大小进行检测,太小则报错

2、调用start, end, err = networkRange((*net.IPNet)(&conf.Subnet))

3、调用start = ip.NextIP(start)跳过.0的地址

4、若conf.RangeStart不为空,则调用validateRangeIP(conf.RangeStart, (*net.IPNet)(&conf.Subnet), nil, nil)进行检测,并且设置start = conf.RangeStart,对于conf.RangeEnd同理

IPAllocator数据结构如下所示:

type IPAllocator struct {
  // start is inclusive and may be allocated
  start    net.IP
  // end is inclusive and may be allocated
  end      net.IP
  conf     *IPAMConfig
  store    backend.Store
}

  

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

// Returns newly allocated IP along with its config

5、func (a *IPAllocator) Get(id string) (*current.IPConfig, []*types.Route, error)

1、设置gw := a.conf.Gateway,若gw == nil,则gw = ip.NextIP(a.conf.Subnet.IP)

2、若a.conf.Args不为nil,则requestedIP = a.conf.Args.IP,若requestedIP不为nil,则

  1. 若requestedIP和gateway相等,则报错
  2. 创建subnet := net.IPNet{IP: a.conf.Subnet.IP, Mask: a.conf.Subnet.Mask},最后调用validateRangeIP(requestedIP, &subnet, a.start, a.end)对IP进行验证
  3. 调用reserved, err := a.store.Reserve(id, requestedIP)
  4. 若reserved为真,则ipConfig := &current.IPConfig{...},routes := convertRoutesToCurrent(a.conf.Routes),最后返回ipConfig和routes

3、若没有指定requestedIP,则遍历获取IP

  1. 调用startIP, endIP := a.getSearchRange()
  2. 从startIP开始对IP进行遍历,跳过gateway IP,若找到合适的IP,则类似地调用reserved, err := a.store.Reserve(id, cur)以及返回ipConfig和routes
  3. 最后,若到达endIP则退出
时间: 2024-10-26 03:47:00

CNI IPAM插件分析 --- 以hostlocal为示例的相关文章

CNI bridge 插件实现代码分析

对于每个CNI 插件在执行函数cmdAdd之前的操作是完全一样的,都是从环境变量和标准输入内读取配置.这在http://www.cnblogs.com/YaoDD/p/6410725.html这篇博文里面已经有完整的叙述了.接下来就直接从CmdAdd函数开始分析CNI bridge插件的执行过程. skel.CmdArgs数据结构如下所示 // CmdArgs captures all the arguments passed in to the plugin // via both env v

结构体中指针赋值问题的分析及C代码示例

问题描述 某结构体的定义如下: typedef struct { int iAge; // 年龄 char szAddr1[100]; // 地址1 char *pszAddr2; // 地址2 char **pszAddr3; // 地址3 } T_PeopleInfo; 请问如何对结构体中的各个成员变量(尤其是指针变量)进行赋值? 问题分析及C代码示例 我们可以看到,在结构体T_PeopleInfo中,pszAddr2和pszAddr3均为指针,其中pszAddr2为一级指针,pszAddr

RocketMQ源码分析之从官方示例窥探:RocketMQ事务消息实现基本思想

RocketMQ4.3.0版本开始支持事务消息,后续分享将开始将剖析事务消息的实现原理.首先从官方给出的Demo实例入手,以此通往RocketMQ事务消息的世界中. 官方版本未发布之前,从apache rocketmq第一个版本上线后,代码中存在与事务消息相关的代码,例如COMMIT.ROLLBACK.PREPARED,在事务消息未开源之前网上对于事务消息的"声音"基本上是使用类似二阶段提交,主要是根据消息系统标志MessageSysFlag中定义来推测的: TRANSACTION_P

CNI portmap插件实现源码分析

DNAT创建的iptables规则如下:(重写目的IP和端口) PREROUTING, OUTPUT: --dst-type local -j CNI-HOSTPORT_DNAT  // PREROUTING和OUTPUT链中目的地址类型为local的跳转至CNI-HOSTPORT-DNAT进行处理 CNI-HOSTPORT-DNAT: -j CNI-DN-abcd123 // 进入相应容器的chain进行处理 CNI-DN-abcd123: -p tcp --dport 8080 -j DNA

survival analysis 生存分析与R 语言示例 入门篇

生存分析,survival analysis,顾名思义是用来研究个体的存活概率与时间的关系.例如研究病人感染了病毒后,多长时间会死亡:工作的机器多长时间会发生崩溃等.  这里“个体的存活”可以推广抽象成某些关注的事件. 所以SA就成了研究某一事件与它的发生时间的联系的方法.这个方法广泛的用在医学.生物学等学科上,近年来也越来越多人用在互联网数据挖掘中,例如用survival analysis去预测信息在社交网络的传播程度,或者去预测用户流失的概率. R里面有很成熟的SA工具. 本文介绍生存分析的

【jQuery】结合accordion插件分析写插件的方法及注意事项

1.jQuery插件的命名方式:jquery.[插件名].js 2.对象方法附加在jQuery.fn上,全局函数附加在jQuery对象本身上 3.插件内部this指向的是通过选择器获取的jQuery对象 4.结尾加分号,插件头部最好也加分号 5.插件应该返回一个jQuery对象,保证插件的链式操作 6.插件内部应用完整的jQuery而不是$,但可以利用闭包,将jQuery传入,使插件内部可以继续使用$符合作为jQuery别名 7.闭包另一大好处:可以避免内部变量影响全局空间 :(function

unity Dotween插件的简单介绍及示例代码

unity里面做插值动画的插件有许多,比较常见的有itween.hotween.dotween.根据大家的反馈和实际体验来说,dotween插件在灵活性.稳定性.易用性上都十分突出.这里简单介绍下它的用法,并在后文做了一些效果示例,还是不错的. 所谓"插值动画",顾名思义就是在两个值中插入其他的值来实现动画.原理非常简单,比如想让某个物体从A地到达B地,我们只知道A和B的坐标,插值动画就可以根据"缓动函数"确定A.B间的其他值,来实现物体从A到B的"运动过

Hadoop2源码分析-YARN RPC 示例介绍

1.概述 之前在<Hadoop2源码分析-RPC探索实战>一文当中介绍了Hadoop的RPC机制,今天给大家分享关于YARN的RPC的机制.下面是今天的分享目录: YARN的RPC介绍 YARN的RPC示例 截图预览 下面开始今天的内容分享. 2.YARN的RPC介绍 我们知道在Hadoop的RPC当中,其主要由RPC,Client及Server这三个大类组成,分别实现对外提供编程接口.客户端实现及服务端实现.如下图所示: 图中是Hadoop的RPC的一个类的关系图,大家可以到<Hado

DispelFrames插件分析

功能:Shows new frames for dispellable buffs for target and focus, and a bright border around default buff frames. 使用了Ace3库 分析: 1.xml定义了两个框体:DispelFrames_TargetFrame和DispelFrames_FocusFrame 2.这两个框体设置了同一个脚本OnUpdate函数:DispelFrames_OnUpdate 3.DispelFrames_