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]>
(cherry picked from commit eed9a39)
  • Loading branch information
w13915984028 committed Feb 19, 2025
1 parent 9df8446 commit 3dd0f20
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 3dd0f20

Please sign in to comment.