Skip to content

Commit

Permalink
MEDIUM: amend server slots management to reserve at least required nu…
Browse files Browse the repository at this point in the history
…mber
  • Loading branch information
ivanmatmati authored and oktalz committed Mar 18, 2024
1 parent 13fc60b commit 496f4e5
Showing 1 changed file with 47 additions and 28 deletions.
75 changes: 47 additions & 28 deletions pkg/service/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ package service

import (
"fmt"
"strconv"
"strings"

"github.com/haproxytech/client-native/v5/models"
Expand Down Expand Up @@ -91,8 +90,6 @@ func (s *Service) updateHAProxySrv(client api.HAProxyClient, srvSlot store.HAPro

// scaleHAproxySrvs adds servers to match available addresses
func (s *Service) scaleHAProxySrvs(backend *store.RuntimeBackend) {
var flag bool
var disabled []*store.HAProxySrv
var annVal int
var annErr error
// Add disabled HAProxySrvs to match "scale-server-slots"
Expand All @@ -108,37 +105,59 @@ func (s *Service) scaleHAProxySrvs(backend *store.RuntimeBackend) {
break
}
}
logger.Tracef("[CONFIG] [BACKEND] [SERVER] backend %s: number of slots %d", backend.Name, srvSlots)
for len(backend.HAProxySrvs) < srvSlots {
// We expect to have these slots : the already existing ones from backend.HAProxySrvs and the new ones to be added backend.Endpoints.Addresses
// Keep in mind this is about slots not servers. New servers can be already added to backend.HAProxySrvs if the room is sufficient.
// The name backend.Endpoints.Addresses is misleading, it's really about new slots that are parts of new servers and can't have been added directly.
expectedSrvSlots := len(backend.Endpoints.Addresses) + len(backend.HAProxySrvs)
// We want at least the expected number of slots ...
newSrvSlots := expectedSrvSlots
// ... but if it's not a modulo srvSlots or if it's zero (shouldn't happen) ...
if expectedSrvSlots%srvSlots != 0 || expectedSrvSlots == 0 {
// ... we compute the nearest number of slots greather than expectedSrvSlots and being a modulo of srvSlots
newSrvSlots = expectedSrvSlots - (expectedSrvSlots % srvSlots) + srvSlots
}

// Get the number of enabled servers in the current list of servers.
enabledSlots := 0
for _, server := range backend.HAProxySrvs {
if server.Address != "" {
enabledSlots++
}
}
// If we have to add new slots we'll have to reload, so we can expand the number of free slots by the number srvSlots.
// But we should add any only if there is no room left in the existing list of servers.
if enabledSlots+len(backend.Endpoints.Addresses) > len(backend.HAProxySrvs) &&
newSrvSlots-(enabledSlots+len(backend.Endpoints.Addresses)) < srvSlots && newSrvSlots > srvSlots {
newSrvSlots += srvSlots
}

// Create the future slice of slots of the size newSrvSlots ...
slots := make([]*store.HAProxySrv, newSrvSlots)
// ... copy the existing servers into ...
copy(slots, backend.HAProxySrvs)
i := len(backend.HAProxySrvs)
// ... then add the new slots ...
for addr := range backend.Endpoints.Addresses {
srv := &store.HAProxySrv{
Name: fmt.Sprintf("SRV_%d", len(backend.HAProxySrvs)+1),
Address: "",
Name: fmt.Sprintf("SRV_%d", i+1),
Address: addr,
Modified: true,
}
backend.HAProxySrvs = append(backend.HAProxySrvs, srv)
disabled = append(disabled, srv)
flag = true
slots[i] = srv
i++
}
instance.ReloadIf(flag, "[CONFIG] [BACKEND] [SERVER] Server slots in backend '%s' scaled to match scale-server-slots value: %s", s.backend.Name, strconv.Itoa(srvSlots))
// Configure remaining addresses in available HAProxySrvs
flag = false
for addr := range backend.Endpoints.Addresses {
if len(disabled) != 0 {
disabled[0].Address = addr
disabled[0].Modified = true
disabled = disabled[1:]
} else {
srv := &store.HAProxySrv{
Name: fmt.Sprintf("SRV_%d", len(backend.HAProxySrvs)+1),
Address: addr,
Modified: true,
}
backend.HAProxySrvs = append(backend.HAProxySrvs, srv)
flag = true
// ... fill in the remaining slots with disabled (empty address) slots.
for j := i; j < len(slots); j++ {
srv := &store.HAProxySrv{
Name: fmt.Sprintf("SRV_%d", j+1),
Address: "",
Modified: true,
}
delete(backend.Endpoints.Addresses, addr)
slots[j] = srv
}
instance.ReloadIf(flag, "[CONFIG] [BACKEND] [SERVER] Server slots in backend '%s' scaled to match available endpoints", s.backend.Name)
instance.ReloadIf(len(backend.HAProxySrvs) < len(slots), "[CONFIG] [BACKEND] [SERVER] Server slots in backend '%s' scaled to match available endpoints", s.backend.Name)
backend.Endpoints.Addresses = map[string]struct{}{}
backend.HAProxySrvs = slots
}

func (s *Service) getRuntimeBackend(k8s store.K8s) (backend *store.RuntimeBackend, err error) {
Expand Down

0 comments on commit 496f4e5

Please sign in to comment.