Skip to content

Commit 3d9290c

Browse files
feat(endpoints): auto-detect provider to adjust ip mapping (#5404)
Signed-off-by: SkalaNetworks <contact@skala.network>
1 parent 024fa77 commit 3d9290c

3 files changed

Lines changed: 267 additions & 59 deletions

File tree

pkg/controller/endpoint_slice.go

Lines changed: 72 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package controller
33
import (
44
"context"
55
"fmt"
6+
"slices"
67
"strings"
78
"time"
89

@@ -177,7 +178,7 @@ func (c *Controller) handleUpdateEndpointSlice(key string) error {
177178
checkIP = util.MasqueradeCheckIP
178179
}
179180
isGenIPPortMapping := !ignoreHealthCheck || isPreferLocalBackend
180-
ipPortMapping, backends = getIPPortMappingBackend(endpointSlices, port, lbVip, checkIP, isGenIPPortMapping)
181+
ipPortMapping, backends = c.getIPPortMappingBackend(endpointSlices, port, lbVip, checkIP, isGenIPPortMapping)
181182
// for performance reason delete lb with no backends
182183
if len(backends) != 0 {
183184
vip = util.JoinHostPort(lbVip, port.Port)
@@ -353,7 +354,7 @@ func (c *Controller) getHealthCheckVip(subnetName, lbVip string) (string, error)
353354
return checkIP, nil
354355
}
355356

356-
func getIPPortMappingBackend(endpointSlices []*discoveryv1.EndpointSlice, servicePort v1.ServicePort, serviceIP, checkVip string, isGenIPPortMapping bool) (map[string]string, []string) {
357+
func (c *Controller) getIPPortMappingBackend(endpointSlices []*discoveryv1.EndpointSlice, servicePort v1.ServicePort, serviceIP, checkVip string, isGenIPPortMapping bool) (map[string]string, []string) {
357358
var (
358359
ipPortMapping = map[string]string{}
359360
backends = []string{}
@@ -374,7 +375,13 @@ func getIPPortMappingBackend(endpointSlices []*discoveryv1.EndpointSlice, servic
374375

375376
for _, endpoint := range endpointSlice.Endpoints {
376377
if isGenIPPortMapping && endpoint.TargetRef.Name != "" {
377-
lspName := getEndpointTargetLSP(endpoint.TargetRef.Name, endpoint.TargetRef.Namespace, util.OvnProvider)
378+
lspName, err := c.getEndpointTargetLSP(endpoint.TargetRef.Name, endpoint.TargetRef.Namespace, endpoint.Addresses)
379+
if err != nil {
380+
err := fmt.Errorf("couldn't get LSP for the endpoint's target: %w", err)
381+
klog.Error(err)
382+
continue
383+
}
384+
378385
for _, address := range endpoint.Addresses {
379386
ipPortMapping[address] = fmt.Sprintf(util.HealthCheckNamedVipTemplate, lspName, checkVip)
380387
}
@@ -401,30 +408,75 @@ func endpointReady(endpoint discoveryv1.Endpoint) bool {
401408
return endpoint.Conditions.Ready == nil || *endpoint.Conditions.Ready
402409
}
403410

404-
// getEndpointTargetLSP returns the name of the LSP for a given target/namespace.
411+
// getMatchingProviderForAddress returns the provider linked to a subnet in which a particular address is present
412+
func getMatchingProviderForAddress(pod *v1.Pod, providers []string, address string) string {
413+
if pod.Annotations == nil {
414+
return ""
415+
}
416+
417+
// Find which provider is linked to this address
418+
for _, provider := range providers {
419+
ipsForProvider, exists := pod.Annotations[fmt.Sprintf(util.IPAddressAnnotationTemplate, provider)]
420+
if !exists {
421+
continue
422+
}
423+
424+
ips := strings.Split(ipsForProvider, ",")
425+
if slices.Contains(ips, address) {
426+
return provider
427+
}
428+
}
429+
430+
return ""
431+
}
432+
433+
// getEndpointTargetLSPName returns the name of the LSP for a pod targeted by an endpoint.
405434
// A custom provider can be specified if the LSP is within a subnet that doesn't use
406435
// the default "ovn" provider.
407-
func getEndpointTargetLSP(target, namespace, provider string) string {
408-
// This pod seems to be a VM launcher pod, but we do not use the same syntax for the LSP
409-
// of normal pods and for VM pods. We need to retrieve the real name of the VM from
410-
// the pod's name to compute the LSP.
411-
if strings.HasPrefix(target, util.VMLauncherPrefix) {
412-
target = getVMNameFromLauncherPod(target)
436+
func getEndpointTargetLSPName(pod *v1.Pod, provider string) string {
437+
// If no provider is specified, use the default one
438+
if provider == "" {
439+
provider = util.OvnProvider
440+
}
441+
442+
target := pod.Name
443+
444+
// If this pod is a VM launcher pod, we need to retrieve the name of the VM. This is necessary
445+
// because we do not use the same syntax for the LSP of normal pods and for VM pods
446+
if vmName, exists := pod.Annotations[fmt.Sprintf(util.VMAnnotationTemplate, provider)]; exists {
447+
target = vmName
413448
}
414449

415-
return ovs.PodNameToPortName(target, namespace, provider)
450+
return ovs.PodNameToPortName(target, pod.Namespace, provider)
416451
}
417452

418-
// getVMNameFromLauncherPod returns the name of a VirtualMachine from the name of its launcher pod (virt-launcher)
419-
func getVMNameFromLauncherPod(podName string) string {
420-
// Remove the VM launcher pod prefix
421-
vmName := strings.TrimPrefix(podName, util.VMLauncherPrefix)
453+
// getEndpointTargetLSP returns the name of the LSP on which addresses are attached for a specific pod
454+
func (c *Controller) getEndpointTargetLSP(pod, namespace string, addresses []string) (string, error) {
455+
// Retrieve the pod object from its namespace and name
456+
podObj, err := c.podsLister.Pods(namespace).Get(pod)
457+
if err != nil {
458+
return "", fmt.Errorf("failed to get pod %s/%s: %w", namespace, pod, err)
459+
}
422460

423-
// Remove the ID of the pod
424-
slice := strings.Split(vmName, "-")
425-
if len(slice) > 0 {
426-
vmName = strings.Join(slice[:len(slice)-1], "-")
461+
// Get all the networks to which the pod is attached
462+
podNetworks, err := c.getPodKubeovnNets(podObj)
463+
if err != nil {
464+
return "", fmt.Errorf("failed to get pod networks: %w", err)
465+
}
466+
467+
// Retrieve all the providers
468+
var providers []string
469+
for _, podNetwork := range podNetworks {
470+
providers = append(providers, podNetwork.ProviderName)
471+
}
472+
473+
// Get the first matching provider for any of the address in the endpoint
474+
var provider string
475+
for _, address := range addresses {
476+
if provider = getMatchingProviderForAddress(podObj, providers, address); provider != "" {
477+
break
478+
}
427479
}
428480

429-
return vmName
481+
return getEndpointTargetLSPName(podObj, provider), nil
430482
}

0 commit comments

Comments
 (0)