HTTP Scaling with Gloo Gateway
This guide demonstrates how to scale applications exposed through Gloo Gateway using the kedify-http scaler. Kedify can autowire Gloo Edge VirtualService routes, delegated RouteTable routes, and Upstream destinations. Kedify also supports Gloo Mesh/Gateway v2 networking.gloo.solo.io/v2 RouteTable resources when they point directly to a Kubernetes SERVICE or to a VIRTUAL_DESTINATION backed by the scaled Kubernetes Service.
Architecture Overview
Section titled “Architecture Overview”For applications exposed through Gloo Gateway, Kedify integrates with Gloo resources using traffic autowiring:
Gloo Gateway -> VirtualService/RouteTable -> kedify-proxy -> Service -> Deployment
The kedify-proxy collects HTTP traffic metrics for the host configured on the HTTPScaledObject. Kedify then scales the target workload up or down, including scale-to-zero when no traffic is present.
When trafficAutowire: gloo is set in kedify-http trigger metadata, Kedify rewrites matching Gloo routes to a Kubernetes service destination pointing at kedify-proxy. Routes that originally point directly to a Kubernetes service and routes that point through a Gloo Upstream are both supported.
Prerequisites
Section titled “Prerequisites”- A running Kubernetes cluster.
- Kedify installed with HTTP Scaler enabled.
- Gloo Gateway installed.
- The
kubectlandhelmcommand line utilities installed and accessible.
For a local walkthrough, install Gloo Gateway with a LoadBalancer gateway proxy:
kubectl create namespace gloo-systemhelm repo add gloo https://storage.googleapis.com/solo-public-helmhelm repo update gloohelm upgrade --install gloo gloo/gloo \ --version 1.21.9 \ --namespace gloo-system \ --set gatewayProxies.gatewayProxy.disableCoreDumps=true \ --set gatewayProxies.gatewayProxy.service.type=LoadBalancer \ --waitStep 1: Deploy a Sample Application
Section titled “Step 1: Deploy a Sample Application”Create a sample deployment and service:
apiVersion: apps/v1kind: Deploymentmetadata: name: http-server namespace: defaultspec: replicas: 0 selector: matchLabels: app: http-server template: metadata: labels: app: http-server spec: containers: - name: http-server image: ghcr.io/kedify/sample-http-server:latest ports: - containerPort: 8080---apiVersion: v1kind: Servicemetadata: name: http-server namespace: defaultspec: ports: - name: http port: 8080 protocol: TCP targetPort: 8080 selector: app: http-serverApply the application manifest:
kubectl apply -f app.yamlStep 2: Create a Gloo Route
Section titled “Step 2: Create a Gloo Route”You can expose the service with a direct Gloo VirtualService route:
apiVersion: gateway.solo.io/v1kind: VirtualServicemetadata: name: http-server namespace: defaultspec: virtualHost: domains: - gloo-http.keda routes: - matchers: - prefix: / routeAction: single: kube: ref: name: http-server namespace: default port: 8080Kedify also supports VirtualService routes that delegate to a RouteTable:
apiVersion: gateway.solo.io/v1kind: RouteTablemetadata: name: http-server-routes namespace: defaultspec: routes: - matchers: - prefix: / routeAction: single: kube: ref: name: http-server namespace: default port: 8080And routes that point to a Gloo Upstream:
apiVersion: gloo.solo.io/v1kind: Upstreammetadata: name: http-server-upstream namespace: defaultspec: kube: serviceName: http-server serviceNamespace: default servicePort: 8080For Gloo Mesh/Gateway v2 native resources, Kedify supports RouteTable
destinations that point directly to a Kubernetes SERVICE:
apiVersion: networking.gloo.solo.io/v2kind: RouteTablemetadata: name: http-server namespace: defaultspec: hosts: - gloo-http.keda virtualGateways: - name: ingress namespace: global http: - name: http-server matchers: - uri: prefix: / forwardTo: destinations: - kind: SERVICE ref: name: http-server namespace: default port: number: 8080Kedify also supports v2 RouteTable destinations that point to a
VIRTUAL_DESTINATION backed by the scaled Kubernetes Service:
apiVersion: networking.gloo.solo.io/v2kind: VirtualDestinationmetadata: name: http-server namespace: defaultspec: services: - name: http-server namespace: default ports: - name: http number: 80 targetPort: number: 8080---apiVersion: networking.gloo.solo.io/v2kind: RouteTablemetadata: name: http-server namespace: defaultspec: hosts: - gloo-http.keda virtualGateways: - name: ingress namespace: global http: - name: http-server matchers: - uri: prefix: / forwardTo: destinations: - kind: VIRTUAL_DESTINATION ref: name: http-server namespace: default port: number: 80ExternalService destinations are intentionally not rewritten because they do
not identify the Kubernetes Service that Kedify scales. They can still exist in
the same Gloo configuration for traffic that is not backed by the scaled
workload.
Step 3: Configure Autoscaling
Section titled “Step 3: Configure Autoscaling”Create a KEDA ScaledObject with the kedify-http trigger and Gloo traffic autowiring:
apiVersion: keda.sh/v1alpha1kind: ScaledObjectmetadata: name: http-server namespace: defaultspec: maxReplicaCount: 5 minReplicaCount: 0 idleReplicaCount: 0 cooldownPeriod: 5 pollingInterval: 1 scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: http-server triggers: - metadata: hosts: gloo-http.keda pathPrefixes: / port: "8080" scalingMetric: requestRate service: http-server targetValue: "1" trafficAutowire: gloo window: "15s" metricType: AverageValue type: kedify-httphosts(gloo-http.keda): The hostname configured on the GlooVirtualService.service(http-server): The Kubernetes Service associated with the application deployment.port(8080): The service port to route to.trafficAutowire(gloo): Enables Gloo Gateway autowiring.
Apply the resources:
kubectl apply -f scaling.yamlAfter reconciliation, Kedify rewrites the matching Gloo route destination to kedify-proxy.
If you apply or change the Gloo route after the generated HTTPScaledObject
already exists, touch the HTTPScaledObject so Kedify reconciles the new route:
kubectl annotate httpscaledobject http-server \ kedify.io/reconcile="$(date +%s)" --overwriteStep 4: Test Autoscaling
Section titled “Step 4: Test Autoscaling”From inside the cluster, call the Gloo gateway proxy:
kubectl run curl --image=curlimages/curl:8.10.1 --restart=Never -- sleep 3600kubectl wait --for=condition=Ready pod/curl --timeout=120skubectl exec curl -- curl -i -H "host: gloo-http.keda" \ http://gateway-proxy.gloo-system.svc.cluster.local/From outside the cluster, use the external address published on the Gloo gateway service:
GLOO_GATEWAY=$(kubectl -n gloo-system get svc gateway-proxy \ -o jsonpath='{.status.loadBalancer.ingress[0].ip}{.status.loadBalancer.ingress[0].hostname}')curl -i -H "Host: gloo-http.keda" "http://$GLOO_GATEWAY/"For local k3d clusters, publish the load balancer port when creating the cluster, for example:
k3d cluster create --port "9080:80@loadbalancer"Then call through localhost:
curl -i -H "Host: gloo-http.keda" http://localhost:9080/For existing k3d clusters with a host port mapped to a node port, expose the
Gloo gateway as NodePort. For example, with 8181:31198@loadbalancer
published:
kubectl -n gloo-system patch svc gateway-proxy --type=json \ -p='[{"op":"replace","path":"/spec/type","value":"NodePort"},{"op":"add","path":"/spec/ports/0/nodePort","value":31198}]'curl -i -H "Host: gloo-http.keda" http://localhost:8181/If your local cluster does not publish a load balancer port, use kubectl port-forward as a fallback:
kubectl -n gloo-system port-forward svc/gateway-proxy 9080:80curl -i -H "Host: gloo-http.keda" http://localhost:9080/The request should cold-start the application and then return an HTTP response. Verify that the deployment scaled out:
kubectl get deployment http-serverWhen traffic stops, Kedify scales the deployment back to zero after the configured cooldown period.
Next Steps
Section titled “Next Steps”Explore the complete HTTP Scaler documentation for more advanced configuration, including header and path based routing, waiting pages, and proxy tuning.