kgateway
Review load balancing, failover, and outlier detection for external traffic entering the mesh through Solo Enterprise for kgateway.
When you use Solo Enterprise for kgateway as ingress to an ambient mesh, it behaves differently from the Istio ingress gateway:
- kgateway does not originate HBONE. Instead, it has a ztunnel and is treated like a mesh client.
- Locality and failover are determined by the gateway’s ztunnel and the waypoint or backend path.
- On the ingress-to-waypoint leg, the gateway sees a single virtual IP (VIP), so DestinationRules do not apply. Policy is deferred to the mesh and waypoint.
Cluster scenarios
The following diagrams give examples of how kgateway handles load balancing, outlier detection, and failover in single-cluster and multicluster setups.
Single-cluster scenario
- The request routes from an external client to a backend service in the mesh.
- The backend service is enrolled in the ambient mesh and runs in a single cluster.
- The backend service has multiple replicas distributed across different zones or regions within the cluster.
- Optionally, the
spec.trafficDistributionornetworking.istio.io/traffic-distributionsetting is configured on the backend service to control locality-based load balancing.
graph LR
External[External<br/>Client] -->|1. HTTPS| Kgateway[kgateway<br/>L7 proxy]
Kgateway -->|2. Mesh traffic| Ztunnel[Gateway<br/>ztunnel]
Ztunnel -->|3. HBONE| Waypoint[Waypoint]
Ztunnel -->|3. If no waypoint, direct load balancing| Backend1[Backend pod<br/>✓ Healthy]
Waypoint -->|4. Load balancing| Backend1
Waypoint -->|4. Load balancing| Backend2[Backend pod<br/>✓ Healthy]
Waypoint -.->|"Outlier detection: ejected"| Backend3[Backend pod<br/>✗ Unhealthy]
style Kgateway fill:#2068F3,color:#fff
style Waypoint fill:#2068F3,color:#fff
Multicluster scenario
- The request routes from an external client to a backend service in the mesh.
- The backend app is exposed as a global service with the
solo.io/service-scope=globalannotation. - The
networking.istio.io/traffic-distributionannotation is set on the global service. Note that other service-scope annotations likesolo.io/service-scope=global-only,solo.io/service-scope=segment,solo.io/service-scope=cluster, orsolo.io/service-takeover: true, behave in the same way. Only the number of endpoints that can be addressed differs, such as only the endpoints within the same cluster or segment.
graph LR
External[External<br/>Client]
subgraph Cluster1["Cluster 1"]
Kgateway[kgateway]
Ztunnel[Gateway<br/>ztunnel]
Waypoint[Waypoint]
Backend1[Backend pod<br/>✓ Healthy]
Kgateway -->|2. Mesh traffic| Ztunnel
Ztunnel -->|3. HBONE| Waypoint
Ztunnel -->|"3. If no waypoint, load balance to global service"| Backend1
Waypoint -->|"4. Local endpoint<br/>(global service)"| Backend1
end
subgraph Cluster2["Cluster 2"]
Backend2[Backend pod<br/>✓ Healthy]
Backend3[Backend pod<br/>✗ Unhealthy]
end
External -->|1. HTTPS| Kgateway
Waypoint -->|"4. Cross-cluster<br/>(global service)"| Backend2
Waypoint -.->|"Outlier detection: ejected"| Backend3
style Kgateway fill:#2068F3,color:#fff
style Waypoint fill:#2068F3,color:#fff
Routing variations:
- Client → ingress gateway → backend
- Client → ingress gateway → waypoint → backend. In this case, the backend has the
istio.io/ingress-use-waypoint=trueservice label to ensure that the ingress gateway routes the incoming request to the waypoint proxy.
Locality determination
Kgateway as an ingress gateway to an ambient mesh does not originate HBONE connections, and instead must have a ztunnel to capture mesh traffic connections. In this way, it behaves as a normal client within the mesh. Locality is therefore determined for each traffic path as follows:
Client → ingress gateway
- Load balancer-specific settings might enforce locality rules, but no locality setting is determined by or for Istio components.
Ingress gateway → backend
- Endpoints are determined by comparing the locality of the ztunnel that serves the ingress gateway with the locality of the backend’s ztunnel.
- After locality is determined, the traffic distribution mode on the backend applies. For example, if the backend has the
Anymode, the ingress gateway round robins between the backend endpoints.
Ingress gateway → waypoint (if applicable)
- Endpoints are determined by comparing the locality of the ztunnel that serves the ingress gateway with the locality of the waypoint.
- After locality is determined, the traffic distribution mode on the waypoint applies. For example, the default
PreferClosemode selects the waypoint that is in the same network, region, and zone as the ingress gateway.
Waypoint → backend (if applicable)
- Endpoints are determined by comparing the waypoint’s locality with the locality of the backend.
- After locality is determined, the traffic distribution mode on the backend applies. For example, if the backend has the
Anymode, the waypoint round robins between the backend endpoints.
Load balancing
Ingress gateway → backend:
Traffic distribution is determined by the traffic distribution setting on the global service. It can be set as:
- Service
spec.trafficDistribution(highest precedence, Kubernetes-native, supportsPreferCloseonly) - Service
networking.istio.io/traffic-distributionannotation (Istio-extended, supports all modes) - ServiceEntry
networking.istio.io/traffic-distributionannotation (Istio-extended, supports all modes). Use this when you use a ServiceEntry. UNSPECIFIED_MODE(default, lowest precedence)
Ingress gateway → waypoint:
Traffic distribution is determined by the traffic distribution setting on the waypoint. It can be set as:
- Service
spec.trafficDistribution(highest precedence, Kubernetes-native, supportsPreferCloseonly) - Service
networking.istio.io/traffic-distributionannotation (Istio-extended, supports all modes)
Waypoint → backend:
Traffic distribution is determined by the traffic distribution setting on the global service. It can be set as:
- Service
spec.trafficDistribution(highest precedence, Kubernetes-native, supportsPreferCloseonly) - Service
networking.istio.io/traffic-distributionannotation (Istio-extended, supports all modes) - ServiceEntry
networking.istio.io/traffic-distributionannotation (Istio-extended, supports all modes). Use this when you use a ServiceEntry. UNSPECIFIED_MODE(default, lowest precedence)
Defaults: If you do not explicitly set traffic distribution modes, PreferClose is used for the waypoint, and PreferNetwork is used for the backend.
To review the available traffic distribution modes and how each mode prioritizes endpoints, see Traffic distribution modes and endpoint priority. Note that these modes apply only if no DestinationRule is in place.
Outlier detection and failover
The traffic distribution settings that are previously described are the recommended method for failover. If these settings cannot meet your failover requirements, you can define an Istio DestinationRule with failover settings in the spec.trafficPolicy.loadBalancer.localityLbSetting section. To detect and handle unhealthy endpoints, you can also define outlier detection conditions in the spec.trafficPolicy.outlierDetection section of a DestinationRule.
The DestinationRule targets the backend service hostname, or a waypoint can enforce it for the service. In a multicluster setup, use the global service hostname (e.g., productpage.bookinfo.mesh.internal). In a single-cluster setup, use the standard Kubernetes service hostname (e.g., productpage.bookinfo.svc.cluster.local or productpage). If multiple services are served by a waypoint, you can specify the hostname of each service in the DestinationRule to set different behavior for each service.
Note that you cannot define a DestinationRule on the request path from kgateway to the waypoint when a waypoint is implemented and your backend has the istio.io/ingress-use-waypoint=true label. Kgateway as an ingress gateway to an ambient mesh implements the istio.io/ingress-use-waypoint=true setting by collapsing the Envoy endpoints to just one endpoint: the service VIP. Because only one endpoint is available to kgateway, a DestinationRule is rendered useless. Instead, kgateway defers all policy to the ambient mesh. The gateway’s ztunnel is responsible for routing the connection to the waypoint, and the waypoint might have its own policy, such as a DestinationRule.
For example configurations, see DestinationRule examples.