Code change:
<!-- Please use this template while reporting a bug and provide as much info as possible. Not doing so may result in your bug not being addressed in a timely manner. Thanks! If the matter is security related, please disclose it privately via --What happened: With a /22 pod network and a /24 assigned to each node, a third node cannot get a pod CIDR if kube-controller-manager has ever been restarted. What you expected to happen: Once a third or fourth node joins, it gets a /24. How to reproduce it (as minimally and precisely as possible): 150% usage on the IPAM controller is not a good sign. Anything else we need to know?: During the creation of the rangeAllocator, Occupy() is called twice on the pod networks. The first time is before subscribing to the node informer. The second time is during the node informer callbacks because on subscribing it calls Add for all existing nodes. I will submit a proposed fix shortly. Environment: Kubernetes version (use ): 1.19.2
/sig network
/triage accepted thanks for finding the bug I 've introduced :)

Related discussion:
text: } } <ins> func TestDoubleOccupyRelease(t *testing.T) { // Run a sequence of operations and check the number of occupied CIDRs // after each one. clusterCIDRStr := "10.42.0.0/16" operations := []struct { cidrStr     string operation   string numOccupied int }{ // Occupy 1 element: +1 { cidrStr:     "10.42.5.0/24", operation:   "occupy", numOccupied: 1, }, // Occupy 1 more element: +1 { cidrStr:     "10.42.9.0/24", operation:   "occupy", numOccupied: 2, }, // Occupy 4 elements overlapping with one from the above: +3 { cidrStr:     "10.42.8.0/22", operation:   "occupy", numOccupied: 5, }, // Occupy an already-coccupied element: no change { cidrStr:     "10.42.9.0/24", operation:   "occupy", numOccupied: 5, }, // Release an coccupied element: -1 { cidrStr:     "10.42.9.0/24", operation:   "release", numOccupied: 4, }, // Release an unoccupied element: no change { cidrStr:     "10.42.9.0/24", operation:   "release", numOccupied: 4, }, // Release 4 elements, only one of which is occupied: -1 { cidrStr:     "10.42.4.0/22", operation:   "release", numOccupied: 3, }, } // Check that there are exactly that many allocatable CIDRs after all // operations have been executed. numAllocatable24s := (1 << 8) - 3 _, clusterCIDR, _ := net.ParseCIDR(clusterCIDRStr) a, err := NewCIDRSet(clusterCIDR, 24) if err != nil { t.Fatalf("Error allocating CIDRSet") } // Execute the operations for _, op := range operations { _, cidr, _ := net.ParseCIDR(op.cidrStr) switch op.operation { case "occupy": a.Occupy(cidr) case "release": a.Release(cidr) default: t.Fatalf("test error: unknown operation %v", op.operation) } if a.allocatedCIDRs != op.numOccupied { t.Fatalf("Expected %d occupied CIDRS, got %d", op.numOccupied, a.allocatedCIDRs) } } // Make sure that we can allocate exactly `numAllocatable24s` elements. for i := 0; i < numAllocatable24s; i++ { _, err := a.AllocateNext() if err != nil { t.Fatalf("Expected to be able to allocate %d CIDRS, failed after %d", numAllocatable24s, i) } } _, err = a.AllocateNext() if err == nil { t.Fatalf("Expected to be able to allocate exactly %d CIDRS, got one more", numAllocatable24s) } } </ins> func TestGetBitforCIDR(t *testing.T) { cases := []struct { clusterCIDRStr string