Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: KEDA Plugin for Headlamp #181

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

adwait-godbole
Copy link

@adwait-godbole adwait-godbole commented Mar 7, 2025

Upstream Issue: headlamp-k8s/headlamp/#2791

Testing the plugin

Prerequisites

  • Docker installed on your system
  • A Kubernetes cluster with KEDA installed
  • Helm installed on your system
  • Node.js and npm installed on your system

Steps to Test

  1. Clone the plugins repository:

    git clone https://github.com/headlamp-k8s/plugins.git
  2. Switch to the keda branch:

    git checkout keda
  3. Navigate to the keda plugin directory:

    cd keda
  4. Install the required dependencies:

    npm install
  5. Start the plugin in development mode:

    npm run start
  6. Launch Headlamp. You should now see "KEDA" in the sidebar.

Generate KEDA Resources for Testing

1. Build the RabbitMQ Client Image

Before deploying the examples, build the RabbitMQ client Docker image using the provided Dockerfile:

# Navigate to the 'test-files' directory
cd test-files

# Build & Push the image to ttl.sh for temporary hosting
# Images on ttl.sh expire after 24 hours by default
# To specify a different expiration time, add a suffix like ":1h" for 1 hour
IMAGE_NAME=$(uuidgen)
docker build -t ttl.sh/${IMAGE_NAME}:1h .
docker push ttl.sh/${IMAGE_NAME}:1h

Take a note of your image name as you'll need to update it in the deployment YAML files.

2. Update the YAML files with your image

Update the image reference in these files:

For example:

Replace

image: some-registry/rabbitmq-client:latest

with

image: ttl.sh/36733c85-1c5e-470b-bb86-f9b93b6d8d82:1h # Replace with your actual image name

3. Create a RabbitMQ Queue

Install RabbitMQ via Helm

Since the Helm stable repository was migrated to the Bitnami Repository, add the Bitnami repo and use it during the installation:

helm repo add bitnami https://charts.bitnami.com/bitnami
Helm 3

RabbitMQ Helm Chart version 7.0.0 or later

helm install rabbitmq --set auth.username=user --set auth.password=PASSWORD bitnami/rabbitmq --wait

Notes:

  • If you are running the rabbitMQ image on KinD, you will run into permission issues unless you set volumePermissions.enabled=true. Use the following command if you are using KinD:

    helm install rabbitmq --set auth.username=user --set auth.password=PASSWORD --set volumePermissions.enabled=true bitnami/rabbitmq --wait
    
  • With RabbitMQ Helm Chart version 6.x.x or earlier, username and password should be specified with rabbitmq.username and rabbitmq.password parameters https://hub.helm.sh/charts/bitnami/rabbitmq

Helm 2

RabbitMQ Helm Chart version 7.0.0 or later

helm install --name rabbitmq --set auth.username=user --set auth.password=PASSWORD bitnami/rabbitmq --wait

Wait for RabbitMQ to Deploy

⚠️ Be sure to wait until the deployment has completed before continuing. ⚠️

kubectl get pods

NAME         READY   STATUS    RESTARTS   AGE
rabbitmq-0   1/1     Running   0          3m3s

4. Deploy a KEDA TriggerAuthentication for RabbitMQ

kubectl apply -f test-files/deploy/triggerAuthentication.yaml

This TriggerAuthentication resource provides the necessary credentials for KEDA to connect to RabbitMQ and monitor the queue.

5. Testing KEDA ScaledObject

Deploy a RabbitMQ Consumer

kubectl apply -f test-files/deploy/consumer-deployment.yaml

Validate the consumer has been deployed

kubectl get deployments

You should see rabbitmq-consumer deployment with 1 running pod but after deploying the ScaledObject, it will display 0 running pods as we haven't yet published any messages to RabbitMQ and hence KEDA will scale down the pods to 0 since we have not mentioned any minReplicaCount in the spec.

NAME                READY   UP-TO-DATE   AVAILABLE   AGE
rabbitmq-consumer   1/1     1            1           2m32s

This consumer is set to consume one message per instance, sleep for 1 second, and then acknowledge completion of the message. This is used to simulate work.

Deploy ScaledObject

kubectl apply -f test-files/deploy/scaledObject.yaml

This ScaledObject configures autoscaling for the rabbitmq-consumer deployment. It is set to scale to a minimum of 0 replicas when there are no messages in the queue, and up to a maximum of 30 replicas when the queue is heavily loaded. The scaling is optimized for maintaining a queue length of 5 messages per replica. After 30 seconds of no events, the replicas will be scaled down (cooldown period). These settings can be adjusted in the YAML Specification as needed.

Trigger the Publisher Job to Generate Messages

Now that all components are set up, trigger the publisher job to send messages to the RabbitMQ queue:

kubectl apply -f test-files/deploy/publisher-job.yaml

This job will publish 300 messages to the RabbitMQ queue, which will trigger scaling of the consumer deployment (via ScaledObject).

Observe Autoscaling in Action

Monitor the scaling activities:

# Watch the deployments scale up
kubectl get deployments -w

# Check the pods being created
kubectl get pods

# View KEDA ScaledObject status
kubectl get scaledobject

You should see the number of replicas for the rabbitmq-consumer deployment increase as messages are added to the queue, and decrease as messages are processed.

Clean Up Resources

When you're done testing, you can clean up the deployed resources:

kubectl delete -f test-files/deploy/publisher-job.yaml
kubectl delete -f test-files/deploy/scaledObject.yaml
kubectl delete -f test-files/deploy/consumer-deployment.yaml

6. Testing KEDA ScaledJob

Deploy ScaledJob

kubectl apply -f test-files/deploy/scaledJob.yaml

This ScaledJob creates Kubernetes Jobs to process messages in the RabbitMQ queue in batch mode. It is set to scale to a minimum of 0 jobs when there are no messages in the queue, and up to a maximum of 30 jobs when the queue is heavily loaded. Unlike the ScaledObject which scales a Deployment, ScaledJob creates separate Job instances that process a batch of messages and then terminate. This ScaledJob is configured to process 10 messages per job with a 30-second timeout. These settings can be adjusted in the YAML Specification as needed.

Trigger the Publisher Job to Generate Messages

Now that all components are set up, trigger the publisher job to send messages to the RabbitMQ queue:

kubectl apply -f test-files/deploy/publisher-job.yaml

This job will publish 300 messages to the RabbitMQ queue, which will trigger the creation of batch processing jobs (via ScaledJob).

Observe Autoscaling in Action

Monitor the scaling activities:

# View the jobs being created
kubectl get jobs

# Check the pods being created
kubectl get pods

# View KEDA ScaledJob status
kubectl get scaledjob

You will see jobs created to process batches of messages based on the ScaledJob configuration.

Clean Up

When you're done testing, you can clean up the deployed resources:

kubectl delete -f test-files/deploy/publisher-job.yaml
kubectl delete -f test-files/deploy/scaledJob.yaml

7. Clean Up All The Resources You Deployed

When you're done testing, you can clean up all the deployed resources via:

kubectl delete -f test-files/deploy/publisher-job.yaml # ignore if you've already done this
kubectl delete -f test-files/deploy/scaledJob.yaml # ignore if you've already done this
kubectl delete -f test-files/deploy/scaledObject.yaml # ignore if you've already done this
kubectl delete -f test-files/deploy/consumer-deployment.yaml # ignore if you've already done this
kubectl delete -f test-files/deploy/triggerAuthentication.yaml
helm uninstall rabbitmq

Phase 1 Implementation Demo:

  1. List and Details View for ScaledObjects
Screencast.from.2025-03-07.23-02-03.mp4
  1. List and Details View for ScaledJobs
Screencast.from.2025-03-07.22-54-07.mp4
  1. List and Details View for TriggerAuthentications
Screencast.from.2025-03-07.23-03-41.mp4
  1. List and Details View for ClusterTriggerAuthentications
Screencast.from.2025-03-07.23-04-47.mp4

@adwait-godbole adwait-godbole changed the title WIP: KEDA Headlamp Plugin WIP: Headlamp Plugin for KEDA Mar 7, 2025
@adwait-godbole adwait-godbole marked this pull request as draft March 7, 2025 18:30
@adwait-godbole adwait-godbole force-pushed the keda-headlamp-plugin branch 2 times, most recently from ebc2f3b to a333dd9 Compare March 12, 2025 11:28
Copy link
Contributor

@yolossn yolossn left a comment

Choose a reason for hiding this comment

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

Good work. Have dropped few comments. Please add steps to test both in readme and the PR description.

Comment on lines +48 to +56
{
id: 'authentications',
label: 'Authentications',
getValue: null,
render: item => {
const triggerAuthenticationRefs = item.spec.triggers
.map(trigger => trigger.authenticationRef)
.filter(Boolean);

Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
{
id: 'authentications',
label: 'Authentications',
getValue: null,
render: item => {
const triggerAuthenticationRefs = item.spec.triggers
.map(trigger => trigger.authenticationRef)
.filter(Boolean);
{
id: 'authentications',
label: 'Authentications',
render: item => {
const triggerAuthenticationRefs = item.spec.triggers
.map(trigger => trigger.authenticationRef)
.filter(Boolean);

Copy link
Author

Choose a reason for hiding this comment

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

@yolossn, earlier I did try doing this but it gives the below error

No overload matches this call.
  Overload 1 of 2, '(props: ResourceListViewWithResourceClassProps<typeof ScaledObject>): ReactElement<any, string | JSXElementConstructor<any>>', gave the following error.
    Type '(item: ScaledObject) => Element' is not assignable to type 'never'.
  Overload 2 of 2, '(props: ResourceListViewProps<KubeObject<any>>): ReactElement<any, string | JSXElementConstructor<any>>', gave the following error.
    Type '(item: ScaledObject) => Element' is not assignable to type 'never'.ts(2769)
(property) render: (item: ScaledObject) => JSX.Element

so I had to do getValue: null

Comment on lines +71 to +78
{
id: 'authentications',
label: 'Authentications',
getValue: null,
render: item => {
const triggerAuthenticationRefs = item.spec.triggers
.map(trigger => trigger.authenticationRef)
.filter(Boolean);
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
{
id: 'authentications',
label: 'Authentications',
getValue: null,
render: item => {
const triggerAuthenticationRefs = item.spec.triggers
.map(trigger => trigger.authenticationRef)
.filter(Boolean);
{
id: 'authentications',
label: 'Authentications',
render: item => {
const triggerAuthenticationRefs = item.spec.triggers
.map(trigger => trigger.authenticationRef)
.filter(Boolean);

Copy link
Author

Choose a reason for hiding this comment

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

same reason as in this comment

@adwait-godbole adwait-godbole changed the title WIP: Headlamp Plugin for KEDA WIP: KEDA Plugin for Headlamp Mar 22, 2025
Signed-off-by: adwait-godbole <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants