# Test automatic rightsizing with PRA

This guide demonstrates vertical scaling with `PodResourceAutoscaler` (PRA). For reproducibility it uses Kedify’s `load-generator` sample app as the workload driver, but the same setup applies to your own applications.

## Prerequisites

- A running Kubernetes cluster.

- The `kubectl` command-line utility installed and accessible.

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

  - If you do not have a connected cluster, see [installation documentation](https://docs.kedify.io/installation/).

- Kedify Agent installed with Pod Resource Autoscaler feature enabled: 

  - `agent.features.podResourceAutoscalersEnabled=true`

  - Installed Agent version: `v0.4.14` or later (see [Versions & Compatibility](https://docs.kedify.io/getting-started/versions/)).

- Kubernetes support for in-place pod resize. 

  - This is enabled by default in Kubernetes `v1.33+`.

  - If using an older cluster, enable the `InPlacePodVerticalScaling` feature gate.

For local testing with `k3d`, you can create a compatible cluster with:

```bash
k3d cluster create pra-demo --no-lb \
  --k3s-arg "--disable=traefik,servicelb@server:*" \
  --k3s-arg "--kube-apiserver-arg=feature-gates=InPlacePodVerticalScaling=true@server:*"
```

## Step 1: Deploy the Example Workload

This guide uses Kedify’s sample `load-generator` application. Source code: [https://github.com/kedify/examples/tree/main/samples/load-generator](https://github.com/kedify/examples/tree/main/samples/load-generator)

Apply the following Deployment and Service:

```bash
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: load-generator
  labels:
    app: load-generator
spec:
  replicas: 1
  selector:
    matchLabels:
      app: load-generator
  template:
    metadata:
      labels:
        app: load-generator
      annotations:
        pra.kedify.io/reconcile: enabled
    spec:
      containers:
        - name: load-generator
          image: ghcr.io/kedify/sample-load-generator:latest
          imagePullPolicy: Always
          ports:
            - containerPort: 8080
              name: http
          env:
            - name: BASELINE_CPU_MILLICORES
              value: "100"
            - name: BASELINE_MEMORY_MIB
              value: "96"
          resources:
            requests:
              cpu: 100m
              memory: 96Mi
            limits:
              cpu: 300m
              memory: 600Mi
          readinessProbe:
            httpGet:
              path: /healthz
              port: http
            periodSeconds: 5
          livenessProbe:
            httpGet:
              path: /healthz
              port: http
            initialDelaySeconds: 5
            periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
  name: load-generator
  labels:
    app: load-generator
spec:
  type: ClusterIP
  ports:
    - name: http
      port: 8080
      targetPort: http
  selector:
    app: load-generator
EOF
```

Verify the Pod is ready:

```bash
kubectl rollout status deploy/load-generator
```

## Step 2: Create PodResourceAutoscaler

Apply PRA configuration that manages both CPU and memory requests/limits:

```bash
cat <<EOF | kubectl apply -f -
apiVersion: keda.kedify.io/v1alpha1
kind: PodResourceAutoscaler
metadata:
  name: load-generator
spec:
  target:
    kind: deployment
    name: load-generator
  containerName: load-generator
  policy:
    pollInterval: 5s
    consecutiveSamples: 2
    cooldown: 30s
    after: containerReady
    delay: 5s
    cpu:
      requests:
        scaleUpThreshold: 75
        scaleDownThreshold: 45
        targetUtilization: 60
      limits:
        scaleUpThreshold: 85
        scaleDownThreshold: 60
        targetUtilization: 70
    memory:
      requests:
        scaleUpThreshold: 75
        scaleDownThreshold: 50
        targetUtilization: 60
      limits:
        scaleUpThreshold: 85
        scaleDownThreshold: 60
        targetUtilization: 70
  bounds:
    cpu:
      requests:
        min: 100m
        max: "2"
        step: 200m
        stepPercent: 50
      limits:
        min: 300m
        max: "3"
        step: 300m
        stepPercent: 50
    memory:
      requests:
        min: 96Mi
        max: 2Gi
        step: 128Mi
        stepPercent: 50
      limits:
        min: 600Mi
        max: 3Gi
        step: 256Mi
        stepPercent: 50
EOF
```

## Step 3: Watch In-Place Resource Resizing

Open a terminal and watch container resources:

```bash
watch "kubectl get pod -l app=load-generator -ojsonpath=\"{.items[0].spec.containers[?(.name=='load-generator')].resources}\" | jq"
```

You should see similar output:

```json
{
  "limits": {
    "cpu": "300m",
    "memory": "600Mi"
  },
  "requests": {
    "cpu": "169m",
    "memory": "196Mi"
  }
}
```

## Step 4: Change Runtime Load Profiles

Start port-forward in another terminal:

```bash
kubectl port-forward svc/load-generator 8080:8080
```

Set workload to `idle` (low footprint) first:

```bash
curl -s -X POST localhost:8080/profile/idle | jq
```

Check current profile:

```bash
curl -s localhost:8080/status | jq
```

You should see similar output:

```json
{
  "baseline": {
    "cpuMillicores": 100,
    "memoryMiB": 96
  },
  "desired": {
    "cpuMillicores": 100,
    "memoryMiB": 96
  },
  "current": {
    "cpuMillicores": 100,
    "memoryMiB": 96
  },
  "activeProfile": "idle",
  "schedule": {
    "active": false
  },
  "cpu": {
    "workers": 2,
    "targetMillicores": 100,
    "maxMillicores": 2000,
    "requestedMillicores": 100
  },
  "memory": {
    "targetMiB": 96,
    "allocatedMiB": 96
  },
  "uptimeSeconds": 26676
}
```

Trigger higher load:

```bash
curl -s -X POST localhost:8080/profile/high | jq
```

Verify in the `watch` output from Step 3 that requests/limits go up.

Then return to `idle`:

```bash
curl -s -X POST localhost:8080/profile/idle | jq
```

Verify in the `watch` output that requests/limits go down again. Replica count should remain `1` for the whole flow.

[![Illustrative high and low CPU samples change configured CPU requests and limits in bounded steps while replica count remains one.](https://docs.kedify.io/assets/images/docs/pra-load-response.svg)](https://docs.kedify.io/assets/images/docs/pra-load-response.svg)

Scroll to exploreDiagram description

Illustrative CPU usage rises then falls. After three qualifying samples, CPU requests change from 200 to 400 to 600 to 400 to 200m, and limits from 300 to 500 to 700 to 500 to 300m. Each side has its own utilization policy. Changes are capped at 200m; replicas remain at one.

This uses the [separate illustrative CPU policy](https://docs.kedify.io/features/pod-resource-autoscaler/#scaling-policy), not captured output or the exact configuration from this tutorial. Compare your observed samples, resize events and actual resources; the elapsed time and values depend on your policy and cluster.

## Step 5: Verify PRA Status and Events

Check PRA status and latest scaling action:

```bash
kubectl describe pra load-generator
kubectl get pra load-generator -o jsonpath='{.status.lastScaleAction}{"\n"}{.status.lastScaleResourceChange}{"\n"}'
```

Inspect related Kubernetes events:

```bash
kubectl get events --sort-by=.lastTimestamp | grep PodResourceAutoscaler
```

You should see events similar to `PodResourceAutoscalerScaleUp` and `PodResourceAutoscalerScaleDown`.

## Cleanup

```bash
kubectl delete pra load-generator
kubectl delete svc load-generator
kubectl delete deploy load-generator
```

## Continue with this topic

**Configure and verify:** [Diagnose resize failures](https://docs.kedify.io/troubleshooting/vertical-scaling/).

**Reference:** [PodResourceAutoscaler API reference](https://docs.kedify.io/reference/kubernetes-api/podresourceautoscaler/).

**Diagnose:** [Pod resources do not resize as expected](https://docs.kedify.io/troubleshooting/vertical-scaling/).

**Related capabilities:** [Pod Resource Autoscaler (PRA)](https://docs.kedify.io/features/pod-resource-autoscaler/).

---
Canonical: https://docs.kedify.io/how-to/pra-vertical-scaling-with-load-generator/
Source: src/content/docs/how-to/pra-vertical-scaling-with-load-generator.md
Documentation index: https://docs.kedify.io/llms.txt
