Skip to content

feat(dataplane): allow setting DataPlane's NodePort port number #1516

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@
[#1409](https://github.com/Kong/gateway-operator/pull/1409)
- Support `NodePort` as ingress service type for `DataPlane`
[#1430](https://github.com/Kong/gateway-operator/pull/1430)
- Allow setting `NodePort` port number for ingress service for `DataPlane`.
[#1516](https://github.com/Kong/gateway-operator/pull/1516)
- Bump default `DataPlane` image to 3.10
Default image changes from `kong` to `kong/kong-gateway`.
[#1405](https://github.com/Kong/gateway-operator/pull/1405)
Expand Down
42 changes: 42 additions & 0 deletions config/samples/dataplane-with-nodeport.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
apiVersion: gateway-operator.konghq.com/v1beta1
kind: DataPlane
metadata:
name: dataplane-node-port
spec:
deployment:
podTemplateSpec:
spec:
containers:
- name: proxy
# renovate: datasource=docker versioning=docker
image: kong/kong-gateway:3.10
env:
- name: KONG_LOG_LEVEL
value: debug
- name: KONG_PROXY_LISTEN
value: 0.0.0.0:9000 reuseport backlog=16384
- name: KONG_PORT_MAPS
value: 8080:9000
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "1024Mi"
cpu: "1000m"
readinessProbe:
initialDelaySeconds: 1
periodSeconds: 1
network:
services:
ingress:
annotations:
foo: bar
ports:
- name: http
port: 8080
targetPort: 9000
- name: http
port: 8083
targetPort: 9000
nodePort: 30083
47 changes: 42 additions & 5 deletions controller/dataplane/owned_resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,11 +364,7 @@ func ensureIngressServiceForDataPlane(
existingService.Spec.Selector = generatedService.Spec.Selector
updated = true
}
if !cmp.Equal(generatedService.Spec.Ports, existingService.Spec.Ports, cmp.FilterPath(func(p cmp.Path) bool {
// We need to check all the service values but the NodePort, as this field is assigned by
// the K8S controlplane components.
return p.Last().String() == ".NodePort"
}, cmp.Ignore())) {
if !comparePorts(existingService.Spec.Ports, generatedService.Spec.Ports, dataPlane) {
existingService.Spec.Ports = generatedService.Spec.Ports
updated = true
}
Expand All @@ -385,3 +381,44 @@ func ensureIngressServiceForDataPlane(

return op.Created, generatedService, cl.Create(ctx, generatedService)
}

// comparePorts compares the ports of two services.
// It returns true if the ports are equal, ignoring the NodePort field
// for the ingress service if it was not set in the dataplane spec.
func comparePorts(
a, b []corev1.ServicePort,
dataPlane *operatorv1beta1.DataPlane,
) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if a[i].Name != b[i].Name {
return false
}
if a[i].Protocol != b[i].Protocol {
return false
}
if a[i].Port != b[i].Port {
return false
}
if a[i].TargetPort != b[i].TargetPort {
return false
}
if a[i].AppProtocol != b[i].AppProtocol {
return false
}

if a[i].NodePort != b[i].NodePort {
if dataPlane != nil &&
dataPlane.Spec.Network.Services != nil &&
dataPlane.Spec.Network.Services.Ingress != nil &&
len(dataPlane.Spec.Network.Services.Ingress.Ports) > i &&
dataPlane.Spec.Network.Services.Ingress.Ports[i].NodePort != 0 {
return false
}
}

}
return true
}
73 changes: 73 additions & 0 deletions controller/dataplane/owned_resources_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,3 +331,76 @@ func TestEnsureIngressServiceForDataPlane(t *testing.T) {
})
}
}

func TestComparePorts(t *testing.T) {
testCases := []struct {
name string
a []corev1.ServicePort
b []corev1.ServicePort
dataPlane *operatorv1beta1.DataPlane
expected bool
}{
{
name: "should return true when NodePort differs but not specified in DataPlane spec",
a: []corev1.ServicePort{{Name: "port-80", Port: 80, NodePort: 30080}},
b: []corev1.ServicePort{{Name: "port-80", Port: 80, NodePort: 30081}},
dataPlane: builder.NewDataPlaneBuilder().
WithIngressServicePorts([]operatorv1beta1.DataPlaneServicePort{
{
Name: "http",
Port: 80,
TargetPort: intstr.FromInt(8000),
// NodePort not specified
},
}).Build(),
expected: true,
},
{
name: "should return false when NodePort differs and is specified in DataPlane spec",
a: []corev1.ServicePort{{Name: "port-80", Port: 80, NodePort: 30080}},
b: []corev1.ServicePort{{Name: "port-80", Port: 80, NodePort: 30081}},
dataPlane: builder.NewDataPlaneBuilder().
WithIngressServicePorts([]operatorv1beta1.DataPlaneServicePort{
{
Name: "http",
Port: 80,
TargetPort: intstr.FromInt(8000),
NodePort: 30080,
},
}).Build(),
expected: false,
},
{
name: "should return true when multiple ports match except NodePort which is not specified",
a: []corev1.ServicePort{
{Name: "port-80", Port: 80, NodePort: 30080},
{Name: "port-443", Port: 443, NodePort: 30443},
},
b: []corev1.ServicePort{
{Name: "port-80", Port: 80, NodePort: 30081},
{Name: "port-443", Port: 443, NodePort: 30444},
},
dataPlane: builder.NewDataPlaneBuilder().
WithIngressServicePorts([]operatorv1beta1.DataPlaneServicePort{
{
Name: "http",
Port: 80,
TargetPort: intstr.FromInt(8000),
},
{
Name: "https",
Port: 443,
TargetPort: intstr.FromInt(8443),
},
}).Build(),
expected: true,
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
actual := comparePorts(tc.a, tc.b, tc.dataPlane)
require.Equal(t, tc.expected, actual)
})
}
}
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ require (
replace (
k8s.io/api => k8s.io/api v0.32.3
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.32.3
k8s.io/apimachinery => k8s.io/apimachinery v0.32.3
k8s.io/apimachinery => k8s.io/apimachinery v0.32.4
k8s.io/apiserver => k8s.io/apiserver v0.32.3
k8s.io/cli-runtime => k8s.io/cli-runtime v0.32.3
k8s.io/client-go => k8s.io/client-go v0.32.3
Expand All @@ -269,12 +269,12 @@ replace (
k8s.io/component-base => k8s.io/component-base v0.32.3
k8s.io/component-helpers => k8s.io/component-helpers v0.32.3
k8s.io/controller-manager => k8s.io/controller-manager v0.32.3
k8s.io/cri-api => k8s.io/cri-api v0.32.3
k8s.io/cri-api => k8s.io/cri-api v0.32.4
k8s.io/cri-client => k8s.io/cri-client v0.32.3
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.32.3
k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.32.3
k8s.io/endpointslice => k8s.io/endpointslice v0.32.3
k8s.io/externaljwt => k8s.io/externaljwt v0.32.3
k8s.io/externaljwt => k8s.io/externaljwt v0.32.4
k8s.io/kms => k8s.io/kms v0.32.3
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.32.3
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.32.3
Expand All @@ -284,7 +284,7 @@ replace (
k8s.io/kubelet => k8s.io/kubelet v0.32.3
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.30.3
k8s.io/metrics => k8s.io/metrics v0.32.3
k8s.io/mount-utils => k8s.io/mount-utils v0.32.3
k8s.io/mount-utils => k8s.io/mount-utils v0.32.4
k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.32.3
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.32.3
k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.32.3
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -686,8 +686,8 @@ k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls=
k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k=
k8s.io/apiextensions-apiserver v0.32.3 h1:4D8vy+9GWerlErCwVIbcQjsWunF9SUGNu7O7hiQTyPY=
k8s.io/apiextensions-apiserver v0.32.3/go.mod h1:8YwcvVRMVzw0r1Stc7XfGAzB/SIVLunqApySV5V7Dss=
k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U=
k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
k8s.io/apimachinery v0.32.4 h1:8EEksaxA7nd7xWJkkwLDN4SvWS5ot9g6Z/VZb3ju25I=
k8s.io/apimachinery v0.32.4/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
k8s.io/apiserver v0.32.3 h1:kOw2KBuHOA+wetX1MkmrxgBr648ksz653j26ESuWNY8=
k8s.io/apiserver v0.32.3/go.mod h1:q1x9B8E/WzShF49wh3ADOh6muSfpmFL0I2t+TG0Zdgc=
k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU=
Expand Down
1 change: 1 addition & 0 deletions pkg/utils/kubernetes/resources/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ func ServicePortsFromDataPlaneIngressOpt(dataplane *operatorv1beta1.DataPlane) S
Protocol: corev1.ProtocolTCP, // Currently, only TCP protocol supported.
Port: p.Port,
TargetPort: targetPort,
NodePort: p.NodePort,
})
alreadyUsedPorts[p.Port] = struct{}{}
}
Expand Down