CNI IPAM插件分析 |
您所在的位置:网站首页 › hostlocal和127001 › CNI IPAM插件分析 |
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 ¤t.IPConfig{....}, nil
|
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |