Developing KEDA scaler mappings
Camel K can derive KEDA triggers from the consumer endpoints of an Integration. This page explains how to extend that discovery with a mapping for another Camel component. For information about configuring autoscaling, see the Integration scaling guide and the KEDA trait reference.
| A scaler mapping translates a Camel component URI into metadata for an existing KEDA scaler. It does not implement a new scaler in the KEDA project. |
How automatic discovery works
When the KEDA trait is enabled, kedaTrait.Configure runs automatic discovery unless keda.auto is set to false. Discovery follows this flow:
-
metadata.ExtractAllinspects all Integration sources and extracts their CamelfromURIs. -
Each URI is passed to
MapToKedaTrigger. -
ParseComponentURIseparates the URI into its component name, path value, and query parameters. -
The component name is used to look up a
ScaleMapperin the registry. -
If a mapper is registered, it converts the path and parameters into a KEDA scaler type and metadata, which become a
KedaTrigger. -
The KEDA trait adds the trigger to the
ScaledObjectthat it creates inApply.
An unsupported Camel component has no registered mapper, so it does not produce an automatically discovered trigger. A manually configured trigger takes precedence over an automatically discovered trigger of the same type. The trait also merges entries from keda.autoMetadata into discovered metadata.
The ScaleMapper registry
The registry and interface are defined in pkg/trait/keda/mapper.go:
type ScaleMapper interface {
Component() string
Map(pathValue string, params map[string]string) (kedaType string, metadata map[string]string)
} Component returns the Camel component name used as the registry key. Map receives the path part of the Camel URI and its decoded query parameters, and returns the corresponding KEDA scaler type and metadata.
Each implementation registers itself by calling keda.Register from an init function. The blank import of pkg/trait/keda/scalers in pkg/trait/keda.go ensures that these registration functions run when the trait package is loaded.
Kafka reference implementation
The Kafka mapper in pkg/trait/keda/scalers/kafka.go is the reference implementation. It maps the Camel URI path to the KEDA topic, the Camel brokers parameter to bootstrapServers, and groupId to consumerGroup.
For example, this Camel source URI:
kafka:orders?brokers=broker:9092&groupId=my-group produces this trigger:
type: kafka
metadata:
topic: orders
bootstrapServers: broker:9092
consumerGroup: my-group Other KEDA Kafka metadata, such as lagThreshold, can be supplied through keda.autoMetadata when it is not derived from the Camel URI.
Complete mapping example
The following example uses fictional component and scaler names to show the complete mapping process.
Assume an Integration consumes from this Camel URI:
my-component:orders?server=broker.example:1234 The Camel component is my-component. The URI path, orders, should map directly to the scaler’s topic metadata field. The Camel server parameter should be adapted to the scaler’s address metadata field.
For example, a mapper in pkg/trait/keda/scalers/my_component.go could look like this:
package scalers
import keda "github.com/apache/camel-k/v2/pkg/trait/keda"
type MyComponentScaler struct{}
func init() {
keda.Register(&MyComponentScaler{})
}
func (m *MyComponentScaler) Component() string {
return "my-component"
}
func (m *MyComponentScaler) Map(pathValue string, params map[string]string) (string, map[string]string) {
metadata := make(map[string]string)
if pathValue != "" {
metadata["topic"] = pathValue
}
if v, ok := params["server"]; ok {
metadata["address"] = v
}
return "my-scaler", metadata
} With that mapper registered, the source URI produces this KEDA trigger:
type: my-scaler
metadata:
topic: orders
address: broker.example:1234 This example shows the two common mapping cases:
-
ordersis copied directly from the Camel URI path into the KEDAtopicfield. -
serveris renamed to the KEDAaddressfield because the Camel component and KEDA scaler use different names for the same value.
The mapper only translates values needed by the scaler. It should not add unrelated Camel endpoint parameters to the KEDA metadata.
Adding a mapping
-
Add
pkg/trait/keda/scalers/<component>.go. -
Define a type that implements
ScaleMapper. -
Return the Camel component name from
Component. -
In
Map, translate only relevant Camel URI path and parameter values to the metadata expected by the existing KEDA scaler, and return its scaler type. -
Register the mapper with
keda.Registerin aninitfunction. -
Add
pkg/trait/keda/scalers/<component>_test.go.
Keep component-specific conversion in the scaler package. Shared URI parsing and registry behavior belong in pkg/trait/keda.
Testing a mapping
Use pkg/trait/keda/scalers/kafka_test.go as the model for a new mapper’s tests. Cover at least:
-
registration under the expected Camel component name;
-
conversion of a complete URI;
-
conversion when optional URI values are absent;
-
exact KEDA scaler type and metadata keys; and
-
MapToKedaTriggerbehavior for the new component.
If the change affects discovery or trigger precedence, add coverage to pkg/trait/keda_test.go as well. Run the focused tests with:
$ go test ./pkg/trait/keda/... ./pkg/trait