Skip to content
1 change: 1 addition & 0 deletions pkg/deployer/values.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ type HelmImage struct {
type HelmService struct {
Type *string `json:"type,omitempty"`
ClusterIP *string `json:"clusterIP,omitempty"`
LoadBalancerIP *string `json:"loadBalancerIP,omitempty"`
ExtraAnnotations map[string]string `json:"extraAnnotations,omitempty"`
ExtraLabels map[string]string `json:"extraLabels,omitempty"`
ExternalTrafficPolicy *string `json:"externalTrafficPolicy,omitempty"`
Expand Down
27 changes: 20 additions & 7 deletions pkg/deployer/values_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,19 +104,32 @@ func AppendPortValue(gwPorts []HelmPort, port int32, name string, gwp *kgateway.
}

// Convert service values from GatewayParameters into helm values to be used by the deployer.
func GetServiceValues(svcConfig *kgateway.Service) *HelmService {
func GetServiceValues(svcConfig *kgateway.Service, loadBalancerIP *string) *HelmService {
// convert the service type enum to its string representation;
// if type is not set, it will default to 0 ("ClusterIP")
var svcType *string
if svcConfig.GetType() != nil {
svcType = ptr.To(string(*svcConfig.GetType()))
var clusterIP *string
var extraAnnotations map[string]string
var extraLabels map[string]string
var externalTrafficPolicy *string

if svcConfig != nil {
if svcConfig.GetType() != nil {
svcType = ptr.To(string(*svcConfig.GetType()))
}
clusterIP = svcConfig.GetClusterIP()
extraAnnotations = svcConfig.GetExtraAnnotations()
extraLabels = svcConfig.GetExtraLabels()
externalTrafficPolicy = svcConfig.GetExternalTrafficPolicy()
}

return &HelmService{
Type: svcType,
ClusterIP: svcConfig.GetClusterIP(),
ExtraAnnotations: svcConfig.GetExtraAnnotations(),
ExtraLabels: svcConfig.GetExtraLabels(),
ExternalTrafficPolicy: svcConfig.GetExternalTrafficPolicy(),
ClusterIP: clusterIP,
LoadBalancerIP: loadBalancerIP,
ExtraAnnotations: extraAnnotations,
ExtraLabels: extraLabels,
ExternalTrafficPolicy: externalTrafficPolicy,
}
}

Expand Down
42 changes: 41 additions & 1 deletion pkg/kgateway/deployer/gateway_parameters.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import (
"errors"
"fmt"
"log/slog"
"net/netip"
"os"
"strings"

"helm.sh/helm/v3/pkg/chart"
"istio.io/istio/pkg/kube/kclient"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/tools/cache"
"k8s.io/utils/ptr"
Expand Down Expand Up @@ -268,6 +270,39 @@ func (k *kgatewayParameters) getGatewayParametersForGatewayClass(gwc *gwv1.Gatew
return mergedGwp, nil
}

// extractLoadBalancerIP extracts the first IP address from Gateway.spec.addresses
// where the address type is IPAddressType. Returns nil if no valid IP address is found.
// If multiple IP addresses are provided, uses the first one and logs a warning.
func extractLoadBalancerIP(gw *gwv1.Gateway) *string {
if len(gw.Spec.Addresses) == 0 {
return nil
}

if len(gw.Spec.Addresses) > 1 {
slog.Warn("multiple IP addresses found in Gateway.spec.addresses, using first valid one",
"gateway", fmt.Sprintf("%s/%s", gw.Namespace, gw.Name),
"count", len(gw.Spec.Addresses),
)
}

for _, addr := range gw.Spec.Addresses {
// IPAddressType or nil (defaults to IPAddressType per Gateway API spec)
if addr.Type == nil || *addr.Type == gwv1.IPAddressType {
// Validate IP format
if parsedIP, err := netip.ParseAddr(addr.Value); err == nil && parsedIP.IsValid() {
return &addr.Value
}
// Log warning for invalid IP but continue searching
slog.Warn("invalid IP address in Gateway.spec.addresses, skipping", "value", addr.Value)
}
}

slog.Error("no valid IP address found in Gateway.spec.addresses",
"gateway", fmt.Sprintf("%s/%s", gw.Namespace, gw.Name),
)
return nil
}

func (k *kgatewayParameters) getValues(gw *gwv1.Gateway, gwParam *kgateway.GatewayParameters) (*deployer.HelmConfig, error) {
irGW := deployer.GetGatewayIR(gw, k.inputs.CommonCollections)
ports := deployer.GetPortsValues(irGW, gwParam, irGW.ControllerName == k.inputs.AgentgatewayControllerName)
Expand Down Expand Up @@ -354,7 +389,12 @@ func (k *kgatewayParameters) getValues(gw *gwv1.Gateway, gwParam *kgateway.Gatew
gateway.Strategy = deployConfig.GetStrategy()

// service values
gateway.Service = deployer.GetServiceValues(svcConfig)
// Extract loadBalancerIP from Gateway.spec.addresses if service type is LoadBalancer
var loadBalancerIP *string
if svcConfig != nil && svcConfig.GetType() != nil && *svcConfig.GetType() == corev1.ServiceTypeLoadBalancer {
loadBalancerIP = extractLoadBalancerIP(gw)
}
gateway.Service = deployer.GetServiceValues(svcConfig, loadBalancerIP)
// serviceaccount values
gateway.ServiceAccount = deployer.GetServiceAccountValues(svcAccountConfig)
// pod template values
Expand Down
3 changes: 3 additions & 0 deletions pkg/kgateway/helm/agentgateway/templates/service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ spec:
{{- with $gateway.service.clusterIP }}
clusterIP: {{ . }}
{{- end }}
{{- with $gateway.service.loadBalancerIP }}
loadBalancerIP: {{ . }}
{{- end }}
ports:
{{- range $p := $gateway.ports }}
- name: {{ $p.name }}
Expand Down
3 changes: 3 additions & 0 deletions pkg/kgateway/helm/envoy/templates/service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ spec:
{{- with $gateway.service.clusterIP }}
clusterIP: {{ . }}
{{- end }}
{{- with $gateway.service.loadBalancerIP }}
loadBalancerIP: {{ . }}
{{- end }}
ports:
{{- range $p := $gateway.ports }}
- name: {{ $p.name }}
Expand Down
Loading
Loading