# TLS Ingress HTTP Autoscaling

This guide demonstrates how to scale applications exposed via Kubernetes Ingress **with HTTPS enabled** using the `kedify-http` scaler. It builds on standard HTTP-based autoscaling by adding TLS support for end-to-end encrypted workloads.

You’ll deploy a sample application configured with TLS, expose it via NGINX Ingress, and configure a `ScaledObject` that supports encrypted traffic. This works seamlessly with Kedify’s traffic autowiring system, enabling scaling to zero based on secure HTTP(S) traffic.

## Architecture Overview

For TLS workloads using Ingress, Kedify intercepts traffic and collects encrypted traffic metrics without interfering with your TLS setup.

**HTTPS Ingress -> kedify-proxy (with TLS support) -> Service -> Deployment**

You can use any ingress controller that supports HTTPS. In this guide, we use **NGINX Ingress** with self-signed certificates.

## Prerequisites

- A Kubernetes cluster (local or remote)

- The `kubectl` CLI installed and configured

- A connected cluster in the [Kedify Dashboard](https://dashboard.kedify.io/)

- [openssl](https://github.com/openssl/openssl) cli (for generating self-signed certs)

- [hey](https://github.com/rakyll/hey) for load testing

To follow along locally:

1. Create a k3d cluster with HTTP/HTTPS ports and no Traefik:

```bash
k3d cluster create \
  --port "9080:80@loadbalancer" \
  --port "9443:443@loadbalancer" \
  --k3s-arg "--disable=traefik@server:*"
```

2. Install NGINX Ingress:

```bash
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

helm install nginx-ingress ingress-nginx/ingress-nginx \
  --namespace nginx-ingress \
  --create-namespace \
  --set controller.publishService.enabled=true \
  --set controller.service.type=LoadBalancer
```

## Step 1: Deploy a TLS-Enabled Application

Start by generating a self-signed TLS certificate and storing it as a Kubernetes secret:

```bash
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout tls.key -out tls.crt \
  -subj "/CN=tls-demo.keda/O=tls-demo.keda" \
  -addext "subjectAltName = DNS:tls-demo.keda"

kubectl create secret tls http-server-tls \
  --cert=tls.crt --key=tls.key
```

Now deploy the application with TLS support:

http-server-tls.yaml

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: http-server-tls
spec:
  replicas: 1
  selector:
    matchLabels:
      app: http-server-tls
  template:
    metadata:
      labels:
        app: http-server-tls
    spec:
      containers:
        - name: http-server
          image: ghcr.io/kedify/sample-http-server:latest
          ports:
            - name: https
              containerPort: 8443
              protocol: TCP
          env:
            - name: RESPONSE_DELAY
              value: "0.3"
            - name: TLS_ENABLED
              value: "true"
            - name: TLS_CERT_FILE
              value: "/certs/tls.crt"
            - name: TLS_KEY_FILE
              value: "/certs/tls.key"
          volumeMounts:
            - name: tls-certs
              mountPath: /certs
              readOnly: true
      volumes:
        - name: tls-certs
          secret:
            secretName: http-server-tls
---
apiVersion: v1
kind: Service
metadata:
  name: http-server-tls
spec:
  ports:
    - name: https
      port: 443
      targetPort: 8443
  selector:
    app: http-server-tls
```

- **Deployment**: A Go-based HTTP server configured to respond over HTTPS.

- **Service**: Exposes the HTTPS port to other cluster resources.

- **Secret**: Contains the TLS certificate and private key.

Apply the resources:

```bash
kubectl apply -f http-server-tls.yaml
```

## Step 2: Expose the Application with Ingress

Now expose your service to external traffic via HTTPS with NGINX:

http-server-tls-ingress.yaml

```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: http-server-tls
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - tls-demo.keda
      secretName: http-server-tls
  rules:
    - host: tls-demo.keda
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: http-server-tls
                port:
                  number: 443
```

Apply it:

```bash
kubectl apply -f http-server-tls-ingress.yaml
```

- **Ingress**: Exposes the HTTPS endpoint to the outside world using NGINX.

- `backend-protocol: HTTPS`: Ensures NGINX talks to the app using TLS internally.

- `tls`: Points to the TLS secret and hostname.

## Step 3: Apply ScaledObject for TLS

Configure a `ScaledObject` to monitor HTTPS traffic on port 443:

scaledobject-tls.yaml

```yaml
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: http-server-tls
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: http-server-tls
  cooldownPeriod: 5
  minReplicaCount: 0
  maxReplicaCount: 10
  fallback:
    failureThreshold: 2
    replicas: 1
  advanced:
    restoreToOriginalReplicaCount: true
    horizontalPodAutoscalerConfig:
      behavior:
        scaleDown:
          stabilizationWindowSeconds: 5
  triggers:
    - type: kedify-http
      metadata:
        hosts: tls-demo.keda
        service: http-server-tls
        port: "443"
        scalingMetric: requestRate
        targetValue: "10"
        granularity: 1s
        window: 10s
        tlsSecretName: http-server-tls
```

Apply it:

```bash
kubectl apply -f scaledobject-tls.yaml
```

- `type` (**kedify-http**): Specifies the Kedify HTTP scaler for monitoring HTTP traffic.

- `metadata.hosts` (**application.keda**): The hostname to monitor for traffic.

- `metadata.pathPrefixes` (**/**): The path prefix to monitor.

- `metadata.service` (**application-service**): The Kubernetes Service associated with the application.

- `metadata.port` (**443**): The port on the service to monitor.

- `metadata.scalingMetric` (**requestRate**): The metric used for scaling decisions.

- `metadata.targetValue` (**1000**): Target request rate; KEDA scales out when traffic meets or exceeds this value.

- `metadata.granularity` (**1s**): The time unit for the targetValue (requests per second).

- `metadata.window` (**10s**): Granularity at which the request rate is measured.

- `metadata.trafficAutowire` (**ingress**): Enables Kedify’s ingress autowiring feature.

- `metadata.tlsSecretName`(**http-server-tls**) References the Secret with the certificate, ensures KEDA can trust your TLS traffic.

You should see the `ScaledObject` in the Kedify Dashboard:

![Kedify Dashboard With ScaledObject](https://docs.kedify.io/assets/images/how-to/http-scaling-for-ingress-based-applications/step-2-scaledobject.png)

## Step 4: Test HTTPS Autoscaling

To verify the server responds:

```bash
# If testing locally with k3d (if testing on a remote cluster, use the Ingress IP or domain)
# we are also skipping self-signed cert verification via -k
curl -Ik -H "Host: tls-demo.keda" https://localhost:9443/
```

You should receive a `200 OK` with the server’s HTML:

```bash
HTTP/2 200
date: Tue, 29 Apr 2025 12:47:02 GMT
content-type: text/html
content-length: 301
x-keda-http-cold-start: true
x-envoy-upstream-service-time: 3124
strict-transport-security: max-age=31536000; includeSubDomains
```

To trigger scaling:

```bash
# If testing locally with k3d (if testing on a remote cluster, use the Ingress IP or domain)
hey -n 10000 -c 150 -host "tls-demo.keda" https://localhost:9443/
```

```bash
Response time histogram:
  0.301 [1]      |
  0.498 [9749]  |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  0.695 [0]      |
  0.892 [0]      |
  1.090 [0]      |
  1.287 [0]      |
  1.484 [0]      |
  1.681 [53]    |
  1.878 [0]      |
  2.075 [53]    |
  2.272 [44]    |
```

In the Kedify Dashboard, you can also observe the traffic load and resulting scaling:

![Kedify Dashboard ScaledObject Detail](https://docs.kedify.io/assets/images/how-to/http-scaling-for-ingress-based-applications/step-3-load.png)

## Step 5: Configure TLS Mode (Optional)

By default, Kedify Proxy performs re-encryption of the traffic to ensure [L7 routing options](https://docs.kedify.io/scalers/http-scaler/#routing-traffic-with-http-headers) and [OTel tracing support](https://docs.kedify.io/how-to/otel-tracing-proxy-and-interceptor/). You can optionally configure TLS mode to `passthrough` to avoid re-encryption overhead, but then you won’t be able to leverage routing with path suffixes and/or headers. Additionally, you will lose the ability to see Kedify Proxy spans in OpenTelemetry tracing.

- `metadata.tlsMode` (**reencrypt** | **passthrough**): Selecting TLS Mode (`reencrypt` or `passthrough`). For `passthrough` it’s not necessary to provide `tlsSecretName` anymore.

## Next Steps

- This guide showed how to scale applications securely using HTTPS.

- You can extend this setup using production TLS certificates from `cert-manager` or your preferred provider.

- Explore the full [HTTP Scaler documentation](https://docs.kedify.io/scalers/http-scaler/) to tune scaling metrics, fallback behavior, and integration with other Ingress providers.

## 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-tls-for-ingress-based-applications/
Source: src/content/docs/how-to/http-scaling-with-tls-for-ingress-based-applications.md
Documentation index: https://docs.kedify.io/llms.txt
