From 30fd9af8649e29a6566a0d101a5ee9607bc979c4 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 20 Oct 2025 17:16:32 +0900 Subject: [PATCH] kubernetesservice: support forwarding UDP Signed-off-by: Akihiro Suda --- hack/bats/extras/k8s.bats | 30 +++++++++++++++---- hack/bats/helpers/load.bash | 1 + .../kubernetesservice/kubernetesservice.go | 11 ++++--- .../kubernetesservice_test.go | 11 +++++++ 4 files changed, 44 insertions(+), 9 deletions(-) diff --git a/hack/bats/extras/k8s.bats b/hack/bats/extras/k8s.bats index fa6dc1c3762..2bc8542812a 100644 --- a/hack/bats/extras/k8s.bats +++ b/hack/bats/extras/k8s.bats @@ -50,15 +50,35 @@ k() { # bats test_tags=nodes:1 @test 'Single-node' { - k create deployment nginx --image="${TEST_CONTAINER_IMAGES["nginx"]}" - k rollout status deployment nginx --timeout 60s + # Deploy test services + services=(nginx coredns) + for svc in "${services[@]}"; do + k create deployment "$svc" --image="${TEST_CONTAINER_IMAGES["$svc"]}" + done + for svc in "${services[@]}"; do + k rollout status deployment "$svc" --timeout 60s + done + + # Test TCP port forwarding k create service nodeport nginx --node-port=31080 --tcp=80:80 run curl --fail --silent --show-error --retry 30 --retry-all-errors http://localhost:31080 assert_success assert_output --partial "Welcome to nginx" - # TODO: support UDP - k delete service nginx - k delete deployment nginx + + # Test UDP port forwarding + # + # `kubectl create service nodeport` does not support UDP, so use `kubectl expose` instead. + # https://github.com/kubernetes/kubernetes/issues/134732 + k expose deployment coredns --port=53 --type=NodePort \ + --overrides='{"spec":{"ports":[{"port":53,"protocol":"UDP","targetPort":53,"nodePort":32053}]}}' + run dig @127.0.0.1 -p 32053 lima-vm.io + assert_success + + # Cleanup + for svc in "${services[@]}"; do + k delete service "$svc" + k delete deployment "$svc" + done } # TODO: add a test for multi-node \ No newline at end of file diff --git a/hack/bats/helpers/load.bash b/hack/bats/helpers/load.bash index 0469585ce9b..99dcf09d30d 100644 --- a/hack/bats/helpers/load.bash +++ b/hack/bats/helpers/load.bash @@ -70,4 +70,5 @@ assert_output_lines_count() { # NOTE: keep this list in sync with hack/test-templates.sh . declare -A -g TEST_CONTAINER_IMAGES=( ["nginx"]="ghcr.io/stargz-containers/nginx:1.19-alpine-org" + ["coredns"]="public.ecr.aws/eks-distro/coredns/coredns:v1.12.2-eks-1-31-latest" ) \ No newline at end of file diff --git a/pkg/guestagent/kubernetesservice/kubernetesservice.go b/pkg/guestagent/kubernetesservice/kubernetesservice.go index eec03ea1b5e..316f173ca37 100644 --- a/pkg/guestagent/kubernetesservice/kubernetesservice.go +++ b/pkg/guestagent/kubernetesservice/kubernetesservice.go @@ -26,9 +26,8 @@ import ( type Protocol string const ( - // UDP/SCTP when lima port forwarding works on those protocols. - TCP Protocol = "tcp" + UDP Protocol = "udp" ) type Entry struct { @@ -134,8 +133,12 @@ func (s *ServiceWatcher) GetPorts() []Entry { } for _, portEntry := range service.Spec.Ports { - if portEntry.Protocol != corev1.ProtocolTCP { - // currently only TCP port can be forwarded + switch portEntry.Protocol { + case corev1.ProtocolTCP, corev1.ProtocolUDP: + // NOP + default: + logrus.Debugf("unsupported protocol %s for service %s/%s, skipping", + portEntry.Protocol, service.Namespace, service.Name) continue } diff --git a/pkg/guestagent/kubernetesservice/kubernetesservice_test.go b/pkg/guestagent/kubernetesservice/kubernetesservice_test.go index dcccedb8443..e8e970a576f 100644 --- a/pkg/guestagent/kubernetesservice/kubernetesservice_test.go +++ b/pkg/guestagent/kubernetesservice/kubernetesservice_test.go @@ -58,6 +58,13 @@ func TestGetPorts(t *testing.T) { TargetPort: intstr.FromInt(80), NodePort: 8080, }, + { + Name: "dns", + Protocol: corev1.ProtocolUDP, + Port: 53, + TargetPort: intstr.FromInt(53), + NodePort: 5353, + }, }, }, }, @@ -65,6 +72,10 @@ func TestGetPorts(t *testing.T) { Protocol: TCP, IP: net.IPv4zero, Port: 8080, + }, { + Protocol: UDP, + IP: net.IPv4zero, + Port: 5353, }}, }, {