diff --git a/pkg/allocate/allocate.go b/pkg/allocate/allocate.go index 45c95d44d..a0ded51b5 100644 --- a/pkg/allocate/allocate.go +++ b/pkg/allocate/allocate.go @@ -195,9 +195,9 @@ func IterateForAssignment(ipnet net.IPNet, rangeStart net.IP, rangeEnd net.IP, r } logging.Debugf("IterateForAssignment input >> ip: %v | ipnet: %v | first IP: %v | last IP: %v", rangeStart, ipnet, firstip, lastip) - reserved := make(map[string]bool) + reserved := make(map[string]string) for _, r := range reservelist { - reserved[r.IP.String()] = true + reserved[r.IP.String()] = r.PodRef } // excluded, "192.168.2.229/30", "192.168.1.229/30", @@ -213,8 +213,11 @@ func IterateForAssignment(ipnet net.IPNet, rangeStart net.IP, rangeEnd net.IP, r endip := IPAddOffset(lastip, uint64(1)) for i := firstip; !i.Equal(endip); i = IPAddOffset(i, uint64(1)) { // if already reserved, skip it - if reserved[i.String()] { - continue + if reserved[i.String()] != "" { + if reserved[i.String()] != podRef { + continue + } + logging.Debugf("Found existing reservation %v with matching podRef %s", i.String(), podRef) } // Lastly, we need to check if this IP is within the range of excluded subnets diff --git a/pkg/storage/etcd.go b/pkg/storage/etcd.go index 548d9e7d8..629dcd36e 100644 --- a/pkg/storage/etcd.go +++ b/pkg/storage/etcd.go @@ -87,7 +87,7 @@ func (i *ETCDIPAM) GetOverlappingRangeStore() (OverlappingRangeStore, error) { } // IsAllocatedInOverlappingRange checks to see if the IP is allocated across the whole cluster (and not just the current range) -func (i *EtcdOverlappingRangeStore) IsAllocatedInOverlappingRange(ctx context.Context, ip net.IP) (bool, error) { +func (i *EtcdOverlappingRangeStore) IsAllocatedInOverlappingRange(ctx context.Context, ip net.IP, podRef string) (bool, error) { logging.Debugf("ETCD IsAllocatedInOverlappingRange is NOT IMPLEMENTED!!!! TODO") return false, nil } diff --git a/pkg/storage/kubernetes/ipam.go b/pkg/storage/kubernetes/ipam.go index fab5e22db..201a061fe 100644 --- a/pkg/storage/kubernetes/ipam.go +++ b/pkg/storage/kubernetes/ipam.go @@ -158,7 +158,7 @@ func (i *KubernetesIPAM) GetOverlappingRangeStore() (storage.OverlappingRangeSto } // IsAllocatedInOverlappingRange checks for IP addresses to see if they're allocated cluster wide, for overlapping ranges -func (c *KubernetesOverlappingRangeStore) IsAllocatedInOverlappingRange(ctx context.Context, ip net.IP) (bool, error) { +func (c *KubernetesOverlappingRangeStore) IsAllocatedInOverlappingRange(ctx context.Context, ip net.IP, podRef string) (bool, error) { // IPv6 doesn't make for valid CR names, so normalize it. normalizedip := strings.ReplaceAll(fmt.Sprint(ip), ":", "-") @@ -180,6 +180,11 @@ func (c *KubernetesOverlappingRangeStore) IsAllocatedInOverlappingRange(ctx cont return false, fmt.Errorf("k8s get OverlappingRangeIPReservation error: %s", err) } + if clusteripres.Spec.PodRef == podRef { + logging.Debugf("IP %v matches existing podRef %s", ip, podRef) + return false, nil + } + logging.Debugf("IP %v is reserved cluster wide.", ip) return true, nil } @@ -205,7 +210,10 @@ func (c *KubernetesOverlappingRangeStore) UpdateOverlappingRangeAllocation(ctx c PodRef: podRef, } - err = c.client.Create(ctx, clusteripres) + if err := c.client.Create(ctx, clusteripres); errors.IsAlreadyExists(err) { + logging.Debugf("clusteripres already exists, updating with %v", clusteripres.Spec) + err = c.client.Update(ctx, clusteripres) + } case whereaboutstypes.Deallocate: verb = "deallocate" @@ -472,7 +480,7 @@ RETRYLOOP: // When it's allocated overlappingrange wide, we add it to a local reserved list // And we try again. if ipamConf.OverlappingRanges { - isallocated, err := overlappingrangestore.IsAllocatedInOverlappingRange(ctx, newip.IP) + isallocated, err := overlappingrangestore.IsAllocatedInOverlappingRange(ctx, newip.IP, podRef) if err != nil { logging.Errorf("Error checking overlappingrange allocation: %v", err) return newip, err diff --git a/pkg/storage/storage.go b/pkg/storage/storage.go index 085cb14c5..6dd96405b 100644 --- a/pkg/storage/storage.go +++ b/pkg/storage/storage.go @@ -33,7 +33,7 @@ type Store interface { // OverlappingRangeStore is an interface for wrapping overlappingrange storage options type OverlappingRangeStore interface { - IsAllocatedInOverlappingRange(ctx context.Context, ip net.IP) (bool, error) + IsAllocatedInOverlappingRange(ctx context.Context, ip net.IP, podRef string) (bool, error) UpdateOverlappingRangeAllocation(ctx context.Context, mode int, ip net.IP, containerID string, podRef string) error }