From 42431249830fc35da7cad599ccdbeaa067aa533d Mon Sep 17 00:00:00 2001 From: Markus Rudy Date: Wed, 29 Jan 2025 11:05:35 +0100 Subject: [PATCH 1/4] kuberesource: remove empty namespace from pod resource --- internal/kuberesource/wrappers.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/internal/kuberesource/wrappers.go b/internal/kuberesource/wrappers.go index 100031439..97e1231e9 100644 --- a/internal/kuberesource/wrappers.go +++ b/internal/kuberesource/wrappers.go @@ -92,7 +92,11 @@ type PodConfig struct { // Pod creates a new PodConfig. func Pod(name, namespace string) *PodConfig { - return &PodConfig{applycorev1.Pod(name, namespace)} + p := applycorev1.Pod(name, namespace) + if namespace == "" && p.ObjectMetaApplyConfiguration != nil { + p.ObjectMetaApplyConfiguration.Namespace = nil + } + return &PodConfig{p} } // LabelSelectorConfig wraps applymetav1.LabelSelectorApplyConfiguration. From 2a6e1da0c530025f54d4fc80be80f17faaa49894 Mon Sep 17 00:00:00 2001 From: Markus Rudy Date: Wed, 29 Jan 2025 11:06:32 +0100 Subject: [PATCH 2/4] kuberesource: remove unused port forwarder --- internal/kuberesource/parts.go | 62 +++++------------------------ internal/kuberesource/parts_test.go | 4 +- 2 files changed, 11 insertions(+), 55 deletions(-) diff --git a/internal/kuberesource/parts.go b/internal/kuberesource/parts.go index 84ba82b23..11e9a79ab 100644 --- a/internal/kuberesource/parts.go +++ b/internal/kuberesource/parts.go @@ -278,58 +278,14 @@ type PortForwarderConfig struct { *applycorev1.PodApplyConfiguration } -// PortForwarder constructs a port forwarder pod. -func PortForwarder(name, namespace string) *PortForwarderConfig { - name = "port-forwarder-" + name - - p := Pod(name, namespace). - WithLabels(map[string]string{"app.kubernetes.io/name": name}). - WithSpec(PodSpec(). - WithContainers( - Container(). - WithName("port-forwarder"). - WithImage("ghcr.io/edgelesssys/contrast/port-forwarder:latest"). - WithCommand("/bin/bash", "-c", "echo Starting port-forward with socat; exec socat -d -d TCP-LISTEN:${LISTEN_PORT},fork TCP:${FORWARD_HOST}:${FORWARD_PORT}"). - WithResources(ResourceRequirements(). - WithMemoryLimitAndRequest(50), - ), - ), - ) - - return &PortForwarderConfig{p} -} - -// WithListenPort sets the port to listen on. -func (p *PortForwarderConfig) WithListenPort(port int32) *PortForwarderConfig { - p.Spec.Containers[0]. - WithPorts( - ContainerPort(). - WithContainerPort(port), - ). - WithEnv( - NewEnvVar("LISTEN_PORT", strconv.Itoa(int(port))), - ). - WithStartupProbe(Probe(). - WithInitialDelaySeconds(1). - WithPeriodSeconds(1). - WithTCPSocket(TCPSocketAction(). - WithPort(intstr.FromInt32(port))), - ) - return p -} - -// WithForwardTarget sets the target host and port to forward to. -func (p *PortForwarderConfig) WithForwardTarget(host string, port int32) *PortForwarderConfig { - p.Spec.Containers[0]. - WithEnv( - NewEnvVar("FORWARD_HOST", host), - NewEnvVar("FORWARD_PORT", strconv.Itoa(int(port))), - ) +// WithForwardTarget sets the target host to forward to. +func (p *PortForwarderConfig) WithForwardTarget(host string) *PortForwarderConfig { + p.Spec.Containers[0].WithEnv(NewEnvVar("FORWARD_HOST", host)) return p } -// PortForwarderMultiplePorts constructs a port forwarder pod for multiple ports. -func PortForwarderMultiplePorts(name, namespace string) *PortForwarderConfig { +// PortForwarder constructs a port forwarder pod for multiple ports. +func PortForwarder(name, namespace string) *PortForwarderConfig { name = "port-forwarder-" + name p := Pod(name, namespace). @@ -349,7 +305,7 @@ func PortForwarderMultiplePorts(name, namespace string) *PortForwarderConfig { return &PortForwarderConfig{p} } -// WithListenPorts sets multiple ports to listen on. Should only be used if PortForwarderMultiplePorts was used initially. +// WithListenPorts sets multiple ports to listen on. func (p *PortForwarderConfig) WithListenPorts(ports []int32) *PortForwarderConfig { var containerPorts []*applycorev1.ContainerPortApplyConfiguration var envVar string @@ -493,7 +449,7 @@ func ServiceForStatefulSet(s *applyappsv1.StatefulSetApplyConfiguration) *applyc // PortForwarderForService creates a Pod that forwards network traffic to the given service. // -// Port forwarders are named "port-forwarder-SVCNAME" and forward the first port in the ServiceSpec. +// Port forwarders are named "port-forwarder-SVCNAME" and forward all ports in the ServiceSpec. func PortForwarderForService(svc *applycorev1.ServiceApplyConfiguration) *applycorev1.PodApplyConfiguration { namespace := "" if svc.Namespace != nil { @@ -505,9 +461,9 @@ func PortForwarderForService(svc *applycorev1.ServiceApplyConfiguration) *applyc ports = append(ports, *port.Port) } - forwarder := PortForwarderMultiplePorts(*svc.Name, namespace). + forwarder := PortForwarder(*svc.Name, namespace). WithListenPorts(ports). - WithForwardTarget(*svc.Name, -1) // port can be -1 since MultiplePortsForwarder ignores FORWARD_PORT env + WithForwardTarget(*svc.Name) return forwarder.PodApplyConfiguration } diff --git a/internal/kuberesource/parts_test.go b/internal/kuberesource/parts_test.go index 5fa4bd94f..a92934fde 100644 --- a/internal/kuberesource/parts_test.go +++ b/internal/kuberesource/parts_test.go @@ -13,8 +13,8 @@ func TestNewPortForwarder(t *testing.T) { require := require.New(t) config := PortForwarder("coordinator", "default"). - WithListenPort(1313). - WithForwardTarget("coordinator", 1313) + WithListenPorts([]int32{1313, 7777}). + WithForwardTarget("coordinator") b, err := EncodeResources(config) require.NoError(err) From 97d06be38f8226db74775a580744963934e12a69 Mon Sep 17 00:00:00 2001 From: Markus Rudy Date: Wed, 29 Jan 2025 11:12:15 +0100 Subject: [PATCH 3/4] kuberesource: only attempt to forward TCP ports --- internal/kuberesource/mutators.go | 7 ++++++- internal/kuberesource/parts.go | 13 +++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/internal/kuberesource/mutators.go b/internal/kuberesource/mutators.go index 9b2b2df51..ddf9c0183 100644 --- a/internal/kuberesource/mutators.go +++ b/internal/kuberesource/mutators.go @@ -5,6 +5,7 @@ package kuberesource import ( "fmt" + "log" "slices" "strconv" "strings" @@ -176,7 +177,11 @@ func AddPortForwarders(resources []any) []any { for _, resource := range resources { switch obj := resource.(type) { case *applycorev1.ServiceApplyConfiguration: - out = append(out, PortForwarderForService(obj)) + forwarder, err := PortForwarderForService(obj) + if err != nil { + log.Printf("WARNING: no port forwarder added for service %q: %v", *obj.Name, err) + } + out = append(out, forwarder) } out = append(out, resource) } diff --git a/internal/kuberesource/parts.go b/internal/kuberesource/parts.go index 11e9a79ab..03b1b9245 100644 --- a/internal/kuberesource/parts.go +++ b/internal/kuberesource/parts.go @@ -449,8 +449,8 @@ func ServiceForStatefulSet(s *applyappsv1.StatefulSetApplyConfiguration) *applyc // PortForwarderForService creates a Pod that forwards network traffic to the given service. // -// Port forwarders are named "port-forwarder-SVCNAME" and forward all ports in the ServiceSpec. -func PortForwarderForService(svc *applycorev1.ServiceApplyConfiguration) *applycorev1.PodApplyConfiguration { +// Port forwarders are named "port-forwarder-SVCNAME" and forward all TCP ports in the ServiceSpec. +func PortForwarderForService(svc *applycorev1.ServiceApplyConfiguration) (*applycorev1.PodApplyConfiguration, error) { namespace := "" if svc.Namespace != nil { namespace = *svc.Namespace @@ -458,14 +458,19 @@ func PortForwarderForService(svc *applycorev1.ServiceApplyConfiguration) *applyc var ports []int32 for _, port := range svc.Spec.Ports { - ports = append(ports, *port.Port) + if port.Protocol == nil || *port.Protocol == corev1.ProtocolTCP { + ports = append(ports, *port.Port) + } + } + if len(ports) == 0 { + return nil, fmt.Errorf("no TCP ports in service spec") } forwarder := PortForwarder(*svc.Name, namespace). WithListenPorts(ports). WithForwardTarget(*svc.Name) - return forwarder.PodApplyConfiguration + return forwarder.PodApplyConfiguration, nil } // Initializer creates a new InitializerConfig. From ab55d7f648c881103e6a24c7083be8eb5b1636d1 Mon Sep 17 00:00:00 2001 From: Markus Rudy Date: Wed, 29 Jan 2025 11:06:50 +0100 Subject: [PATCH 4/4] kuberesource: add signal handler to portforwarder Co-authored-by: 3u13r --- internal/kuberesource/parts.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/internal/kuberesource/parts.go b/internal/kuberesource/parts.go index 03b1b9245..7d074c086 100644 --- a/internal/kuberesource/parts.go +++ b/internal/kuberesource/parts.go @@ -284,6 +284,19 @@ func (p *PortForwarderConfig) WithForwardTarget(host string) *PortForwarderConfi return p } +const portForwarderScript = `echo Starting port-forward with socat >&2 +handler() { + echo "Received SIGTERM, forwarding to children" >&2 + kill -TERM -1 +} +trap handler TERM +set -x +for port in ${LISTEN_PORTS}; do + socat -d -d TCP-LISTEN:$port,fork TCP:${FORWARD_HOST}:$port & +done +wait +` + // PortForwarder constructs a port forwarder pod for multiple ports. func PortForwarder(name, namespace string) *PortForwarderConfig { name = "port-forwarder-" + name @@ -295,7 +308,7 @@ func PortForwarder(name, namespace string) *PortForwarderConfig { Container(). WithName("port-forwarder"). WithImage("ghcr.io/edgelesssys/contrast/port-forwarder:latest"). - WithCommand("/bin/bash", "-c", "echo Starting port-forward with socat; for port in ${LISTEN_PORTS}; do socat -d -d TCP-LISTEN:$port,fork TCP:${FORWARD_HOST}:$port & done; wait"). + WithCommand("/bin/bash", "-c", portForwarderScript). WithResources(ResourceRequirements(). WithMemoryLimitAndRequest(50), ),