Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 99 additions & 2 deletions docs/versioned/eventing/configuration/keda-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,77 @@ data:

```

## Configure KEDA scaling globally

To configure the KEDA scaling behaviour globally for all resources you can edit the configmap `config-kafka-autoscaler` in the `knative-eventing` namespace.

Note that the `min-scale` and `max-scale` parameters both refer to the number of Kafka consumers, not the number of dispatcher pods. The number of dispatcher pods in the StatefulSet is determined by `scale / POD_CAPACITY`, where `POD_CAPACITY` is an environment variable you can configure on the `kafka-controller` deployment, and defaults to `20`.
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: config-kafka-autoscaler
namespace: knative-eventing
data:
# What autoscaling class should be used. Can either be keda.autoscaling.knative.dev or dispabled.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# What autoscaling class should be used. Can either be keda.autoscaling.knative.dev or dispabled.
# What autoscaling class should be used. Can either be keda.autoscaling.knative.dev or deactivated.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(typo + inclusive language)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

disabled is the key we are using in the code afaik - I just took it from the repo

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 it is there since longer.

class: keda.autoscaling.knative.dev
# The period in seconds the autoscaler waits until it scales down
cooldown-period: "30"
# The lag that is used for scaling (1<->N)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably have a unit?

lag-threshold: "100"
# The maximum number of replicas to scale up to
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This says "replicas", but the comment above talks about "Kafka consumers" (which I assume means threads reading from a shared consumer group)?

max-scale: "50"
# The minimum number of replicas to scale down to
min-scale: "0"
# The interval in seconds the autoscaler uses to poll metrics in order to inform its scaling decisions
polling-interval: "10"
```

## Understanding KEDA Scaling Patterns

KEDA uses different lag thresholds to determine when to scale your Kafka components:

### Scaling from 0 to 1 (Activation)
- **Trigger**: When consumer lag exceeds the `activation-lag-threshold` (default: 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

activation-lag-threshold doesn't seem to be in the above ConfigMap. Is this another key?

- **Behavior**: KEDA activates the first replica when any messages are waiting in the Kafka queue
- **Use case**: Quick response to incoming events when the system is idle

### Scaling from 1 to N (Scale Up)
- **Trigger**: When consumer lag exceeds the `lag-threshold` (default: 100)
- **Behavior**: KEDA adds more consumer replicas based on the lag-to-threshold ratio
- **Formula**: `desired_replicas = min(ceil(current_lag / lag_threshold), max_scale)`

### Scaling Down and to Zero
- **Trigger**: When consumer lag falls below thresholds
- **Behavior**: KEDA waits for the `cooldown-period` (default: 30 seconds) before reducing replicas
- **Scale to zero**: Occurs when lag is below `activation-lag-threshold` for the duration of the cooldown period

### StatefulSet Pod Calculation
Each resource type (KafkaSources, Triggers, etc.) has its own dispatcher StatefulSet. Within each StatefulSet, the number of dispatcher pods is calculated as:
```
dispatcher_pods = ceil(total_consumers_for_resource_type / POD_CAPACITY)
```

Where `POD_CAPACITY` defaults to 20, meaning each dispatcher pod can handle up to 20 Kafka consumers.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the example above, max-scale was set to 50, which seems like it would mean 3 dispatcher pods (the same as if the value were 60). Is there a practical difference between 41 and 60 here given the default value of POD_CAPACITY?

I ask because we had a few samples for Serving autoscaling where the end result was that a single request coming in for a scaled-down pod would sometimes cause 2 pods to start, because the pending request + the "spare capacity" factor ended up crossing the one-pod capacity threshold (i.e. the "spare capacity" number was exactly equal to "pod capacity", so ceil(200 + 1 / 200) => 2).


**Important**: Each resource (KafkaSource, Trigger, Subscription) creates its own consumer group, and KEDA scales the number of consumers within that consumer group. All consumers for a given resource type are distributed across the dispatcher pods in that type's StatefulSet.

To maintain a **fixed minimum number of StatefulSet pods** for a resource type, calculate the total consumers needed:
```
total_consumers = sum_of_all_min_scales_for_resource_type
min_dispatcher_pods = ceil(total_consumers / POD_CAPACITY)
```

For example:
- 2 Triggers each with `min-scale: "40"` = 80 total consumers
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not rendered as a list. You probably need a blank line between the bulletpoint and the "For example:" header.

Screenshot From 2025-09-30 18-57-47

- With default `POD_CAPACITY: 20`, this creates `ceil(80/20) = 4` dispatcher pods for the Trigger StatefulSet
- All 80 consumers are distributed across these 4 pods

## Configure Autoscaling for a Resource

If you want to customize how KEDA scales a KafkaSource, trigger, or subscription you can set annotations on the resource:
If you want to customize how KEDA scales a KafkaSource, trigger, or subscription you can set annotations on the resource.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: here trigger, or subscription have a small first letter, but here a capital first letter :)


Note that the `min-scale` and `max-scale` parameters both refer to the number of Kafka consumers, not the number of dispatcher pods. The number of dispatcher pods in the StatefulSet is determined by `scale / POD_CAPACITY`, where `POD_CAPACITY` is an environment variable you can configure on the `kafka-controller` deployment, and defaults to `20`.

```yaml
apiVersion: <eventing|messaging|sources>.knative.dev/v1
Expand All @@ -54,7 +122,7 @@ metadata:
# The lag that is used for scaling (1<->N)
autoscaling.eventing.knative.dev/lag-threshold: "100"
# The lag that is used for activation (0<->1)
autoscaling.eventing.knative.dev: "0"
autoscaling.eventing.knative.dev/activation-lag-threshold: "0"
spec:
# Spec fields for the resource...
```
Expand All @@ -72,3 +140,32 @@ metadata:
spec:
# Spec fields for the resource...
```

## Manual Scaling with KEDA Disabled

When KEDA is disabled (either globally or for specific resources), you can manually control the number of StatefulSet pods by scaling the consumer group resources directly.

Each Kafka resource creates a corresponding `ConsumerGroup` resource in the same namespace that controls the number of consumers. You can manually scale these to achieve your desired pod count:

```bash
# List all consumer groups in your workload namespace
kubectl get consumergroups -n <your-namespace>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use the FQN of the resource, @Cali0707 ?


# Scale a specific consumer group to desired consumer count
kubectl scale consumergroup <consumergroup-name> --replicas=<desired-consumer-count> -n <your-namespace>
```

Consumer groups are named: `knative-trigger-<namespace>-<trigger-name>`

To calculate the desired consumer count for a target number of StatefulSet pods:
```
desired_consumer_count = target_pods × POD_CAPACITY
```

For example, to ensure 3 dispatcher pods for a Trigger named "my-trigger" in the "default" namespace:
```bash
# Set consumer count to 60 (3 pods × 20 POD_CAPACITY)
kubectl scale consumergroup knative-trigger-default-my-trigger --replicas=60 -n default
```

**Note**: Manual scaling is persistent until you re-enable KEDA autoscaling or manually change the scale again. The StatefulSet will automatically adjust its pod count based on the consumer group replica count.
Loading