# Getting Started with KEDA Autoscaling (/integrations/keda/tutorials/getting-started)



The KubeMQ KEDA external scaler enables Kubernetes-native autoscaling based on KubeMQ queue depth. It queries the `Waiting` message count from a KubeMQ [queue](/learn/queues) channel and exposes it as a KEDA metric, so a `ScaledObject` can scale queue-consuming workloads — GPU inference workers, batch processors, task consumers — up and down as the queue fills and drains.

This guide installs the scaler with Helm and wires up your first `ScaledObject`.

<Callout type="info">
  All Helm commands below assume you are running from the `kubemq-keda/` directory of the scaler repository, where the chart at `deploy/helm/kubemq-keda-scaler/` lives.
</Callout>

## Installation steps [#installation-steps]

<Steps>
  <Step>
    ### Prerequisites [#prerequisites]

    | Requirement   | Version / Detail                                                    |
    | ------------- | ------------------------------------------------------------------- |
    | Kubernetes    | **1.27+** (required for native gRPC probes)                         |
    | CLI tools     | `kubectl` and [Helm](https://helm.sh)                               |
    | KEDA          | **2.10+** installed in the cluster                                  |
    | KubeMQ broker | Reachable in-cluster, e.g. `kubemq.default.svc.cluster.local:50000` |

    You can confirm your cluster version with `kubectl version`, and check whether KEDA is already present with `kubectl get pods -n keda`.
  </Step>

  <Step>
    ### Install KEDA (if needed) [#install-keda-if-needed]

    If KEDA is not already running in the cluster, install it with the official Helm chart:

    ```bash
    helm repo add kedacore https://kedacore.github.io/charts
    helm install keda kedacore/keda --namespace keda --create-namespace
    ```

    This deploys the KEDA operator and metrics adapter into the `keda` namespace. The KubeMQ scaler is independent of this install — it registers with KEDA through the `ScaledObject` you create later.
  </Step>

  <Step>
    ### Deploy the Scaler via Helm [#deploy-the-scaler-via-helm]

    Install the KubeMQ KEDA scaler from the chart bundled in the repository:

    ```bash
    helm install kubemq-keda-scaler deploy/helm/kubemq-keda-scaler/
    ```

    This deploys the scaler workload (image `kubemq/kubemq-keda-scaler:1.0.0`) and a `ClusterIP` Service that exposes its gRPC server on port `9090`. The chart runs the container as a non-root user with a read-only root filesystem by default.

    To install with custom values — for example, debug logging:

    ```bash
    helm install kubemq-keda-scaler deploy/helm/kubemq-keda-scaler/ \
      --set env.logLevel=debug \
      --set resources.requests.cpu=100m
    ```
  </Step>

  <Step>
    ### Verify the Scaler Service [#verify-the-scaler-service]

    Confirm the scaler's Kubernetes Service is up:

    ```bash
    kubectl get svc kubemq-keda-scaler
    ```

    You should see a `ClusterIP` Service exposing the gRPC port `9090`:

    ```text
    NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
    kubemq-keda-scaler   ClusterIP   10.96.142.10    <none>        9090/TCP   30s
    ```

    The Service forwards port `9090` to the container's named `grpc` target port. KEDA connects to this Service when it polls the scaler for metrics.
  </Step>

  <Step>
    ### Determine the Scaler Service FQDN [#determine-the-scaler-service-fqdn]

    KEDA reaches the scaler through its in-cluster DNS name. The FQDN format is:

    ```text
    <release-name>-kubemq-keda-scaler.<namespace>.svc.cluster.local:9090
    ```

    For the default install above (release name `kubemq-keda-scaler`, namespace `default`), the chart's Service name resolves to:

    ```text
    kubemq-keda-scaler.default.svc.cluster.local:9090
    ```

    For a Helm install with release name `my-release` in namespace `keda`, it would be `my-release-kubemq-keda-scaler.keda.svc.cluster.local:9090`. You will use this value as the `scalerAddress` in the next step.
  </Step>

  <Step>
    ### Create a ScaledObject [#create-a-scaledobject]

    Define a `ScaledObject` that targets your queue-consuming `Deployment` and points the `external` trigger at both the scaler Service and your KubeMQ broker. This basic example scales `my-queue-consumer` based on the `Waiting` count of `my-queue`, targeting 10 waiting messages per replica:

    ```yaml title="scaled-object-basic.yaml"
    apiVersion: keda.sh/v1alpha1
    kind: ScaledObject
    metadata:
      name: kubemq-queue-scaler
    spec:
      scaleTargetRef:
        name: my-queue-consumer
      pollingInterval: 15
      cooldownPeriod: 60
      minReplicaCount: 1
      maxReplicaCount: 10
      triggers:
        - type: external
          metadata:
            scalerAddress: kubemq-keda-scaler.default.svc.cluster.local:9090
            kubemqAddress: kubemq.default.svc.cluster.local:50000
            queueName: my-queue
            targetWaiting: "10"
    ```

    Apply it:

    ```bash
    kubectl apply -f scaled-object-basic.yaml
    ```

    The three required metadata fields are `scalerAddress` (the scaler Service FQDN from the previous step), `kubemqAddress` (your broker's `host:port`), and `queueName` (the queue channel to monitor). `targetWaiting` is the target number of waiting messages per replica — KEDA divides the live `Waiting` count by this value to compute the desired replica count.
  </Step>

  <Step>
    ### Watch It Scale [#watch-it-scale]

    Send messages to `my-queue` from any KubeMQ producer and watch KEDA scale the target `Deployment` up as the `Waiting` count climbs:

    ```bash
    kubectl get hpa -w
    ```

    KEDA creates a Horizontal Pod Autoscaler behind the scenes; the `-w` flag streams replica changes live. As the consumer drains the queue and `Waiting` drops, the deployment scales back down once the `cooldownPeriod` (60 seconds in this example) has elapsed.
  </Step>

  <Step>
    ### Verify Scaler Health [#verify-scaler-health]

    The scaler exposes a standard gRPC Health service on the same port `9090`. Both liveness and readiness probes check the gRPC server's health only — not KubeMQ broker connectivity. To test it manually, port-forward the Service and call the health endpoint with [`grpcurl`](https://github.com/fullstorydev/grpcurl):

    ```bash
    kubectl port-forward svc/kubemq-keda-scaler 9090:9090
    ```

    In a second terminal:

    ```bash
    grpcurl -plaintext localhost:9090 grpc.health.v1.Health/Check
    ```

    A healthy scaler responds:

    ```json
    {
      "status": "SERVING"
    }
    ```
  </Step>
</Steps>

<Callout type="warn">
  The scaler's gRPC server runs **plaintext** (no TLS) by design for v1. It is intended to run as a `ClusterIP` Service, accessible only within the cluster. For production, apply a `NetworkPolicy` that restricts ingress to the gRPC port to the KEDA operator namespace.
</Callout>

## Next Steps [#next-steps]

<Cards>
  <Card title="Autoscale a Queue Consumer" href="/integrations/keda/how-to/autoscale-queue-consumer" description="Tune polling, cooldown, replica bounds, and the full set of trigger metadata fields." />

  <Card title="Scale to Zero" href="/integrations/keda/how-to/scale-to-zero" description="Use activationTargetWaiting and push mode to scale workloads from zero replicas." />

  <Card title="TLS and Authentication" href="/integrations/keda/how-to/tls-and-auth" description="Connect the scaler to a secured KubeMQ broker with TLS and an auth token." />

  <Card title="ScaledObject Metadata" href="/integrations/keda/reference/scaled-object-metadata" description="Complete trigger metadata, scaler Service address, Helm values, and example manifests." />
</Cards>
