# HTTP Scaling with Gloo Gateway

This guide demonstrates how to scale applications exposed through [Gloo Gateway](https://docs.solo.io/gloo-edge/latest/) 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

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

- A running Kubernetes cluster.

- Kedify installed with HTTP Scaler enabled.

- Gloo Gateway installed.

- The `kubectl` and `helm` command line utilities installed and accessible.

For a local walkthrough, install Gloo Gateway with a LoadBalancer gateway proxy:

```bash
kubectl create namespace gloo-system
helm repo add gloo https://storage.googleapis.com/solo-public-helm
helm repo update gloo
helm upgrade --install gloo gloo/gloo \
  --version 1.21.9 \
  --namespace gloo-system \
  --set gatewayProxies.gatewayProxy.disableCoreDumps=true \
  --set gatewayProxies.gatewayProxy.service.type=LoadBalancer \
  --wait
```

If `gateway-proxy` fails to start with `Failed to create temporary file`, mount a writable `/tmp` and wait for the rollout:

```bash
kubectl -n gloo-system patch deployment gateway-proxy --type=json \
  -p='[{"op":"add","path":"/spec/template/spec/volumes/-","value":{"name":"tmp","emptyDir":{}}},{"op":"add","path":"/spec/template/spec/containers/0/volumeMounts/-","value":{"name":"tmp","mountPath":"/tmp"}}]'
kubectl -n gloo-system rollout status deployment/gateway-proxy --timeout=180s
```

## Step 1: Deploy a Sample Application

Create a sample deployment and service:

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: http-server
  namespace: default
spec:
  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: v1
kind: Service
metadata:
  name: http-server
  namespace: default
spec:
  ports:
    - name: http
      port: 8080
      protocol: TCP
      targetPort: 8080
  selector:
    app: http-server
```

Apply the application manifest:

```bash
kubectl apply -f app.yaml
```

## Step 2: Create a Gloo Route

You can expose the service with a direct Gloo `VirtualService` route:

```yaml
apiVersion: gateway.solo.io/v1
kind: VirtualService
metadata:
  name: http-server
  namespace: default
spec:
  virtualHost:
    domains:
      - gloo-http.keda
    routes:
      - matchers:
          - prefix: /
        routeAction:
          single:
            kube:
              ref:
                name: http-server
                namespace: default
              port: 8080
```

Kedify also supports `VirtualService` routes that delegate to a `RouteTable`:

```yaml
apiVersion: gateway.solo.io/v1
kind: RouteTable
metadata:
  name: http-server-routes
  namespace: default
spec:
  routes:
    - matchers:
        - prefix: /
      routeAction:
        single:
          kube:
            ref:
              name: http-server
              namespace: default
            port: 8080
```

And routes that point to a Gloo `Upstream`:

```yaml
apiVersion: gloo.solo.io/v1
kind: Upstream
metadata:
  name: http-server-upstream
  namespace: default
spec:
  kube:
    serviceName: http-server
    serviceNamespace: default
    servicePort: 8080
```

For Gloo Mesh/Gateway v2 native resources, Kedify supports `RouteTable` destinations that point directly to a Kubernetes `SERVICE`:

```yaml
apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: http-server
  namespace: default
spec:
  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: 8080
```

Kedify also supports v2 `RouteTable` destinations that point to a `VIRTUAL_DESTINATION` backed by the scaled Kubernetes Service:

```yaml
apiVersion: networking.gloo.solo.io/v2
kind: VirtualDestination
metadata:
  name: http-server
  namespace: default
spec:
  services:
    - name: http-server
      namespace: default
  ports:
    - name: http
      number: 80
      targetPort:
        number: 8080
---
apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: http-server
  namespace: default
spec:
  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: 80
```

`ExternalService` 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

Create a KEDA `ScaledObject` with the `kedify-http` trigger and Gloo traffic autowiring:

```yaml
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: http-server
  namespace: default
spec:
  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-http
```

- `hosts` (**gloo-http.keda**): The hostname configured on the Gloo `VirtualService`.

- `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:

```bash
kubectl apply -f scaling.yaml
```

After 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:

```bash
kubectl annotate httpscaledobject http-server \
  kedify.io/reconcile="$(date +%s)" --overwrite
```

The autowiring rewrite above modifies the live `VirtualService` (or `RouteTable`) destination, so a GitOps controller will report drift and revert it on the next sync, breaking the wiring. Configure the controller to ignore the autowired destination field. See [Argo CD and GitOps Considerations](https://docs.kedify.io/scalers/http-scaler/#argo-cd-and-gitops-considerations) for the `ignoreDifferences` and `RespectIgnoreDifferences` setup (documented there for `Ingress`; the same approach applies to Gloo routes).

## Step 4: Test Autoscaling

From inside the cluster, call the Gloo gateway proxy:

```bash
kubectl run curl --image=curlimages/curl:8.10.1 --restart=Never -- sleep 3600
kubectl wait --for=condition=Ready pod/curl --timeout=120s
kubectl 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:

```bash
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:

```bash
k3d cluster create --port "9080:80@loadbalancer"
```

Then call through localhost:

```bash
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:

```bash
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:

```bash
kubectl -n gloo-system port-forward svc/gateway-proxy 9080:80
curl -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:

```bash
kubectl get deployment http-server
```

When traffic stops, Kedify scales the deployment back to zero after the configured cooldown period.

## Next Steps

Explore the complete [HTTP Scaler documentation](https://docs.kedify.io/scalers/http-scaler/) for more advanced configuration, including header and path based routing, waiting pages, and proxy tuning.

## Continue with this topic

**Reference:** [HTTP scaler and inference configuration](https://docs.kedify.io/reference/http-scaler/).

**Diagnose:** [Workload does not scale, or scales too slowly](https://docs.kedify.io/troubleshooting/workload-scaling/).

**Related capabilities:** [Diagnose HTTP requests with logs and error metrics](https://docs.kedify.io/how-to/kedify-proxy-access-logs-and-metrics/).

---
Canonical: https://docs.kedify.io/how-to/http-scaling-with-gloo-gateway/
Source: src/content/docs/how-to/http-scaling-with-gloo-gateway.md
Documentation index: https://docs.kedify.io/llms.txt
