Skip to content

Commit

Permalink
Try to release IP if it has been allocated to current LB
Browse files Browse the repository at this point in the history
To solve the duplicated allocation error when LB is frequently
created and deleted.

Signed-off-by: Jian Wang <[email protected]>
  • Loading branch information
w13915984028 committed Jan 27, 2025
1 parent 1741161 commit 5ada963
Showing 1 changed file with 30 additions and 0 deletions.
30 changes: 30 additions & 0 deletions pkg/controller/loadbalancer/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"net"
"reflect"
"strings"
"time"

ctlcniv1 "github.com/harvester/harvester/pkg/generated/controllers/k8s.cni.cncf.io/v1"
Expand All @@ -30,6 +31,8 @@ const (
AnnotationKeyProject = lb.GroupName + "/project"
AnnotationKeyNamespace = lb.GroupName + "/namespace"
AnnotationKeyCluster = lb.GroupName + "/cluster"

DuplicateAllocationKeyWord = "duplicate allocation is not allowed"
)

var (
Expand Down Expand Up @@ -277,6 +280,15 @@ func (h *Handler) ensureAllocatedAddressPool(lbCopy, lb *lbv1.LoadBalancer) (*lb
ip, err := h.allocateIPFromPool(lb)
if err != nil {
logrus.Debugf("lb %s/%s fail to allocate from pool %s", lb.Namespace, lb.Name, err.Error())
// if unlucky the DuplicateAllocationKeyWord is reported, try to release IP, do not overwrite original error
if strings.Contains(err.Error(), DuplicateAllocationKeyWord) {
pool, releaseErr := h.tryReleaseDuplicatedIPToPool(lb)
if releaseErr != nil {
logrus.Infof("lb %s/%s error: %s, try to release ip to pool %s, error: %s", lb.Namespace, lb.Name, err.Error(), pool, releaseErr.Error())
} else {
logrus.Infof("lb %s/%s error: %s, try to release ip to pool %s, ok", lb.Namespace, lb.Name, err.Error(), pool)
}
}
return lb, err
}

Expand All @@ -302,6 +314,24 @@ func (h *Handler) allocateIPFromPool(lb *lbv1.LoadBalancer) (*lbv1.AllocatedAddr
return h.requestIP(lb, pool)
}

func (h *Handler) tryReleaseDuplicatedIPToPool(lb *lbv1.LoadBalancer) (string, error) {
pool := lb.Spec.IPPool
if pool == "" {
// match an IP pool automatically if not specified
pool, err := h.selectIPPool(lb)
if err != nil {
return pool, err
}
}

// if pool is not ready, just fail and wait
a := h.allocatorMap.Get(pool)
if a == nil {
return pool, fmt.Errorf("fail to get allocator %s", pool)
}
return pool, a.Release(fmt.Sprintf("%s/%s", lb.Namespace, lb.Name), "")
}

func (h *Handler) requestIP(lb *lbv1.LoadBalancer, pool string) (*lbv1.AllocatedAddress, error) {
allocator := h.allocatorMap.Get(pool)
if allocator == nil {
Expand Down

0 comments on commit 5ada963

Please sign in to comment.