Getting started ​
This page walks through a complete first request through the extension: enable it on a shoot, create a Gateway, attach an HTTPRoute, and hit the LoadBalancer with curl. Follow it top-to-bottom and you should have a working ingress in ~5 minutes after the shoot has reconciled.
If you're looking for the field reference, see configuration.md. If something goes wrong along the way, see troubleshooting.md.
Prerequisites ​
- A Gardener landscape where an operator has already registered the extension. If you're the operator, follow deployment.md first.
- A shoot with
spec.purpose: evaluation(enforced by the admission webhook during the GEP-68 incubation phase). kubectlaccess to the shoot cluster.
1. Enable the extension on your shoot ​
Add the extension to spec.extensions:
apiVersion: core.gardener.cloud/v1beta1
kind: Shoot
metadata:
name: my-shoot
namespace: garden-my-project
spec:
purpose: evaluation
extensions:
- type: envoy-gateway
providerConfig:
apiVersion: envoy-gateway.extensions.gardener.cloud/v1alpha1
kind: EnvoyGatewayConfig
controlPlane:
logLevel: info
# ... rest of the shoot specApply it and wait for the shoot to reconcile. When the extension has finished, the shoot cluster contains:
- The Envoy Gateway control-plane Deployment (2 replicas by default) in
kube-system. - A single
GatewayClassnamedgardener-envoy-gatewayinAccepted=Truestate. - Standard-channel Gateway API CRDs (
Gateway,HTTPRoute,GRPCRoute,ReferenceGrant,BackendTLSPolicy,ListenerSet). - Envoy Gateway's own CRDs (
EnvoyProxy,BackendTrafficPolicy, …).
Sanity-check from the shoot:
kubectl get gatewayclass gardener-envoy-gateway
# NAME CONTROLLER ACCEPTED AGE
# gardener-envoy-gateway gateway.envoyproxy.io/gatewayclass-controller True 1m2. Deploy a demo backend ​
Anything that speaks HTTP works. httpbin is a common choice:
apiVersion: v1
kind: Namespace
metadata:
name: demo
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin
namespace: demo
spec:
replicas: 1
selector:
matchLabels: { app: httpbin }
template:
metadata:
labels: { app: httpbin }
spec:
containers:
- name: httpbin
image: mccutchen/go-httpbin:v2.15.0
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: httpbin
namespace: demo
spec:
selector: { app: httpbin }
ports:
- name: http
port: 80
targetPort: 80803. Create a Gateway ​
The Gateway is the L4 listener the LB routes traffic to. It references the gardener-envoy-gateway GatewayClass and opens port 80:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: demo
namespace: demo
spec:
gatewayClassName: gardener-envoy-gateway
listeners:
- name: http
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: SameApply it. Envoy Gateway spawns a per-Gateway Envoy Deployment and a LoadBalancer Service in the shoot; the cloud-provider LB controller provisions the underlying LB and writes its address back to Gateway.status.addresses:
kubectl -n demo wait --for=condition=Programmed gateway/demo --timeout=5m
kubectl -n demo get gateway demo -o jsonpath='{.status.addresses[0].value}'
# 34.107.xxx.yyyIf the address stays empty for more than ~5 minutes, see the Gateway stays Programmed=False section.
4. Attach an HTTPRoute ​
The HTTPRoute describes routing rules and picks the Gateway it attaches to via parentRefs:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httpbin
namespace: demo
spec:
parentRefs:
- name: demo
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: httpbin
port: 805. Send a request ​
LB=$(kubectl -n demo get gateway demo -o jsonpath='{.status.addresses[0].value}')
curl -s "http://${LB}/get" | jq .
# {
# "headers": {
# "Host": ["34.107.xxx.yyy"],
# "User-Agent": ["curl/8.5.0"],
# ...
# },
# "method": "GET",
# "url": "http://34.107.xxx.yyy/get"
# }That's the full path: extension → GatewayClass → Gateway → cloud LB → Envoy data-plane → HTTPRoute → your backend Service.
Cleanup ​
Remove the demo resources; leave the extension alone if you want to keep using it:
kubectl delete namespace demoThe Envoy data-plane Deployment and its LoadBalancer Service are cleaned up automatically once the Gateway disappears.
To also remove the extension itself from the shoot, delete the spec.extensions[] entry. The extension refuses to detach while user-owned Gateway objects still exist in the shoot — see the delete guard in configuration.md.
Next steps ​
- Route by hostname, headers, or method — see the upstream HTTPRoute reference.
- Terminate TLS at the
Gateway— see the upstream TLS termination guide. - Tune the Envoy proxy (resources, tracing, access logs) via a custom
EnvoyProxyreferenced fromGateway.spec.infrastructure.parametersRef. - Migrating from
Ingress? The upstream Migrating from Ingress guide is the best starting point.