Skip to content

Commit be4b495

Browse files
committed
feat(loadbalancer): add healthCheckNodePort opt-in support
Signed-off-by: Zadkiel AHARONIAN <hello@zadkiel.fr>
1 parent 25de738 commit be4b495

File tree

3 files changed

+108
-2
lines changed

3 files changed

+108
-2
lines changed

docs/loadbalancer-annotations.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,12 @@ The default value is `5`.
7272
### `service.beta.kubernetes.io/scw-loadbalancer-health-check-port`
7373
This is the annotation to explicitly define the port used for health checks.
7474
It is possible to set a single port for all backends like `18080` or per port like `80:10080;443:10443`.
75-
The port must be a valid TCP/UDP port (1-65535).
75+
The special value `auto` will use the service's `spec.healthCheckNodePort` when `externalTrafficPolicy` is `Local`.
76+
The port must be a valid TCP/UDP port (1-65535) or `auto`.
7677
If not set, the service port is used as the health check port.
7778

79+
> **Note**: In a future major release, `auto` will become the default behavior when not explicitly set.
80+
7881
### `service.beta.kubernetes.io/scw-loadbalancer-health-check-http-uri`
7982
This is the annotation to set the URI that is used by the `http` health check.
8083
It is possible to set the uri per port, like `80:/;443,8443:mydomain.tld/healthz`.

scaleway/loadbalancers_annotations.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,10 @@ const (
8888

8989
// serviceAnnotationLoadBalancerHealthCheckPort is the annotation to explicitly define the port used for health checks
9090
// It is possible to set a single port for all backends like "18080" or per port like "80:10080;443:10443"
91-
// The port must be a valid TCP/UDP port (1-65535)
91+
// The special value "auto" will use the service's spec.healthCheckNodePort when externalTrafficPolicy is Local
92+
// The port must be a valid TCP/UDP port (1-65535) or "auto"
9293
// If not set, the service port is used as the health check port
94+
// Note: In a future major release, "auto" will become the default behavior
9395
serviceAnnotationLoadBalancerHealthCheckPort = "service.beta.kubernetes.io/scw-loadbalancer-health-check-port"
9496

9597
// serviceAnnotationLoadBalancerSendProxyV2 is the annotation that enables PROXY protocol version 2 (must be supported by backend servers)
@@ -637,6 +639,7 @@ func getHealthCheckTransientCheckDelay(service *v1.Service) (*scw.Duration, erro
637639

638640
// getHealthCheckPort returns the port to use for health checks.
639641
// It supports per-port configuration with the format "80:10080;443:10443" or a single port like "18080".
642+
// The special value "auto" will use the service's spec.healthCheckNodePort when externalTrafficPolicy is Local.
640643
// If the annotation is not set, it returns the provided nodePort as default.
641644
func getHealthCheckPort(service *v1.Service, nodePort int32) (int32, error) {
642645
annotation, ok := service.Annotations[serviceAnnotationLoadBalancerHealthCheckPort]
@@ -654,6 +657,14 @@ func getHealthCheckPort(service *v1.Service, nodePort int32) (int32, error) {
654657
return nodePort, nil
655658
}
656659

660+
if strings.ToLower(portStr) == "auto" {
661+
if service.Spec.ExternalTrafficPolicy == v1.ServiceExternalTrafficPolicyTypeLocal && service.Spec.HealthCheckNodePort != 0 {
662+
return service.Spec.HealthCheckNodePort, nil
663+
}
664+
klog.V(4).Infof("health-check-port set to 'auto' but externalTrafficPolicy is not Local or healthCheckNodePort is not set, using nodePort %d", nodePort)
665+
return nodePort, nil
666+
}
667+
657668
port, err := strconv.ParseInt(portStr, 10, 32)
658669
if err != nil {
659670
klog.Errorf("invalid value for annotation %s: %s is not a valid port number", serviceAnnotationLoadBalancerHealthCheckPort, portStr)

scaleway/loadbalancers_test.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,98 @@ func TestGetHealthCheckPort(t *testing.T) {
434434
result: 0,
435435
errMessage: "load balancer invalid annotation",
436436
},
437+
// Auto value tests
438+
{
439+
name: "auto with externalTrafficPolicy Local and healthCheckNodePort set",
440+
svc: &v1.Service{
441+
ObjectMeta: metav1.ObjectMeta{
442+
Annotations: map[string]string{
443+
"service.beta.kubernetes.io/scw-loadbalancer-health-check-port": "auto",
444+
},
445+
},
446+
Spec: v1.ServiceSpec{
447+
ExternalTrafficPolicy: v1.ServiceExternalTrafficPolicyTypeLocal,
448+
HealthCheckNodePort: 32000,
449+
Ports: []v1.ServicePort{
450+
{
451+
NodePort: 30080,
452+
Port: 80,
453+
},
454+
},
455+
},
456+
},
457+
nodePort: 30080,
458+
result: 32000,
459+
errMessage: "",
460+
},
461+
{
462+
name: "AUTO (uppercase) with externalTrafficPolicy Local and healthCheckNodePort set",
463+
svc: &v1.Service{
464+
ObjectMeta: metav1.ObjectMeta{
465+
Annotations: map[string]string{
466+
"service.beta.kubernetes.io/scw-loadbalancer-health-check-port": "AUTO",
467+
},
468+
},
469+
Spec: v1.ServiceSpec{
470+
ExternalTrafficPolicy: v1.ServiceExternalTrafficPolicyTypeLocal,
471+
HealthCheckNodePort: 32000,
472+
Ports: []v1.ServicePort{
473+
{
474+
NodePort: 30080,
475+
Port: 80,
476+
},
477+
},
478+
},
479+
},
480+
nodePort: 30080,
481+
result: 32000,
482+
errMessage: "",
483+
},
484+
{
485+
name: "auto with externalTrafficPolicy Cluster, fallback to nodePort",
486+
svc: &v1.Service{
487+
ObjectMeta: metav1.ObjectMeta{
488+
Annotations: map[string]string{
489+
"service.beta.kubernetes.io/scw-loadbalancer-health-check-port": "auto",
490+
},
491+
},
492+
Spec: v1.ServiceSpec{
493+
ExternalTrafficPolicy: v1.ServiceExternalTrafficPolicyTypeCluster,
494+
Ports: []v1.ServicePort{
495+
{
496+
NodePort: 30080,
497+
Port: 80,
498+
},
499+
},
500+
},
501+
},
502+
nodePort: 30080,
503+
result: 30080,
504+
errMessage: "",
505+
},
506+
{
507+
name: "auto with externalTrafficPolicy Local but healthCheckNodePort is 0, fallback to nodePort",
508+
svc: &v1.Service{
509+
ObjectMeta: metav1.ObjectMeta{
510+
Annotations: map[string]string{
511+
"service.beta.kubernetes.io/scw-loadbalancer-health-check-port": "auto",
512+
},
513+
},
514+
Spec: v1.ServiceSpec{
515+
ExternalTrafficPolicy: v1.ServiceExternalTrafficPolicyTypeLocal,
516+
HealthCheckNodePort: 0,
517+
Ports: []v1.ServicePort{
518+
{
519+
NodePort: 30080,
520+
Port: 80,
521+
},
522+
},
523+
},
524+
},
525+
nodePort: 30080,
526+
result: 30080,
527+
errMessage: "",
528+
},
437529
}
438530

439531
for _, tc := range testCases {

0 commit comments

Comments
 (0)