From 24caa920d1d9b42d9875909adb0c4c3d05d908de Mon Sep 17 00:00:00 2001 From: shubhusion Date: Fri, 28 Jun 2024 13:51:01 +0530 Subject: [PATCH 01/33] Created Procedure for Setting Up a Scaler Signed-off-by: Shubham Sharma Signed-off-by: shubhusion --- content/docs/2.14/operate/setupscaler.md | 116 +++++++++++++++++++++++ content/docs/2.15/operate/setupscaler.md | 116 +++++++++++++++++++++++ 2 files changed, 232 insertions(+) create mode 100644 content/docs/2.14/operate/setupscaler.md create mode 100644 content/docs/2.15/operate/setupscaler.md diff --git a/content/docs/2.14/operate/setupscaler.md b/content/docs/2.14/operate/setupscaler.md new file mode 100644 index 000000000..7279354e3 --- /dev/null +++ b/content/docs/2.14/operate/setupscaler.md @@ -0,0 +1,116 @@ ++++ +title = "Setupscaler" +weight = 500 +description = "Procedure to Setup a Scaler in KEDA" ++++ + +## Prerequisites + +1. **Kubernetes Cluster**: + - Ensure you have a running Kubernetes cluster set up and accessible. + - If you don't have a cluster yet, follow the [official Kubernetes documentation](https://kubernetes.io/docs/setup/) to create a new cluster suitable for your environment (local machine, cloud provider, etc.). + +2. **KEDA Installation**: + - KEDA needs to be installed on your Kubernetes cluster before you can use it. + - Follow the [KEDA installation guide](https://keda.sh/docs/2.14/deploy/) carefully, including any prerequisites specific to your Kubernetes setup. + - The installation guide provides instructions for different installation methods (e.g., YAML, Helm charts, etc.). Choose the method that suits your needs. + +3. **kubectl**: + - The `kubectl` command-line tool is required to interact with your Kubernetes cluster. + - Follow the [official kubectl installation guide](https://kubernetes.io/docs/tasks/tools/#kubectl) to install `kubectl` on your operating system. + - Once installed, configure `kubectl` to communicate with your Kubernetes cluster by following the cluster-specific instructions provided by your Kubernetes setup. + +## Step 1: Identify the Scaler You Need + +KEDA supports various scalers that correspond to different event sources or triggers. Determining the right scaler is crucial for scaling your application based on the desired event source. + +1. Visit the [KEDA Scalers documentation](https://keda.sh/docs/2.14/scalers/) and browse through the list of available scalers. +2. Identify the scaler that matches the event source you want to use for scaling your application. For example: + - If you want to scale based on incoming HTTP traffic, you would need the **HTTP scaler**. + - If you want to scale based on messages in a RabbitMQ queue, you would need the **RabbitMQ scaler**. + - If you want to scale based on a cron schedule, you would need the **Cron scaler**. +3. Open the documentation page for your chosen scaler and familiarize yourself with its specific requirements and configuration options. + +## Step 2: Install the Required Scaler (if needed) + +Some scalers are part of the core KEDA installation, while others need to be installed separately as add-ons. + +1. Refer to the documentation of your chosen scaler to check if it needs to be installed separately. +2. If the scaler needs to be installed separately, follow the installation instructions provided in the scaler's documentation carefully. + - The installation process typically involves running a command (e.g., `helm install` for Helm charts) or applying YAML manifests using `kubectl`. +3. Verify that the scaler has been installed successfully by checking the output of the installation process or by running any provided verification commands. + +## Step 3: Create a ScaledObject Configuration File + +KEDA uses a custom resource called `ScaledObject` to define how your application should be scaled based on the chosen event source or trigger. + +1. Create a new file (e.g., `scaledobject.yaml`) in a text editor or using the command line. +2. Define the `ScaledObject` configuration in this file, following the structure and examples provided in the documentation of your chosen scaler. +3. Typically, the `ScaledObject` configuration includes the following sections: + - `metadata`: Specifies the name and namespace for the `ScaledObject`. + - `spec.scaleTargetRef`: Identifies the Kubernetes deployment or other resource that should be scaled. + - `spec.pollingInterval` (optional): Specifies how often KEDA should check for scaling events (defaults to 15 seconds). + - `spec.cooldownPeriod` (optional): Specifies the cool-down period in seconds after a scaling event (defaults to 300 seconds). + - `spec.maxReplicaCount` (optional): Specifies the maximum number of replicas to scale up to (defaults to 100). + - `spec.triggers`: Defines the specific configuration for your chosen scaler, including any required parameters or settings. +4. Refer to the scaler's documentation for detailed explanations and examples of the `triggers` section and any other required or optional configuration settings. +5. Save the `scaledobject.yaml` file after making the necessary modifications. + +## Step 4: Apply the ScaledObject Configuration + +Once you have created the `ScaledObject` configuration file, apply it to your Kubernetes cluster using `kubectl`: + +1. Open a terminal or command prompt and navigate to the directory containing the `scaledobject.yaml` file. +2. Run the following command to apply the `ScaledObject` configuration: + + ```bash + kubectl apply -f scaledobject.yaml + ``` + + ```plaintext + scaledobject.keda.sh/ created + ``` + +3. Verify that the `ScaledObject` has been created successfully by running: + + ```bash + kubectl get scaledobjects + ``` + + This should display the `ScaledObject` you just created. + + ```plaintext + NAME SCALETARGETKIND SCALETARGETNAME MIN MAX TRIGGERS AUTHENTICATION READY ACTIVE FALLBACK AGE + Deployment 1 10 cpu True False 10s + ``` + +After applying the `ScaledObject` configuration, KEDA will start monitoring the specified event source and scale your application accordingly, based on the configurations you provided. + +## Step 5: Monitor Scaling Events + +You can monitor the scaling events and logs generated by KEDA using the following commands: + +1. List all `ScaledObjects` in your cluster: + + ```bash + kubectl get scaledobjects + ``` + + This will show you the current state of your `ScaledObject` and the number of replicas. + + ```plaintext + NAME SCALETARGETKIND SCALETARGETNAME MIN MAX TRIGGERS AUTHENTICATION READY ACTIVE FALLBACK AGE + Deployment 1 10 cpu True False 10s + ``` + +2. View the logs of the KEDA operator: + + ```bash + kubectl logs -n keda -l app=keda-operator + ``` + + The KEDA operator logs will show you detailed information about scaling events, decisions made by KEDA based on the event source, and any errors or warnings. + + ```plaintext + {"level":"info","ts":,"logger":"scalehandler","msg":"Successfully scaled deployment","scaledobject.Namespace":"","scaledobject.Name":"","scaler":} + ``` diff --git a/content/docs/2.15/operate/setupscaler.md b/content/docs/2.15/operate/setupscaler.md new file mode 100644 index 000000000..7279354e3 --- /dev/null +++ b/content/docs/2.15/operate/setupscaler.md @@ -0,0 +1,116 @@ ++++ +title = "Setupscaler" +weight = 500 +description = "Procedure to Setup a Scaler in KEDA" ++++ + +## Prerequisites + +1. **Kubernetes Cluster**: + - Ensure you have a running Kubernetes cluster set up and accessible. + - If you don't have a cluster yet, follow the [official Kubernetes documentation](https://kubernetes.io/docs/setup/) to create a new cluster suitable for your environment (local machine, cloud provider, etc.). + +2. **KEDA Installation**: + - KEDA needs to be installed on your Kubernetes cluster before you can use it. + - Follow the [KEDA installation guide](https://keda.sh/docs/2.14/deploy/) carefully, including any prerequisites specific to your Kubernetes setup. + - The installation guide provides instructions for different installation methods (e.g., YAML, Helm charts, etc.). Choose the method that suits your needs. + +3. **kubectl**: + - The `kubectl` command-line tool is required to interact with your Kubernetes cluster. + - Follow the [official kubectl installation guide](https://kubernetes.io/docs/tasks/tools/#kubectl) to install `kubectl` on your operating system. + - Once installed, configure `kubectl` to communicate with your Kubernetes cluster by following the cluster-specific instructions provided by your Kubernetes setup. + +## Step 1: Identify the Scaler You Need + +KEDA supports various scalers that correspond to different event sources or triggers. Determining the right scaler is crucial for scaling your application based on the desired event source. + +1. Visit the [KEDA Scalers documentation](https://keda.sh/docs/2.14/scalers/) and browse through the list of available scalers. +2. Identify the scaler that matches the event source you want to use for scaling your application. For example: + - If you want to scale based on incoming HTTP traffic, you would need the **HTTP scaler**. + - If you want to scale based on messages in a RabbitMQ queue, you would need the **RabbitMQ scaler**. + - If you want to scale based on a cron schedule, you would need the **Cron scaler**. +3. Open the documentation page for your chosen scaler and familiarize yourself with its specific requirements and configuration options. + +## Step 2: Install the Required Scaler (if needed) + +Some scalers are part of the core KEDA installation, while others need to be installed separately as add-ons. + +1. Refer to the documentation of your chosen scaler to check if it needs to be installed separately. +2. If the scaler needs to be installed separately, follow the installation instructions provided in the scaler's documentation carefully. + - The installation process typically involves running a command (e.g., `helm install` for Helm charts) or applying YAML manifests using `kubectl`. +3. Verify that the scaler has been installed successfully by checking the output of the installation process or by running any provided verification commands. + +## Step 3: Create a ScaledObject Configuration File + +KEDA uses a custom resource called `ScaledObject` to define how your application should be scaled based on the chosen event source or trigger. + +1. Create a new file (e.g., `scaledobject.yaml`) in a text editor or using the command line. +2. Define the `ScaledObject` configuration in this file, following the structure and examples provided in the documentation of your chosen scaler. +3. Typically, the `ScaledObject` configuration includes the following sections: + - `metadata`: Specifies the name and namespace for the `ScaledObject`. + - `spec.scaleTargetRef`: Identifies the Kubernetes deployment or other resource that should be scaled. + - `spec.pollingInterval` (optional): Specifies how often KEDA should check for scaling events (defaults to 15 seconds). + - `spec.cooldownPeriod` (optional): Specifies the cool-down period in seconds after a scaling event (defaults to 300 seconds). + - `spec.maxReplicaCount` (optional): Specifies the maximum number of replicas to scale up to (defaults to 100). + - `spec.triggers`: Defines the specific configuration for your chosen scaler, including any required parameters or settings. +4. Refer to the scaler's documentation for detailed explanations and examples of the `triggers` section and any other required or optional configuration settings. +5. Save the `scaledobject.yaml` file after making the necessary modifications. + +## Step 4: Apply the ScaledObject Configuration + +Once you have created the `ScaledObject` configuration file, apply it to your Kubernetes cluster using `kubectl`: + +1. Open a terminal or command prompt and navigate to the directory containing the `scaledobject.yaml` file. +2. Run the following command to apply the `ScaledObject` configuration: + + ```bash + kubectl apply -f scaledobject.yaml + ``` + + ```plaintext + scaledobject.keda.sh/ created + ``` + +3. Verify that the `ScaledObject` has been created successfully by running: + + ```bash + kubectl get scaledobjects + ``` + + This should display the `ScaledObject` you just created. + + ```plaintext + NAME SCALETARGETKIND SCALETARGETNAME MIN MAX TRIGGERS AUTHENTICATION READY ACTIVE FALLBACK AGE + Deployment 1 10 cpu True False 10s + ``` + +After applying the `ScaledObject` configuration, KEDA will start monitoring the specified event source and scale your application accordingly, based on the configurations you provided. + +## Step 5: Monitor Scaling Events + +You can monitor the scaling events and logs generated by KEDA using the following commands: + +1. List all `ScaledObjects` in your cluster: + + ```bash + kubectl get scaledobjects + ``` + + This will show you the current state of your `ScaledObject` and the number of replicas. + + ```plaintext + NAME SCALETARGETKIND SCALETARGETNAME MIN MAX TRIGGERS AUTHENTICATION READY ACTIVE FALLBACK AGE + Deployment 1 10 cpu True False 10s + ``` + +2. View the logs of the KEDA operator: + + ```bash + kubectl logs -n keda -l app=keda-operator + ``` + + The KEDA operator logs will show you detailed information about scaling events, decisions made by KEDA based on the event source, and any errors or warnings. + + ```plaintext + {"level":"info","ts":,"logger":"scalehandler","msg":"Successfully scaled deployment","scaledobject.Namespace":"","scaledobject.Name":"","scaler":} + ``` From 3f00c4313545cb20b7ab565289595e86f4a888e9 Mon Sep 17 00:00:00 2001 From: shubhusion Date: Tue, 30 Jul 2024 20:55:56 +0530 Subject: [PATCH 02/33] Added a Note Signed-off-by: shubhusion --- content/docs/2.14/operate/setupscaler.md | 6 +++++- content/docs/2.15/operate/setupscaler.md | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/content/docs/2.14/operate/setupscaler.md b/content/docs/2.14/operate/setupscaler.md index 7279354e3..a56feb769 100644 --- a/content/docs/2.14/operate/setupscaler.md +++ b/content/docs/2.14/operate/setupscaler.md @@ -26,7 +26,11 @@ KEDA supports various scalers that correspond to different event sources or trig 1. Visit the [KEDA Scalers documentation](https://keda.sh/docs/2.14/scalers/) and browse through the list of available scalers. 2. Identify the scaler that matches the event source you want to use for scaling your application. For example: - - If you want to scale based on incoming HTTP traffic, you would need the **HTTP scaler**. + - If you want to scale based on incoming HTTP traffic, you would need the **HTTP Add-on**. + + > **Note:** + > The HTTP Add-on is still in beta stage and may not provide the full functionality or stability expected in a production environment. + - If you want to scale based on messages in a RabbitMQ queue, you would need the **RabbitMQ scaler**. - If you want to scale based on a cron schedule, you would need the **Cron scaler**. 3. Open the documentation page for your chosen scaler and familiarize yourself with its specific requirements and configuration options. diff --git a/content/docs/2.15/operate/setupscaler.md b/content/docs/2.15/operate/setupscaler.md index 7279354e3..a56feb769 100644 --- a/content/docs/2.15/operate/setupscaler.md +++ b/content/docs/2.15/operate/setupscaler.md @@ -26,7 +26,11 @@ KEDA supports various scalers that correspond to different event sources or trig 1. Visit the [KEDA Scalers documentation](https://keda.sh/docs/2.14/scalers/) and browse through the list of available scalers. 2. Identify the scaler that matches the event source you want to use for scaling your application. For example: - - If you want to scale based on incoming HTTP traffic, you would need the **HTTP scaler**. + - If you want to scale based on incoming HTTP traffic, you would need the **HTTP Add-on**. + + > **Note:** + > The HTTP Add-on is still in beta stage and may not provide the full functionality or stability expected in a production environment. + - If you want to scale based on messages in a RabbitMQ queue, you would need the **RabbitMQ scaler**. - If you want to scale based on a cron schedule, you would need the **Cron scaler**. 3. Open the documentation page for your chosen scaler and familiarize yourself with its specific requirements and configuration options. From 68f0a47646a516378c3b9a90f9a29ce93219951f Mon Sep 17 00:00:00 2001 From: SHUBHAM SHARMA <96301987+shubhusion@users.noreply.github.com> Date: Mon, 5 Aug 2024 19:11:38 +0530 Subject: [PATCH 03/33] Update content/docs/2.14/operate/setupscaler.md Co-authored-by: Zbynek Roubalik Signed-off-by: SHUBHAM SHARMA <96301987+shubhusion@users.noreply.github.com> --- content/docs/2.14/operate/setupscaler.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/2.14/operate/setupscaler.md b/content/docs/2.14/operate/setupscaler.md index a56feb769..ff5346a1c 100644 --- a/content/docs/2.14/operate/setupscaler.md +++ b/content/docs/2.14/operate/setupscaler.md @@ -1,7 +1,7 @@ +++ title = "Setupscaler" weight = 500 -description = "Procedure to Setup a Scaler in KEDA" +description = "Procedure to Setup a Autoscaling with KEDA" +++ ## Prerequisites From 98cda61b4d06ff7f0efe9e6b643956e9e7c0c4a6 Mon Sep 17 00:00:00 2001 From: SHUBHAM SHARMA <96301987+shubhusion@users.noreply.github.com> Date: Mon, 5 Aug 2024 19:11:54 +0530 Subject: [PATCH 04/33] Update content/docs/2.14/operate/setupscaler.md Co-authored-by: Zbynek Roubalik Signed-off-by: SHUBHAM SHARMA <96301987+shubhusion@users.noreply.github.com> --- content/docs/2.14/operate/setupscaler.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/2.14/operate/setupscaler.md b/content/docs/2.14/operate/setupscaler.md index ff5346a1c..f24707dc2 100644 --- a/content/docs/2.14/operate/setupscaler.md +++ b/content/docs/2.14/operate/setupscaler.md @@ -1,5 +1,5 @@ +++ -title = "Setupscaler" +title = "Setup Autoscaling with KEDA" weight = 500 description = "Procedure to Setup a Autoscaling with KEDA" +++ From 2909cf4aab1d6c90796c2c1d9142851cf7020b84 Mon Sep 17 00:00:00 2001 From: SHUBHAM SHARMA <96301987+shubhusion@users.noreply.github.com> Date: Mon, 5 Aug 2024 19:12:12 +0530 Subject: [PATCH 05/33] Update content/docs/2.15/operate/setupscaler.md Co-authored-by: Zbynek Roubalik Signed-off-by: SHUBHAM SHARMA <96301987+shubhusion@users.noreply.github.com> --- content/docs/2.15/operate/setupscaler.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/2.15/operate/setupscaler.md b/content/docs/2.15/operate/setupscaler.md index a56feb769..fa9d8d722 100644 --- a/content/docs/2.15/operate/setupscaler.md +++ b/content/docs/2.15/operate/setupscaler.md @@ -1,5 +1,5 @@ +++ -title = "Setupscaler" +title = "Setup Autoscaling with KEDA" weight = 500 description = "Procedure to Setup a Scaler in KEDA" +++ From 1b843b357c328417ec9579ea9f58f8cf4500fd4b Mon Sep 17 00:00:00 2001 From: SHUBHAM SHARMA <96301987+shubhusion@users.noreply.github.com> Date: Mon, 5 Aug 2024 19:12:28 +0530 Subject: [PATCH 06/33] Update content/docs/2.15/operate/setupscaler.md Co-authored-by: Zbynek Roubalik Signed-off-by: SHUBHAM SHARMA <96301987+shubhusion@users.noreply.github.com> --- content/docs/2.15/operate/setupscaler.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/2.15/operate/setupscaler.md b/content/docs/2.15/operate/setupscaler.md index fa9d8d722..a8efd7078 100644 --- a/content/docs/2.15/operate/setupscaler.md +++ b/content/docs/2.15/operate/setupscaler.md @@ -26,7 +26,7 @@ KEDA supports various scalers that correspond to different event sources or trig 1. Visit the [KEDA Scalers documentation](https://keda.sh/docs/2.14/scalers/) and browse through the list of available scalers. 2. Identify the scaler that matches the event source you want to use for scaling your application. For example: - - If you want to scale based on incoming HTTP traffic, you would need the **HTTP Add-on**. + - If you want to scale based on incoming HTTP traffic, you would need the [HTTP Add-on](https://kedacore.github.io/http-add-on/). > **Note:** > The HTTP Add-on is still in beta stage and may not provide the full functionality or stability expected in a production environment. From e941483c23bcca7b8cf7424478d70d8147331b00 Mon Sep 17 00:00:00 2001 From: SHUBHAM SHARMA <96301987+shubhusion@users.noreply.github.com> Date: Mon, 5 Aug 2024 19:12:38 +0530 Subject: [PATCH 07/33] Update content/docs/2.14/operate/setupscaler.md Co-authored-by: Zbynek Roubalik Signed-off-by: SHUBHAM SHARMA <96301987+shubhusion@users.noreply.github.com> --- content/docs/2.14/operate/setupscaler.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/2.14/operate/setupscaler.md b/content/docs/2.14/operate/setupscaler.md index f24707dc2..6bca2879c 100644 --- a/content/docs/2.14/operate/setupscaler.md +++ b/content/docs/2.14/operate/setupscaler.md @@ -26,7 +26,7 @@ KEDA supports various scalers that correspond to different event sources or trig 1. Visit the [KEDA Scalers documentation](https://keda.sh/docs/2.14/scalers/) and browse through the list of available scalers. 2. Identify the scaler that matches the event source you want to use for scaling your application. For example: - - If you want to scale based on incoming HTTP traffic, you would need the **HTTP Add-on**. + - If you want to scale based on incoming HTTP traffic, you would need the [HTTP Add-on](https://kedacore.github.io/http-add-on/). > **Note:** > The HTTP Add-on is still in beta stage and may not provide the full functionality or stability expected in a production environment. From 5de13765902be62b3a2f424621b310d2457f65e6 Mon Sep 17 00:00:00 2001 From: shubhusion Date: Mon, 5 Aug 2024 21:55:14 +0530 Subject: [PATCH 08/33] Changed File location Signed-off-by: shubhusion --- content/docs/2.15/{operate => }/setupscaler.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename content/docs/2.15/{operate => }/setupscaler.md (100%) diff --git a/content/docs/2.15/operate/setupscaler.md b/content/docs/2.15/setupscaler.md similarity index 100% rename from content/docs/2.15/operate/setupscaler.md rename to content/docs/2.15/setupscaler.md From 8c6ae103bf97edbba28045831d1b575324cd0ba8 Mon Sep 17 00:00:00 2001 From: shubhusion Date: Fri, 28 Jun 2024 13:51:01 +0530 Subject: [PATCH 09/33] Created Procedure for Setting Up a Scaler Signed-off-by: Shubham Sharma Signed-off-by: shubhusion --- content/docs/2.14/operate/setupscaler.md | 116 +++++++++++++++++++++++ content/docs/2.15/operate/setupscaler.md | 116 +++++++++++++++++++++++ 2 files changed, 232 insertions(+) create mode 100644 content/docs/2.14/operate/setupscaler.md create mode 100644 content/docs/2.15/operate/setupscaler.md diff --git a/content/docs/2.14/operate/setupscaler.md b/content/docs/2.14/operate/setupscaler.md new file mode 100644 index 000000000..7279354e3 --- /dev/null +++ b/content/docs/2.14/operate/setupscaler.md @@ -0,0 +1,116 @@ ++++ +title = "Setupscaler" +weight = 500 +description = "Procedure to Setup a Scaler in KEDA" ++++ + +## Prerequisites + +1. **Kubernetes Cluster**: + - Ensure you have a running Kubernetes cluster set up and accessible. + - If you don't have a cluster yet, follow the [official Kubernetes documentation](https://kubernetes.io/docs/setup/) to create a new cluster suitable for your environment (local machine, cloud provider, etc.). + +2. **KEDA Installation**: + - KEDA needs to be installed on your Kubernetes cluster before you can use it. + - Follow the [KEDA installation guide](https://keda.sh/docs/2.14/deploy/) carefully, including any prerequisites specific to your Kubernetes setup. + - The installation guide provides instructions for different installation methods (e.g., YAML, Helm charts, etc.). Choose the method that suits your needs. + +3. **kubectl**: + - The `kubectl` command-line tool is required to interact with your Kubernetes cluster. + - Follow the [official kubectl installation guide](https://kubernetes.io/docs/tasks/tools/#kubectl) to install `kubectl` on your operating system. + - Once installed, configure `kubectl` to communicate with your Kubernetes cluster by following the cluster-specific instructions provided by your Kubernetes setup. + +## Step 1: Identify the Scaler You Need + +KEDA supports various scalers that correspond to different event sources or triggers. Determining the right scaler is crucial for scaling your application based on the desired event source. + +1. Visit the [KEDA Scalers documentation](https://keda.sh/docs/2.14/scalers/) and browse through the list of available scalers. +2. Identify the scaler that matches the event source you want to use for scaling your application. For example: + - If you want to scale based on incoming HTTP traffic, you would need the **HTTP scaler**. + - If you want to scale based on messages in a RabbitMQ queue, you would need the **RabbitMQ scaler**. + - If you want to scale based on a cron schedule, you would need the **Cron scaler**. +3. Open the documentation page for your chosen scaler and familiarize yourself with its specific requirements and configuration options. + +## Step 2: Install the Required Scaler (if needed) + +Some scalers are part of the core KEDA installation, while others need to be installed separately as add-ons. + +1. Refer to the documentation of your chosen scaler to check if it needs to be installed separately. +2. If the scaler needs to be installed separately, follow the installation instructions provided in the scaler's documentation carefully. + - The installation process typically involves running a command (e.g., `helm install` for Helm charts) or applying YAML manifests using `kubectl`. +3. Verify that the scaler has been installed successfully by checking the output of the installation process or by running any provided verification commands. + +## Step 3: Create a ScaledObject Configuration File + +KEDA uses a custom resource called `ScaledObject` to define how your application should be scaled based on the chosen event source or trigger. + +1. Create a new file (e.g., `scaledobject.yaml`) in a text editor or using the command line. +2. Define the `ScaledObject` configuration in this file, following the structure and examples provided in the documentation of your chosen scaler. +3. Typically, the `ScaledObject` configuration includes the following sections: + - `metadata`: Specifies the name and namespace for the `ScaledObject`. + - `spec.scaleTargetRef`: Identifies the Kubernetes deployment or other resource that should be scaled. + - `spec.pollingInterval` (optional): Specifies how often KEDA should check for scaling events (defaults to 15 seconds). + - `spec.cooldownPeriod` (optional): Specifies the cool-down period in seconds after a scaling event (defaults to 300 seconds). + - `spec.maxReplicaCount` (optional): Specifies the maximum number of replicas to scale up to (defaults to 100). + - `spec.triggers`: Defines the specific configuration for your chosen scaler, including any required parameters or settings. +4. Refer to the scaler's documentation for detailed explanations and examples of the `triggers` section and any other required or optional configuration settings. +5. Save the `scaledobject.yaml` file after making the necessary modifications. + +## Step 4: Apply the ScaledObject Configuration + +Once you have created the `ScaledObject` configuration file, apply it to your Kubernetes cluster using `kubectl`: + +1. Open a terminal or command prompt and navigate to the directory containing the `scaledobject.yaml` file. +2. Run the following command to apply the `ScaledObject` configuration: + + ```bash + kubectl apply -f scaledobject.yaml + ``` + + ```plaintext + scaledobject.keda.sh/ created + ``` + +3. Verify that the `ScaledObject` has been created successfully by running: + + ```bash + kubectl get scaledobjects + ``` + + This should display the `ScaledObject` you just created. + + ```plaintext + NAME SCALETARGETKIND SCALETARGETNAME MIN MAX TRIGGERS AUTHENTICATION READY ACTIVE FALLBACK AGE + Deployment 1 10 cpu True False 10s + ``` + +After applying the `ScaledObject` configuration, KEDA will start monitoring the specified event source and scale your application accordingly, based on the configurations you provided. + +## Step 5: Monitor Scaling Events + +You can monitor the scaling events and logs generated by KEDA using the following commands: + +1. List all `ScaledObjects` in your cluster: + + ```bash + kubectl get scaledobjects + ``` + + This will show you the current state of your `ScaledObject` and the number of replicas. + + ```plaintext + NAME SCALETARGETKIND SCALETARGETNAME MIN MAX TRIGGERS AUTHENTICATION READY ACTIVE FALLBACK AGE + Deployment 1 10 cpu True False 10s + ``` + +2. View the logs of the KEDA operator: + + ```bash + kubectl logs -n keda -l app=keda-operator + ``` + + The KEDA operator logs will show you detailed information about scaling events, decisions made by KEDA based on the event source, and any errors or warnings. + + ```plaintext + {"level":"info","ts":,"logger":"scalehandler","msg":"Successfully scaled deployment","scaledobject.Namespace":"","scaledobject.Name":"","scaler":} + ``` diff --git a/content/docs/2.15/operate/setupscaler.md b/content/docs/2.15/operate/setupscaler.md new file mode 100644 index 000000000..7279354e3 --- /dev/null +++ b/content/docs/2.15/operate/setupscaler.md @@ -0,0 +1,116 @@ ++++ +title = "Setupscaler" +weight = 500 +description = "Procedure to Setup a Scaler in KEDA" ++++ + +## Prerequisites + +1. **Kubernetes Cluster**: + - Ensure you have a running Kubernetes cluster set up and accessible. + - If you don't have a cluster yet, follow the [official Kubernetes documentation](https://kubernetes.io/docs/setup/) to create a new cluster suitable for your environment (local machine, cloud provider, etc.). + +2. **KEDA Installation**: + - KEDA needs to be installed on your Kubernetes cluster before you can use it. + - Follow the [KEDA installation guide](https://keda.sh/docs/2.14/deploy/) carefully, including any prerequisites specific to your Kubernetes setup. + - The installation guide provides instructions for different installation methods (e.g., YAML, Helm charts, etc.). Choose the method that suits your needs. + +3. **kubectl**: + - The `kubectl` command-line tool is required to interact with your Kubernetes cluster. + - Follow the [official kubectl installation guide](https://kubernetes.io/docs/tasks/tools/#kubectl) to install `kubectl` on your operating system. + - Once installed, configure `kubectl` to communicate with your Kubernetes cluster by following the cluster-specific instructions provided by your Kubernetes setup. + +## Step 1: Identify the Scaler You Need + +KEDA supports various scalers that correspond to different event sources or triggers. Determining the right scaler is crucial for scaling your application based on the desired event source. + +1. Visit the [KEDA Scalers documentation](https://keda.sh/docs/2.14/scalers/) and browse through the list of available scalers. +2. Identify the scaler that matches the event source you want to use for scaling your application. For example: + - If you want to scale based on incoming HTTP traffic, you would need the **HTTP scaler**. + - If you want to scale based on messages in a RabbitMQ queue, you would need the **RabbitMQ scaler**. + - If you want to scale based on a cron schedule, you would need the **Cron scaler**. +3. Open the documentation page for your chosen scaler and familiarize yourself with its specific requirements and configuration options. + +## Step 2: Install the Required Scaler (if needed) + +Some scalers are part of the core KEDA installation, while others need to be installed separately as add-ons. + +1. Refer to the documentation of your chosen scaler to check if it needs to be installed separately. +2. If the scaler needs to be installed separately, follow the installation instructions provided in the scaler's documentation carefully. + - The installation process typically involves running a command (e.g., `helm install` for Helm charts) or applying YAML manifests using `kubectl`. +3. Verify that the scaler has been installed successfully by checking the output of the installation process or by running any provided verification commands. + +## Step 3: Create a ScaledObject Configuration File + +KEDA uses a custom resource called `ScaledObject` to define how your application should be scaled based on the chosen event source or trigger. + +1. Create a new file (e.g., `scaledobject.yaml`) in a text editor or using the command line. +2. Define the `ScaledObject` configuration in this file, following the structure and examples provided in the documentation of your chosen scaler. +3. Typically, the `ScaledObject` configuration includes the following sections: + - `metadata`: Specifies the name and namespace for the `ScaledObject`. + - `spec.scaleTargetRef`: Identifies the Kubernetes deployment or other resource that should be scaled. + - `spec.pollingInterval` (optional): Specifies how often KEDA should check for scaling events (defaults to 15 seconds). + - `spec.cooldownPeriod` (optional): Specifies the cool-down period in seconds after a scaling event (defaults to 300 seconds). + - `spec.maxReplicaCount` (optional): Specifies the maximum number of replicas to scale up to (defaults to 100). + - `spec.triggers`: Defines the specific configuration for your chosen scaler, including any required parameters or settings. +4. Refer to the scaler's documentation for detailed explanations and examples of the `triggers` section and any other required or optional configuration settings. +5. Save the `scaledobject.yaml` file after making the necessary modifications. + +## Step 4: Apply the ScaledObject Configuration + +Once you have created the `ScaledObject` configuration file, apply it to your Kubernetes cluster using `kubectl`: + +1. Open a terminal or command prompt and navigate to the directory containing the `scaledobject.yaml` file. +2. Run the following command to apply the `ScaledObject` configuration: + + ```bash + kubectl apply -f scaledobject.yaml + ``` + + ```plaintext + scaledobject.keda.sh/ created + ``` + +3. Verify that the `ScaledObject` has been created successfully by running: + + ```bash + kubectl get scaledobjects + ``` + + This should display the `ScaledObject` you just created. + + ```plaintext + NAME SCALETARGETKIND SCALETARGETNAME MIN MAX TRIGGERS AUTHENTICATION READY ACTIVE FALLBACK AGE + Deployment 1 10 cpu True False 10s + ``` + +After applying the `ScaledObject` configuration, KEDA will start monitoring the specified event source and scale your application accordingly, based on the configurations you provided. + +## Step 5: Monitor Scaling Events + +You can monitor the scaling events and logs generated by KEDA using the following commands: + +1. List all `ScaledObjects` in your cluster: + + ```bash + kubectl get scaledobjects + ``` + + This will show you the current state of your `ScaledObject` and the number of replicas. + + ```plaintext + NAME SCALETARGETKIND SCALETARGETNAME MIN MAX TRIGGERS AUTHENTICATION READY ACTIVE FALLBACK AGE + Deployment 1 10 cpu True False 10s + ``` + +2. View the logs of the KEDA operator: + + ```bash + kubectl logs -n keda -l app=keda-operator + ``` + + The KEDA operator logs will show you detailed information about scaling events, decisions made by KEDA based on the event source, and any errors or warnings. + + ```plaintext + {"level":"info","ts":,"logger":"scalehandler","msg":"Successfully scaled deployment","scaledobject.Namespace":"","scaledobject.Name":"","scaler":} + ``` From a5d80c0982602dc5d1460283a544b183d5a8dc95 Mon Sep 17 00:00:00 2001 From: Uchechukwu Obasi Date: Fri, 28 Jun 2024 14:04:43 +0100 Subject: [PATCH 10/33] chore: strip out raw HTML from docs (#1414) Signed-off-by: shubhusion --- content/docs/1.4/concepts/external-scalers.md | 172 ++++++++------- content/docs/1.5/concepts/external-scalers.md | 172 ++++++++------- content/docs/2.0/concepts/external-scalers.md | 205 ++++++++++-------- content/docs/2.0/migration.md | 165 +++++++------- content/docs/2.0/operate/cluster.md | 8 +- content/docs/2.1/concepts/external-scalers.md | 205 ++++++++++-------- content/docs/2.1/migration.md | 165 +++++++------- content/docs/2.1/operate/cluster.md | 8 +- .../docs/2.10/concepts/external-scalers.md | 179 ++++++++------- content/docs/2.10/migration.md | 165 +++++++------- content/docs/2.10/operate/cluster.md | 67 +++--- .../docs/2.11/concepts/external-scalers.md | 179 ++++++++------- content/docs/2.11/migration.md | 165 +++++++------- content/docs/2.11/operate/cluster.md | 67 +++--- .../docs/2.12/concepts/external-scalers.md | 179 ++++++++------- content/docs/2.12/migration.md | 165 +++++++------- content/docs/2.12/operate/cluster.md | 69 +++--- .../docs/2.13/concepts/external-scalers.md | 179 ++++++++------- content/docs/2.13/migration.md | 165 +++++++------- content/docs/2.13/operate/cluster.md | 71 +++--- .../docs/2.14/concepts/external-scalers.md | 179 ++++++++------- content/docs/2.14/migration.md | 165 +++++++------- content/docs/2.14/operate/cluster.md | 79 +++---- .../docs/2.15/concepts/external-scalers.md | 179 ++++++++------- content/docs/2.15/migration.md | 165 +++++++------- content/docs/2.15/operate/cluster.md | 81 +++---- content/docs/2.2/concepts/external-scalers.md | 205 ++++++++++-------- content/docs/2.2/migration.md | 165 +++++++------- content/docs/2.2/operate/cluster.md | 10 +- content/docs/2.3/concepts/external-scalers.md | 205 ++++++++++-------- content/docs/2.3/migration.md | 165 +++++++------- content/docs/2.3/operate/cluster.md | 12 +- content/docs/2.4/concepts/external-scalers.md | 205 ++++++++++-------- content/docs/2.4/migration.md | 165 +++++++------- content/docs/2.4/operate/cluster.md | 22 +- content/docs/2.5/concepts/external-scalers.md | 183 ++++++++-------- content/docs/2.5/migration.md | 165 +++++++------- content/docs/2.5/operate/cluster.md | 31 ++- content/docs/2.6/concepts/external-scalers.md | 179 ++++++++------- content/docs/2.6/migration.md | 165 +++++++------- content/docs/2.6/operate/cluster.md | 45 ++-- content/docs/2.7/concepts/external-scalers.md | 179 ++++++++------- content/docs/2.7/migration.md | 165 +++++++------- content/docs/2.7/operate/cluster.md | 45 ++-- content/docs/2.8/concepts/external-scalers.md | 179 ++++++++------- content/docs/2.8/migration.md | 165 +++++++------- content/docs/2.8/operate/cluster.md | 44 ++-- content/docs/2.9/concepts/external-scalers.md | 179 ++++++++------- content/docs/2.9/migration.md | 165 +++++++------- content/docs/2.9/operate/cluster.md | 78 +++---- 50 files changed, 3536 insertions(+), 3183 deletions(-) diff --git a/content/docs/1.4/concepts/external-scalers.md b/content/docs/1.4/concepts/external-scalers.md index 5bf6b7495..f02eeeb5d 100644 --- a/content/docs/1.4/concepts/external-scalers.md +++ b/content/docs/1.4/concepts/external-scalers.md @@ -27,11 +27,12 @@ type Scaler interface { ``` The `Scaler` interface defines 4 methods: + - `IsActive` is called on `pollingInterval` defined in the ScaledObject/ScaledJob CRDs and scaling to 1 happens if this returns true. - `Close` is called to allow the scaler to clean up connections or other resources. - `GetMetricSpec` returns the target value for the HPA definition for the scaler. For more details refer to [Implementing `GetMetricSpec`](#4-implementing-getmetricspec). - `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`. For more details refer to [Implementing `GetMetrics`](#5-implementing-getmetrics). -> Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates replicaCount based on metric value and target value. + > Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates replicaCount based on metric value and target value. ### External Scaler GRPC interface @@ -51,6 +52,7 @@ service ExternalScaler { - `IsActive` maps to the `IsActive` method on the `Scaler` interface. Few things to notice: + - `IsActive`, `StreamIsActive`, and `GetMetricsSpec` are called with a `ScaledObjectRef` that contains the scaledObject name/namespace as well as the content of `metadata` defined in the trigger. For example the following `ScaledObject`: @@ -85,6 +87,7 @@ KEDA will attempt a connection to `service-address.svc.local:9090` and calls `Is } } ``` + ## Implementing KEDA external scaler GRPC interface ### Implementing an external scaler: @@ -110,6 +113,7 @@ go mod init example.com/external-scaler/sample mkdir externalscaler protoc externalscaler.proto --go_out=plugins=grpc:externalscaler ``` + {{< /collapsible >}} {{< collapsible "C#" >}} @@ -146,9 +150,8 @@ mkdir Services ```bash npm install --save grpc request ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 3. Implementing `IsActive` @@ -178,6 +181,7 @@ spec: Full implementation can be found here: https://github.com/kedacore/external-scaler-samples `main.go` + ```golang func (e *ExternalScaler) IsActive(ctx context.Context, scaledObject *pb.ScaledObjectRef) (*pb.IsActiveResponse, error) { // request.Scalermetadata contains the `metadata` defined in the ScaledObject @@ -224,12 +228,14 @@ func (e *ExternalScaler) IsActive(ctx context.Context, scaledObject *pb.ScaledOb }, nil } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} Full implementation can be found here: https://github.com/kedacore/external-scaler-samples `Services/ExternalScalerService.cs` + ```csharp public class ExternalScalerService : ExternalScaler.ExternalScalerBase { @@ -262,79 +268,84 @@ public class ExternalScalerService : ExternalScaler.ExternalScalerBase } } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} `index.js` + ```js -const grpc = require('grpc') -const request = require('request') -const externalScalerProto = grpc.load('externalscaler.proto') +const grpc = require("grpc"); +const request = require("request"); +const externalScalerProto = grpc.load("externalscaler.proto"); -const server = new grpc.Server() +const server = new grpc.Server(); server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { isActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { - const now = new Date() - const yesterday = new Date(new Date().setDate(new Date().getDate()-1)); - - const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}` - const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}` - const radiusKm = 500 - const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}` - - request.get({ - url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, - json: true, - }, (err, resp, data) => { - if (err) { - callback({ - code: grpc.status.INTERNAL, - details: err, - }) - } else if (resp.statusCode !== 200) { - callback({ - code: grpc.status.INTERNAL, - details: `expected status 200, got ${resp.statusCode}` - }) - } else { - // count how many earthquakes with mag > 1.0 - let count = 0 - data.features.forEach(i => { - if (i.properties.mag > 1.0) { - count++ - } - }) - callback(null, { - result: count > 2, - }) + const now = new Date(); + const yesterday = new Date(new Date().setDate(new Date().getDate() - 1)); + + const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}`; + const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}`; + const radiusKm = 500; + const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}`; + + request.get( + { + url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, + json: true, + }, + (err, resp, data) => { + if (err) { + callback({ + code: grpc.status.INTERNAL, + details: err, + }); + } else if (resp.statusCode !== 200) { + callback({ + code: grpc.status.INTERNAL, + details: `expected status 200, got ${resp.statusCode}`, + }); + } else { + // count how many earthquakes with mag > 1.0 + let count = 0; + data.features.forEach((i) => { + if (i.properties.mag > 1.0) { + count++; + } + }); + callback(null, { + result: count > 2, + }); + } } - }) + ); } - } -}) + }, +}); -server.bind('127.0.0.1:9090', grpc.ServerCredentials.createInsecure()) -console.log('Server listening on 127.0.0.1:9090') +server.bind("127.0.0.1:9090", grpc.ServerCredentials.createInsecure()); +console.log("Server listening on 127.0.0.1:9090"); -server.start() +server.start(); ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 4. Implementing `GetMetricSpec` `GetMetricSpec` returns the `target` value for [the HPA definition for the scaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/). This scaler will define a static target of 10, but the threshold value is often specified in the metadata for other scalers. {{< collapsible "Golang" >}} + ```golang func (e *ExternalScaler) GetMetricSpec(context.Context, *pb.ScaledObjectRef) (*pb.GetMetricSpecResponse, error) { return &pb.GetMetricSpecResponse{ @@ -345,9 +356,11 @@ func (e *ExternalScaler) GetMetricSpec(context.Context, *pb.ScaledObjectRef) (*p }, nil } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} + ```csharp public override async Task GetMetricSpec(ScaledObjectRef request, ServerCallContext context) { @@ -362,31 +375,35 @@ public override async Task GetMetricSpec(ScaledObjectRef return Task.FromResult(resp); } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} + ```js server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetricSpec: (call, callback) => { callback(null, { - metricSpecs: [{ - metricName: 'earthquakeThreshold', - targetSize: 10, - }] - }) - } -}) + metricSpecs: [ + { + metricName: "earthquakeThreshold", + targetSize: 10, + }, + ], + }); + }, +}); ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 5. Implementing `GetMetrics` `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`, in this example it's `earthquakeThreshold`. {{< collapsible "Golang" >}} + ```golang func (e *ExternalScaler) GetMetrics(_ context.Context, metricRequest *pb.GetMetricsRequest) (*pb.GetMetricsResponse, error) { longitude := metricRequest.ScaledObjectRef.ScalerMetadata["longitude"] @@ -409,9 +426,11 @@ func (e *ExternalScaler) GetMetrics(_ context.Context, metricRequest *pb.GetMetr }, nil } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} + ```csharp public override async Task GetMetrics(GetMetricsRequest request, ServerCallContext context) { @@ -436,38 +455,43 @@ public override async Task GetMetrics(GetMetricsRequest requ return resp; } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} + ```js server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetrics: (call, callback) => { - const longitude = call.request.scaledObjectRef.scalerMetadata.longitude - const latitude = call.request.scaledObjectRef.scalerMetadata.latitude + const longitude = call.request.scaledObjectRef.scalerMetadata.longitude; + const latitude = call.request.scaledObjectRef.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { getEarthquakeCount((err, count) => { if (err) { callback({ code: grpc.status.INTERNAL, details: err, - }) + }); } else { callback(null, { - metricValues: [{ - metricName: 'earthquakeThreshold', - metricValue: count, - }] - }) + metricValues: [ + { + metricName: "earthquakeThreshold", + metricValue: count, + }, + ], + }); } - }) + }); } - } -}) + }, +}); ``` + {{< /collapsible >}} diff --git a/content/docs/1.5/concepts/external-scalers.md b/content/docs/1.5/concepts/external-scalers.md index 271e5ef34..712967345 100644 --- a/content/docs/1.5/concepts/external-scalers.md +++ b/content/docs/1.5/concepts/external-scalers.md @@ -27,11 +27,12 @@ type Scaler interface { ``` The `Scaler` interface defines 4 methods: + - `IsActive` is called on `pollingInterval` defined in the ScaledObject/ScaledJob CRDs and scaling to 1 happens if this returns true. - `Close` is called to allow the scaler to clean up connections or other resources. - `GetMetricSpec` returns the target value for the HPA definition for the scaler. For more details refer to [Implementing `GetMetricSpec`](#4-implementing-getmetricspec). - `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`. For more details refer to [Implementing `GetMetrics`](#5-implementing-getmetrics). -> Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates replicaCount based on metric value and target value. + > Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates replicaCount based on metric value and target value. ### External Scaler GRPC interface @@ -51,6 +52,7 @@ service ExternalScaler { - `IsActive` maps to the `IsActive` method on the `Scaler` interface. Few things to notice: + - `IsActive`, `StreamIsActive`, and `GetMetricsSpec` are called with a `ScaledObjectRef` that contains the scaledObject name/namespace as well as the content of `metadata` defined in the trigger. For example the following `ScaledObject`: @@ -85,6 +87,7 @@ KEDA will attempt a connection to `service-address.svc.local:9090` and calls `Is } } ``` + ## Implementing KEDA external scaler GRPC interface ### Implementing an external scaler: @@ -110,6 +113,7 @@ go mod init example.com/external-scaler/sample mkdir externalscaler protoc externalscaler.proto --go_out=plugins=grpc:externalscaler ``` + {{< /collapsible >}} {{< collapsible "C#" >}} @@ -146,9 +150,8 @@ mkdir Services ```bash npm install --save grpc request ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 3. Implementing `IsActive` @@ -178,6 +181,7 @@ spec: Full implementation can be found here: https://github.com/kedacore/external-scaler-samples `main.go` + ```golang func (e *ExternalScaler) IsActive(ctx context.Context, scaledObject *pb.ScaledObjectRef) (*pb.IsActiveResponse, error) { // request.Scalermetadata contains the `metadata` defined in the ScaledObject @@ -224,12 +228,14 @@ func (e *ExternalScaler) IsActive(ctx context.Context, scaledObject *pb.ScaledOb }, nil } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} Full implementation can be found here: https://github.com/kedacore/external-scaler-samples `Services/ExternalScalerService.cs` + ```csharp public class ExternalScalerService : ExternalScaler.ExternalScalerBase { @@ -262,79 +268,84 @@ public class ExternalScalerService : ExternalScaler.ExternalScalerBase } } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} `index.js` + ```js -const grpc = require('grpc') -const request = require('request') -const externalScalerProto = grpc.load('externalscaler.proto') +const grpc = require("grpc"); +const request = require("request"); +const externalScalerProto = grpc.load("externalscaler.proto"); -const server = new grpc.Server() +const server = new grpc.Server(); server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { isActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { - const now = new Date() - const yesterday = new Date(new Date().setDate(new Date().getDate()-1)); - - const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}` - const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}` - const radiusKm = 500 - const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}` - - request.get({ - url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, - json: true, - }, (err, resp, data) => { - if (err) { - callback({ - code: grpc.status.INTERNAL, - details: err, - }) - } else if (resp.statusCode !== 200) { - callback({ - code: grpc.status.INTERNAL, - details: `expected status 200, got ${resp.statusCode}` - }) - } else { - // count how many earthquakes with mag > 1.0 - let count = 0 - data.features.forEach(i => { - if (i.properties.mag > 1.0) { - count++ - } - }) - callback(null, { - result: count > 2, - }) + const now = new Date(); + const yesterday = new Date(new Date().setDate(new Date().getDate() - 1)); + + const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}`; + const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}`; + const radiusKm = 500; + const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}`; + + request.get( + { + url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, + json: true, + }, + (err, resp, data) => { + if (err) { + callback({ + code: grpc.status.INTERNAL, + details: err, + }); + } else if (resp.statusCode !== 200) { + callback({ + code: grpc.status.INTERNAL, + details: `expected status 200, got ${resp.statusCode}`, + }); + } else { + // count how many earthquakes with mag > 1.0 + let count = 0; + data.features.forEach((i) => { + if (i.properties.mag > 1.0) { + count++; + } + }); + callback(null, { + result: count > 2, + }); + } } - }) + ); } - } -}) + }, +}); -server.bind('127.0.0.1:9090', grpc.ServerCredentials.createInsecure()) -console.log('Server listening on 127.0.0.1:9090') +server.bind("127.0.0.1:9090", grpc.ServerCredentials.createInsecure()); +console.log("Server listening on 127.0.0.1:9090"); -server.start() +server.start(); ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 4. Implementing `GetMetricSpec` `GetMetricSpec` returns the `target` value for [the HPA definition for the scaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/). This scaler will define a static target of 10, but the threshold value is often specified in the metadata for other scalers. {{< collapsible "Golang" >}} + ```golang func (e *ExternalScaler) GetMetricSpec(context.Context, *pb.ScaledObjectRef) (*pb.GetMetricSpecResponse, error) { return &pb.GetMetricSpecResponse{ @@ -345,9 +356,11 @@ func (e *ExternalScaler) GetMetricSpec(context.Context, *pb.ScaledObjectRef) (*p }, nil } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} + ```csharp public override async Task GetMetricSpec(ScaledObjectRef request, ServerCallContext context) { @@ -362,31 +375,35 @@ public override async Task GetMetricSpec(ScaledObjectRef return Task.FromResult(resp); } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} + ```js server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetricSpec: (call, callback) => { callback(null, { - metricSpecs: [{ - metricName: 'earthquakeThreshold', - targetSize: 10, - }] - }) - } -}) + metricSpecs: [ + { + metricName: "earthquakeThreshold", + targetSize: 10, + }, + ], + }); + }, +}); ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 5. Implementing `GetMetrics` `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`, in this example it's `earthquakeThreshold`. {{< collapsible "Golang" >}} + ```golang func (e *ExternalScaler) GetMetrics(_ context.Context, metricRequest *pb.GetMetricsRequest) (*pb.GetMetricsResponse, error) { longitude := metricRequest.ScaledObjectRef.ScalerMetadata["longitude"] @@ -409,9 +426,11 @@ func (e *ExternalScaler) GetMetrics(_ context.Context, metricRequest *pb.GetMetr }, nil } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} + ```csharp public override async Task GetMetrics(GetMetricsRequest request, ServerCallContext context) { @@ -436,38 +455,43 @@ public override async Task GetMetrics(GetMetricsRequest requ return resp; } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} + ```js server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetrics: (call, callback) => { - const longitude = call.request.scaledObjectRef.scalerMetadata.longitude - const latitude = call.request.scaledObjectRef.scalerMetadata.latitude + const longitude = call.request.scaledObjectRef.scalerMetadata.longitude; + const latitude = call.request.scaledObjectRef.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { getEarthquakeCount((err, count) => { if (err) { callback({ code: grpc.status.INTERNAL, details: err, - }) + }); } else { callback(null, { - metricValues: [{ - metricName: 'earthquakeThreshold', - metricValue: count, - }] - }) + metricValues: [ + { + metricName: "earthquakeThreshold", + metricValue: count, + }, + ], + }); } - }) + }); } - } -}) + }, +}); ``` + {{< /collapsible >}} diff --git a/content/docs/2.0/concepts/external-scalers.md b/content/docs/2.0/concepts/external-scalers.md index 27ed9e0c6..1945394d3 100644 --- a/content/docs/2.0/concepts/external-scalers.md +++ b/content/docs/2.0/concepts/external-scalers.md @@ -33,15 +33,15 @@ type PushScaler interface { ``` The `Scaler` interface defines 4 methods: + - `IsActive` is called on `pollingInterval` defined in the ScaledObject/ScaledJob CRDs and scaling to 1 happens if this returns true. - `Close` is called to allow the scaler to clean up connections or other resources. - `GetMetricSpec` returns the target value for the HPA definition for the scaler. For more details refer to [Implementing `GetMetricSpec`](#5-implementing-getmetricspec). - `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`. For more details refer to [Implementing `GetMetrics`](#6-implementing-getmetrics). -> Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA uses the metric target type `AverageValue` for external metrics. This will cause the metric value returned by the external scaler to be divided by the number of replicas. + > Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA uses the metric target type `AverageValue` for external metrics. This will cause the metric value returned by the external scaler to be divided by the number of replicas. The `PushScaler` interface adds `Run` method. The `Run` method receives a push channel (`active`), that the scaler can push `true` to any time to force scaling action independently from `pollingInterval`. - ### External Scaler GRPC interface KEDA comes with 2 external scalers [`external`](../scalers/external.md) and [`external-push`](../scalers/external-push.md). @@ -62,6 +62,7 @@ service ExternalScaler { - `StreamIsActive` maps to the `Run` method on the `PushScaler` interface. Few things to notice: + - Lack of `Close` method as the GRPC connection defines the lifetime of the scaler - `IsActive`, `StreamIsActive`, and `GetMetricsSpec` are called with a `ScaledObjectRef` that contains the scaledObject name/namespace as well as the content of `metadata` defined in the trigger. @@ -125,6 +126,7 @@ go mod init example.com/external-scaler/sample mkdir externalscaler protoc externalscaler.proto --go_out=plugins=grpc:externalscaler ``` + {{< /collapsible >}} {{< collapsible "C#" >}} @@ -161,9 +163,8 @@ mkdir Services ```bash npm install --save grpc request ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 3. Implementing `IsActive` @@ -193,6 +194,7 @@ spec: Full implementation can be found here: https://github.com/kedacore/external-scaler-samples `main.go` + ```golang func (e *ExternalScaler) IsActive(ctx context.Context, scaledObject *pb.ScaledObjectRef) (*pb.IsActiveResponse, error) { // request.Scalermetadata contains the `metadata` defined in the ScaledObject @@ -239,12 +241,14 @@ func (e *ExternalScaler) IsActive(ctx context.Context, scaledObject *pb.ScaledOb }, nil } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} Full implementation can be found here: https://github.com/kedacore/external-scaler-samples `Services/ExternalScalerService.cs` + ```csharp public class ExternalScalerService : ExternalScaler.ExternalScalerBase { @@ -277,73 +281,77 @@ public class ExternalScalerService : ExternalScaler.ExternalScalerBase } } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} `index.js` + ```js -const grpc = require('grpc') -const request = require('request') -const externalScalerProto = grpc.load('externalscaler.proto') +const grpc = require("grpc"); +const request = require("request"); +const externalScalerProto = grpc.load("externalscaler.proto"); -const server = new grpc.Server() +const server = new grpc.Server(); server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { isActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { - const now = new Date() - const yesterday = new Date(new Date().setDate(new Date().getDate()-1)); - - const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}` - const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}` - const radiusKm = 500 - const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}` - - request.get({ - url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, - json: true, - }, (err, resp, data) => { - if (err) { - callback({ - code: grpc.status.INTERNAL, - details: err, - }) - } else if (resp.statusCode !== 200) { - callback({ - code: grpc.status.INTERNAL, - details: `expected status 200, got ${resp.statusCode}` - }) - } else { - // count how many earthquakes with mag > 1.0 - let count = 0 - data.features.forEach(i => { - if (i.properties.mag > 1.0) { - count++ - } - }) - callback(null, { - result: count > 2, - }) + const now = new Date(); + const yesterday = new Date(new Date().setDate(new Date().getDate() - 1)); + + const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}`; + const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}`; + const radiusKm = 500; + const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}`; + + request.get( + { + url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, + json: true, + }, + (err, resp, data) => { + if (err) { + callback({ + code: grpc.status.INTERNAL, + details: err, + }); + } else if (resp.statusCode !== 200) { + callback({ + code: grpc.status.INTERNAL, + details: `expected status 200, got ${resp.statusCode}`, + }); + } else { + // count how many earthquakes with mag > 1.0 + let count = 0; + data.features.forEach((i) => { + if (i.properties.mag > 1.0) { + count++; + } + }); + callback(null, { + result: count > 2, + }); + } } - }) + ); } - } -}) + }, +}); -server.bind('127.0.0.1:9090', grpc.ServerCredentials.createInsecure()) -console.log('Server listening on 127.0.0.1:9090') +server.bind("127.0.0.1:9090", grpc.ServerCredentials.createInsecure()); +console.log("Server listening on 127.0.0.1:9090"); -server.start() +server.start(); ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 4. Implementing `StreamIsActive` @@ -351,8 +359,8 @@ Unlike `IsActive`, `StreamIsActive` is called once when KEDA reconciles the `Sca This implementation creates a timer and queries USGS APIs on that timer, effectively ignoring `pollingInterval` set in the scaledObject. Alternatively any other asynchronous event can be used instead of a timer, like an HTTP request, or a network connection. - {{< collapsible "Golang" >}} + ```golang func (e *ExternalScaler) StreamIsActive(scaledObject *pb.ScaledObjectRef, epsServer pb.ExternalScaler_StreamIsActiveServer) error { longitude := scaledObject.ScalerMetadata["longitude"] @@ -380,9 +388,11 @@ func (e *ExternalScaler) StreamIsActive(scaledObject *pb.ScaledObjectRef, epsSer } } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} + ```csharp public override async Task StreamIsActive(ScaledObjectRef request, IServerStreamWriter responseStream, ServerCallContext context) { @@ -410,49 +420,51 @@ public override async Task StreamIsActive(ScaledObjectRef request, IServerStream } } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} + ```js server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... streamIsActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { const interval = setInterval(() => { getEarthquakeCount((err, count) => { if (err) { - console.error(err) + console.error(err); } else if (count > 2) { call.write({ result: true, - }) + }); } - }) + }); }, 1000 * 60 * 60); - call.on('end', () => { - clearInterval(interval) - }) + call.on("end", () => { + clearInterval(interval); + }); } - } -}) + }, +}); ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 5. Implementing `GetMetricSpec` `GetMetricSpec` returns the `target` value for [the HPA definition for the scaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/). This scaler will define a static target of 10, but the threshold value is often specified in the metadata for other scalers. {{< collapsible "Golang" >}} + ```golang func (e *ExternalScaler) GetMetricSpec(context.Context, *pb.ScaledObjectRef) (*pb.GetMetricSpecResponse, error) { return &pb.GetMetricSpecResponse{ @@ -463,9 +475,11 @@ func (e *ExternalScaler) GetMetricSpec(context.Context, *pb.ScaledObjectRef) (*p }, nil } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} + ```csharp public override async Task GetMetricSpec(ScaledObjectRef request, ServerCallContext context) { @@ -480,31 +494,35 @@ public override async Task GetMetricSpec(ScaledObjectRef return Task.FromResult(resp); } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} + ```js server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetricSpec: (call, callback) => { callback(null, { - metricSpecs: [{ - metricName: 'earthquakeThreshold', - targetSize: 10, - }] - }) - } -}) + metricSpecs: [ + { + metricName: "earthquakeThreshold", + targetSize: 10, + }, + ], + }); + }, +}); ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 6. Implementing `GetMetrics` `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`, in this example it's `earthquakeThreshold`. {{< collapsible "Golang" >}} + ```golang func (e *ExternalScaler) GetMetrics(_ context.Context, metricRequest *pb.GetMetricsRequest) (*pb.GetMetricsResponse, error) { longitude := metricRequest.ScaledObjectRef.ScalerMetadata["longitude"] @@ -527,9 +545,11 @@ func (e *ExternalScaler) GetMetrics(_ context.Context, metricRequest *pb.GetMetr }, nil } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} + ```csharp public override async Task GetMetrics(GetMetricsRequest request, ServerCallContext context) { @@ -554,38 +574,43 @@ public override async Task GetMetrics(GetMetricsRequest requ return resp; } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} + ```js server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetrics: (call, callback) => { - const longitude = call.request.scaledObjectRef.scalerMetadata.longitude - const latitude = call.request.scaledObjectRef.scalerMetadata.latitude + const longitude = call.request.scaledObjectRef.scalerMetadata.longitude; + const latitude = call.request.scaledObjectRef.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { getEarthquakeCount((err, count) => { if (err) { callback({ code: grpc.status.INTERNAL, details: err, - }) + }); } else { callback(null, { - metricValues: [{ - metricName: 'earthquakeThreshold', - metricValue: count, - }] - }) + metricValues: [ + { + metricName: "earthquakeThreshold", + metricValue: count, + }, + ], + }); } - }) + }); } - } -}) + }, +}); ``` + {{< /collapsible >}} diff --git a/content/docs/2.0/migration.md b/content/docs/2.0/migration.md index b7e2cbad5..fe54ad324 100644 --- a/content/docs/2.0/migration.md +++ b/content/docs/2.0/migration.md @@ -11,15 +11,17 @@ Please note that you **can not** run both KEDA v1 and v2 on the same Kubernetes KEDA v2 is using a new API namespace for it's Custom Resources Definitions (CRD): `keda.sh` instead of `keda.k8s.io` and introduces a new Custom Resource for scaling of Jobs. See full details on KEDA Custom Resources [here](../concepts/#custom-resources-crd). Here's an overview of what's changed: + - [Scaling of Deployments](#scaling-of-deployments) - [Scaling of Jobs](#scaling-of-jobs) - [Improved flexibility & usability of trigger metadata](#improved-flexibility--usability-of-trigger-metadata) - [Scalers](#scalers) - [TriggerAuthentication](#triggerauthentication) - ### Scaling of Deployments + In order to scale `Deployments` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Rename property `spec.scaleTargetRef.deploymentName` to `spec.scaleTargetRef.name` - Rename property `spec.scaleTargetRef.containerName` to `spec.scaleTargetRef.envSourceContainerName` @@ -27,22 +29,23 @@ In order to scale `Deployments` with KEDA v2, you need to do only a few modifica Please see the examples below or refer to the full [v2 ScaledObject Specification](../concepts/scaling-deployments/#scaledobject-spec) - **Example of v1 ScaledObject** +**Example of v1 ScaledObject** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } labels: - deploymentName: {deployment-name} + deploymentName: { deployment-name } spec: scaleTargetRef: - deploymentName: {deployment-name} - containerName: {container-name} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + deploymentName: { deployment-name } + containerName: { container-name } + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -50,18 +53,18 @@ spec: **Example of v2 ScaledObject** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed kind: ScaledObject -metadata: # <--- labels.deploymentName is not needed - name: {scaled-object-name} +metadata: # <--- labels.deploymentName is not needed + name: { scaled-object-name } spec: scaleTargetRef: - name: {deployment-name} # <--- Property name was changed - envSourceContainerName: {container-name} # <--- Property name was changed - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + name: { deployment-name } # <--- Property name was changed + envSourceContainerName: { container-name } # <--- Property name was changed + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -69,34 +72,36 @@ spec: ### Scaling of Jobs In order to scale `Jobs` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Change the value of `kind` property from `ScaledObject` to `ScaledJob` - Remove property `spec.scaleType` -- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` +- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` You can configure `successfulJobsHistoryLimit` and `failedJobsHistoryLimit`. They will remove the old job histories automatically. Please see the examples below or refer to the full [v2 ScaledJob Specification](../concepts/scaling-jobs/#scaledjob-spec) **Example of v1 ScaledObject for Jobs scaling** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } spec: scaleType: job jobTargetRef: - parallelism: 1 + parallelism: 1 completions: 1 activeDeadlineSeconds: 600 - backoffLimit: 6 + backoffLimit: 6 template: # {job template} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to create jobs} ``` @@ -104,21 +109,21 @@ spec: **Example of v2 ScaledJob** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed -kind: ScaledJob # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +kind: ScaledJob # <--- Property value was changed metadata: - name: {scaled-job-name} -spec: # <--- spec.scaleType is not needed + name: { scaled-job-name } +spec: # <--- spec.scaleType is not needed jobTargetRef: - parallelism: 1 - completions: 1 + parallelism: 1 + completions: 1 activeDeadlineSeconds: 600 backoffLimit: 6 template: # {job template} - pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed - successfulJobsHistoryLimit: 5 # <--- property is added - failedJobsHistoryLimit: 5 # <--- Property is added + pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed + successfulJobsHistoryLimit: 5 # <--- property is added + failedJobsHistoryLimit: 5 # <--- Property is added maxReplicaCount: 100 triggers: # {list of triggers to create jobs} @@ -132,68 +137,74 @@ We've introduced more options to configure trigger metadata to give users more f Here's an overview: -| Scaler | 1.x | 2.0 | -|--------|--------|--------| -| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | -| `azure-monitor` | `activeDirectoryClientId`
`activeDirectoryClientPassword` | `activeDirectoryClientId`
`activeDirectoryClientIdFromEnv`
`activeDirectoryClientPasswordFromEnv` | -| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | -| `azure-servicebus` | `connection` | `connectionFromEnv` | -| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`)
`connection` (**Default**: `EventHub`) | `storageConnectionFromEnv`
`connectionFromEnv` | -| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `kafka` | _(none)_ | _(none)_ -| `rabbitmq` | `apiHost`
`host` | ~~`apiHost`~~
`host`
`hostFromEnv` | -| `prometheus` | _(none)_ | _(none)_ | -| `cron` | _(none)_ | _(none)_ | -| `redis` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `redis-streams` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | -| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ -| `liiklus` | _(none)_ | _(none)_ | -| `stan` | _(none)_ | _(none)_ | -| `huawei-cloudeye` | | _(none)_ | _(none)_ | -| `postgresql` | `connection`
`password` | `connectionFromEnv`
`passwordFromEnv` | -| `mysql` | `connectionString`
`password` | `connectionStringFromEnv`
`passwordFromEnv` | +| Scaler | 1.x | 2.0 | +| -------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------- | +| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | +| `azure-monitor` | `activeDirectoryClientId` `activeDirectoryClientPassword` | `activeDirectoryClientId` `activeDirectoryClientIdFromEnv` `activeDirectoryClientPasswordFromEnv` | +| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | +| `azure-servicebus` | `connection` | `connectionFromEnv` | +| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`) `connection` (**Default**: `EventHub`) | `storageConnectionFromEnv` `connectionFromEnv` | +| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `kafka` | _(none)_ | _(none)_ | +| `rabbitmq` | `apiHost` `host` | ~~`apiHost`~~ `host` `hostFromEnv` | +| `prometheus` | _(none)_ | _(none)_ | +| `cron` | _(none)_ | _(none)_ | +| `redis` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `redis-streams` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | +| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ | +| `liiklus` | _(none)_ | _(none)_ | +| `stan` | _(none)_ | _(none)_ | +| `huawei-cloudeye` | | _(none)_ | _(none)_ | +| `postgresql` | `connection` `password` | `connectionFromEnv` `passwordFromEnv` | +| `mysql` | `connectionString` `password` | `connectionStringFromEnv` `passwordFromEnv` | ### Scalers **Azure Service Bus** - - `queueLength` was renamed to `messageCount` + +- `queueLength` was renamed to `messageCount` **Kafka** - - `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. + +- `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. **RabbitMQ** In KEDA 2.0 the RabbitMQ scaler has only `host` parameter, and the protocol for communication can be specified by -`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP -protocol. +`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP +protocol. Example of RabbitMQ trigger before 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - includeUnacked: 'true' - apiHost: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + includeUnacked: "true" + apiHost: "https://guest:password@localhost:443/vhostname" +``` The same trigger in 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - protocol: 'http' - host: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + protocol: "http" + host: "https://guest:password@localhost:443/vhostname" +``` ### TriggerAuthentication + In order to use Authentication via `TriggerAuthentication` with KEDA v2, you need to change: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` For more details please refer to the full diff --git a/content/docs/2.0/operate/cluster.md b/content/docs/2.0/operate/cluster.md index 96925a55e..3620e816a 100644 --- a/content/docs/2.0/operate/cluster.md +++ b/content/docs/2.0/operate/cluster.md @@ -15,7 +15,7 @@ KEDA is designed, tested and supported to be run on any Kubernetes cluster that The KEDA runtime require the following resources in a production-ready setup: | Deployment | CPU | Memory | -|----------------|-------------------------|-------------------------------| +| -------------- | ----------------------- | ----------------------------- | | Operator | Limit: 1, Request: 100m | Limit: 1000Mi, Request: 100Mi | | Metrics Server | Limit: 1, Request: 100m | Limit: 1000Mi, Request: 100Mi | @@ -40,7 +40,7 @@ KEDA does not provide full support for high-availability due to upstream limitat Here is an overview of all KEDA deployments and the HA notes: -| Deployment | Support Replicas | Note | -| -------------- | ---------------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Deployment | Support Replicas | Note | +| -------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Metrics Server | 1 | You can run multiple replicas of our metrics sever, and it is recommended to add the `--enable-aggregator-routing=true` CLI flag to the kube-apiserver so that requests sent to our metrics servers are load balanced. However, [you can only run one active metric server in a Kubernetes cluster serving external.metrics.k8s.io](https://github.com/kubernetes-sigs/custom-metrics-apiserver/issues/70) which has to be the KEDA metric server. | -| Operator | 1 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover.

This is only supported as of KEDA v2.6 if you are using our Helm chart. | +| Operator | 1 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover.This is only supported as of KEDA v2.6 if you are using our Helm chart. | diff --git a/content/docs/2.1/concepts/external-scalers.md b/content/docs/2.1/concepts/external-scalers.md index 27ed9e0c6..1945394d3 100644 --- a/content/docs/2.1/concepts/external-scalers.md +++ b/content/docs/2.1/concepts/external-scalers.md @@ -33,15 +33,15 @@ type PushScaler interface { ``` The `Scaler` interface defines 4 methods: + - `IsActive` is called on `pollingInterval` defined in the ScaledObject/ScaledJob CRDs and scaling to 1 happens if this returns true. - `Close` is called to allow the scaler to clean up connections or other resources. - `GetMetricSpec` returns the target value for the HPA definition for the scaler. For more details refer to [Implementing `GetMetricSpec`](#5-implementing-getmetricspec). - `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`. For more details refer to [Implementing `GetMetrics`](#6-implementing-getmetrics). -> Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA uses the metric target type `AverageValue` for external metrics. This will cause the metric value returned by the external scaler to be divided by the number of replicas. + > Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA uses the metric target type `AverageValue` for external metrics. This will cause the metric value returned by the external scaler to be divided by the number of replicas. The `PushScaler` interface adds `Run` method. The `Run` method receives a push channel (`active`), that the scaler can push `true` to any time to force scaling action independently from `pollingInterval`. - ### External Scaler GRPC interface KEDA comes with 2 external scalers [`external`](../scalers/external.md) and [`external-push`](../scalers/external-push.md). @@ -62,6 +62,7 @@ service ExternalScaler { - `StreamIsActive` maps to the `Run` method on the `PushScaler` interface. Few things to notice: + - Lack of `Close` method as the GRPC connection defines the lifetime of the scaler - `IsActive`, `StreamIsActive`, and `GetMetricsSpec` are called with a `ScaledObjectRef` that contains the scaledObject name/namespace as well as the content of `metadata` defined in the trigger. @@ -125,6 +126,7 @@ go mod init example.com/external-scaler/sample mkdir externalscaler protoc externalscaler.proto --go_out=plugins=grpc:externalscaler ``` + {{< /collapsible >}} {{< collapsible "C#" >}} @@ -161,9 +163,8 @@ mkdir Services ```bash npm install --save grpc request ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 3. Implementing `IsActive` @@ -193,6 +194,7 @@ spec: Full implementation can be found here: https://github.com/kedacore/external-scaler-samples `main.go` + ```golang func (e *ExternalScaler) IsActive(ctx context.Context, scaledObject *pb.ScaledObjectRef) (*pb.IsActiveResponse, error) { // request.Scalermetadata contains the `metadata` defined in the ScaledObject @@ -239,12 +241,14 @@ func (e *ExternalScaler) IsActive(ctx context.Context, scaledObject *pb.ScaledOb }, nil } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} Full implementation can be found here: https://github.com/kedacore/external-scaler-samples `Services/ExternalScalerService.cs` + ```csharp public class ExternalScalerService : ExternalScaler.ExternalScalerBase { @@ -277,73 +281,77 @@ public class ExternalScalerService : ExternalScaler.ExternalScalerBase } } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} `index.js` + ```js -const grpc = require('grpc') -const request = require('request') -const externalScalerProto = grpc.load('externalscaler.proto') +const grpc = require("grpc"); +const request = require("request"); +const externalScalerProto = grpc.load("externalscaler.proto"); -const server = new grpc.Server() +const server = new grpc.Server(); server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { isActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { - const now = new Date() - const yesterday = new Date(new Date().setDate(new Date().getDate()-1)); - - const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}` - const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}` - const radiusKm = 500 - const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}` - - request.get({ - url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, - json: true, - }, (err, resp, data) => { - if (err) { - callback({ - code: grpc.status.INTERNAL, - details: err, - }) - } else if (resp.statusCode !== 200) { - callback({ - code: grpc.status.INTERNAL, - details: `expected status 200, got ${resp.statusCode}` - }) - } else { - // count how many earthquakes with mag > 1.0 - let count = 0 - data.features.forEach(i => { - if (i.properties.mag > 1.0) { - count++ - } - }) - callback(null, { - result: count > 2, - }) + const now = new Date(); + const yesterday = new Date(new Date().setDate(new Date().getDate() - 1)); + + const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}`; + const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}`; + const radiusKm = 500; + const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}`; + + request.get( + { + url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, + json: true, + }, + (err, resp, data) => { + if (err) { + callback({ + code: grpc.status.INTERNAL, + details: err, + }); + } else if (resp.statusCode !== 200) { + callback({ + code: grpc.status.INTERNAL, + details: `expected status 200, got ${resp.statusCode}`, + }); + } else { + // count how many earthquakes with mag > 1.0 + let count = 0; + data.features.forEach((i) => { + if (i.properties.mag > 1.0) { + count++; + } + }); + callback(null, { + result: count > 2, + }); + } } - }) + ); } - } -}) + }, +}); -server.bind('127.0.0.1:9090', grpc.ServerCredentials.createInsecure()) -console.log('Server listening on 127.0.0.1:9090') +server.bind("127.0.0.1:9090", grpc.ServerCredentials.createInsecure()); +console.log("Server listening on 127.0.0.1:9090"); -server.start() +server.start(); ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 4. Implementing `StreamIsActive` @@ -351,8 +359,8 @@ Unlike `IsActive`, `StreamIsActive` is called once when KEDA reconciles the `Sca This implementation creates a timer and queries USGS APIs on that timer, effectively ignoring `pollingInterval` set in the scaledObject. Alternatively any other asynchronous event can be used instead of a timer, like an HTTP request, or a network connection. - {{< collapsible "Golang" >}} + ```golang func (e *ExternalScaler) StreamIsActive(scaledObject *pb.ScaledObjectRef, epsServer pb.ExternalScaler_StreamIsActiveServer) error { longitude := scaledObject.ScalerMetadata["longitude"] @@ -380,9 +388,11 @@ func (e *ExternalScaler) StreamIsActive(scaledObject *pb.ScaledObjectRef, epsSer } } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} + ```csharp public override async Task StreamIsActive(ScaledObjectRef request, IServerStreamWriter responseStream, ServerCallContext context) { @@ -410,49 +420,51 @@ public override async Task StreamIsActive(ScaledObjectRef request, IServerStream } } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} + ```js server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... streamIsActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { const interval = setInterval(() => { getEarthquakeCount((err, count) => { if (err) { - console.error(err) + console.error(err); } else if (count > 2) { call.write({ result: true, - }) + }); } - }) + }); }, 1000 * 60 * 60); - call.on('end', () => { - clearInterval(interval) - }) + call.on("end", () => { + clearInterval(interval); + }); } - } -}) + }, +}); ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 5. Implementing `GetMetricSpec` `GetMetricSpec` returns the `target` value for [the HPA definition for the scaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/). This scaler will define a static target of 10, but the threshold value is often specified in the metadata for other scalers. {{< collapsible "Golang" >}} + ```golang func (e *ExternalScaler) GetMetricSpec(context.Context, *pb.ScaledObjectRef) (*pb.GetMetricSpecResponse, error) { return &pb.GetMetricSpecResponse{ @@ -463,9 +475,11 @@ func (e *ExternalScaler) GetMetricSpec(context.Context, *pb.ScaledObjectRef) (*p }, nil } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} + ```csharp public override async Task GetMetricSpec(ScaledObjectRef request, ServerCallContext context) { @@ -480,31 +494,35 @@ public override async Task GetMetricSpec(ScaledObjectRef return Task.FromResult(resp); } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} + ```js server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetricSpec: (call, callback) => { callback(null, { - metricSpecs: [{ - metricName: 'earthquakeThreshold', - targetSize: 10, - }] - }) - } -}) + metricSpecs: [ + { + metricName: "earthquakeThreshold", + targetSize: 10, + }, + ], + }); + }, +}); ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 6. Implementing `GetMetrics` `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`, in this example it's `earthquakeThreshold`. {{< collapsible "Golang" >}} + ```golang func (e *ExternalScaler) GetMetrics(_ context.Context, metricRequest *pb.GetMetricsRequest) (*pb.GetMetricsResponse, error) { longitude := metricRequest.ScaledObjectRef.ScalerMetadata["longitude"] @@ -527,9 +545,11 @@ func (e *ExternalScaler) GetMetrics(_ context.Context, metricRequest *pb.GetMetr }, nil } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} + ```csharp public override async Task GetMetrics(GetMetricsRequest request, ServerCallContext context) { @@ -554,38 +574,43 @@ public override async Task GetMetrics(GetMetricsRequest requ return resp; } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} + ```js server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetrics: (call, callback) => { - const longitude = call.request.scaledObjectRef.scalerMetadata.longitude - const latitude = call.request.scaledObjectRef.scalerMetadata.latitude + const longitude = call.request.scaledObjectRef.scalerMetadata.longitude; + const latitude = call.request.scaledObjectRef.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { getEarthquakeCount((err, count) => { if (err) { callback({ code: grpc.status.INTERNAL, details: err, - }) + }); } else { callback(null, { - metricValues: [{ - metricName: 'earthquakeThreshold', - metricValue: count, - }] - }) + metricValues: [ + { + metricName: "earthquakeThreshold", + metricValue: count, + }, + ], + }); } - }) + }); } - } -}) + }, +}); ``` + {{< /collapsible >}} diff --git a/content/docs/2.1/migration.md b/content/docs/2.1/migration.md index 5ee8a6455..29e8408c8 100644 --- a/content/docs/2.1/migration.md +++ b/content/docs/2.1/migration.md @@ -11,15 +11,17 @@ Please note that you **can not** run both KEDA v1 and v2 on the same Kubernetes KEDA v2 is using a new API namespace for its Custom Resources Definitions (CRD): `keda.sh` instead of `keda.k8s.io` and introduces a new Custom Resource for scaling of Jobs. See full details on KEDA Custom Resources [here](../concepts/#custom-resources-crd). Here's an overview of what's changed: + - [Scaling of Deployments](#scaling-of-deployments) - [Scaling of Jobs](#scaling-of-jobs) - [Improved flexibility & usability of trigger metadata](#improved-flexibility--usability-of-trigger-metadata) - [Scalers](#scalers) - [TriggerAuthentication](#triggerauthentication) - ### Scaling of Deployments + In order to scale `Deployments` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Rename property `spec.scaleTargetRef.deploymentName` to `spec.scaleTargetRef.name` - Rename property `spec.scaleTargetRef.containerName` to `spec.scaleTargetRef.envSourceContainerName` @@ -27,22 +29,23 @@ In order to scale `Deployments` with KEDA v2, you need to do only a few modifica Please see the examples below or refer to the full [v2 ScaledObject Specification](../concepts/scaling-deployments/#scaledobject-spec) - **Example of v1 ScaledObject** +**Example of v1 ScaledObject** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } labels: - deploymentName: {deployment-name} + deploymentName: { deployment-name } spec: scaleTargetRef: - deploymentName: {deployment-name} - containerName: {container-name} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + deploymentName: { deployment-name } + containerName: { container-name } + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -50,18 +53,18 @@ spec: **Example of v2 ScaledObject** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed kind: ScaledObject -metadata: # <--- labels.deploymentName is not needed - name: {scaled-object-name} +metadata: # <--- labels.deploymentName is not needed + name: { scaled-object-name } spec: scaleTargetRef: - name: {deployment-name} # <--- Property name was changed - envSourceContainerName: {container-name} # <--- Property name was changed - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + name: { deployment-name } # <--- Property name was changed + envSourceContainerName: { container-name } # <--- Property name was changed + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -69,34 +72,36 @@ spec: ### Scaling of Jobs In order to scale `Jobs` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Change the value of `kind` property from `ScaledObject` to `ScaledJob` - Remove property `spec.scaleType` -- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` +- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` You can configure `successfulJobsHistoryLimit` and `failedJobsHistoryLimit`. They will remove the old job histories automatically. Please see the examples below or refer to the full [v2 ScaledJob Specification](../concepts/scaling-jobs/#scaledjob-spec) **Example of v1 ScaledObject for Jobs scaling** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } spec: scaleType: job jobTargetRef: - parallelism: 1 + parallelism: 1 completions: 1 activeDeadlineSeconds: 600 - backoffLimit: 6 + backoffLimit: 6 template: # {job template} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to create jobs} ``` @@ -104,21 +109,21 @@ spec: **Example of v2 ScaledJob** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed -kind: ScaledJob # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +kind: ScaledJob # <--- Property value was changed metadata: - name: {scaled-job-name} -spec: # <--- spec.scaleType is not needed + name: { scaled-job-name } +spec: # <--- spec.scaleType is not needed jobTargetRef: - parallelism: 1 - completions: 1 + parallelism: 1 + completions: 1 activeDeadlineSeconds: 600 backoffLimit: 6 template: # {job template} - pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed - successfulJobsHistoryLimit: 5 # <--- property is added - failedJobsHistoryLimit: 5 # <--- Property is added + pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed + successfulJobsHistoryLimit: 5 # <--- property is added + failedJobsHistoryLimit: 5 # <--- Property is added maxReplicaCount: 100 triggers: # {list of triggers to create jobs} @@ -132,68 +137,74 @@ We've introduced more options to configure trigger metadata to give users more f Here's an overview: -| Scaler | 1.x | 2.0 | -|--------|--------|--------| -| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | -| `azure-monitor` | `activeDirectoryClientId`
`activeDirectoryClientPassword` | `activeDirectoryClientId`
`activeDirectoryClientIdFromEnv`
`activeDirectoryClientPasswordFromEnv` | -| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | -| `azure-servicebus` | `connection` | `connectionFromEnv` | -| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`)
`connection` (**Default**: `EventHub`) | `storageConnectionFromEnv`
`connectionFromEnv` | -| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `kafka` | _(none)_ | _(none)_ -| `rabbitmq` | `apiHost`
`host` | ~~`apiHost`~~
`host`
`hostFromEnv` | -| `prometheus` | _(none)_ | _(none)_ | -| `cron` | _(none)_ | _(none)_ | -| `redis` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `redis-streams` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | -| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ -| `liiklus` | _(none)_ | _(none)_ | -| `stan` | _(none)_ | _(none)_ | -| `huawei-cloudeye` | | _(none)_ | _(none)_ | -| `postgresql` | `connection`
`password` | `connectionFromEnv`
`passwordFromEnv` | -| `mysql` | `connectionString`
`password` | `connectionStringFromEnv`
`passwordFromEnv` | +| Scaler | 1.x | 2.0 | +| -------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------- | +| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | +| `azure-monitor` | `activeDirectoryClientId` `activeDirectoryClientPassword` | `activeDirectoryClientId` `activeDirectoryClientIdFromEnv` `activeDirectoryClientPasswordFromEnv` | +| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | +| `azure-servicebus` | `connection` | `connectionFromEnv` | +| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`) `connection` (**Default**: `EventHub`) | `storageConnectionFromEnv` `connectionFromEnv` | +| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `kafka` | _(none)_ | _(none)_ | +| `rabbitmq` | `apiHost` `host` | ~~`apiHost`~~ `host` `hostFromEnv` | +| `prometheus` | _(none)_ | _(none)_ | +| `cron` | _(none)_ | _(none)_ | +| `redis` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `redis-streams` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | +| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ | +| `liiklus` | _(none)_ | _(none)_ | +| `stan` | _(none)_ | _(none)_ | +| `huawei-cloudeye` | | _(none)_ | _(none)_ | +| `postgresql` | `connection` `password` | `connectionFromEnv` `passwordFromEnv` | +| `mysql` | `connectionString` `password` | `connectionStringFromEnv` `passwordFromEnv` | ### Scalers **Azure Service Bus** - - `queueLength` was renamed to `messageCount` + +- `queueLength` was renamed to `messageCount` **Kafka** - - `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. + +- `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. **RabbitMQ** In KEDA 2.0 the RabbitMQ scaler has only `host` parameter, and the protocol for communication can be specified by -`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP -protocol. +`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP +protocol. Example of RabbitMQ trigger before 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - includeUnacked: 'true' - apiHost: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + includeUnacked: "true" + apiHost: "https://guest:password@localhost:443/vhostname" +``` The same trigger in 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - protocol: 'http' - host: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + protocol: "http" + host: "https://guest:password@localhost:443/vhostname" +``` ### TriggerAuthentication + In order to use Authentication via `TriggerAuthentication` with KEDA v2, you need to change: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` For more details please refer to the full diff --git a/content/docs/2.1/operate/cluster.md b/content/docs/2.1/operate/cluster.md index c4ccbb85f..fab8edc37 100644 --- a/content/docs/2.1/operate/cluster.md +++ b/content/docs/2.1/operate/cluster.md @@ -15,7 +15,7 @@ KEDA is designed, tested and supported to be run on any Kubernetes cluster that The KEDA runtime require the following resources in a production-ready setup: | Deployment | CPU | Memory | -|----------------|-------------------------|-------------------------------| +| -------------- | ----------------------- | ----------------------------- | | Operator | Limit: 1, Request: 100m | Limit: 1000Mi, Request: 100Mi | | Metrics Server | Limit: 1, Request: 100m | Limit: 1000Mi, Request: 100Mi | @@ -40,10 +40,10 @@ KEDA does not provide full support for high-availability due to upstream limitat Here is an overview of all KEDA deployments and the HA notes: -| Deployment | Support Replicas | Note | -| -------------- | ---------------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Deployment | Support Replicas | Note | +| -------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Metrics Server | 1 | You can run multiple replicas of our metrics sever, and it is recommended to add the `--enable-aggregator-routing=true` CLI flag to the kube-apiserver so that requests sent to our metrics servers are load balanced. However, [you can only run one active metric server in a Kubernetes cluster serving external.metrics.k8s.io](https://github.com/kubernetes-sigs/custom-metrics-apiserver/issues/70) which has to be the KEDA metric server. | -| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover.

This is only supported as of KEDA v2.6 if you are using our Helm chart. | +| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover.This is only supported as of KEDA v2.6 if you are using our Helm chart. | ## HTTP Timeouts diff --git a/content/docs/2.10/concepts/external-scalers.md b/content/docs/2.10/concepts/external-scalers.md index 5badde098..aa00a18a0 100644 --- a/content/docs/2.10/concepts/external-scalers.md +++ b/content/docs/2.10/concepts/external-scalers.md @@ -9,7 +9,7 @@ Built-in scalers run in the KEDA process/pod, while external scalers require an This document describes the external scaler interfaces and how to implement them in Go, Node, and .NET; however for more details on GRPC refer to [the official GRPC documentation](https://grpc.io/docs/) ->Want to learn about existing external scalers? Explore our [external scaler community](https://github.com/kedacore/external-scalers). +> Want to learn about existing external scalers? Explore our [external scaler community](https://github.com/kedacore/external-scalers). ## Overview @@ -45,7 +45,7 @@ The `Scaler` interface defines 3 methods: - `GetMetricSpecForScaling` returns the target value for the HPA definition for the scaler. For more details refer to [Implementing `GetMetricSpec`](#5-implementing-getmetricspec). - `GetMetricsAndActivity` is called on `pollingInterval` and. When activity returns `true`, KEDA will scale to what is returned by the metric limited by `maxReplicaCount` on the ScaledObject/ScaledJob. When `false` is returned, KEDA will scale to `minReplicaCount` or optionally `idleReplicaCount`. More details around the defaults and how these options work together can be found on the [ScaledObjectSpec](https://keda.sh/docs/latest/concepts/scaling-deployments/#scaledobject-spec). -> Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA supports both `AverageValue` and `Value` metric target types for external metrics. When `AverageValue` (the default metric type) is used, the metric value returned by the external scaler will be divided by the number of replicas. + > Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA supports both `AverageValue` and `Value` metric target types for external metrics. When `AverageValue` (the default metric type) is used, the metric value returned by the external scaler will be divided by the number of replicas. The `PushScaler` interface adds a `Run` method. This method receives a push channel (`active`), on which the scaler can send `true` at any time. The purpose of this mechanism is to initiate a scaling operation independently from `pollingInterval`. @@ -115,7 +115,7 @@ KEDA will attempt a GRPC connection to `service-address.svc.local:9090` immediat } ``` ->**Note**: KEDA will issue all of the above RPC calls except `StreamIsActive` if `spec.triggers.type` is `external`. It _must_ be `external-push` for `StreamIsActive` to be called. +> **Note**: KEDA will issue all of the above RPC calls except `StreamIsActive` if `spec.triggers.type` is `external`. It _must_ be `external-push` for `StreamIsActive` to be called. ## Implementing KEDA external scaler GRPC interface @@ -182,8 +182,6 @@ npm install --save grpc request {{< /collapsible >}} -
- #### 3. Implementing `IsActive` Just like `IsActive(ctx context.Context) (bool, error)` in the go interface, the `IsActive` method in the GRPC interface is called every `pollingInterval` with a `ScaledObjectRef` object that contains the scaledObject name, namespace, and scaler metadata. @@ -310,70 +308,71 @@ public class ExternalScalerService : ExternalScaler.ExternalScalerBase Put the following code into your `index.js` file: ```js -const grpc = require('grpc') -const request = require('request') -const externalScalerProto = grpc.load('externalscaler.proto') +const grpc = require("grpc"); +const request = require("request"); +const externalScalerProto = grpc.load("externalscaler.proto"); -const server = new grpc.Server() +const server = new grpc.Server(); server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { isActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { - const now = new Date() - const yesterday = new Date(new Date().setDate(new Date().getDate()-1)); - - const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}` - const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}` - const radiusKm = 500 - const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}` - - request.get({ - url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, - json: true, - }, (err, resp, data) => { - if (err) { - callback({ - code: grpc.status.INTERNAL, - details: err, - }) - } else if (resp.statusCode !== 200) { - callback({ - code: grpc.status.INTERNAL, - details: `expected status 200, got ${resp.statusCode}` - }) - } else { - // count how many earthquakes with mag > 1.0 - let count = 0 - data.features.forEach(i => { - if (i.properties.mag > 1.0) { - count++ - } - }) - callback(null, { - result: count > 2, - }) + const now = new Date(); + const yesterday = new Date(new Date().setDate(new Date().getDate() - 1)); + + const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}`; + const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}`; + const radiusKm = 500; + const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}`; + + request.get( + { + url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, + json: true, + }, + (err, resp, data) => { + if (err) { + callback({ + code: grpc.status.INTERNAL, + details: err, + }); + } else if (resp.statusCode !== 200) { + callback({ + code: grpc.status.INTERNAL, + details: `expected status 200, got ${resp.statusCode}`, + }); + } else { + // count how many earthquakes with mag > 1.0 + let count = 0; + data.features.forEach((i) => { + if (i.properties.mag > 1.0) { + count++; + } + }); + callback(null, { + result: count > 2, + }); + } } - }) + ); } - } -}) + }, +}); -server.bind('127.0.0.1:9090', grpc.ServerCredentials.createInsecure()) -console.log('Server listening on 127.0.0.1:9090') +server.bind("127.0.0.1:9090", grpc.ServerCredentials.createInsecure()); +console.log("Server listening on 127.0.0.1:9090"); -server.start() +server.start(); ``` {{< /collapsible >}} -
- #### 4. Implementing `StreamIsActive` Unlike `IsActive`, `StreamIsActive` is called once when KEDA reconciles the `ScaledObject`, and expects the external scaler to maintain a long-lived connection and push `IsActiveResponse` objects whenever the scaler needs KEDA to activate the deployment. @@ -450,38 +449,36 @@ public override async Task StreamIsActive(ScaledObjectRef request, IServerStream server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... streamIsActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { const interval = setInterval(() => { getEarthquakeCount((err, count) => { if (err) { - console.error(err) + console.error(err); } else if (count > 2) { call.write({ result: true, - }) + }); } - }) + }); }, 1000 * 60 * 60); - call.on('end', () => { - clearInterval(interval) - }) + call.on("end", () => { + clearInterval(interval); + }); } - } -}) + }, +}); ``` {{< /collapsible >}} -
- #### 5. Implementing `GetMetricSpec` `GetMetricSpec` returns the `target` value for [the HPA definition for the scaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/). This scaler will define a static target of 10, but the threshold value is often specified in the metadata for other scalers. @@ -527,19 +524,19 @@ server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetricSpec: (call, callback) => { callback(null, { - metricSpecs: [{ - metricName: 'earthquakeThreshold', - targetSize: 10, - }] - }) - } -}) + metricSpecs: [ + { + metricName: "earthquakeThreshold", + targetSize: 10, + }, + ], + }); + }, +}); ``` {{< /collapsible >}} -
- #### 6. Implementing `GetMetrics` `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`, in this example it's `earthquakeThreshold`. @@ -606,32 +603,34 @@ public override async Task GetMetrics(GetMetricsRequest requ server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetrics: (call, callback) => { - const longitude = call.request.scaledObjectRef.scalerMetadata.longitude - const latitude = call.request.scaledObjectRef.scalerMetadata.latitude + const longitude = call.request.scaledObjectRef.scalerMetadata.longitude; + const latitude = call.request.scaledObjectRef.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { getEarthquakeCount((err, count) => { if (err) { callback({ code: grpc.status.INTERNAL, details: err, - }) + }); } else { callback(null, { - metricValues: [{ - metricName: 'earthquakeThreshold', - metricValue: count, - }] - }) + metricValues: [ + { + metricName: "earthquakeThreshold", + metricValue: count, + }, + ], + }); } - }) + }); } - } -}) + }, +}); ``` {{< /collapsible >}} diff --git a/content/docs/2.10/migration.md b/content/docs/2.10/migration.md index 5ee8a6455..29e8408c8 100644 --- a/content/docs/2.10/migration.md +++ b/content/docs/2.10/migration.md @@ -11,15 +11,17 @@ Please note that you **can not** run both KEDA v1 and v2 on the same Kubernetes KEDA v2 is using a new API namespace for its Custom Resources Definitions (CRD): `keda.sh` instead of `keda.k8s.io` and introduces a new Custom Resource for scaling of Jobs. See full details on KEDA Custom Resources [here](../concepts/#custom-resources-crd). Here's an overview of what's changed: + - [Scaling of Deployments](#scaling-of-deployments) - [Scaling of Jobs](#scaling-of-jobs) - [Improved flexibility & usability of trigger metadata](#improved-flexibility--usability-of-trigger-metadata) - [Scalers](#scalers) - [TriggerAuthentication](#triggerauthentication) - ### Scaling of Deployments + In order to scale `Deployments` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Rename property `spec.scaleTargetRef.deploymentName` to `spec.scaleTargetRef.name` - Rename property `spec.scaleTargetRef.containerName` to `spec.scaleTargetRef.envSourceContainerName` @@ -27,22 +29,23 @@ In order to scale `Deployments` with KEDA v2, you need to do only a few modifica Please see the examples below or refer to the full [v2 ScaledObject Specification](../concepts/scaling-deployments/#scaledobject-spec) - **Example of v1 ScaledObject** +**Example of v1 ScaledObject** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } labels: - deploymentName: {deployment-name} + deploymentName: { deployment-name } spec: scaleTargetRef: - deploymentName: {deployment-name} - containerName: {container-name} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + deploymentName: { deployment-name } + containerName: { container-name } + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -50,18 +53,18 @@ spec: **Example of v2 ScaledObject** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed kind: ScaledObject -metadata: # <--- labels.deploymentName is not needed - name: {scaled-object-name} +metadata: # <--- labels.deploymentName is not needed + name: { scaled-object-name } spec: scaleTargetRef: - name: {deployment-name} # <--- Property name was changed - envSourceContainerName: {container-name} # <--- Property name was changed - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + name: { deployment-name } # <--- Property name was changed + envSourceContainerName: { container-name } # <--- Property name was changed + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -69,34 +72,36 @@ spec: ### Scaling of Jobs In order to scale `Jobs` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Change the value of `kind` property from `ScaledObject` to `ScaledJob` - Remove property `spec.scaleType` -- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` +- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` You can configure `successfulJobsHistoryLimit` and `failedJobsHistoryLimit`. They will remove the old job histories automatically. Please see the examples below or refer to the full [v2 ScaledJob Specification](../concepts/scaling-jobs/#scaledjob-spec) **Example of v1 ScaledObject for Jobs scaling** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } spec: scaleType: job jobTargetRef: - parallelism: 1 + parallelism: 1 completions: 1 activeDeadlineSeconds: 600 - backoffLimit: 6 + backoffLimit: 6 template: # {job template} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to create jobs} ``` @@ -104,21 +109,21 @@ spec: **Example of v2 ScaledJob** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed -kind: ScaledJob # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +kind: ScaledJob # <--- Property value was changed metadata: - name: {scaled-job-name} -spec: # <--- spec.scaleType is not needed + name: { scaled-job-name } +spec: # <--- spec.scaleType is not needed jobTargetRef: - parallelism: 1 - completions: 1 + parallelism: 1 + completions: 1 activeDeadlineSeconds: 600 backoffLimit: 6 template: # {job template} - pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed - successfulJobsHistoryLimit: 5 # <--- property is added - failedJobsHistoryLimit: 5 # <--- Property is added + pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed + successfulJobsHistoryLimit: 5 # <--- property is added + failedJobsHistoryLimit: 5 # <--- Property is added maxReplicaCount: 100 triggers: # {list of triggers to create jobs} @@ -132,68 +137,74 @@ We've introduced more options to configure trigger metadata to give users more f Here's an overview: -| Scaler | 1.x | 2.0 | -|--------|--------|--------| -| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | -| `azure-monitor` | `activeDirectoryClientId`
`activeDirectoryClientPassword` | `activeDirectoryClientId`
`activeDirectoryClientIdFromEnv`
`activeDirectoryClientPasswordFromEnv` | -| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | -| `azure-servicebus` | `connection` | `connectionFromEnv` | -| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`)
`connection` (**Default**: `EventHub`) | `storageConnectionFromEnv`
`connectionFromEnv` | -| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `kafka` | _(none)_ | _(none)_ -| `rabbitmq` | `apiHost`
`host` | ~~`apiHost`~~
`host`
`hostFromEnv` | -| `prometheus` | _(none)_ | _(none)_ | -| `cron` | _(none)_ | _(none)_ | -| `redis` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `redis-streams` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | -| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ -| `liiklus` | _(none)_ | _(none)_ | -| `stan` | _(none)_ | _(none)_ | -| `huawei-cloudeye` | | _(none)_ | _(none)_ | -| `postgresql` | `connection`
`password` | `connectionFromEnv`
`passwordFromEnv` | -| `mysql` | `connectionString`
`password` | `connectionStringFromEnv`
`passwordFromEnv` | +| Scaler | 1.x | 2.0 | +| -------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------- | +| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | +| `azure-monitor` | `activeDirectoryClientId` `activeDirectoryClientPassword` | `activeDirectoryClientId` `activeDirectoryClientIdFromEnv` `activeDirectoryClientPasswordFromEnv` | +| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | +| `azure-servicebus` | `connection` | `connectionFromEnv` | +| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`) `connection` (**Default**: `EventHub`) | `storageConnectionFromEnv` `connectionFromEnv` | +| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `kafka` | _(none)_ | _(none)_ | +| `rabbitmq` | `apiHost` `host` | ~~`apiHost`~~ `host` `hostFromEnv` | +| `prometheus` | _(none)_ | _(none)_ | +| `cron` | _(none)_ | _(none)_ | +| `redis` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `redis-streams` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | +| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ | +| `liiklus` | _(none)_ | _(none)_ | +| `stan` | _(none)_ | _(none)_ | +| `huawei-cloudeye` | | _(none)_ | _(none)_ | +| `postgresql` | `connection` `password` | `connectionFromEnv` `passwordFromEnv` | +| `mysql` | `connectionString` `password` | `connectionStringFromEnv` `passwordFromEnv` | ### Scalers **Azure Service Bus** - - `queueLength` was renamed to `messageCount` + +- `queueLength` was renamed to `messageCount` **Kafka** - - `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. + +- `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. **RabbitMQ** In KEDA 2.0 the RabbitMQ scaler has only `host` parameter, and the protocol for communication can be specified by -`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP -protocol. +`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP +protocol. Example of RabbitMQ trigger before 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - includeUnacked: 'true' - apiHost: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + includeUnacked: "true" + apiHost: "https://guest:password@localhost:443/vhostname" +``` The same trigger in 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - protocol: 'http' - host: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + protocol: "http" + host: "https://guest:password@localhost:443/vhostname" +``` ### TriggerAuthentication + In order to use Authentication via `TriggerAuthentication` with KEDA v2, you need to change: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` For more details please refer to the full diff --git a/content/docs/2.10/operate/cluster.md b/content/docs/2.10/operate/cluster.md index fe08db931..b705893e8 100644 --- a/content/docs/2.10/operate/cluster.md +++ b/content/docs/2.10/operate/cluster.md @@ -14,12 +14,12 @@ However, maintainers can decide to extend this by supporting more minor versions As a reference, this compatibility matrix shows supported k8s versions per KEDA version: -| KEDA | Kubernetes | -|-----------|---------------| -| v2.10 | v1.24 - v1.26 | -| v2.9 | v1.23 - v1.25 | -| v2.8 | v1.17 - v1.25 | -| v2.7 | v1.17 - v1.25 | +| KEDA | Kubernetes | +| ----- | ------------- | +| v2.10 | v1.24 - v1.26 | +| v2.9 | v1.23 - v1.25 | +| v2.8 | v1.17 - v1.25 | +| v2.7 | v1.17 - v1.25 | ### Cluster Capacity @@ -41,12 +41,10 @@ KEDA requires to be accessible inside the cluster to be able to autoscale. Here is an overview of the required ports that need to be accessible for KEDA to work: - | Port | Why? | Remarks | | ------ | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication.

This is not applicable for Google Cloud. | +| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication. This is not applicable for Google Cloud. | | `6443` | Used by Kubernetes API server to get metrics | Only required for Google Cloud because it uses Control Plane → port 6443 on the Pod IP range for communication | - ## High Availability @@ -54,10 +52,10 @@ KEDA does not provide full support for high-availability due to upstream limitat Here is an overview of all KEDA deployments and the HA notes: -| Deployment | Support Replicas | Note | -| -------------- | ---------------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Deployment | Support Replicas | Note | +| -------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Metrics Server | 1 | You can run multiple replicas of our metrics sever, and it is recommended to add the `--enable-aggregator-routing=true` CLI flag to the kube-apiserver so that requests sent to our metrics servers are load balanced. However, [you can only run one active metric server in a Kubernetes cluster serving external.metrics.k8s.io](https://github.com/kubernetes-sigs/custom-metrics-apiserver/issues/70) which has to be the KEDA metric server. | -| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover. | +| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover. | ## HTTP Timeouts @@ -79,7 +77,7 @@ All applicable scalers will use this timeout. Setting a per-scaler timeout is cu ## HTTP connection disable keep alive -Keep alive behaviour is enabled by default for every HTTP connection, this could stack a huge amount of connections (one per scaler) in some scenarios. +Keep alive behaviour is enabled by default for every HTTP connection, this could stack a huge amount of connections (one per scaler) in some scenarios. You can disable keep alive for every HTTP connection by adding the relevant environment variable to both the KEDA Operator, and KEDA Metrics Server deployments: @@ -108,6 +106,7 @@ Our industry has seen an evolution of TLS versions and some are more secure than By default, KEDA uses TLS1.2 as a minimum TLS version given it is the lowest version without vulnerabilities. However, if you need to support another version you can configure it by using the environment variable `KEDA_HTTP_MIN_TLS_VERSION`. For example: + ```yaml - env: KEDA_HTTP_MIN_TLS_VERSION: TLS13 @@ -119,17 +118,18 @@ The following values are allowed: `TLS13`, `TLS12`, `TLS11` and `TLS10`. The Kubernetes client config used within KEDA Operator and KEDA Metrics Adapter can be adjusted by passing the following command-line flags to the binary: -| Adapter Flag | Client Config Setting | Default Value | Description | -| ------------------- | ----------------------- | ------------- | -------------------------------------------------------------- | -| kube-api-qps | cfg.QPS | 20.0 | Set the QPS rate for throttling requests sent to the apiserver | -| kube-api-burst | cfg.Burst | 30 | Set the burst for throttling requests sent to the apiserver | -| disable-compression | cfg.DisableCompression | true | Disable compression for response in k8s restAPI in client-go, see [this Kubernetes issue](https://github.com/kubernetes/kubernetes/issues/112296) for details | +| Adapter Flag | Client Config Setting | Default Value | Description | +| ------------------- | ---------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| kube-api-qps | cfg.QPS | 20.0 | Set the QPS rate for throttling requests sent to the apiserver | +| kube-api-burst | cfg.Burst | 30 | Set the burst for throttling requests sent to the apiserver | +| disable-compression | cfg.DisableCompression | true | Disable compression for response in k8s restAPI in client-go, see [this Kubernetes issue](https://github.com/kubernetes/kubernetes/issues/112296) for details | ## Configure `MaxConcurrentReconciles` for Controllers To implement internal controllers KEDA uses the [controller-runtime project](https://github.com/kubernetes-sigs/controller-runtime), that enables configuration of [MaxConcurrentReconciles property](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/controller#Options), ie. the maximum number of concurrent reconciles which can be run for a controller. KEDA Operator exposes properties for specifying `MaxConcurrentReconciles` for following controllers/reconcilers: + - `ScaledObjectReconciler` - responsible for watching and managing `ScaledObjects`, ie. validates input trigger specification, starts scaling logic and manages dependent HPA. - `ScaledJobReconciler` - responsible for watching and managing `ScaledJobs` and dependent Kubernetes Jobs @@ -137,15 +137,16 @@ KEDA Metrics Server exposes property for specifying `MaxConcurrentReconciles` fo To modify this properties you can set environment variables on both KEDA Operator and Metrics Server Deployments: -| Environment variable name | Deployment | Default Value | Affected reconciler | -| ------------------------------------- | -------------- | ------------- | -------------------------------------------------------------- | -| KEDA_SCALEDOBJECT_CTRL_MAX_RECONCILES | Operator | 5 | ScaledObjectReconciler | -| KEDA_SCALEDJOB_CTRL_MAX_RECONCILES | Operator | 1 | ScaledJobReconciler | -| KEDA_METRICS_CTRL_MAX_RECONCILES | Metrics Server | 1 | MetricsScaledObjectReconciler | +| Environment variable name | Deployment | Default Value | Affected reconciler | +| ------------------------------------- | -------------- | ------------- | ----------------------------- | +| KEDA_SCALEDOBJECT_CTRL_MAX_RECONCILES | Operator | 5 | ScaledObjectReconciler | +| KEDA_SCALEDJOB_CTRL_MAX_RECONCILES | Operator | 1 | ScaledJobReconciler | +| KEDA_METRICS_CTRL_MAX_RECONCILES | Metrics Server | 1 | MetricsScaledObjectReconciler | ## Configure Leader Election Like reconciliation, KEDA also uses the [controller-runtime project](https://github.com/kubernetes-sigs/controller-runtime) for electing the leader replica. The following properties can be configured for either the Operator and Metrics Server Deployment: + - [`LeaseDuration`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options.LeaseDuration) - [`RenewDeadline`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options.RenewDeadline) - [`RetryPeriod`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options.RetryPeriod) @@ -168,25 +169,29 @@ To learn more please refer to [security section](./security#use-your-own-tls-cer ## Restrict Secret Access By default, KEDA requires adding `secrets` to the cluster role as following: + ```yaml - apiGroups: - - "" + - "" resources: - - external - - pods - - secrets - - services + - external + - pods + - secrets + - services verbs: - - get - - list - - watch + - get + - list + - watch ``` + However, this might lead to security risk (especially in production environment) since it will grant permission to read `secrets` from all namespaces. To restrict `secret` access and limited to KEDA namespace, you could add `KEDA_RESTRICT_SECRET_ACCESS` as environment variable to both KEDA Operator and KEDA Metrics Server: + ```yaml env: - name: KEDA_RESTRICT_SECRET_ACCESS value: "true" ``` + This allows you to omit `secrets` from the cluster role, which will disallow `TriggerAuthentication` to be used for your triggers if the `TriggerAuthentication` is using secrets. You can, however, still use `ClusterTriggerAuthentication`. diff --git a/content/docs/2.11/concepts/external-scalers.md b/content/docs/2.11/concepts/external-scalers.md index 5badde098..aa00a18a0 100644 --- a/content/docs/2.11/concepts/external-scalers.md +++ b/content/docs/2.11/concepts/external-scalers.md @@ -9,7 +9,7 @@ Built-in scalers run in the KEDA process/pod, while external scalers require an This document describes the external scaler interfaces and how to implement them in Go, Node, and .NET; however for more details on GRPC refer to [the official GRPC documentation](https://grpc.io/docs/) ->Want to learn about existing external scalers? Explore our [external scaler community](https://github.com/kedacore/external-scalers). +> Want to learn about existing external scalers? Explore our [external scaler community](https://github.com/kedacore/external-scalers). ## Overview @@ -45,7 +45,7 @@ The `Scaler` interface defines 3 methods: - `GetMetricSpecForScaling` returns the target value for the HPA definition for the scaler. For more details refer to [Implementing `GetMetricSpec`](#5-implementing-getmetricspec). - `GetMetricsAndActivity` is called on `pollingInterval` and. When activity returns `true`, KEDA will scale to what is returned by the metric limited by `maxReplicaCount` on the ScaledObject/ScaledJob. When `false` is returned, KEDA will scale to `minReplicaCount` or optionally `idleReplicaCount`. More details around the defaults and how these options work together can be found on the [ScaledObjectSpec](https://keda.sh/docs/latest/concepts/scaling-deployments/#scaledobject-spec). -> Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA supports both `AverageValue` and `Value` metric target types for external metrics. When `AverageValue` (the default metric type) is used, the metric value returned by the external scaler will be divided by the number of replicas. + > Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA supports both `AverageValue` and `Value` metric target types for external metrics. When `AverageValue` (the default metric type) is used, the metric value returned by the external scaler will be divided by the number of replicas. The `PushScaler` interface adds a `Run` method. This method receives a push channel (`active`), on which the scaler can send `true` at any time. The purpose of this mechanism is to initiate a scaling operation independently from `pollingInterval`. @@ -115,7 +115,7 @@ KEDA will attempt a GRPC connection to `service-address.svc.local:9090` immediat } ``` ->**Note**: KEDA will issue all of the above RPC calls except `StreamIsActive` if `spec.triggers.type` is `external`. It _must_ be `external-push` for `StreamIsActive` to be called. +> **Note**: KEDA will issue all of the above RPC calls except `StreamIsActive` if `spec.triggers.type` is `external`. It _must_ be `external-push` for `StreamIsActive` to be called. ## Implementing KEDA external scaler GRPC interface @@ -182,8 +182,6 @@ npm install --save grpc request {{< /collapsible >}} -
- #### 3. Implementing `IsActive` Just like `IsActive(ctx context.Context) (bool, error)` in the go interface, the `IsActive` method in the GRPC interface is called every `pollingInterval` with a `ScaledObjectRef` object that contains the scaledObject name, namespace, and scaler metadata. @@ -310,70 +308,71 @@ public class ExternalScalerService : ExternalScaler.ExternalScalerBase Put the following code into your `index.js` file: ```js -const grpc = require('grpc') -const request = require('request') -const externalScalerProto = grpc.load('externalscaler.proto') +const grpc = require("grpc"); +const request = require("request"); +const externalScalerProto = grpc.load("externalscaler.proto"); -const server = new grpc.Server() +const server = new grpc.Server(); server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { isActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { - const now = new Date() - const yesterday = new Date(new Date().setDate(new Date().getDate()-1)); - - const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}` - const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}` - const radiusKm = 500 - const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}` - - request.get({ - url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, - json: true, - }, (err, resp, data) => { - if (err) { - callback({ - code: grpc.status.INTERNAL, - details: err, - }) - } else if (resp.statusCode !== 200) { - callback({ - code: grpc.status.INTERNAL, - details: `expected status 200, got ${resp.statusCode}` - }) - } else { - // count how many earthquakes with mag > 1.0 - let count = 0 - data.features.forEach(i => { - if (i.properties.mag > 1.0) { - count++ - } - }) - callback(null, { - result: count > 2, - }) + const now = new Date(); + const yesterday = new Date(new Date().setDate(new Date().getDate() - 1)); + + const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}`; + const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}`; + const radiusKm = 500; + const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}`; + + request.get( + { + url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, + json: true, + }, + (err, resp, data) => { + if (err) { + callback({ + code: grpc.status.INTERNAL, + details: err, + }); + } else if (resp.statusCode !== 200) { + callback({ + code: grpc.status.INTERNAL, + details: `expected status 200, got ${resp.statusCode}`, + }); + } else { + // count how many earthquakes with mag > 1.0 + let count = 0; + data.features.forEach((i) => { + if (i.properties.mag > 1.0) { + count++; + } + }); + callback(null, { + result: count > 2, + }); + } } - }) + ); } - } -}) + }, +}); -server.bind('127.0.0.1:9090', grpc.ServerCredentials.createInsecure()) -console.log('Server listening on 127.0.0.1:9090') +server.bind("127.0.0.1:9090", grpc.ServerCredentials.createInsecure()); +console.log("Server listening on 127.0.0.1:9090"); -server.start() +server.start(); ``` {{< /collapsible >}} -
- #### 4. Implementing `StreamIsActive` Unlike `IsActive`, `StreamIsActive` is called once when KEDA reconciles the `ScaledObject`, and expects the external scaler to maintain a long-lived connection and push `IsActiveResponse` objects whenever the scaler needs KEDA to activate the deployment. @@ -450,38 +449,36 @@ public override async Task StreamIsActive(ScaledObjectRef request, IServerStream server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... streamIsActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { const interval = setInterval(() => { getEarthquakeCount((err, count) => { if (err) { - console.error(err) + console.error(err); } else if (count > 2) { call.write({ result: true, - }) + }); } - }) + }); }, 1000 * 60 * 60); - call.on('end', () => { - clearInterval(interval) - }) + call.on("end", () => { + clearInterval(interval); + }); } - } -}) + }, +}); ``` {{< /collapsible >}} -
- #### 5. Implementing `GetMetricSpec` `GetMetricSpec` returns the `target` value for [the HPA definition for the scaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/). This scaler will define a static target of 10, but the threshold value is often specified in the metadata for other scalers. @@ -527,19 +524,19 @@ server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetricSpec: (call, callback) => { callback(null, { - metricSpecs: [{ - metricName: 'earthquakeThreshold', - targetSize: 10, - }] - }) - } -}) + metricSpecs: [ + { + metricName: "earthquakeThreshold", + targetSize: 10, + }, + ], + }); + }, +}); ``` {{< /collapsible >}} -
- #### 6. Implementing `GetMetrics` `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`, in this example it's `earthquakeThreshold`. @@ -606,32 +603,34 @@ public override async Task GetMetrics(GetMetricsRequest requ server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetrics: (call, callback) => { - const longitude = call.request.scaledObjectRef.scalerMetadata.longitude - const latitude = call.request.scaledObjectRef.scalerMetadata.latitude + const longitude = call.request.scaledObjectRef.scalerMetadata.longitude; + const latitude = call.request.scaledObjectRef.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { getEarthquakeCount((err, count) => { if (err) { callback({ code: grpc.status.INTERNAL, details: err, - }) + }); } else { callback(null, { - metricValues: [{ - metricName: 'earthquakeThreshold', - metricValue: count, - }] - }) + metricValues: [ + { + metricName: "earthquakeThreshold", + metricValue: count, + }, + ], + }); } - }) + }); } - } -}) + }, +}); ``` {{< /collapsible >}} diff --git a/content/docs/2.11/migration.md b/content/docs/2.11/migration.md index 5ee8a6455..29e8408c8 100644 --- a/content/docs/2.11/migration.md +++ b/content/docs/2.11/migration.md @@ -11,15 +11,17 @@ Please note that you **can not** run both KEDA v1 and v2 on the same Kubernetes KEDA v2 is using a new API namespace for its Custom Resources Definitions (CRD): `keda.sh` instead of `keda.k8s.io` and introduces a new Custom Resource for scaling of Jobs. See full details on KEDA Custom Resources [here](../concepts/#custom-resources-crd). Here's an overview of what's changed: + - [Scaling of Deployments](#scaling-of-deployments) - [Scaling of Jobs](#scaling-of-jobs) - [Improved flexibility & usability of trigger metadata](#improved-flexibility--usability-of-trigger-metadata) - [Scalers](#scalers) - [TriggerAuthentication](#triggerauthentication) - ### Scaling of Deployments + In order to scale `Deployments` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Rename property `spec.scaleTargetRef.deploymentName` to `spec.scaleTargetRef.name` - Rename property `spec.scaleTargetRef.containerName` to `spec.scaleTargetRef.envSourceContainerName` @@ -27,22 +29,23 @@ In order to scale `Deployments` with KEDA v2, you need to do only a few modifica Please see the examples below or refer to the full [v2 ScaledObject Specification](../concepts/scaling-deployments/#scaledobject-spec) - **Example of v1 ScaledObject** +**Example of v1 ScaledObject** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } labels: - deploymentName: {deployment-name} + deploymentName: { deployment-name } spec: scaleTargetRef: - deploymentName: {deployment-name} - containerName: {container-name} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + deploymentName: { deployment-name } + containerName: { container-name } + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -50,18 +53,18 @@ spec: **Example of v2 ScaledObject** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed kind: ScaledObject -metadata: # <--- labels.deploymentName is not needed - name: {scaled-object-name} +metadata: # <--- labels.deploymentName is not needed + name: { scaled-object-name } spec: scaleTargetRef: - name: {deployment-name} # <--- Property name was changed - envSourceContainerName: {container-name} # <--- Property name was changed - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + name: { deployment-name } # <--- Property name was changed + envSourceContainerName: { container-name } # <--- Property name was changed + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -69,34 +72,36 @@ spec: ### Scaling of Jobs In order to scale `Jobs` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Change the value of `kind` property from `ScaledObject` to `ScaledJob` - Remove property `spec.scaleType` -- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` +- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` You can configure `successfulJobsHistoryLimit` and `failedJobsHistoryLimit`. They will remove the old job histories automatically. Please see the examples below or refer to the full [v2 ScaledJob Specification](../concepts/scaling-jobs/#scaledjob-spec) **Example of v1 ScaledObject for Jobs scaling** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } spec: scaleType: job jobTargetRef: - parallelism: 1 + parallelism: 1 completions: 1 activeDeadlineSeconds: 600 - backoffLimit: 6 + backoffLimit: 6 template: # {job template} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to create jobs} ``` @@ -104,21 +109,21 @@ spec: **Example of v2 ScaledJob** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed -kind: ScaledJob # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +kind: ScaledJob # <--- Property value was changed metadata: - name: {scaled-job-name} -spec: # <--- spec.scaleType is not needed + name: { scaled-job-name } +spec: # <--- spec.scaleType is not needed jobTargetRef: - parallelism: 1 - completions: 1 + parallelism: 1 + completions: 1 activeDeadlineSeconds: 600 backoffLimit: 6 template: # {job template} - pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed - successfulJobsHistoryLimit: 5 # <--- property is added - failedJobsHistoryLimit: 5 # <--- Property is added + pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed + successfulJobsHistoryLimit: 5 # <--- property is added + failedJobsHistoryLimit: 5 # <--- Property is added maxReplicaCount: 100 triggers: # {list of triggers to create jobs} @@ -132,68 +137,74 @@ We've introduced more options to configure trigger metadata to give users more f Here's an overview: -| Scaler | 1.x | 2.0 | -|--------|--------|--------| -| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | -| `azure-monitor` | `activeDirectoryClientId`
`activeDirectoryClientPassword` | `activeDirectoryClientId`
`activeDirectoryClientIdFromEnv`
`activeDirectoryClientPasswordFromEnv` | -| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | -| `azure-servicebus` | `connection` | `connectionFromEnv` | -| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`)
`connection` (**Default**: `EventHub`) | `storageConnectionFromEnv`
`connectionFromEnv` | -| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `kafka` | _(none)_ | _(none)_ -| `rabbitmq` | `apiHost`
`host` | ~~`apiHost`~~
`host`
`hostFromEnv` | -| `prometheus` | _(none)_ | _(none)_ | -| `cron` | _(none)_ | _(none)_ | -| `redis` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `redis-streams` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | -| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ -| `liiklus` | _(none)_ | _(none)_ | -| `stan` | _(none)_ | _(none)_ | -| `huawei-cloudeye` | | _(none)_ | _(none)_ | -| `postgresql` | `connection`
`password` | `connectionFromEnv`
`passwordFromEnv` | -| `mysql` | `connectionString`
`password` | `connectionStringFromEnv`
`passwordFromEnv` | +| Scaler | 1.x | 2.0 | +| -------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------- | +| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | +| `azure-monitor` | `activeDirectoryClientId` `activeDirectoryClientPassword` | `activeDirectoryClientId` `activeDirectoryClientIdFromEnv` `activeDirectoryClientPasswordFromEnv` | +| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | +| `azure-servicebus` | `connection` | `connectionFromEnv` | +| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`) `connection` (**Default**: `EventHub`) | `storageConnectionFromEnv` `connectionFromEnv` | +| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `kafka` | _(none)_ | _(none)_ | +| `rabbitmq` | `apiHost` `host` | ~~`apiHost`~~ `host` `hostFromEnv` | +| `prometheus` | _(none)_ | _(none)_ | +| `cron` | _(none)_ | _(none)_ | +| `redis` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `redis-streams` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | +| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ | +| `liiklus` | _(none)_ | _(none)_ | +| `stan` | _(none)_ | _(none)_ | +| `huawei-cloudeye` | | _(none)_ | _(none)_ | +| `postgresql` | `connection` `password` | `connectionFromEnv` `passwordFromEnv` | +| `mysql` | `connectionString` `password` | `connectionStringFromEnv` `passwordFromEnv` | ### Scalers **Azure Service Bus** - - `queueLength` was renamed to `messageCount` + +- `queueLength` was renamed to `messageCount` **Kafka** - - `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. + +- `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. **RabbitMQ** In KEDA 2.0 the RabbitMQ scaler has only `host` parameter, and the protocol for communication can be specified by -`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP -protocol. +`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP +protocol. Example of RabbitMQ trigger before 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - includeUnacked: 'true' - apiHost: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + includeUnacked: "true" + apiHost: "https://guest:password@localhost:443/vhostname" +``` The same trigger in 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - protocol: 'http' - host: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + protocol: "http" + host: "https://guest:password@localhost:443/vhostname" +``` ### TriggerAuthentication + In order to use Authentication via `TriggerAuthentication` with KEDA v2, you need to change: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` For more details please refer to the full diff --git a/content/docs/2.11/operate/cluster.md b/content/docs/2.11/operate/cluster.md index 9cdadfe80..ffb15a12a 100644 --- a/content/docs/2.11/operate/cluster.md +++ b/content/docs/2.11/operate/cluster.md @@ -14,13 +14,13 @@ However, maintainers can decide to extend this by supporting more minor versions As a reference, this compatibility matrix shows supported k8s versions per KEDA version: -| KEDA | Kubernetes | -|-----------|---------------| -| v2.11 | v1.25 - v1.27 | -| v2.10 | v1.24 - v1.26 | -| v2.9 | v1.23 - v1.25 | -| v2.8 | v1.17 - v1.25 | -| v2.7 | v1.17 - v1.25 | +| KEDA | Kubernetes | +| ----- | ------------- | +| v2.11 | v1.25 - v1.27 | +| v2.10 | v1.24 - v1.26 | +| v2.9 | v1.23 - v1.25 | +| v2.8 | v1.17 - v1.25 | +| v2.7 | v1.17 - v1.25 | ### Cluster Capacity @@ -42,12 +42,10 @@ KEDA requires to be accessible inside the cluster to be able to autoscale. Here is an overview of the required ports that need to be accessible for KEDA to work: - | Port | Why? | Remarks | | ------ | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication.

This is not applicable for Google Cloud. | +| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication. This is not applicable for Google Cloud. | | `6443` | Used by Kubernetes API server to get metrics | Only required for Google Cloud because it uses Control Plane → port 6443 on the Pod IP range for communication | - ## High Availability @@ -55,10 +53,10 @@ KEDA does not provide full support for high-availability due to upstream limitat Here is an overview of all KEDA deployments and the HA notes: -| Deployment | Support Replicas | Note | -| -------------- | ---------------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Deployment | Support Replicas | Note | +| -------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Metrics Server | 1 | You can run multiple replicas of our metrics sever, and it is recommended to add the `--enable-aggregator-routing=true` CLI flag to the kube-apiserver so that requests sent to our metrics servers are load balanced. However, [you can only run one active metric server in a Kubernetes cluster serving external.metrics.k8s.io](https://github.com/kubernetes-sigs/custom-metrics-apiserver/issues/70) which has to be the KEDA metric server. | -| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover. | +| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover. | ## HTTP Timeouts @@ -80,7 +78,7 @@ All applicable scalers will use this timeout. Setting a per-scaler timeout is cu ## HTTP connection disable keep alive -Keep alive behaviour is enabled by default for every HTTP connection, this could stack a huge amount of connections (one per scaler) in some scenarios. +Keep alive behaviour is enabled by default for every HTTP connection, this could stack a huge amount of connections (one per scaler) in some scenarios. You can disable keep alive for every HTTP connection by adding the relevant environment variable to both the KEDA Operator, and KEDA Metrics Server deployments: @@ -109,6 +107,7 @@ Our industry has seen an evolution of TLS versions and some are more secure than By default, KEDA uses TLS1.2 as a minimum TLS version given it is the lowest version without vulnerabilities. However, if you need to support another version you can configure it by using the environment variable `KEDA_HTTP_MIN_TLS_VERSION`. For example: + ```yaml - env: KEDA_HTTP_MIN_TLS_VERSION: TLS13 @@ -120,17 +119,18 @@ The following values are allowed: `TLS13`, `TLS12`, `TLS11` and `TLS10`. The Kubernetes client config used within KEDA Operator and KEDA Metrics Adapter can be adjusted by passing the following command-line flags to the binary: -| Adapter Flag | Client Config Setting | Default Value | Description | -| ------------------- | ----------------------- | ------------- | -------------------------------------------------------------- | -| kube-api-qps | cfg.QPS | 20.0 | Set the QPS rate for throttling requests sent to the apiserver | -| kube-api-burst | cfg.Burst | 30 | Set the burst for throttling requests sent to the apiserver | -| disable-compression | cfg.DisableCompression | true | Disable compression for response in k8s restAPI in client-go, see [this Kubernetes issue](https://github.com/kubernetes/kubernetes/issues/112296) for details | +| Adapter Flag | Client Config Setting | Default Value | Description | +| ------------------- | ---------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| kube-api-qps | cfg.QPS | 20.0 | Set the QPS rate for throttling requests sent to the apiserver | +| kube-api-burst | cfg.Burst | 30 | Set the burst for throttling requests sent to the apiserver | +| disable-compression | cfg.DisableCompression | true | Disable compression for response in k8s restAPI in client-go, see [this Kubernetes issue](https://github.com/kubernetes/kubernetes/issues/112296) for details | ## Configure `MaxConcurrentReconciles` for Controllers To implement internal controllers KEDA uses the [controller-runtime project](https://github.com/kubernetes-sigs/controller-runtime), that enables configuration of [MaxConcurrentReconciles property](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/controller#Options), ie. the maximum number of concurrent reconciles which can be run for a controller. KEDA Operator exposes properties for specifying `MaxConcurrentReconciles` for following controllers/reconcilers: + - `ScaledObjectReconciler` - responsible for watching and managing `ScaledObjects`, ie. validates input trigger specification, starts scaling logic and manages dependent HPA. - `ScaledJobReconciler` - responsible for watching and managing `ScaledJobs` and dependent Kubernetes Jobs @@ -138,14 +138,15 @@ KEDA Metrics Server exposes property for specifying `MaxConcurrentReconciles` fo To modify this properties you can set environment variables on both KEDA Operator and Metrics Server Deployments: -| Environment variable name | Deployment | Default Value | Affected reconciler | -| ------------------------------------- | -------------- | ------------- | -------------------------------------------------------------- | -| KEDA_SCALEDOBJECT_CTRL_MAX_RECONCILES | Operator | 5 | ScaledObjectReconciler | -| KEDA_SCALEDJOB_CTRL_MAX_RECONCILES | Operator | 1 | ScaledJobReconciler | +| Environment variable name | Deployment | Default Value | Affected reconciler | +| ------------------------------------- | ---------- | ------------- | ---------------------- | +| KEDA_SCALEDOBJECT_CTRL_MAX_RECONCILES | Operator | 5 | ScaledObjectReconciler | +| KEDA_SCALEDJOB_CTRL_MAX_RECONCILES | Operator | 1 | ScaledJobReconciler | ## Configure Leader Election Like reconciliation, KEDA also uses the [controller-runtime project](https://github.com/kubernetes-sigs/controller-runtime) for electing the leader replica. The following properties can be configured for either the Operator and Metrics Server Deployment: + - [`LeaseDuration`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options.LeaseDuration) - [`RenewDeadline`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options.RenewDeadline) - [`RetryPeriod`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options.RetryPeriod) @@ -168,25 +169,29 @@ To learn more please refer to [security section](./security#use-your-own-tls-cer ## Restrict Secret Access By default, KEDA requires adding `secrets` to the cluster role as following: + ```yaml - apiGroups: - - "" + - "" resources: - - external - - pods - - secrets - - services + - external + - pods + - secrets + - services verbs: - - get - - list - - watch + - get + - list + - watch ``` + However, this might lead to security risk (especially in production environment) since it will grant permission to read `secrets` from all namespaces. To restrict `secret` access and limited to KEDA namespace, you could add `KEDA_RESTRICT_SECRET_ACCESS` as environment variable to both KEDA Operator and KEDA Metrics Server: + ```yaml env: - name: KEDA_RESTRICT_SECRET_ACCESS value: "true" ``` + This allows you to omit `secrets` from the cluster role, which will disallow `TriggerAuthentication` to be used for your triggers if the `TriggerAuthentication` is using secrets. You can, however, still use `ClusterTriggerAuthentication`. diff --git a/content/docs/2.12/concepts/external-scalers.md b/content/docs/2.12/concepts/external-scalers.md index 5badde098..aa00a18a0 100644 --- a/content/docs/2.12/concepts/external-scalers.md +++ b/content/docs/2.12/concepts/external-scalers.md @@ -9,7 +9,7 @@ Built-in scalers run in the KEDA process/pod, while external scalers require an This document describes the external scaler interfaces and how to implement them in Go, Node, and .NET; however for more details on GRPC refer to [the official GRPC documentation](https://grpc.io/docs/) ->Want to learn about existing external scalers? Explore our [external scaler community](https://github.com/kedacore/external-scalers). +> Want to learn about existing external scalers? Explore our [external scaler community](https://github.com/kedacore/external-scalers). ## Overview @@ -45,7 +45,7 @@ The `Scaler` interface defines 3 methods: - `GetMetricSpecForScaling` returns the target value for the HPA definition for the scaler. For more details refer to [Implementing `GetMetricSpec`](#5-implementing-getmetricspec). - `GetMetricsAndActivity` is called on `pollingInterval` and. When activity returns `true`, KEDA will scale to what is returned by the metric limited by `maxReplicaCount` on the ScaledObject/ScaledJob. When `false` is returned, KEDA will scale to `minReplicaCount` or optionally `idleReplicaCount`. More details around the defaults and how these options work together can be found on the [ScaledObjectSpec](https://keda.sh/docs/latest/concepts/scaling-deployments/#scaledobject-spec). -> Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA supports both `AverageValue` and `Value` metric target types for external metrics. When `AverageValue` (the default metric type) is used, the metric value returned by the external scaler will be divided by the number of replicas. + > Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA supports both `AverageValue` and `Value` metric target types for external metrics. When `AverageValue` (the default metric type) is used, the metric value returned by the external scaler will be divided by the number of replicas. The `PushScaler` interface adds a `Run` method. This method receives a push channel (`active`), on which the scaler can send `true` at any time. The purpose of this mechanism is to initiate a scaling operation independently from `pollingInterval`. @@ -115,7 +115,7 @@ KEDA will attempt a GRPC connection to `service-address.svc.local:9090` immediat } ``` ->**Note**: KEDA will issue all of the above RPC calls except `StreamIsActive` if `spec.triggers.type` is `external`. It _must_ be `external-push` for `StreamIsActive` to be called. +> **Note**: KEDA will issue all of the above RPC calls except `StreamIsActive` if `spec.triggers.type` is `external`. It _must_ be `external-push` for `StreamIsActive` to be called. ## Implementing KEDA external scaler GRPC interface @@ -182,8 +182,6 @@ npm install --save grpc request {{< /collapsible >}} -
- #### 3. Implementing `IsActive` Just like `IsActive(ctx context.Context) (bool, error)` in the go interface, the `IsActive` method in the GRPC interface is called every `pollingInterval` with a `ScaledObjectRef` object that contains the scaledObject name, namespace, and scaler metadata. @@ -310,70 +308,71 @@ public class ExternalScalerService : ExternalScaler.ExternalScalerBase Put the following code into your `index.js` file: ```js -const grpc = require('grpc') -const request = require('request') -const externalScalerProto = grpc.load('externalscaler.proto') +const grpc = require("grpc"); +const request = require("request"); +const externalScalerProto = grpc.load("externalscaler.proto"); -const server = new grpc.Server() +const server = new grpc.Server(); server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { isActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { - const now = new Date() - const yesterday = new Date(new Date().setDate(new Date().getDate()-1)); - - const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}` - const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}` - const radiusKm = 500 - const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}` - - request.get({ - url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, - json: true, - }, (err, resp, data) => { - if (err) { - callback({ - code: grpc.status.INTERNAL, - details: err, - }) - } else if (resp.statusCode !== 200) { - callback({ - code: grpc.status.INTERNAL, - details: `expected status 200, got ${resp.statusCode}` - }) - } else { - // count how many earthquakes with mag > 1.0 - let count = 0 - data.features.forEach(i => { - if (i.properties.mag > 1.0) { - count++ - } - }) - callback(null, { - result: count > 2, - }) + const now = new Date(); + const yesterday = new Date(new Date().setDate(new Date().getDate() - 1)); + + const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}`; + const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}`; + const radiusKm = 500; + const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}`; + + request.get( + { + url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, + json: true, + }, + (err, resp, data) => { + if (err) { + callback({ + code: grpc.status.INTERNAL, + details: err, + }); + } else if (resp.statusCode !== 200) { + callback({ + code: grpc.status.INTERNAL, + details: `expected status 200, got ${resp.statusCode}`, + }); + } else { + // count how many earthquakes with mag > 1.0 + let count = 0; + data.features.forEach((i) => { + if (i.properties.mag > 1.0) { + count++; + } + }); + callback(null, { + result: count > 2, + }); + } } - }) + ); } - } -}) + }, +}); -server.bind('127.0.0.1:9090', grpc.ServerCredentials.createInsecure()) -console.log('Server listening on 127.0.0.1:9090') +server.bind("127.0.0.1:9090", grpc.ServerCredentials.createInsecure()); +console.log("Server listening on 127.0.0.1:9090"); -server.start() +server.start(); ``` {{< /collapsible >}} -
- #### 4. Implementing `StreamIsActive` Unlike `IsActive`, `StreamIsActive` is called once when KEDA reconciles the `ScaledObject`, and expects the external scaler to maintain a long-lived connection and push `IsActiveResponse` objects whenever the scaler needs KEDA to activate the deployment. @@ -450,38 +449,36 @@ public override async Task StreamIsActive(ScaledObjectRef request, IServerStream server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... streamIsActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { const interval = setInterval(() => { getEarthquakeCount((err, count) => { if (err) { - console.error(err) + console.error(err); } else if (count > 2) { call.write({ result: true, - }) + }); } - }) + }); }, 1000 * 60 * 60); - call.on('end', () => { - clearInterval(interval) - }) + call.on("end", () => { + clearInterval(interval); + }); } - } -}) + }, +}); ``` {{< /collapsible >}} -
- #### 5. Implementing `GetMetricSpec` `GetMetricSpec` returns the `target` value for [the HPA definition for the scaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/). This scaler will define a static target of 10, but the threshold value is often specified in the metadata for other scalers. @@ -527,19 +524,19 @@ server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetricSpec: (call, callback) => { callback(null, { - metricSpecs: [{ - metricName: 'earthquakeThreshold', - targetSize: 10, - }] - }) - } -}) + metricSpecs: [ + { + metricName: "earthquakeThreshold", + targetSize: 10, + }, + ], + }); + }, +}); ``` {{< /collapsible >}} -
- #### 6. Implementing `GetMetrics` `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`, in this example it's `earthquakeThreshold`. @@ -606,32 +603,34 @@ public override async Task GetMetrics(GetMetricsRequest requ server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetrics: (call, callback) => { - const longitude = call.request.scaledObjectRef.scalerMetadata.longitude - const latitude = call.request.scaledObjectRef.scalerMetadata.latitude + const longitude = call.request.scaledObjectRef.scalerMetadata.longitude; + const latitude = call.request.scaledObjectRef.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { getEarthquakeCount((err, count) => { if (err) { callback({ code: grpc.status.INTERNAL, details: err, - }) + }); } else { callback(null, { - metricValues: [{ - metricName: 'earthquakeThreshold', - metricValue: count, - }] - }) + metricValues: [ + { + metricName: "earthquakeThreshold", + metricValue: count, + }, + ], + }); } - }) + }); } - } -}) + }, +}); ``` {{< /collapsible >}} diff --git a/content/docs/2.12/migration.md b/content/docs/2.12/migration.md index 5ee8a6455..29e8408c8 100644 --- a/content/docs/2.12/migration.md +++ b/content/docs/2.12/migration.md @@ -11,15 +11,17 @@ Please note that you **can not** run both KEDA v1 and v2 on the same Kubernetes KEDA v2 is using a new API namespace for its Custom Resources Definitions (CRD): `keda.sh` instead of `keda.k8s.io` and introduces a new Custom Resource for scaling of Jobs. See full details on KEDA Custom Resources [here](../concepts/#custom-resources-crd). Here's an overview of what's changed: + - [Scaling of Deployments](#scaling-of-deployments) - [Scaling of Jobs](#scaling-of-jobs) - [Improved flexibility & usability of trigger metadata](#improved-flexibility--usability-of-trigger-metadata) - [Scalers](#scalers) - [TriggerAuthentication](#triggerauthentication) - ### Scaling of Deployments + In order to scale `Deployments` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Rename property `spec.scaleTargetRef.deploymentName` to `spec.scaleTargetRef.name` - Rename property `spec.scaleTargetRef.containerName` to `spec.scaleTargetRef.envSourceContainerName` @@ -27,22 +29,23 @@ In order to scale `Deployments` with KEDA v2, you need to do only a few modifica Please see the examples below or refer to the full [v2 ScaledObject Specification](../concepts/scaling-deployments/#scaledobject-spec) - **Example of v1 ScaledObject** +**Example of v1 ScaledObject** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } labels: - deploymentName: {deployment-name} + deploymentName: { deployment-name } spec: scaleTargetRef: - deploymentName: {deployment-name} - containerName: {container-name} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + deploymentName: { deployment-name } + containerName: { container-name } + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -50,18 +53,18 @@ spec: **Example of v2 ScaledObject** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed kind: ScaledObject -metadata: # <--- labels.deploymentName is not needed - name: {scaled-object-name} +metadata: # <--- labels.deploymentName is not needed + name: { scaled-object-name } spec: scaleTargetRef: - name: {deployment-name} # <--- Property name was changed - envSourceContainerName: {container-name} # <--- Property name was changed - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + name: { deployment-name } # <--- Property name was changed + envSourceContainerName: { container-name } # <--- Property name was changed + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -69,34 +72,36 @@ spec: ### Scaling of Jobs In order to scale `Jobs` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Change the value of `kind` property from `ScaledObject` to `ScaledJob` - Remove property `spec.scaleType` -- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` +- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` You can configure `successfulJobsHistoryLimit` and `failedJobsHistoryLimit`. They will remove the old job histories automatically. Please see the examples below or refer to the full [v2 ScaledJob Specification](../concepts/scaling-jobs/#scaledjob-spec) **Example of v1 ScaledObject for Jobs scaling** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } spec: scaleType: job jobTargetRef: - parallelism: 1 + parallelism: 1 completions: 1 activeDeadlineSeconds: 600 - backoffLimit: 6 + backoffLimit: 6 template: # {job template} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to create jobs} ``` @@ -104,21 +109,21 @@ spec: **Example of v2 ScaledJob** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed -kind: ScaledJob # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +kind: ScaledJob # <--- Property value was changed metadata: - name: {scaled-job-name} -spec: # <--- spec.scaleType is not needed + name: { scaled-job-name } +spec: # <--- spec.scaleType is not needed jobTargetRef: - parallelism: 1 - completions: 1 + parallelism: 1 + completions: 1 activeDeadlineSeconds: 600 backoffLimit: 6 template: # {job template} - pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed - successfulJobsHistoryLimit: 5 # <--- property is added - failedJobsHistoryLimit: 5 # <--- Property is added + pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed + successfulJobsHistoryLimit: 5 # <--- property is added + failedJobsHistoryLimit: 5 # <--- Property is added maxReplicaCount: 100 triggers: # {list of triggers to create jobs} @@ -132,68 +137,74 @@ We've introduced more options to configure trigger metadata to give users more f Here's an overview: -| Scaler | 1.x | 2.0 | -|--------|--------|--------| -| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | -| `azure-monitor` | `activeDirectoryClientId`
`activeDirectoryClientPassword` | `activeDirectoryClientId`
`activeDirectoryClientIdFromEnv`
`activeDirectoryClientPasswordFromEnv` | -| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | -| `azure-servicebus` | `connection` | `connectionFromEnv` | -| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`)
`connection` (**Default**: `EventHub`) | `storageConnectionFromEnv`
`connectionFromEnv` | -| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `kafka` | _(none)_ | _(none)_ -| `rabbitmq` | `apiHost`
`host` | ~~`apiHost`~~
`host`
`hostFromEnv` | -| `prometheus` | _(none)_ | _(none)_ | -| `cron` | _(none)_ | _(none)_ | -| `redis` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `redis-streams` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | -| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ -| `liiklus` | _(none)_ | _(none)_ | -| `stan` | _(none)_ | _(none)_ | -| `huawei-cloudeye` | | _(none)_ | _(none)_ | -| `postgresql` | `connection`
`password` | `connectionFromEnv`
`passwordFromEnv` | -| `mysql` | `connectionString`
`password` | `connectionStringFromEnv`
`passwordFromEnv` | +| Scaler | 1.x | 2.0 | +| -------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------- | +| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | +| `azure-monitor` | `activeDirectoryClientId` `activeDirectoryClientPassword` | `activeDirectoryClientId` `activeDirectoryClientIdFromEnv` `activeDirectoryClientPasswordFromEnv` | +| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | +| `azure-servicebus` | `connection` | `connectionFromEnv` | +| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`) `connection` (**Default**: `EventHub`) | `storageConnectionFromEnv` `connectionFromEnv` | +| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `kafka` | _(none)_ | _(none)_ | +| `rabbitmq` | `apiHost` `host` | ~~`apiHost`~~ `host` `hostFromEnv` | +| `prometheus` | _(none)_ | _(none)_ | +| `cron` | _(none)_ | _(none)_ | +| `redis` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `redis-streams` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | +| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ | +| `liiklus` | _(none)_ | _(none)_ | +| `stan` | _(none)_ | _(none)_ | +| `huawei-cloudeye` | | _(none)_ | _(none)_ | +| `postgresql` | `connection` `password` | `connectionFromEnv` `passwordFromEnv` | +| `mysql` | `connectionString` `password` | `connectionStringFromEnv` `passwordFromEnv` | ### Scalers **Azure Service Bus** - - `queueLength` was renamed to `messageCount` + +- `queueLength` was renamed to `messageCount` **Kafka** - - `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. + +- `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. **RabbitMQ** In KEDA 2.0 the RabbitMQ scaler has only `host` parameter, and the protocol for communication can be specified by -`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP -protocol. +`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP +protocol. Example of RabbitMQ trigger before 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - includeUnacked: 'true' - apiHost: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + includeUnacked: "true" + apiHost: "https://guest:password@localhost:443/vhostname" +``` The same trigger in 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - protocol: 'http' - host: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + protocol: "http" + host: "https://guest:password@localhost:443/vhostname" +``` ### TriggerAuthentication + In order to use Authentication via `TriggerAuthentication` with KEDA v2, you need to change: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` For more details please refer to the full diff --git a/content/docs/2.12/operate/cluster.md b/content/docs/2.12/operate/cluster.md index e60759578..4f200e90a 100644 --- a/content/docs/2.12/operate/cluster.md +++ b/content/docs/2.12/operate/cluster.md @@ -14,14 +14,14 @@ However, maintainers can decide to extend this by supporting more minor versions As a reference, this compatibility matrix shows supported k8s versions per KEDA version: -| KEDA | Kubernetes | -|-----------|---------------| -| v2.12 | v1.26 - v1.28 | -| v2.11 | v1.25 - v1.27 | -| v2.10 | v1.24 - v1.26 | -| v2.9 | v1.23 - v1.25 | -| v2.8 | v1.17 - v1.25 | -| v2.7 | v1.17 - v1.25 | +| KEDA | Kubernetes | +| ----- | ------------- | +| v2.12 | v1.26 - v1.28 | +| v2.11 | v1.25 - v1.27 | +| v2.10 | v1.24 - v1.26 | +| v2.9 | v1.23 - v1.25 | +| v2.8 | v1.17 - v1.25 | +| v2.7 | v1.17 - v1.25 | ### Cluster Capacity @@ -43,12 +43,10 @@ KEDA requires to be accessible inside the cluster to be able to autoscale. Here is an overview of the required ports that need to be accessible for KEDA to work: - | Port | Why? | Remarks | | ------ | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication.

This is not applicable for Google Cloud. | +| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication. This is not applicable for Google Cloud. | | `6443` | Used by Kubernetes API server to get metrics | Only required for Google Cloud because it uses Control Plane → port 6443 on the Pod IP range for communication | - ## High Availability @@ -56,10 +54,10 @@ KEDA does not provide full support for high-availability due to upstream limitat Here is an overview of all KEDA deployments and the HA notes: -| Deployment | Support Replicas | Note | -| -------------- | ---------------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Deployment | Support Replicas | Note | +| -------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Metrics Server | 1 | You can run multiple replicas of our metrics sever, and it is recommended to add the `--enable-aggregator-routing=true` CLI flag to the kube-apiserver so that requests sent to our metrics servers are load balanced. However, [you can only run one active metric server in a Kubernetes cluster serving external.metrics.k8s.io](https://github.com/kubernetes-sigs/custom-metrics-apiserver/issues/70) which has to be the KEDA metric server. | -| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover. | +| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover. | ## HTTP Timeouts @@ -81,7 +79,7 @@ All applicable scalers will use this timeout. Setting a per-scaler timeout is cu ## HTTP connection disable keep alive -Keep alive behaviour is enabled by default for every HTTP connection, this could stack a huge amount of connections (one per scaler) in some scenarios. +Keep alive behaviour is enabled by default for every HTTP connection, this could stack a huge amount of connections (one per scaler) in some scenarios. You can disable keep alive for every HTTP connection by adding the relevant environment variable to both the KEDA Operator, and KEDA Metrics Server deployments: @@ -110,6 +108,7 @@ Our industry has seen an evolution of TLS versions and some are more secure than By default, KEDA uses TLS1.2 as a minimum TLS version given it is the lowest version without vulnerabilities. However, if you need to support another version you can configure it by using the environment variable `KEDA_HTTP_MIN_TLS_VERSION`. For example: + ```yaml - env: KEDA_HTTP_MIN_TLS_VERSION: TLS13 @@ -121,17 +120,18 @@ The following values are allowed: `TLS13`, `TLS12`, `TLS11` and `TLS10`. The Kubernetes client config used within KEDA Operator and KEDA Metrics Adapter can be adjusted by passing the following command-line flags to the binary: -| Adapter Flag | Client Config Setting | Default Value | Description | -| ------------------- | ----------------------- | ------------- | -------------------------------------------------------------- | -| kube-api-qps | cfg.QPS | 20.0 | Set the QPS rate for throttling requests sent to the apiserver | -| kube-api-burst | cfg.Burst | 30 | Set the burst for throttling requests sent to the apiserver | -| disable-compression | cfg.DisableCompression | true | Disable compression for response in k8s restAPI in client-go, see [this Kubernetes issue](https://github.com/kubernetes/kubernetes/issues/112296) for details | +| Adapter Flag | Client Config Setting | Default Value | Description | +| ------------------- | ---------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| kube-api-qps | cfg.QPS | 20.0 | Set the QPS rate for throttling requests sent to the apiserver | +| kube-api-burst | cfg.Burst | 30 | Set the burst for throttling requests sent to the apiserver | +| disable-compression | cfg.DisableCompression | true | Disable compression for response in k8s restAPI in client-go, see [this Kubernetes issue](https://github.com/kubernetes/kubernetes/issues/112296) for details | ## Configure `MaxConcurrentReconciles` for Controllers To implement internal controllers KEDA uses the [controller-runtime project](https://github.com/kubernetes-sigs/controller-runtime), that enables configuration of [MaxConcurrentReconciles property](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/controller#Options), ie. the maximum number of concurrent reconciles which can be run for a controller. KEDA Operator exposes properties for specifying `MaxConcurrentReconciles` for following controllers/reconcilers: + - `ScaledObjectReconciler` - responsible for watching and managing `ScaledObjects`, ie. validates input trigger specification, starts scaling logic and manages dependent HPA. - `ScaledJobReconciler` - responsible for watching and managing `ScaledJobs` and dependent Kubernetes Jobs @@ -139,14 +139,15 @@ KEDA Metrics Server exposes property for specifying `MaxConcurrentReconciles` fo To modify this properties you can set environment variables on both KEDA Operator and Metrics Server Deployments: -| Environment variable name | Deployment | Default Value | Affected reconciler | -| ------------------------------------- | -------------- | ------------- | -------------------------------------------------------------- | -| KEDA_SCALEDOBJECT_CTRL_MAX_RECONCILES | Operator | 5 | ScaledObjectReconciler | -| KEDA_SCALEDJOB_CTRL_MAX_RECONCILES | Operator | 1 | ScaledJobReconciler | +| Environment variable name | Deployment | Default Value | Affected reconciler | +| ------------------------------------- | ---------- | ------------- | ---------------------- | +| KEDA_SCALEDOBJECT_CTRL_MAX_RECONCILES | Operator | 5 | ScaledObjectReconciler | +| KEDA_SCALEDJOB_CTRL_MAX_RECONCILES | Operator | 1 | ScaledJobReconciler | ## Configure Leader Election Like reconciliation, KEDA also uses the [controller-runtime project](https://github.com/kubernetes-sigs/controller-runtime) for electing the leader replica. The following properties can be configured for either the Operator and Metrics Server Deployment: + - [`LeaseDuration`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options.LeaseDuration) - [`RenewDeadline`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options.RenewDeadline) - [`RetryPeriod`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options.RetryPeriod) @@ -169,25 +170,29 @@ To learn more please refer to [security section](./security#use-your-own-tls-cer ## Restrict Secret Access By default, KEDA requires adding `secrets` to the cluster role as following: + ```yaml - apiGroups: - - "" + - "" resources: - - external - - pods - - secrets - - services + - external + - pods + - secrets + - services verbs: - - get - - list - - watch + - get + - list + - watch ``` + However, this might lead to security risk (especially in production environment) since it will grant permission to read `secrets` from all namespaces. To restrict `secret` access and limited to KEDA namespace, you could add `KEDA_RESTRICT_SECRET_ACCESS` as environment variable to both KEDA Operator and KEDA Metrics Server: + ```yaml env: - name: KEDA_RESTRICT_SECRET_ACCESS value: "true" ``` + This allows you to omit `secrets` from the cluster role, which will disallow `TriggerAuthentication` to be used for your triggers if the `TriggerAuthentication` is using secrets. You can, however, still use `ClusterTriggerAuthentication`. diff --git a/content/docs/2.13/concepts/external-scalers.md b/content/docs/2.13/concepts/external-scalers.md index 5badde098..aa00a18a0 100644 --- a/content/docs/2.13/concepts/external-scalers.md +++ b/content/docs/2.13/concepts/external-scalers.md @@ -9,7 +9,7 @@ Built-in scalers run in the KEDA process/pod, while external scalers require an This document describes the external scaler interfaces and how to implement them in Go, Node, and .NET; however for more details on GRPC refer to [the official GRPC documentation](https://grpc.io/docs/) ->Want to learn about existing external scalers? Explore our [external scaler community](https://github.com/kedacore/external-scalers). +> Want to learn about existing external scalers? Explore our [external scaler community](https://github.com/kedacore/external-scalers). ## Overview @@ -45,7 +45,7 @@ The `Scaler` interface defines 3 methods: - `GetMetricSpecForScaling` returns the target value for the HPA definition for the scaler. For more details refer to [Implementing `GetMetricSpec`](#5-implementing-getmetricspec). - `GetMetricsAndActivity` is called on `pollingInterval` and. When activity returns `true`, KEDA will scale to what is returned by the metric limited by `maxReplicaCount` on the ScaledObject/ScaledJob. When `false` is returned, KEDA will scale to `minReplicaCount` or optionally `idleReplicaCount`. More details around the defaults and how these options work together can be found on the [ScaledObjectSpec](https://keda.sh/docs/latest/concepts/scaling-deployments/#scaledobject-spec). -> Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA supports both `AverageValue` and `Value` metric target types for external metrics. When `AverageValue` (the default metric type) is used, the metric value returned by the external scaler will be divided by the number of replicas. + > Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA supports both `AverageValue` and `Value` metric target types for external metrics. When `AverageValue` (the default metric type) is used, the metric value returned by the external scaler will be divided by the number of replicas. The `PushScaler` interface adds a `Run` method. This method receives a push channel (`active`), on which the scaler can send `true` at any time. The purpose of this mechanism is to initiate a scaling operation independently from `pollingInterval`. @@ -115,7 +115,7 @@ KEDA will attempt a GRPC connection to `service-address.svc.local:9090` immediat } ``` ->**Note**: KEDA will issue all of the above RPC calls except `StreamIsActive` if `spec.triggers.type` is `external`. It _must_ be `external-push` for `StreamIsActive` to be called. +> **Note**: KEDA will issue all of the above RPC calls except `StreamIsActive` if `spec.triggers.type` is `external`. It _must_ be `external-push` for `StreamIsActive` to be called. ## Implementing KEDA external scaler GRPC interface @@ -182,8 +182,6 @@ npm install --save grpc request {{< /collapsible >}} -
- #### 3. Implementing `IsActive` Just like `IsActive(ctx context.Context) (bool, error)` in the go interface, the `IsActive` method in the GRPC interface is called every `pollingInterval` with a `ScaledObjectRef` object that contains the scaledObject name, namespace, and scaler metadata. @@ -310,70 +308,71 @@ public class ExternalScalerService : ExternalScaler.ExternalScalerBase Put the following code into your `index.js` file: ```js -const grpc = require('grpc') -const request = require('request') -const externalScalerProto = grpc.load('externalscaler.proto') +const grpc = require("grpc"); +const request = require("request"); +const externalScalerProto = grpc.load("externalscaler.proto"); -const server = new grpc.Server() +const server = new grpc.Server(); server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { isActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { - const now = new Date() - const yesterday = new Date(new Date().setDate(new Date().getDate()-1)); - - const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}` - const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}` - const radiusKm = 500 - const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}` - - request.get({ - url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, - json: true, - }, (err, resp, data) => { - if (err) { - callback({ - code: grpc.status.INTERNAL, - details: err, - }) - } else if (resp.statusCode !== 200) { - callback({ - code: grpc.status.INTERNAL, - details: `expected status 200, got ${resp.statusCode}` - }) - } else { - // count how many earthquakes with mag > 1.0 - let count = 0 - data.features.forEach(i => { - if (i.properties.mag > 1.0) { - count++ - } - }) - callback(null, { - result: count > 2, - }) + const now = new Date(); + const yesterday = new Date(new Date().setDate(new Date().getDate() - 1)); + + const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}`; + const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}`; + const radiusKm = 500; + const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}`; + + request.get( + { + url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, + json: true, + }, + (err, resp, data) => { + if (err) { + callback({ + code: grpc.status.INTERNAL, + details: err, + }); + } else if (resp.statusCode !== 200) { + callback({ + code: grpc.status.INTERNAL, + details: `expected status 200, got ${resp.statusCode}`, + }); + } else { + // count how many earthquakes with mag > 1.0 + let count = 0; + data.features.forEach((i) => { + if (i.properties.mag > 1.0) { + count++; + } + }); + callback(null, { + result: count > 2, + }); + } } - }) + ); } - } -}) + }, +}); -server.bind('127.0.0.1:9090', grpc.ServerCredentials.createInsecure()) -console.log('Server listening on 127.0.0.1:9090') +server.bind("127.0.0.1:9090", grpc.ServerCredentials.createInsecure()); +console.log("Server listening on 127.0.0.1:9090"); -server.start() +server.start(); ``` {{< /collapsible >}} -
- #### 4. Implementing `StreamIsActive` Unlike `IsActive`, `StreamIsActive` is called once when KEDA reconciles the `ScaledObject`, and expects the external scaler to maintain a long-lived connection and push `IsActiveResponse` objects whenever the scaler needs KEDA to activate the deployment. @@ -450,38 +449,36 @@ public override async Task StreamIsActive(ScaledObjectRef request, IServerStream server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... streamIsActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { const interval = setInterval(() => { getEarthquakeCount((err, count) => { if (err) { - console.error(err) + console.error(err); } else if (count > 2) { call.write({ result: true, - }) + }); } - }) + }); }, 1000 * 60 * 60); - call.on('end', () => { - clearInterval(interval) - }) + call.on("end", () => { + clearInterval(interval); + }); } - } -}) + }, +}); ``` {{< /collapsible >}} -
- #### 5. Implementing `GetMetricSpec` `GetMetricSpec` returns the `target` value for [the HPA definition for the scaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/). This scaler will define a static target of 10, but the threshold value is often specified in the metadata for other scalers. @@ -527,19 +524,19 @@ server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetricSpec: (call, callback) => { callback(null, { - metricSpecs: [{ - metricName: 'earthquakeThreshold', - targetSize: 10, - }] - }) - } -}) + metricSpecs: [ + { + metricName: "earthquakeThreshold", + targetSize: 10, + }, + ], + }); + }, +}); ``` {{< /collapsible >}} -
- #### 6. Implementing `GetMetrics` `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`, in this example it's `earthquakeThreshold`. @@ -606,32 +603,34 @@ public override async Task GetMetrics(GetMetricsRequest requ server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetrics: (call, callback) => { - const longitude = call.request.scaledObjectRef.scalerMetadata.longitude - const latitude = call.request.scaledObjectRef.scalerMetadata.latitude + const longitude = call.request.scaledObjectRef.scalerMetadata.longitude; + const latitude = call.request.scaledObjectRef.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { getEarthquakeCount((err, count) => { if (err) { callback({ code: grpc.status.INTERNAL, details: err, - }) + }); } else { callback(null, { - metricValues: [{ - metricName: 'earthquakeThreshold', - metricValue: count, - }] - }) + metricValues: [ + { + metricName: "earthquakeThreshold", + metricValue: count, + }, + ], + }); } - }) + }); } - } -}) + }, +}); ``` {{< /collapsible >}} diff --git a/content/docs/2.13/migration.md b/content/docs/2.13/migration.md index 5ee8a6455..29e8408c8 100644 --- a/content/docs/2.13/migration.md +++ b/content/docs/2.13/migration.md @@ -11,15 +11,17 @@ Please note that you **can not** run both KEDA v1 and v2 on the same Kubernetes KEDA v2 is using a new API namespace for its Custom Resources Definitions (CRD): `keda.sh` instead of `keda.k8s.io` and introduces a new Custom Resource for scaling of Jobs. See full details on KEDA Custom Resources [here](../concepts/#custom-resources-crd). Here's an overview of what's changed: + - [Scaling of Deployments](#scaling-of-deployments) - [Scaling of Jobs](#scaling-of-jobs) - [Improved flexibility & usability of trigger metadata](#improved-flexibility--usability-of-trigger-metadata) - [Scalers](#scalers) - [TriggerAuthentication](#triggerauthentication) - ### Scaling of Deployments + In order to scale `Deployments` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Rename property `spec.scaleTargetRef.deploymentName` to `spec.scaleTargetRef.name` - Rename property `spec.scaleTargetRef.containerName` to `spec.scaleTargetRef.envSourceContainerName` @@ -27,22 +29,23 @@ In order to scale `Deployments` with KEDA v2, you need to do only a few modifica Please see the examples below or refer to the full [v2 ScaledObject Specification](../concepts/scaling-deployments/#scaledobject-spec) - **Example of v1 ScaledObject** +**Example of v1 ScaledObject** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } labels: - deploymentName: {deployment-name} + deploymentName: { deployment-name } spec: scaleTargetRef: - deploymentName: {deployment-name} - containerName: {container-name} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + deploymentName: { deployment-name } + containerName: { container-name } + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -50,18 +53,18 @@ spec: **Example of v2 ScaledObject** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed kind: ScaledObject -metadata: # <--- labels.deploymentName is not needed - name: {scaled-object-name} +metadata: # <--- labels.deploymentName is not needed + name: { scaled-object-name } spec: scaleTargetRef: - name: {deployment-name} # <--- Property name was changed - envSourceContainerName: {container-name} # <--- Property name was changed - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + name: { deployment-name } # <--- Property name was changed + envSourceContainerName: { container-name } # <--- Property name was changed + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -69,34 +72,36 @@ spec: ### Scaling of Jobs In order to scale `Jobs` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Change the value of `kind` property from `ScaledObject` to `ScaledJob` - Remove property `spec.scaleType` -- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` +- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` You can configure `successfulJobsHistoryLimit` and `failedJobsHistoryLimit`. They will remove the old job histories automatically. Please see the examples below or refer to the full [v2 ScaledJob Specification](../concepts/scaling-jobs/#scaledjob-spec) **Example of v1 ScaledObject for Jobs scaling** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } spec: scaleType: job jobTargetRef: - parallelism: 1 + parallelism: 1 completions: 1 activeDeadlineSeconds: 600 - backoffLimit: 6 + backoffLimit: 6 template: # {job template} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to create jobs} ``` @@ -104,21 +109,21 @@ spec: **Example of v2 ScaledJob** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed -kind: ScaledJob # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +kind: ScaledJob # <--- Property value was changed metadata: - name: {scaled-job-name} -spec: # <--- spec.scaleType is not needed + name: { scaled-job-name } +spec: # <--- spec.scaleType is not needed jobTargetRef: - parallelism: 1 - completions: 1 + parallelism: 1 + completions: 1 activeDeadlineSeconds: 600 backoffLimit: 6 template: # {job template} - pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed - successfulJobsHistoryLimit: 5 # <--- property is added - failedJobsHistoryLimit: 5 # <--- Property is added + pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed + successfulJobsHistoryLimit: 5 # <--- property is added + failedJobsHistoryLimit: 5 # <--- Property is added maxReplicaCount: 100 triggers: # {list of triggers to create jobs} @@ -132,68 +137,74 @@ We've introduced more options to configure trigger metadata to give users more f Here's an overview: -| Scaler | 1.x | 2.0 | -|--------|--------|--------| -| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | -| `azure-monitor` | `activeDirectoryClientId`
`activeDirectoryClientPassword` | `activeDirectoryClientId`
`activeDirectoryClientIdFromEnv`
`activeDirectoryClientPasswordFromEnv` | -| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | -| `azure-servicebus` | `connection` | `connectionFromEnv` | -| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`)
`connection` (**Default**: `EventHub`) | `storageConnectionFromEnv`
`connectionFromEnv` | -| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `kafka` | _(none)_ | _(none)_ -| `rabbitmq` | `apiHost`
`host` | ~~`apiHost`~~
`host`
`hostFromEnv` | -| `prometheus` | _(none)_ | _(none)_ | -| `cron` | _(none)_ | _(none)_ | -| `redis` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `redis-streams` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | -| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ -| `liiklus` | _(none)_ | _(none)_ | -| `stan` | _(none)_ | _(none)_ | -| `huawei-cloudeye` | | _(none)_ | _(none)_ | -| `postgresql` | `connection`
`password` | `connectionFromEnv`
`passwordFromEnv` | -| `mysql` | `connectionString`
`password` | `connectionStringFromEnv`
`passwordFromEnv` | +| Scaler | 1.x | 2.0 | +| -------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------- | +| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | +| `azure-monitor` | `activeDirectoryClientId` `activeDirectoryClientPassword` | `activeDirectoryClientId` `activeDirectoryClientIdFromEnv` `activeDirectoryClientPasswordFromEnv` | +| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | +| `azure-servicebus` | `connection` | `connectionFromEnv` | +| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`) `connection` (**Default**: `EventHub`) | `storageConnectionFromEnv` `connectionFromEnv` | +| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `kafka` | _(none)_ | _(none)_ | +| `rabbitmq` | `apiHost` `host` | ~~`apiHost`~~ `host` `hostFromEnv` | +| `prometheus` | _(none)_ | _(none)_ | +| `cron` | _(none)_ | _(none)_ | +| `redis` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `redis-streams` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | +| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ | +| `liiklus` | _(none)_ | _(none)_ | +| `stan` | _(none)_ | _(none)_ | +| `huawei-cloudeye` | | _(none)_ | _(none)_ | +| `postgresql` | `connection` `password` | `connectionFromEnv` `passwordFromEnv` | +| `mysql` | `connectionString` `password` | `connectionStringFromEnv` `passwordFromEnv` | ### Scalers **Azure Service Bus** - - `queueLength` was renamed to `messageCount` + +- `queueLength` was renamed to `messageCount` **Kafka** - - `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. + +- `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. **RabbitMQ** In KEDA 2.0 the RabbitMQ scaler has only `host` parameter, and the protocol for communication can be specified by -`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP -protocol. +`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP +protocol. Example of RabbitMQ trigger before 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - includeUnacked: 'true' - apiHost: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + includeUnacked: "true" + apiHost: "https://guest:password@localhost:443/vhostname" +``` The same trigger in 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - protocol: 'http' - host: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + protocol: "http" + host: "https://guest:password@localhost:443/vhostname" +``` ### TriggerAuthentication + In order to use Authentication via `TriggerAuthentication` with KEDA v2, you need to change: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` For more details please refer to the full diff --git a/content/docs/2.13/operate/cluster.md b/content/docs/2.13/operate/cluster.md index 70f84c8f4..4f9c61068 100644 --- a/content/docs/2.13/operate/cluster.md +++ b/content/docs/2.13/operate/cluster.md @@ -14,15 +14,15 @@ However, maintainers can decide to extend this by supporting more minor versions As a reference, this compatibility matrix shows supported k8s versions per KEDA version: -| KEDA | Kubernetes | -|-----------|---------------| -| v2.13 | v1.27 - v1.29 | -| v2.12 | v1.26 - v1.28 | -| v2.11 | v1.25 - v1.27 | -| v2.10 | v1.24 - v1.26 | -| v2.9 | v1.23 - v1.25 | -| v2.8 | v1.17 - v1.25 | -| v2.7 | v1.17 - v1.25 | +| KEDA | Kubernetes | +| ----- | ------------- | +| v2.13 | v1.27 - v1.29 | +| v2.12 | v1.26 - v1.28 | +| v2.11 | v1.25 - v1.27 | +| v2.10 | v1.24 - v1.26 | +| v2.9 | v1.23 - v1.25 | +| v2.8 | v1.17 - v1.25 | +| v2.7 | v1.17 - v1.25 | ### Cluster Capacity @@ -44,12 +44,10 @@ KEDA requires to be accessible inside the cluster to be able to autoscale. Here is an overview of the required ports that need to be accessible for KEDA to work: - | Port | Why? | Remarks | | ------ | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication.

This is not applicable for Google Cloud. | +| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication. This is not applicable for Google Cloud. | | `6443` | Used by Kubernetes API server to get metrics | Only required for Google Cloud because it uses Control Plane → port 6443 on the Pod IP range for communication | - ## High Availability @@ -57,10 +55,10 @@ KEDA does not provide full support for high-availability due to upstream limitat Here is an overview of all KEDA deployments and the HA notes: -| Deployment | Support Replicas | Note | -| -------------- | ---------------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Deployment | Support Replicas | Note | +| -------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Metrics Server | 1 | You can run multiple replicas of our metrics sever, and it is recommended to add the `--enable-aggregator-routing=true` CLI flag to the kube-apiserver so that requests sent to our metrics servers are load balanced. However, [you can only run one active metric server in a Kubernetes cluster serving external.metrics.k8s.io](https://github.com/kubernetes-sigs/custom-metrics-apiserver/issues/70) which has to be the KEDA metric server. | -| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover. | +| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover. | ## HTTP Timeouts @@ -82,7 +80,7 @@ All applicable scalers will use this timeout. Setting a per-scaler timeout is cu ## HTTP connection disable keep alive -Keep alive behaviour is enabled by default for every HTTP connection, this could stack a huge amount of connections (one per scaler) in some scenarios. +Keep alive behaviour is enabled by default for every HTTP connection, this could stack a huge amount of connections (one per scaler) in some scenarios. You can disable keep alive for every HTTP connection by adding the relevant environment variable to both the KEDA Operator, and KEDA Metrics Server deployments: @@ -111,6 +109,7 @@ Our industry has seen an evolution of TLS versions and some are more secure than By default, KEDA uses TLS1.2 as a minimum TLS version given it is the lowest version without vulnerabilities. However, if you need to support another version you can configure it by using the environment variable `KEDA_HTTP_MIN_TLS_VERSION`. For example: + ```yaml - env: KEDA_HTTP_MIN_TLS_VERSION: TLS13 @@ -122,17 +121,18 @@ The following values are allowed: `TLS13`, `TLS12`, `TLS11` and `TLS10`. The Kubernetes client config used within KEDA Operator and KEDA Metrics Adapter can be adjusted by passing the following command-line flags to the binary: -| Adapter Flag | Client Config Setting | Default Value | Description | -| ------------------- | ----------------------- | ------------- | -------------------------------------------------------------- | -| kube-api-qps | cfg.QPS | 20.0 | Set the QPS rate for throttling requests sent to the apiserver | -| kube-api-burst | cfg.Burst | 30 | Set the burst for throttling requests sent to the apiserver | -| disable-compression | cfg.DisableCompression | true | Disable compression for response in k8s restAPI in client-go, see [this Kubernetes issue](https://github.com/kubernetes/kubernetes/issues/112296) for details | +| Adapter Flag | Client Config Setting | Default Value | Description | +| ------------------- | ---------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| kube-api-qps | cfg.QPS | 20.0 | Set the QPS rate for throttling requests sent to the apiserver | +| kube-api-burst | cfg.Burst | 30 | Set the burst for throttling requests sent to the apiserver | +| disable-compression | cfg.DisableCompression | true | Disable compression for response in k8s restAPI in client-go, see [this Kubernetes issue](https://github.com/kubernetes/kubernetes/issues/112296) for details | ## Configure `MaxConcurrentReconciles` for Controllers To implement internal controllers KEDA uses the [controller-runtime project](https://github.com/kubernetes-sigs/controller-runtime), that enables configuration of [MaxConcurrentReconciles property](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/controller#Options), ie. the maximum number of concurrent reconciles which can be run for a controller. KEDA Operator exposes properties for specifying `MaxConcurrentReconciles` for following controllers/reconcilers: + - `ScaledObjectReconciler` - responsible for watching and managing `ScaledObjects`, ie. validates input trigger specification, starts scaling logic and manages dependent HPA. - `ScaledJobReconciler` - responsible for watching and managing `ScaledJobs` and dependent Kubernetes Jobs @@ -140,14 +140,15 @@ KEDA Metrics Server exposes property for specifying `MaxConcurrentReconciles` fo To modify this properties you can set environment variables on both KEDA Operator and Metrics Server Deployments: -| Environment variable name | Deployment | Default Value | Affected reconciler | -| ------------------------------------- | -------------- | ------------- | -------------------------------------------------------------- | -| KEDA_SCALEDOBJECT_CTRL_MAX_RECONCILES | Operator | 5 | ScaledObjectReconciler | -| KEDA_SCALEDJOB_CTRL_MAX_RECONCILES | Operator | 1 | ScaledJobReconciler | +| Environment variable name | Deployment | Default Value | Affected reconciler | +| ------------------------------------- | ---------- | ------------- | ---------------------- | +| KEDA_SCALEDOBJECT_CTRL_MAX_RECONCILES | Operator | 5 | ScaledObjectReconciler | +| KEDA_SCALEDJOB_CTRL_MAX_RECONCILES | Operator | 1 | ScaledJobReconciler | ## Configure Leader Election Like reconciliation, KEDA also uses the [controller-runtime project](https://github.com/kubernetes-sigs/controller-runtime) for electing the leader replica. The following properties can be configured for either the Operator and Metrics Server Deployment: + - [`LeaseDuration`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options.LeaseDuration) - [`RenewDeadline`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options.RenewDeadline) - [`RetryPeriod`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options.RetryPeriod) @@ -170,25 +171,29 @@ To learn more please refer to [security section](./security#use-your-own-tls-cer ## Restrict Secret Access By default, KEDA requires adding `secrets` to the cluster role as following: + ```yaml - apiGroups: - - "" + - "" resources: - - external - - pods - - secrets - - services + - external + - pods + - secrets + - services verbs: - - get - - list - - watch + - get + - list + - watch ``` + However, this might lead to security risk (especially in production environment) since it will grant permission to read `secrets` from all namespaces. To restrict `secret` access and limited to KEDA namespace, you could add `KEDA_RESTRICT_SECRET_ACCESS` as environment variable to both KEDA Operator and KEDA Metrics Server: + ```yaml env: - name: KEDA_RESTRICT_SECRET_ACCESS value: "true" ``` + This allows you to omit `secrets` from the cluster role, which will disallow `TriggerAuthentication` to be used for your triggers if the `TriggerAuthentication` is using secrets. You can, however, still use `ClusterTriggerAuthentication`. diff --git a/content/docs/2.14/concepts/external-scalers.md b/content/docs/2.14/concepts/external-scalers.md index 5badde098..aa00a18a0 100644 --- a/content/docs/2.14/concepts/external-scalers.md +++ b/content/docs/2.14/concepts/external-scalers.md @@ -9,7 +9,7 @@ Built-in scalers run in the KEDA process/pod, while external scalers require an This document describes the external scaler interfaces and how to implement them in Go, Node, and .NET; however for more details on GRPC refer to [the official GRPC documentation](https://grpc.io/docs/) ->Want to learn about existing external scalers? Explore our [external scaler community](https://github.com/kedacore/external-scalers). +> Want to learn about existing external scalers? Explore our [external scaler community](https://github.com/kedacore/external-scalers). ## Overview @@ -45,7 +45,7 @@ The `Scaler` interface defines 3 methods: - `GetMetricSpecForScaling` returns the target value for the HPA definition for the scaler. For more details refer to [Implementing `GetMetricSpec`](#5-implementing-getmetricspec). - `GetMetricsAndActivity` is called on `pollingInterval` and. When activity returns `true`, KEDA will scale to what is returned by the metric limited by `maxReplicaCount` on the ScaledObject/ScaledJob. When `false` is returned, KEDA will scale to `minReplicaCount` or optionally `idleReplicaCount`. More details around the defaults and how these options work together can be found on the [ScaledObjectSpec](https://keda.sh/docs/latest/concepts/scaling-deployments/#scaledobject-spec). -> Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA supports both `AverageValue` and `Value` metric target types for external metrics. When `AverageValue` (the default metric type) is used, the metric value returned by the external scaler will be divided by the number of replicas. + > Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA supports both `AverageValue` and `Value` metric target types for external metrics. When `AverageValue` (the default metric type) is used, the metric value returned by the external scaler will be divided by the number of replicas. The `PushScaler` interface adds a `Run` method. This method receives a push channel (`active`), on which the scaler can send `true` at any time. The purpose of this mechanism is to initiate a scaling operation independently from `pollingInterval`. @@ -115,7 +115,7 @@ KEDA will attempt a GRPC connection to `service-address.svc.local:9090` immediat } ``` ->**Note**: KEDA will issue all of the above RPC calls except `StreamIsActive` if `spec.triggers.type` is `external`. It _must_ be `external-push` for `StreamIsActive` to be called. +> **Note**: KEDA will issue all of the above RPC calls except `StreamIsActive` if `spec.triggers.type` is `external`. It _must_ be `external-push` for `StreamIsActive` to be called. ## Implementing KEDA external scaler GRPC interface @@ -182,8 +182,6 @@ npm install --save grpc request {{< /collapsible >}} -
- #### 3. Implementing `IsActive` Just like `IsActive(ctx context.Context) (bool, error)` in the go interface, the `IsActive` method in the GRPC interface is called every `pollingInterval` with a `ScaledObjectRef` object that contains the scaledObject name, namespace, and scaler metadata. @@ -310,70 +308,71 @@ public class ExternalScalerService : ExternalScaler.ExternalScalerBase Put the following code into your `index.js` file: ```js -const grpc = require('grpc') -const request = require('request') -const externalScalerProto = grpc.load('externalscaler.proto') +const grpc = require("grpc"); +const request = require("request"); +const externalScalerProto = grpc.load("externalscaler.proto"); -const server = new grpc.Server() +const server = new grpc.Server(); server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { isActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { - const now = new Date() - const yesterday = new Date(new Date().setDate(new Date().getDate()-1)); - - const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}` - const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}` - const radiusKm = 500 - const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}` - - request.get({ - url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, - json: true, - }, (err, resp, data) => { - if (err) { - callback({ - code: grpc.status.INTERNAL, - details: err, - }) - } else if (resp.statusCode !== 200) { - callback({ - code: grpc.status.INTERNAL, - details: `expected status 200, got ${resp.statusCode}` - }) - } else { - // count how many earthquakes with mag > 1.0 - let count = 0 - data.features.forEach(i => { - if (i.properties.mag > 1.0) { - count++ - } - }) - callback(null, { - result: count > 2, - }) + const now = new Date(); + const yesterday = new Date(new Date().setDate(new Date().getDate() - 1)); + + const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}`; + const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}`; + const radiusKm = 500; + const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}`; + + request.get( + { + url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, + json: true, + }, + (err, resp, data) => { + if (err) { + callback({ + code: grpc.status.INTERNAL, + details: err, + }); + } else if (resp.statusCode !== 200) { + callback({ + code: grpc.status.INTERNAL, + details: `expected status 200, got ${resp.statusCode}`, + }); + } else { + // count how many earthquakes with mag > 1.0 + let count = 0; + data.features.forEach((i) => { + if (i.properties.mag > 1.0) { + count++; + } + }); + callback(null, { + result: count > 2, + }); + } } - }) + ); } - } -}) + }, +}); -server.bind('127.0.0.1:9090', grpc.ServerCredentials.createInsecure()) -console.log('Server listening on 127.0.0.1:9090') +server.bind("127.0.0.1:9090", grpc.ServerCredentials.createInsecure()); +console.log("Server listening on 127.0.0.1:9090"); -server.start() +server.start(); ``` {{< /collapsible >}} -
- #### 4. Implementing `StreamIsActive` Unlike `IsActive`, `StreamIsActive` is called once when KEDA reconciles the `ScaledObject`, and expects the external scaler to maintain a long-lived connection and push `IsActiveResponse` objects whenever the scaler needs KEDA to activate the deployment. @@ -450,38 +449,36 @@ public override async Task StreamIsActive(ScaledObjectRef request, IServerStream server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... streamIsActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { const interval = setInterval(() => { getEarthquakeCount((err, count) => { if (err) { - console.error(err) + console.error(err); } else if (count > 2) { call.write({ result: true, - }) + }); } - }) + }); }, 1000 * 60 * 60); - call.on('end', () => { - clearInterval(interval) - }) + call.on("end", () => { + clearInterval(interval); + }); } - } -}) + }, +}); ``` {{< /collapsible >}} -
- #### 5. Implementing `GetMetricSpec` `GetMetricSpec` returns the `target` value for [the HPA definition for the scaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/). This scaler will define a static target of 10, but the threshold value is often specified in the metadata for other scalers. @@ -527,19 +524,19 @@ server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetricSpec: (call, callback) => { callback(null, { - metricSpecs: [{ - metricName: 'earthquakeThreshold', - targetSize: 10, - }] - }) - } -}) + metricSpecs: [ + { + metricName: "earthquakeThreshold", + targetSize: 10, + }, + ], + }); + }, +}); ``` {{< /collapsible >}} -
- #### 6. Implementing `GetMetrics` `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`, in this example it's `earthquakeThreshold`. @@ -606,32 +603,34 @@ public override async Task GetMetrics(GetMetricsRequest requ server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetrics: (call, callback) => { - const longitude = call.request.scaledObjectRef.scalerMetadata.longitude - const latitude = call.request.scaledObjectRef.scalerMetadata.latitude + const longitude = call.request.scaledObjectRef.scalerMetadata.longitude; + const latitude = call.request.scaledObjectRef.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { getEarthquakeCount((err, count) => { if (err) { callback({ code: grpc.status.INTERNAL, details: err, - }) + }); } else { callback(null, { - metricValues: [{ - metricName: 'earthquakeThreshold', - metricValue: count, - }] - }) + metricValues: [ + { + metricName: "earthquakeThreshold", + metricValue: count, + }, + ], + }); } - }) + }); } - } -}) + }, +}); ``` {{< /collapsible >}} diff --git a/content/docs/2.14/migration.md b/content/docs/2.14/migration.md index 5ee8a6455..29e8408c8 100644 --- a/content/docs/2.14/migration.md +++ b/content/docs/2.14/migration.md @@ -11,15 +11,17 @@ Please note that you **can not** run both KEDA v1 and v2 on the same Kubernetes KEDA v2 is using a new API namespace for its Custom Resources Definitions (CRD): `keda.sh` instead of `keda.k8s.io` and introduces a new Custom Resource for scaling of Jobs. See full details on KEDA Custom Resources [here](../concepts/#custom-resources-crd). Here's an overview of what's changed: + - [Scaling of Deployments](#scaling-of-deployments) - [Scaling of Jobs](#scaling-of-jobs) - [Improved flexibility & usability of trigger metadata](#improved-flexibility--usability-of-trigger-metadata) - [Scalers](#scalers) - [TriggerAuthentication](#triggerauthentication) - ### Scaling of Deployments + In order to scale `Deployments` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Rename property `spec.scaleTargetRef.deploymentName` to `spec.scaleTargetRef.name` - Rename property `spec.scaleTargetRef.containerName` to `spec.scaleTargetRef.envSourceContainerName` @@ -27,22 +29,23 @@ In order to scale `Deployments` with KEDA v2, you need to do only a few modifica Please see the examples below or refer to the full [v2 ScaledObject Specification](../concepts/scaling-deployments/#scaledobject-spec) - **Example of v1 ScaledObject** +**Example of v1 ScaledObject** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } labels: - deploymentName: {deployment-name} + deploymentName: { deployment-name } spec: scaleTargetRef: - deploymentName: {deployment-name} - containerName: {container-name} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + deploymentName: { deployment-name } + containerName: { container-name } + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -50,18 +53,18 @@ spec: **Example of v2 ScaledObject** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed kind: ScaledObject -metadata: # <--- labels.deploymentName is not needed - name: {scaled-object-name} +metadata: # <--- labels.deploymentName is not needed + name: { scaled-object-name } spec: scaleTargetRef: - name: {deployment-name} # <--- Property name was changed - envSourceContainerName: {container-name} # <--- Property name was changed - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + name: { deployment-name } # <--- Property name was changed + envSourceContainerName: { container-name } # <--- Property name was changed + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -69,34 +72,36 @@ spec: ### Scaling of Jobs In order to scale `Jobs` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Change the value of `kind` property from `ScaledObject` to `ScaledJob` - Remove property `spec.scaleType` -- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` +- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` You can configure `successfulJobsHistoryLimit` and `failedJobsHistoryLimit`. They will remove the old job histories automatically. Please see the examples below or refer to the full [v2 ScaledJob Specification](../concepts/scaling-jobs/#scaledjob-spec) **Example of v1 ScaledObject for Jobs scaling** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } spec: scaleType: job jobTargetRef: - parallelism: 1 + parallelism: 1 completions: 1 activeDeadlineSeconds: 600 - backoffLimit: 6 + backoffLimit: 6 template: # {job template} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to create jobs} ``` @@ -104,21 +109,21 @@ spec: **Example of v2 ScaledJob** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed -kind: ScaledJob # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +kind: ScaledJob # <--- Property value was changed metadata: - name: {scaled-job-name} -spec: # <--- spec.scaleType is not needed + name: { scaled-job-name } +spec: # <--- spec.scaleType is not needed jobTargetRef: - parallelism: 1 - completions: 1 + parallelism: 1 + completions: 1 activeDeadlineSeconds: 600 backoffLimit: 6 template: # {job template} - pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed - successfulJobsHistoryLimit: 5 # <--- property is added - failedJobsHistoryLimit: 5 # <--- Property is added + pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed + successfulJobsHistoryLimit: 5 # <--- property is added + failedJobsHistoryLimit: 5 # <--- Property is added maxReplicaCount: 100 triggers: # {list of triggers to create jobs} @@ -132,68 +137,74 @@ We've introduced more options to configure trigger metadata to give users more f Here's an overview: -| Scaler | 1.x | 2.0 | -|--------|--------|--------| -| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | -| `azure-monitor` | `activeDirectoryClientId`
`activeDirectoryClientPassword` | `activeDirectoryClientId`
`activeDirectoryClientIdFromEnv`
`activeDirectoryClientPasswordFromEnv` | -| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | -| `azure-servicebus` | `connection` | `connectionFromEnv` | -| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`)
`connection` (**Default**: `EventHub`) | `storageConnectionFromEnv`
`connectionFromEnv` | -| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `kafka` | _(none)_ | _(none)_ -| `rabbitmq` | `apiHost`
`host` | ~~`apiHost`~~
`host`
`hostFromEnv` | -| `prometheus` | _(none)_ | _(none)_ | -| `cron` | _(none)_ | _(none)_ | -| `redis` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `redis-streams` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | -| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ -| `liiklus` | _(none)_ | _(none)_ | -| `stan` | _(none)_ | _(none)_ | -| `huawei-cloudeye` | | _(none)_ | _(none)_ | -| `postgresql` | `connection`
`password` | `connectionFromEnv`
`passwordFromEnv` | -| `mysql` | `connectionString`
`password` | `connectionStringFromEnv`
`passwordFromEnv` | +| Scaler | 1.x | 2.0 | +| -------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------- | +| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | +| `azure-monitor` | `activeDirectoryClientId` `activeDirectoryClientPassword` | `activeDirectoryClientId` `activeDirectoryClientIdFromEnv` `activeDirectoryClientPasswordFromEnv` | +| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | +| `azure-servicebus` | `connection` | `connectionFromEnv` | +| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`) `connection` (**Default**: `EventHub`) | `storageConnectionFromEnv` `connectionFromEnv` | +| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `kafka` | _(none)_ | _(none)_ | +| `rabbitmq` | `apiHost` `host` | ~~`apiHost`~~ `host` `hostFromEnv` | +| `prometheus` | _(none)_ | _(none)_ | +| `cron` | _(none)_ | _(none)_ | +| `redis` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `redis-streams` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | +| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ | +| `liiklus` | _(none)_ | _(none)_ | +| `stan` | _(none)_ | _(none)_ | +| `huawei-cloudeye` | | _(none)_ | _(none)_ | +| `postgresql` | `connection` `password` | `connectionFromEnv` `passwordFromEnv` | +| `mysql` | `connectionString` `password` | `connectionStringFromEnv` `passwordFromEnv` | ### Scalers **Azure Service Bus** - - `queueLength` was renamed to `messageCount` + +- `queueLength` was renamed to `messageCount` **Kafka** - - `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. + +- `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. **RabbitMQ** In KEDA 2.0 the RabbitMQ scaler has only `host` parameter, and the protocol for communication can be specified by -`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP -protocol. +`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP +protocol. Example of RabbitMQ trigger before 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - includeUnacked: 'true' - apiHost: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + includeUnacked: "true" + apiHost: "https://guest:password@localhost:443/vhostname" +``` The same trigger in 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - protocol: 'http' - host: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + protocol: "http" + host: "https://guest:password@localhost:443/vhostname" +``` ### TriggerAuthentication + In order to use Authentication via `TriggerAuthentication` with KEDA v2, you need to change: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` For more details please refer to the full diff --git a/content/docs/2.14/operate/cluster.md b/content/docs/2.14/operate/cluster.md index bf0541bba..4ec1e1049 100644 --- a/content/docs/2.14/operate/cluster.md +++ b/content/docs/2.14/operate/cluster.md @@ -14,16 +14,16 @@ However, maintainers can decide to extend this by supporting more minor versions As a reference, this compatibility matrix shows supported k8s versions per KEDA version: -| KEDA | Kubernetes | -|-----------|---------------| -| v2.14 | v1.27 - v1.29 | -| v2.13 | v1.27 - v1.29 | -| v2.12 | v1.26 - v1.28 | -| v2.11 | v1.25 - v1.27 | -| v2.10 | v1.24 - v1.26 | -| v2.9 | v1.23 - v1.25 | -| v2.8 | v1.17 - v1.25 | -| v2.7 | v1.17 - v1.25 | +| KEDA | Kubernetes | +| ----- | ------------- | +| v2.14 | v1.27 - v1.29 | +| v2.13 | v1.27 - v1.29 | +| v2.12 | v1.26 - v1.28 | +| v2.11 | v1.25 - v1.27 | +| v2.10 | v1.24 - v1.26 | +| v2.9 | v1.23 - v1.25 | +| v2.8 | v1.17 - v1.25 | +| v2.7 | v1.17 - v1.25 | ### Cluster Capacity @@ -45,12 +45,10 @@ KEDA requires to be accessible inside the cluster to be able to autoscale. Here is an overview of the required ports that need to be accessible for KEDA to work: - | Port | Why? | Remarks | | ------ | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication.

This is not applicable for Google Cloud. | +| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication. This is not applicable for Google Cloud. | | `6443` | Used by Kubernetes API server to get metrics | Only required for Google Cloud because it uses Control Plane → port 6443 on the Pod IP range for communication | - ## High Availability @@ -58,10 +56,10 @@ KEDA does not provide full support for high-availability due to upstream limitat Here is an overview of all KEDA deployments and the HA notes: -| Deployment | Support Replicas | Note | -| -------------- | ---------------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Deployment | Support Replicas | Note | +| -------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Metrics Server | 1 | You can run multiple replicas of our metrics sever, and it is recommended to add the `--enable-aggregator-routing=true` CLI flag to the kube-apiserver so that requests sent to our metrics servers are load balanced. However, [you can only run one active metric server in a Kubernetes cluster serving external.metrics.k8s.io](https://github.com/kubernetes-sigs/custom-metrics-apiserver/issues/70) which has to be the KEDA metric server. | -| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover. | +| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover. | ## HTTP Timeouts @@ -112,6 +110,7 @@ Our industry has seen an evolution of TLS versions and some are more secure than By default, KEDA uses TLS1.2 as a minimum TLS version given it is the lowest version without vulnerabilities. However, if you need to support another version you can configure it by using the environment variable `KEDA_HTTP_MIN_TLS_VERSION`. For example: + ```yaml - env: KEDA_HTTP_MIN_TLS_VERSION: TLS13 @@ -123,26 +122,27 @@ The following values are allowed: `TLS13`, `TLS12`, `TLS11` and `TLS10`. The Kubernetes client config used within KEDA Operator and KEDA Metrics Adapter can be adjusted by passing the following command-line flags to the binary: -| Adapter Flag | Client Config Setting | Default Value | Description | -| ------------------- | ----------------------- | ------------- | -------------------------------------------------------------- | -| kube-api-qps | cfg.QPS | 20.0 | Set the QPS rate for throttling requests sent to the apiserver | -| kube-api-burst | cfg.Burst | 30 | Set the burst for throttling requests sent to the apiserver | -| disable-compression | cfg.DisableCompression | true | Disable compression for response in k8s restAPI in client-go, see [this Kubernetes issue](https://github.com/kubernetes/kubernetes/issues/112296) for details | +| Adapter Flag | Client Config Setting | Default Value | Description | +| ------------------- | ---------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| kube-api-qps | cfg.QPS | 20.0 | Set the QPS rate for throttling requests sent to the apiserver | +| kube-api-burst | cfg.Burst | 30 | Set the burst for throttling requests sent to the apiserver | +| disable-compression | cfg.DisableCompression | true | Disable compression for response in k8s restAPI in client-go, see [this Kubernetes issue](https://github.com/kubernetes/kubernetes/issues/112296) for details | ## gRPC Metrics Service Parameters The gRPC Metrics Service is part of the KEDA Operator deployment and serves scaling events and metrics from the scalers over gRPC to the Metrics API Service, that in turn serves them to the Kubernetes API Server. The gRPC Metrics Service config used by the KEDA Metrics Adapter to connect to the KEDA Operator can be adjusted by passing the following command-line flags to the Adapter binary: -| Adapter Flag | Default Value | Description | -| ----------------------------------- | ------------------------------------------------- | ---------------------------------------------- | -| metrics-service-address | keda-operator.keda.svc.cluster.local:9666 | The address of the gRPC Metrics Service Server | -| metrics-service-grpc-authority | "" | Host Authority override for the Metrics Service if the Host Authority is not the same as the address used for the gRPC Metrics Service Server. This is required for mutual TLS when the identity of the adapter server as presented in its TLS certificate is not the same as the metrics-service-address | +| Adapter Flag | Default Value | Description | +| ------------------------------ | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| metrics-service-address | keda-operator.keda.svc.cluster.local:9666 | The address of the gRPC Metrics Service Server | +| metrics-service-grpc-authority | "" | Host Authority override for the Metrics Service if the Host Authority is not the same as the address used for the gRPC Metrics Service Server. This is required for mutual TLS when the identity of the adapter server as presented in its TLS certificate is not the same as the metrics-service-address | ## Configure `MaxConcurrentReconciles` for Controllers To implement internal controllers KEDA uses the [controller-runtime project](https://github.com/kubernetes-sigs/controller-runtime), that enables configuration of [MaxConcurrentReconciles property](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/controller#Options), ie. the maximum number of concurrent reconciles which can be run for a controller. KEDA Operator exposes properties for specifying `MaxConcurrentReconciles` for following controllers/reconcilers: + - `ScaledObjectReconciler` - responsible for watching and managing `ScaledObjects`, ie. validates input trigger specification, starts scaling logic and manages dependent HPA. - `ScaledJobReconciler` - responsible for watching and managing `ScaledJobs` and dependent Kubernetes Jobs @@ -150,14 +150,15 @@ KEDA Metrics Server exposes property for specifying `MaxConcurrentReconciles` fo To modify this properties you can set environment variables on both KEDA Operator and Metrics Server Deployments: -| Environment variable name | Deployment | Default Value | Affected reconciler | -| ------------------------------------- | -------------- | ------------- | -------------------------------------------------------------- | -| KEDA_SCALEDOBJECT_CTRL_MAX_RECONCILES | Operator | 5 | ScaledObjectReconciler | -| KEDA_SCALEDJOB_CTRL_MAX_RECONCILES | Operator | 1 | ScaledJobReconciler | +| Environment variable name | Deployment | Default Value | Affected reconciler | +| ------------------------------------- | ---------- | ------------- | ---------------------- | +| KEDA_SCALEDOBJECT_CTRL_MAX_RECONCILES | Operator | 5 | ScaledObjectReconciler | +| KEDA_SCALEDJOB_CTRL_MAX_RECONCILES | Operator | 1 | ScaledJobReconciler | ## Configure Leader Election Like reconciliation, KEDA also uses the [controller-runtime project](https://github.com/kubernetes-sigs/controller-runtime) for electing the leader replica. The following properties can be configured for either the Operator and Metrics Server Deployment: + - [`LeaseDuration`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options.LeaseDuration) - [`RenewDeadline`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options.RenewDeadline) - [`RetryPeriod`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options.RetryPeriod) @@ -194,25 +195,29 @@ To learn more please refer to [security section](./security#use-your-own-tls-cer ## Restrict Secret Access By default, KEDA requires adding `secrets` to the cluster role as following: + ```yaml - apiGroups: - - "" + - "" resources: - - external - - pods - - secrets - - services + - external + - pods + - secrets + - services verbs: - - get - - list - - watch + - get + - list + - watch ``` + However, this might lead to security risk (especially in production environment) since it will grant permission to read `secrets` from all namespaces. To restrict `secret` access and limited to KEDA namespace, you could add `KEDA_RESTRICT_SECRET_ACCESS` as environment variable to both KEDA Operator and KEDA Metrics Server: + ```yaml env: - name: KEDA_RESTRICT_SECRET_ACCESS value: "true" ``` + This allows you to omit `secrets` from the cluster role, which will disallow `TriggerAuthentication` to be used for your triggers if the `TriggerAuthentication` is using secrets. You can, however, still use `ClusterTriggerAuthentication`. diff --git a/content/docs/2.15/concepts/external-scalers.md b/content/docs/2.15/concepts/external-scalers.md index 5badde098..aa00a18a0 100644 --- a/content/docs/2.15/concepts/external-scalers.md +++ b/content/docs/2.15/concepts/external-scalers.md @@ -9,7 +9,7 @@ Built-in scalers run in the KEDA process/pod, while external scalers require an This document describes the external scaler interfaces and how to implement them in Go, Node, and .NET; however for more details on GRPC refer to [the official GRPC documentation](https://grpc.io/docs/) ->Want to learn about existing external scalers? Explore our [external scaler community](https://github.com/kedacore/external-scalers). +> Want to learn about existing external scalers? Explore our [external scaler community](https://github.com/kedacore/external-scalers). ## Overview @@ -45,7 +45,7 @@ The `Scaler` interface defines 3 methods: - `GetMetricSpecForScaling` returns the target value for the HPA definition for the scaler. For more details refer to [Implementing `GetMetricSpec`](#5-implementing-getmetricspec). - `GetMetricsAndActivity` is called on `pollingInterval` and. When activity returns `true`, KEDA will scale to what is returned by the metric limited by `maxReplicaCount` on the ScaledObject/ScaledJob. When `false` is returned, KEDA will scale to `minReplicaCount` or optionally `idleReplicaCount`. More details around the defaults and how these options work together can be found on the [ScaledObjectSpec](https://keda.sh/docs/latest/concepts/scaling-deployments/#scaledobject-spec). -> Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA supports both `AverageValue` and `Value` metric target types for external metrics. When `AverageValue` (the default metric type) is used, the metric value returned by the external scaler will be divided by the number of replicas. + > Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA supports both `AverageValue` and `Value` metric target types for external metrics. When `AverageValue` (the default metric type) is used, the metric value returned by the external scaler will be divided by the number of replicas. The `PushScaler` interface adds a `Run` method. This method receives a push channel (`active`), on which the scaler can send `true` at any time. The purpose of this mechanism is to initiate a scaling operation independently from `pollingInterval`. @@ -115,7 +115,7 @@ KEDA will attempt a GRPC connection to `service-address.svc.local:9090` immediat } ``` ->**Note**: KEDA will issue all of the above RPC calls except `StreamIsActive` if `spec.triggers.type` is `external`. It _must_ be `external-push` for `StreamIsActive` to be called. +> **Note**: KEDA will issue all of the above RPC calls except `StreamIsActive` if `spec.triggers.type` is `external`. It _must_ be `external-push` for `StreamIsActive` to be called. ## Implementing KEDA external scaler GRPC interface @@ -182,8 +182,6 @@ npm install --save grpc request {{< /collapsible >}} -
- #### 3. Implementing `IsActive` Just like `IsActive(ctx context.Context) (bool, error)` in the go interface, the `IsActive` method in the GRPC interface is called every `pollingInterval` with a `ScaledObjectRef` object that contains the scaledObject name, namespace, and scaler metadata. @@ -310,70 +308,71 @@ public class ExternalScalerService : ExternalScaler.ExternalScalerBase Put the following code into your `index.js` file: ```js -const grpc = require('grpc') -const request = require('request') -const externalScalerProto = grpc.load('externalscaler.proto') +const grpc = require("grpc"); +const request = require("request"); +const externalScalerProto = grpc.load("externalscaler.proto"); -const server = new grpc.Server() +const server = new grpc.Server(); server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { isActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { - const now = new Date() - const yesterday = new Date(new Date().setDate(new Date().getDate()-1)); - - const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}` - const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}` - const radiusKm = 500 - const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}` - - request.get({ - url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, - json: true, - }, (err, resp, data) => { - if (err) { - callback({ - code: grpc.status.INTERNAL, - details: err, - }) - } else if (resp.statusCode !== 200) { - callback({ - code: grpc.status.INTERNAL, - details: `expected status 200, got ${resp.statusCode}` - }) - } else { - // count how many earthquakes with mag > 1.0 - let count = 0 - data.features.forEach(i => { - if (i.properties.mag > 1.0) { - count++ - } - }) - callback(null, { - result: count > 2, - }) + const now = new Date(); + const yesterday = new Date(new Date().setDate(new Date().getDate() - 1)); + + const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}`; + const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}`; + const radiusKm = 500; + const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}`; + + request.get( + { + url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, + json: true, + }, + (err, resp, data) => { + if (err) { + callback({ + code: grpc.status.INTERNAL, + details: err, + }); + } else if (resp.statusCode !== 200) { + callback({ + code: grpc.status.INTERNAL, + details: `expected status 200, got ${resp.statusCode}`, + }); + } else { + // count how many earthquakes with mag > 1.0 + let count = 0; + data.features.forEach((i) => { + if (i.properties.mag > 1.0) { + count++; + } + }); + callback(null, { + result: count > 2, + }); + } } - }) + ); } - } -}) + }, +}); -server.bind('127.0.0.1:9090', grpc.ServerCredentials.createInsecure()) -console.log('Server listening on 127.0.0.1:9090') +server.bind("127.0.0.1:9090", grpc.ServerCredentials.createInsecure()); +console.log("Server listening on 127.0.0.1:9090"); -server.start() +server.start(); ``` {{< /collapsible >}} -
- #### 4. Implementing `StreamIsActive` Unlike `IsActive`, `StreamIsActive` is called once when KEDA reconciles the `ScaledObject`, and expects the external scaler to maintain a long-lived connection and push `IsActiveResponse` objects whenever the scaler needs KEDA to activate the deployment. @@ -450,38 +449,36 @@ public override async Task StreamIsActive(ScaledObjectRef request, IServerStream server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... streamIsActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { const interval = setInterval(() => { getEarthquakeCount((err, count) => { if (err) { - console.error(err) + console.error(err); } else if (count > 2) { call.write({ result: true, - }) + }); } - }) + }); }, 1000 * 60 * 60); - call.on('end', () => { - clearInterval(interval) - }) + call.on("end", () => { + clearInterval(interval); + }); } - } -}) + }, +}); ``` {{< /collapsible >}} -
- #### 5. Implementing `GetMetricSpec` `GetMetricSpec` returns the `target` value for [the HPA definition for the scaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/). This scaler will define a static target of 10, but the threshold value is often specified in the metadata for other scalers. @@ -527,19 +524,19 @@ server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetricSpec: (call, callback) => { callback(null, { - metricSpecs: [{ - metricName: 'earthquakeThreshold', - targetSize: 10, - }] - }) - } -}) + metricSpecs: [ + { + metricName: "earthquakeThreshold", + targetSize: 10, + }, + ], + }); + }, +}); ``` {{< /collapsible >}} -
- #### 6. Implementing `GetMetrics` `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`, in this example it's `earthquakeThreshold`. @@ -606,32 +603,34 @@ public override async Task GetMetrics(GetMetricsRequest requ server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetrics: (call, callback) => { - const longitude = call.request.scaledObjectRef.scalerMetadata.longitude - const latitude = call.request.scaledObjectRef.scalerMetadata.latitude + const longitude = call.request.scaledObjectRef.scalerMetadata.longitude; + const latitude = call.request.scaledObjectRef.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { getEarthquakeCount((err, count) => { if (err) { callback({ code: grpc.status.INTERNAL, details: err, - }) + }); } else { callback(null, { - metricValues: [{ - metricName: 'earthquakeThreshold', - metricValue: count, - }] - }) + metricValues: [ + { + metricName: "earthquakeThreshold", + metricValue: count, + }, + ], + }); } - }) + }); } - } -}) + }, +}); ``` {{< /collapsible >}} diff --git a/content/docs/2.15/migration.md b/content/docs/2.15/migration.md index 5ee8a6455..29e8408c8 100644 --- a/content/docs/2.15/migration.md +++ b/content/docs/2.15/migration.md @@ -11,15 +11,17 @@ Please note that you **can not** run both KEDA v1 and v2 on the same Kubernetes KEDA v2 is using a new API namespace for its Custom Resources Definitions (CRD): `keda.sh` instead of `keda.k8s.io` and introduces a new Custom Resource for scaling of Jobs. See full details on KEDA Custom Resources [here](../concepts/#custom-resources-crd). Here's an overview of what's changed: + - [Scaling of Deployments](#scaling-of-deployments) - [Scaling of Jobs](#scaling-of-jobs) - [Improved flexibility & usability of trigger metadata](#improved-flexibility--usability-of-trigger-metadata) - [Scalers](#scalers) - [TriggerAuthentication](#triggerauthentication) - ### Scaling of Deployments + In order to scale `Deployments` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Rename property `spec.scaleTargetRef.deploymentName` to `spec.scaleTargetRef.name` - Rename property `spec.scaleTargetRef.containerName` to `spec.scaleTargetRef.envSourceContainerName` @@ -27,22 +29,23 @@ In order to scale `Deployments` with KEDA v2, you need to do only a few modifica Please see the examples below or refer to the full [v2 ScaledObject Specification](../concepts/scaling-deployments/#scaledobject-spec) - **Example of v1 ScaledObject** +**Example of v1 ScaledObject** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } labels: - deploymentName: {deployment-name} + deploymentName: { deployment-name } spec: scaleTargetRef: - deploymentName: {deployment-name} - containerName: {container-name} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + deploymentName: { deployment-name } + containerName: { container-name } + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -50,18 +53,18 @@ spec: **Example of v2 ScaledObject** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed kind: ScaledObject -metadata: # <--- labels.deploymentName is not needed - name: {scaled-object-name} +metadata: # <--- labels.deploymentName is not needed + name: { scaled-object-name } spec: scaleTargetRef: - name: {deployment-name} # <--- Property name was changed - envSourceContainerName: {container-name} # <--- Property name was changed - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + name: { deployment-name } # <--- Property name was changed + envSourceContainerName: { container-name } # <--- Property name was changed + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -69,34 +72,36 @@ spec: ### Scaling of Jobs In order to scale `Jobs` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Change the value of `kind` property from `ScaledObject` to `ScaledJob` - Remove property `spec.scaleType` -- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` +- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` You can configure `successfulJobsHistoryLimit` and `failedJobsHistoryLimit`. They will remove the old job histories automatically. Please see the examples below or refer to the full [v2 ScaledJob Specification](../concepts/scaling-jobs/#scaledjob-spec) **Example of v1 ScaledObject for Jobs scaling** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } spec: scaleType: job jobTargetRef: - parallelism: 1 + parallelism: 1 completions: 1 activeDeadlineSeconds: 600 - backoffLimit: 6 + backoffLimit: 6 template: # {job template} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to create jobs} ``` @@ -104,21 +109,21 @@ spec: **Example of v2 ScaledJob** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed -kind: ScaledJob # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +kind: ScaledJob # <--- Property value was changed metadata: - name: {scaled-job-name} -spec: # <--- spec.scaleType is not needed + name: { scaled-job-name } +spec: # <--- spec.scaleType is not needed jobTargetRef: - parallelism: 1 - completions: 1 + parallelism: 1 + completions: 1 activeDeadlineSeconds: 600 backoffLimit: 6 template: # {job template} - pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed - successfulJobsHistoryLimit: 5 # <--- property is added - failedJobsHistoryLimit: 5 # <--- Property is added + pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed + successfulJobsHistoryLimit: 5 # <--- property is added + failedJobsHistoryLimit: 5 # <--- Property is added maxReplicaCount: 100 triggers: # {list of triggers to create jobs} @@ -132,68 +137,74 @@ We've introduced more options to configure trigger metadata to give users more f Here's an overview: -| Scaler | 1.x | 2.0 | -|--------|--------|--------| -| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | -| `azure-monitor` | `activeDirectoryClientId`
`activeDirectoryClientPassword` | `activeDirectoryClientId`
`activeDirectoryClientIdFromEnv`
`activeDirectoryClientPasswordFromEnv` | -| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | -| `azure-servicebus` | `connection` | `connectionFromEnv` | -| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`)
`connection` (**Default**: `EventHub`) | `storageConnectionFromEnv`
`connectionFromEnv` | -| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `kafka` | _(none)_ | _(none)_ -| `rabbitmq` | `apiHost`
`host` | ~~`apiHost`~~
`host`
`hostFromEnv` | -| `prometheus` | _(none)_ | _(none)_ | -| `cron` | _(none)_ | _(none)_ | -| `redis` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `redis-streams` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | -| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ -| `liiklus` | _(none)_ | _(none)_ | -| `stan` | _(none)_ | _(none)_ | -| `huawei-cloudeye` | | _(none)_ | _(none)_ | -| `postgresql` | `connection`
`password` | `connectionFromEnv`
`passwordFromEnv` | -| `mysql` | `connectionString`
`password` | `connectionStringFromEnv`
`passwordFromEnv` | +| Scaler | 1.x | 2.0 | +| -------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------- | +| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | +| `azure-monitor` | `activeDirectoryClientId` `activeDirectoryClientPassword` | `activeDirectoryClientId` `activeDirectoryClientIdFromEnv` `activeDirectoryClientPasswordFromEnv` | +| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | +| `azure-servicebus` | `connection` | `connectionFromEnv` | +| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`) `connection` (**Default**: `EventHub`) | `storageConnectionFromEnv` `connectionFromEnv` | +| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `kafka` | _(none)_ | _(none)_ | +| `rabbitmq` | `apiHost` `host` | ~~`apiHost`~~ `host` `hostFromEnv` | +| `prometheus` | _(none)_ | _(none)_ | +| `cron` | _(none)_ | _(none)_ | +| `redis` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `redis-streams` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | +| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ | +| `liiklus` | _(none)_ | _(none)_ | +| `stan` | _(none)_ | _(none)_ | +| `huawei-cloudeye` | | _(none)_ | _(none)_ | +| `postgresql` | `connection` `password` | `connectionFromEnv` `passwordFromEnv` | +| `mysql` | `connectionString` `password` | `connectionStringFromEnv` `passwordFromEnv` | ### Scalers **Azure Service Bus** - - `queueLength` was renamed to `messageCount` + +- `queueLength` was renamed to `messageCount` **Kafka** - - `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. + +- `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. **RabbitMQ** In KEDA 2.0 the RabbitMQ scaler has only `host` parameter, and the protocol for communication can be specified by -`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP -protocol. +`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP +protocol. Example of RabbitMQ trigger before 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - includeUnacked: 'true' - apiHost: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + includeUnacked: "true" + apiHost: "https://guest:password@localhost:443/vhostname" +``` The same trigger in 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - protocol: 'http' - host: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + protocol: "http" + host: "https://guest:password@localhost:443/vhostname" +``` ### TriggerAuthentication + In order to use Authentication via `TriggerAuthentication` with KEDA v2, you need to change: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` For more details please refer to the full diff --git a/content/docs/2.15/operate/cluster.md b/content/docs/2.15/operate/cluster.md index 905782f9f..4de7f51ed 100644 --- a/content/docs/2.15/operate/cluster.md +++ b/content/docs/2.15/operate/cluster.md @@ -14,17 +14,17 @@ However, maintainers can decide to extend this by supporting more minor versions As a reference, this compatibility matrix shows supported k8s versions per KEDA version: -| KEDA | Kubernetes | -|-----------|---------------| -| v2.15 | v1.28 - v1.30 | -| v2.14 | v1.27 - v1.29 | -| v2.13 | v1.27 - v1.29 | -| v2.12 | v1.26 - v1.28 | -| v2.11 | v1.25 - v1.27 | -| v2.10 | v1.24 - v1.26 | -| v2.9 | v1.23 - v1.25 | -| v2.8 | v1.17 - v1.25 | -| v2.7 | v1.17 - v1.25 | +| KEDA | Kubernetes | +| ----- | ------------- | +| v2.15 | v1.28 - v1.30 | +| v2.14 | v1.27 - v1.29 | +| v2.13 | v1.27 - v1.29 | +| v2.12 | v1.26 - v1.28 | +| v2.11 | v1.25 - v1.27 | +| v2.10 | v1.24 - v1.26 | +| v2.9 | v1.23 - v1.25 | +| v2.8 | v1.17 - v1.25 | +| v2.7 | v1.17 - v1.25 | ### Cluster Capacity @@ -46,12 +46,10 @@ KEDA requires to be accessible inside the cluster to be able to autoscale. Here is an overview of the required ports that need to be accessible for KEDA to work: - | Port | Why? | Remarks | | ------ | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication.

This is not applicable for Google Cloud. | +| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication. This is not applicable for Google Cloud. | | `6443` | Used by Kubernetes API server to get metrics | Only required for Google Cloud because it uses Control Plane → port 6443 on the Pod IP range for communication | - ## High Availability @@ -59,10 +57,10 @@ KEDA does not provide full support for high-availability due to upstream limitat Here is an overview of all KEDA deployments and the HA notes: -| Deployment | Support Replicas | Note | -| -------------- | ---------------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Deployment | Support Replicas | Note | +| -------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Metrics Server | 1 | You can run multiple replicas of our metrics sever, and it is recommended to add the `--enable-aggregator-routing=true` CLI flag to the kube-apiserver so that requests sent to our metrics servers are load balanced. However, [you can only run one active metric server in a Kubernetes cluster serving external.metrics.k8s.io](https://github.com/kubernetes-sigs/custom-metrics-apiserver/issues/70) which has to be the KEDA metric server. | -| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover. | +| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover. | ## HTTP Timeouts @@ -113,6 +111,7 @@ Our industry has seen an evolution of TLS versions and some are more secure than By default, KEDA uses TLS1.2 as a minimum TLS version given it is the lowest version without vulnerabilities. However, if you need to support another version you can configure it by using the environment variable `KEDA_HTTP_MIN_TLS_VERSION`. For example: + ```yaml - env: KEDA_HTTP_MIN_TLS_VERSION: TLS13 @@ -124,26 +123,27 @@ The following values are allowed: `TLS13`, `TLS12`, `TLS11` and `TLS10`. The Kubernetes client config used within KEDA Operator and KEDA Metrics Adapter can be adjusted by passing the following command-line flags to the binary: -| Adapter Flag | Client Config Setting | Default Value | Description | -| ------------------- | ----------------------- | ------------- | -------------------------------------------------------------- | -| kube-api-qps | cfg.QPS | 20.0 | Set the QPS rate for throttling requests sent to the apiserver | -| kube-api-burst | cfg.Burst | 30 | Set the burst for throttling requests sent to the apiserver | -| disable-compression | cfg.DisableCompression | true | Disable compression for response in k8s restAPI in client-go, see [this Kubernetes issue](https://github.com/kubernetes/kubernetes/issues/112296) for details | +| Adapter Flag | Client Config Setting | Default Value | Description | +| ------------------- | ---------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| kube-api-qps | cfg.QPS | 20.0 | Set the QPS rate for throttling requests sent to the apiserver | +| kube-api-burst | cfg.Burst | 30 | Set the burst for throttling requests sent to the apiserver | +| disable-compression | cfg.DisableCompression | true | Disable compression for response in k8s restAPI in client-go, see [this Kubernetes issue](https://github.com/kubernetes/kubernetes/issues/112296) for details | ## gRPC Metrics Service Parameters The gRPC Metrics Service is part of the KEDA Operator deployment and serves scaling events and metrics from the scalers over gRPC to the Metrics API Service, that in turn serves them to the Kubernetes API Server. The gRPC Metrics Service config used by the KEDA Metrics Adapter to connect to the KEDA Operator can be adjusted by passing the following command-line flags to the Adapter binary: -| Adapter Flag | Default Value | Description | -| ----------------------------------- | ------------------------------------------------- | ---------------------------------------------- | -| metrics-service-address | keda-operator.keda.svc.cluster.local:9666 | The address of the gRPC Metrics Service Server | -| metrics-service-grpc-authority | "" | Host Authority override for the Metrics Service if the Host Authority is not the same as the address used for the gRPC Metrics Service Server. This is required for mutual TLS when the identity of the adapter server as presented in its TLS certificate is not the same as the metrics-service-address | +| Adapter Flag | Default Value | Description | +| ------------------------------ | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| metrics-service-address | keda-operator.keda.svc.cluster.local:9666 | The address of the gRPC Metrics Service Server | +| metrics-service-grpc-authority | "" | Host Authority override for the Metrics Service if the Host Authority is not the same as the address used for the gRPC Metrics Service Server. This is required for mutual TLS when the identity of the adapter server as presented in its TLS certificate is not the same as the metrics-service-address | ## Configure `MaxConcurrentReconciles` for Controllers To implement internal controllers KEDA uses the [controller-runtime project](https://github.com/kubernetes-sigs/controller-runtime), that enables configuration of [MaxConcurrentReconciles property](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/controller#Options), ie. the maximum number of concurrent reconciles which can be run for a controller. KEDA Operator exposes properties for specifying `MaxConcurrentReconciles` for following controllers/reconcilers: + - `ScaledObjectReconciler` - responsible for watching and managing `ScaledObjects`, ie. validates input trigger specification, starts scaling logic and manages dependent HPA. - `ScaledJobReconciler` - responsible for watching and managing `ScaledJobs` and dependent Kubernetes Jobs @@ -151,14 +151,15 @@ KEDA Metrics Server exposes property for specifying `MaxConcurrentReconciles` fo To modify this properties you can set environment variables on both KEDA Operator and Metrics Server Deployments: -| Environment variable name | Deployment | Default Value | Affected reconciler | -| ------------------------------------- | -------------- | ------------- | -------------------------------------------------------------- | -| KEDA_SCALEDOBJECT_CTRL_MAX_RECONCILES | Operator | 5 | ScaledObjectReconciler | -| KEDA_SCALEDJOB_CTRL_MAX_RECONCILES | Operator | 1 | ScaledJobReconciler | +| Environment variable name | Deployment | Default Value | Affected reconciler | +| ------------------------------------- | ---------- | ------------- | ---------------------- | +| KEDA_SCALEDOBJECT_CTRL_MAX_RECONCILES | Operator | 5 | ScaledObjectReconciler | +| KEDA_SCALEDJOB_CTRL_MAX_RECONCILES | Operator | 1 | ScaledJobReconciler | ## Configure Leader Election Like reconciliation, KEDA also uses the [controller-runtime project](https://github.com/kubernetes-sigs/controller-runtime) for electing the leader replica. The following properties can be configured for either the Operator and Metrics Server Deployment: + - [`LeaseDuration`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options.LeaseDuration) - [`RenewDeadline`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options.RenewDeadline) - [`RetryPeriod`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options.RetryPeriod) @@ -195,25 +196,29 @@ To learn more please refer to [security section](./security#use-your-own-tls-cer ## Restrict Secret Access By default, KEDA requires adding `secrets` to the cluster role as following: + ```yaml - apiGroups: - - "" + - "" resources: - - external - - pods - - secrets - - services + - external + - pods + - secrets + - services verbs: - - get - - list - - watch + - get + - list + - watch ``` + However, this might lead to security risk (especially in production environment) since it will grant permission to read `secrets` from all namespaces. To restrict `secret` access and limited to KEDA namespace, you could add `KEDA_RESTRICT_SECRET_ACCESS` as environment variable to both KEDA Operator and KEDA Metrics Server: + ```yaml env: - name: KEDA_RESTRICT_SECRET_ACCESS value: "true" ``` + This allows you to omit `secrets` from the cluster role, which will disallow `TriggerAuthentication` to be used for your triggers if the `TriggerAuthentication` is using secrets. You can, however, still use `ClusterTriggerAuthentication`. diff --git a/content/docs/2.2/concepts/external-scalers.md b/content/docs/2.2/concepts/external-scalers.md index 27ed9e0c6..1945394d3 100644 --- a/content/docs/2.2/concepts/external-scalers.md +++ b/content/docs/2.2/concepts/external-scalers.md @@ -33,15 +33,15 @@ type PushScaler interface { ``` The `Scaler` interface defines 4 methods: + - `IsActive` is called on `pollingInterval` defined in the ScaledObject/ScaledJob CRDs and scaling to 1 happens if this returns true. - `Close` is called to allow the scaler to clean up connections or other resources. - `GetMetricSpec` returns the target value for the HPA definition for the scaler. For more details refer to [Implementing `GetMetricSpec`](#5-implementing-getmetricspec). - `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`. For more details refer to [Implementing `GetMetrics`](#6-implementing-getmetrics). -> Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA uses the metric target type `AverageValue` for external metrics. This will cause the metric value returned by the external scaler to be divided by the number of replicas. + > Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA uses the metric target type `AverageValue` for external metrics. This will cause the metric value returned by the external scaler to be divided by the number of replicas. The `PushScaler` interface adds `Run` method. The `Run` method receives a push channel (`active`), that the scaler can push `true` to any time to force scaling action independently from `pollingInterval`. - ### External Scaler GRPC interface KEDA comes with 2 external scalers [`external`](../scalers/external.md) and [`external-push`](../scalers/external-push.md). @@ -62,6 +62,7 @@ service ExternalScaler { - `StreamIsActive` maps to the `Run` method on the `PushScaler` interface. Few things to notice: + - Lack of `Close` method as the GRPC connection defines the lifetime of the scaler - `IsActive`, `StreamIsActive`, and `GetMetricsSpec` are called with a `ScaledObjectRef` that contains the scaledObject name/namespace as well as the content of `metadata` defined in the trigger. @@ -125,6 +126,7 @@ go mod init example.com/external-scaler/sample mkdir externalscaler protoc externalscaler.proto --go_out=plugins=grpc:externalscaler ``` + {{< /collapsible >}} {{< collapsible "C#" >}} @@ -161,9 +163,8 @@ mkdir Services ```bash npm install --save grpc request ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 3. Implementing `IsActive` @@ -193,6 +194,7 @@ spec: Full implementation can be found here: https://github.com/kedacore/external-scaler-samples `main.go` + ```golang func (e *ExternalScaler) IsActive(ctx context.Context, scaledObject *pb.ScaledObjectRef) (*pb.IsActiveResponse, error) { // request.Scalermetadata contains the `metadata` defined in the ScaledObject @@ -239,12 +241,14 @@ func (e *ExternalScaler) IsActive(ctx context.Context, scaledObject *pb.ScaledOb }, nil } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} Full implementation can be found here: https://github.com/kedacore/external-scaler-samples `Services/ExternalScalerService.cs` + ```csharp public class ExternalScalerService : ExternalScaler.ExternalScalerBase { @@ -277,73 +281,77 @@ public class ExternalScalerService : ExternalScaler.ExternalScalerBase } } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} `index.js` + ```js -const grpc = require('grpc') -const request = require('request') -const externalScalerProto = grpc.load('externalscaler.proto') +const grpc = require("grpc"); +const request = require("request"); +const externalScalerProto = grpc.load("externalscaler.proto"); -const server = new grpc.Server() +const server = new grpc.Server(); server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { isActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { - const now = new Date() - const yesterday = new Date(new Date().setDate(new Date().getDate()-1)); - - const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}` - const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}` - const radiusKm = 500 - const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}` - - request.get({ - url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, - json: true, - }, (err, resp, data) => { - if (err) { - callback({ - code: grpc.status.INTERNAL, - details: err, - }) - } else if (resp.statusCode !== 200) { - callback({ - code: grpc.status.INTERNAL, - details: `expected status 200, got ${resp.statusCode}` - }) - } else { - // count how many earthquakes with mag > 1.0 - let count = 0 - data.features.forEach(i => { - if (i.properties.mag > 1.0) { - count++ - } - }) - callback(null, { - result: count > 2, - }) + const now = new Date(); + const yesterday = new Date(new Date().setDate(new Date().getDate() - 1)); + + const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}`; + const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}`; + const radiusKm = 500; + const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}`; + + request.get( + { + url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, + json: true, + }, + (err, resp, data) => { + if (err) { + callback({ + code: grpc.status.INTERNAL, + details: err, + }); + } else if (resp.statusCode !== 200) { + callback({ + code: grpc.status.INTERNAL, + details: `expected status 200, got ${resp.statusCode}`, + }); + } else { + // count how many earthquakes with mag > 1.0 + let count = 0; + data.features.forEach((i) => { + if (i.properties.mag > 1.0) { + count++; + } + }); + callback(null, { + result: count > 2, + }); + } } - }) + ); } - } -}) + }, +}); -server.bind('127.0.0.1:9090', grpc.ServerCredentials.createInsecure()) -console.log('Server listening on 127.0.0.1:9090') +server.bind("127.0.0.1:9090", grpc.ServerCredentials.createInsecure()); +console.log("Server listening on 127.0.0.1:9090"); -server.start() +server.start(); ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 4. Implementing `StreamIsActive` @@ -351,8 +359,8 @@ Unlike `IsActive`, `StreamIsActive` is called once when KEDA reconciles the `Sca This implementation creates a timer and queries USGS APIs on that timer, effectively ignoring `pollingInterval` set in the scaledObject. Alternatively any other asynchronous event can be used instead of a timer, like an HTTP request, or a network connection. - {{< collapsible "Golang" >}} + ```golang func (e *ExternalScaler) StreamIsActive(scaledObject *pb.ScaledObjectRef, epsServer pb.ExternalScaler_StreamIsActiveServer) error { longitude := scaledObject.ScalerMetadata["longitude"] @@ -380,9 +388,11 @@ func (e *ExternalScaler) StreamIsActive(scaledObject *pb.ScaledObjectRef, epsSer } } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} + ```csharp public override async Task StreamIsActive(ScaledObjectRef request, IServerStreamWriter responseStream, ServerCallContext context) { @@ -410,49 +420,51 @@ public override async Task StreamIsActive(ScaledObjectRef request, IServerStream } } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} + ```js server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... streamIsActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { const interval = setInterval(() => { getEarthquakeCount((err, count) => { if (err) { - console.error(err) + console.error(err); } else if (count > 2) { call.write({ result: true, - }) + }); } - }) + }); }, 1000 * 60 * 60); - call.on('end', () => { - clearInterval(interval) - }) + call.on("end", () => { + clearInterval(interval); + }); } - } -}) + }, +}); ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 5. Implementing `GetMetricSpec` `GetMetricSpec` returns the `target` value for [the HPA definition for the scaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/). This scaler will define a static target of 10, but the threshold value is often specified in the metadata for other scalers. {{< collapsible "Golang" >}} + ```golang func (e *ExternalScaler) GetMetricSpec(context.Context, *pb.ScaledObjectRef) (*pb.GetMetricSpecResponse, error) { return &pb.GetMetricSpecResponse{ @@ -463,9 +475,11 @@ func (e *ExternalScaler) GetMetricSpec(context.Context, *pb.ScaledObjectRef) (*p }, nil } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} + ```csharp public override async Task GetMetricSpec(ScaledObjectRef request, ServerCallContext context) { @@ -480,31 +494,35 @@ public override async Task GetMetricSpec(ScaledObjectRef return Task.FromResult(resp); } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} + ```js server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetricSpec: (call, callback) => { callback(null, { - metricSpecs: [{ - metricName: 'earthquakeThreshold', - targetSize: 10, - }] - }) - } -}) + metricSpecs: [ + { + metricName: "earthquakeThreshold", + targetSize: 10, + }, + ], + }); + }, +}); ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 6. Implementing `GetMetrics` `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`, in this example it's `earthquakeThreshold`. {{< collapsible "Golang" >}} + ```golang func (e *ExternalScaler) GetMetrics(_ context.Context, metricRequest *pb.GetMetricsRequest) (*pb.GetMetricsResponse, error) { longitude := metricRequest.ScaledObjectRef.ScalerMetadata["longitude"] @@ -527,9 +545,11 @@ func (e *ExternalScaler) GetMetrics(_ context.Context, metricRequest *pb.GetMetr }, nil } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} + ```csharp public override async Task GetMetrics(GetMetricsRequest request, ServerCallContext context) { @@ -554,38 +574,43 @@ public override async Task GetMetrics(GetMetricsRequest requ return resp; } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} + ```js server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetrics: (call, callback) => { - const longitude = call.request.scaledObjectRef.scalerMetadata.longitude - const latitude = call.request.scaledObjectRef.scalerMetadata.latitude + const longitude = call.request.scaledObjectRef.scalerMetadata.longitude; + const latitude = call.request.scaledObjectRef.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { getEarthquakeCount((err, count) => { if (err) { callback({ code: grpc.status.INTERNAL, details: err, - }) + }); } else { callback(null, { - metricValues: [{ - metricName: 'earthquakeThreshold', - metricValue: count, - }] - }) + metricValues: [ + { + metricName: "earthquakeThreshold", + metricValue: count, + }, + ], + }); } - }) + }); } - } -}) + }, +}); ``` + {{< /collapsible >}} diff --git a/content/docs/2.2/migration.md b/content/docs/2.2/migration.md index 5ee8a6455..29e8408c8 100644 --- a/content/docs/2.2/migration.md +++ b/content/docs/2.2/migration.md @@ -11,15 +11,17 @@ Please note that you **can not** run both KEDA v1 and v2 on the same Kubernetes KEDA v2 is using a new API namespace for its Custom Resources Definitions (CRD): `keda.sh` instead of `keda.k8s.io` and introduces a new Custom Resource for scaling of Jobs. See full details on KEDA Custom Resources [here](../concepts/#custom-resources-crd). Here's an overview of what's changed: + - [Scaling of Deployments](#scaling-of-deployments) - [Scaling of Jobs](#scaling-of-jobs) - [Improved flexibility & usability of trigger metadata](#improved-flexibility--usability-of-trigger-metadata) - [Scalers](#scalers) - [TriggerAuthentication](#triggerauthentication) - ### Scaling of Deployments + In order to scale `Deployments` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Rename property `spec.scaleTargetRef.deploymentName` to `spec.scaleTargetRef.name` - Rename property `spec.scaleTargetRef.containerName` to `spec.scaleTargetRef.envSourceContainerName` @@ -27,22 +29,23 @@ In order to scale `Deployments` with KEDA v2, you need to do only a few modifica Please see the examples below or refer to the full [v2 ScaledObject Specification](../concepts/scaling-deployments/#scaledobject-spec) - **Example of v1 ScaledObject** +**Example of v1 ScaledObject** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } labels: - deploymentName: {deployment-name} + deploymentName: { deployment-name } spec: scaleTargetRef: - deploymentName: {deployment-name} - containerName: {container-name} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + deploymentName: { deployment-name } + containerName: { container-name } + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -50,18 +53,18 @@ spec: **Example of v2 ScaledObject** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed kind: ScaledObject -metadata: # <--- labels.deploymentName is not needed - name: {scaled-object-name} +metadata: # <--- labels.deploymentName is not needed + name: { scaled-object-name } spec: scaleTargetRef: - name: {deployment-name} # <--- Property name was changed - envSourceContainerName: {container-name} # <--- Property name was changed - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + name: { deployment-name } # <--- Property name was changed + envSourceContainerName: { container-name } # <--- Property name was changed + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -69,34 +72,36 @@ spec: ### Scaling of Jobs In order to scale `Jobs` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Change the value of `kind` property from `ScaledObject` to `ScaledJob` - Remove property `spec.scaleType` -- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` +- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` You can configure `successfulJobsHistoryLimit` and `failedJobsHistoryLimit`. They will remove the old job histories automatically. Please see the examples below or refer to the full [v2 ScaledJob Specification](../concepts/scaling-jobs/#scaledjob-spec) **Example of v1 ScaledObject for Jobs scaling** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } spec: scaleType: job jobTargetRef: - parallelism: 1 + parallelism: 1 completions: 1 activeDeadlineSeconds: 600 - backoffLimit: 6 + backoffLimit: 6 template: # {job template} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to create jobs} ``` @@ -104,21 +109,21 @@ spec: **Example of v2 ScaledJob** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed -kind: ScaledJob # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +kind: ScaledJob # <--- Property value was changed metadata: - name: {scaled-job-name} -spec: # <--- spec.scaleType is not needed + name: { scaled-job-name } +spec: # <--- spec.scaleType is not needed jobTargetRef: - parallelism: 1 - completions: 1 + parallelism: 1 + completions: 1 activeDeadlineSeconds: 600 backoffLimit: 6 template: # {job template} - pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed - successfulJobsHistoryLimit: 5 # <--- property is added - failedJobsHistoryLimit: 5 # <--- Property is added + pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed + successfulJobsHistoryLimit: 5 # <--- property is added + failedJobsHistoryLimit: 5 # <--- Property is added maxReplicaCount: 100 triggers: # {list of triggers to create jobs} @@ -132,68 +137,74 @@ We've introduced more options to configure trigger metadata to give users more f Here's an overview: -| Scaler | 1.x | 2.0 | -|--------|--------|--------| -| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | -| `azure-monitor` | `activeDirectoryClientId`
`activeDirectoryClientPassword` | `activeDirectoryClientId`
`activeDirectoryClientIdFromEnv`
`activeDirectoryClientPasswordFromEnv` | -| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | -| `azure-servicebus` | `connection` | `connectionFromEnv` | -| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`)
`connection` (**Default**: `EventHub`) | `storageConnectionFromEnv`
`connectionFromEnv` | -| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `kafka` | _(none)_ | _(none)_ -| `rabbitmq` | `apiHost`
`host` | ~~`apiHost`~~
`host`
`hostFromEnv` | -| `prometheus` | _(none)_ | _(none)_ | -| `cron` | _(none)_ | _(none)_ | -| `redis` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `redis-streams` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | -| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ -| `liiklus` | _(none)_ | _(none)_ | -| `stan` | _(none)_ | _(none)_ | -| `huawei-cloudeye` | | _(none)_ | _(none)_ | -| `postgresql` | `connection`
`password` | `connectionFromEnv`
`passwordFromEnv` | -| `mysql` | `connectionString`
`password` | `connectionStringFromEnv`
`passwordFromEnv` | +| Scaler | 1.x | 2.0 | +| -------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------- | +| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | +| `azure-monitor` | `activeDirectoryClientId` `activeDirectoryClientPassword` | `activeDirectoryClientId` `activeDirectoryClientIdFromEnv` `activeDirectoryClientPasswordFromEnv` | +| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | +| `azure-servicebus` | `connection` | `connectionFromEnv` | +| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`) `connection` (**Default**: `EventHub`) | `storageConnectionFromEnv` `connectionFromEnv` | +| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `kafka` | _(none)_ | _(none)_ | +| `rabbitmq` | `apiHost` `host` | ~~`apiHost`~~ `host` `hostFromEnv` | +| `prometheus` | _(none)_ | _(none)_ | +| `cron` | _(none)_ | _(none)_ | +| `redis` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `redis-streams` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | +| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ | +| `liiklus` | _(none)_ | _(none)_ | +| `stan` | _(none)_ | _(none)_ | +| `huawei-cloudeye` | | _(none)_ | _(none)_ | +| `postgresql` | `connection` `password` | `connectionFromEnv` `passwordFromEnv` | +| `mysql` | `connectionString` `password` | `connectionStringFromEnv` `passwordFromEnv` | ### Scalers **Azure Service Bus** - - `queueLength` was renamed to `messageCount` + +- `queueLength` was renamed to `messageCount` **Kafka** - - `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. + +- `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. **RabbitMQ** In KEDA 2.0 the RabbitMQ scaler has only `host` parameter, and the protocol for communication can be specified by -`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP -protocol. +`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP +protocol. Example of RabbitMQ trigger before 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - includeUnacked: 'true' - apiHost: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + includeUnacked: "true" + apiHost: "https://guest:password@localhost:443/vhostname" +``` The same trigger in 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - protocol: 'http' - host: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + protocol: "http" + host: "https://guest:password@localhost:443/vhostname" +``` ### TriggerAuthentication + In order to use Authentication via `TriggerAuthentication` with KEDA v2, you need to change: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` For more details please refer to the full diff --git a/content/docs/2.2/operate/cluster.md b/content/docs/2.2/operate/cluster.md index 862719278..f010cc0f2 100644 --- a/content/docs/2.2/operate/cluster.md +++ b/content/docs/2.2/operate/cluster.md @@ -29,12 +29,10 @@ KEDA requires to be accessible inside the cluster to be able to autoscale. Here is an overview of the required ports that need to be accessible for KEDA to work: - | Port | Why? | Remarks | | ------ | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication.

This is not applicable for Google Cloud. | +| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication. This is not applicable for Google Cloud. | | `6443` | Used by Kubernetes API server to get metrics | Only required for Google Cloud because it uses Control Plane → port 6443 on the Pod IP range for communication | - ## High Availability @@ -42,10 +40,10 @@ KEDA does not provide full support for high-availability due to upstream limitat Here is an overview of all KEDA deployments and the HA notes: -| Deployment | Support Replicas | Note | -| -------------- | ---------------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Deployment | Support Replicas | Note | +| -------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Metrics Server | 1 | You can run multiple replicas of our metrics sever, and it is recommended to add the `--enable-aggregator-routing=true` CLI flag to the kube-apiserver so that requests sent to our metrics servers are load balanced. However, [you can only run one active metric server in a Kubernetes cluster serving external.metrics.k8s.io](https://github.com/kubernetes-sigs/custom-metrics-apiserver/issues/70) which has to be the KEDA metric server. | -| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover.

This is only supported as of KEDA v2.6 if you are using our Helm chart. | +| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover.This is only supported as of KEDA v2.6 if you are using our Helm chart. | ## HTTP Timeouts diff --git a/content/docs/2.3/concepts/external-scalers.md b/content/docs/2.3/concepts/external-scalers.md index 27ed9e0c6..1945394d3 100644 --- a/content/docs/2.3/concepts/external-scalers.md +++ b/content/docs/2.3/concepts/external-scalers.md @@ -33,15 +33,15 @@ type PushScaler interface { ``` The `Scaler` interface defines 4 methods: + - `IsActive` is called on `pollingInterval` defined in the ScaledObject/ScaledJob CRDs and scaling to 1 happens if this returns true. - `Close` is called to allow the scaler to clean up connections or other resources. - `GetMetricSpec` returns the target value for the HPA definition for the scaler. For more details refer to [Implementing `GetMetricSpec`](#5-implementing-getmetricspec). - `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`. For more details refer to [Implementing `GetMetrics`](#6-implementing-getmetrics). -> Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA uses the metric target type `AverageValue` for external metrics. This will cause the metric value returned by the external scaler to be divided by the number of replicas. + > Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA uses the metric target type `AverageValue` for external metrics. This will cause the metric value returned by the external scaler to be divided by the number of replicas. The `PushScaler` interface adds `Run` method. The `Run` method receives a push channel (`active`), that the scaler can push `true` to any time to force scaling action independently from `pollingInterval`. - ### External Scaler GRPC interface KEDA comes with 2 external scalers [`external`](../scalers/external.md) and [`external-push`](../scalers/external-push.md). @@ -62,6 +62,7 @@ service ExternalScaler { - `StreamIsActive` maps to the `Run` method on the `PushScaler` interface. Few things to notice: + - Lack of `Close` method as the GRPC connection defines the lifetime of the scaler - `IsActive`, `StreamIsActive`, and `GetMetricsSpec` are called with a `ScaledObjectRef` that contains the scaledObject name/namespace as well as the content of `metadata` defined in the trigger. @@ -125,6 +126,7 @@ go mod init example.com/external-scaler/sample mkdir externalscaler protoc externalscaler.proto --go_out=plugins=grpc:externalscaler ``` + {{< /collapsible >}} {{< collapsible "C#" >}} @@ -161,9 +163,8 @@ mkdir Services ```bash npm install --save grpc request ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 3. Implementing `IsActive` @@ -193,6 +194,7 @@ spec: Full implementation can be found here: https://github.com/kedacore/external-scaler-samples `main.go` + ```golang func (e *ExternalScaler) IsActive(ctx context.Context, scaledObject *pb.ScaledObjectRef) (*pb.IsActiveResponse, error) { // request.Scalermetadata contains the `metadata` defined in the ScaledObject @@ -239,12 +241,14 @@ func (e *ExternalScaler) IsActive(ctx context.Context, scaledObject *pb.ScaledOb }, nil } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} Full implementation can be found here: https://github.com/kedacore/external-scaler-samples `Services/ExternalScalerService.cs` + ```csharp public class ExternalScalerService : ExternalScaler.ExternalScalerBase { @@ -277,73 +281,77 @@ public class ExternalScalerService : ExternalScaler.ExternalScalerBase } } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} `index.js` + ```js -const grpc = require('grpc') -const request = require('request') -const externalScalerProto = grpc.load('externalscaler.proto') +const grpc = require("grpc"); +const request = require("request"); +const externalScalerProto = grpc.load("externalscaler.proto"); -const server = new grpc.Server() +const server = new grpc.Server(); server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { isActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { - const now = new Date() - const yesterday = new Date(new Date().setDate(new Date().getDate()-1)); - - const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}` - const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}` - const radiusKm = 500 - const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}` - - request.get({ - url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, - json: true, - }, (err, resp, data) => { - if (err) { - callback({ - code: grpc.status.INTERNAL, - details: err, - }) - } else if (resp.statusCode !== 200) { - callback({ - code: grpc.status.INTERNAL, - details: `expected status 200, got ${resp.statusCode}` - }) - } else { - // count how many earthquakes with mag > 1.0 - let count = 0 - data.features.forEach(i => { - if (i.properties.mag > 1.0) { - count++ - } - }) - callback(null, { - result: count > 2, - }) + const now = new Date(); + const yesterday = new Date(new Date().setDate(new Date().getDate() - 1)); + + const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}`; + const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}`; + const radiusKm = 500; + const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}`; + + request.get( + { + url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, + json: true, + }, + (err, resp, data) => { + if (err) { + callback({ + code: grpc.status.INTERNAL, + details: err, + }); + } else if (resp.statusCode !== 200) { + callback({ + code: grpc.status.INTERNAL, + details: `expected status 200, got ${resp.statusCode}`, + }); + } else { + // count how many earthquakes with mag > 1.0 + let count = 0; + data.features.forEach((i) => { + if (i.properties.mag > 1.0) { + count++; + } + }); + callback(null, { + result: count > 2, + }); + } } - }) + ); } - } -}) + }, +}); -server.bind('127.0.0.1:9090', grpc.ServerCredentials.createInsecure()) -console.log('Server listening on 127.0.0.1:9090') +server.bind("127.0.0.1:9090", grpc.ServerCredentials.createInsecure()); +console.log("Server listening on 127.0.0.1:9090"); -server.start() +server.start(); ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 4. Implementing `StreamIsActive` @@ -351,8 +359,8 @@ Unlike `IsActive`, `StreamIsActive` is called once when KEDA reconciles the `Sca This implementation creates a timer and queries USGS APIs on that timer, effectively ignoring `pollingInterval` set in the scaledObject. Alternatively any other asynchronous event can be used instead of a timer, like an HTTP request, or a network connection. - {{< collapsible "Golang" >}} + ```golang func (e *ExternalScaler) StreamIsActive(scaledObject *pb.ScaledObjectRef, epsServer pb.ExternalScaler_StreamIsActiveServer) error { longitude := scaledObject.ScalerMetadata["longitude"] @@ -380,9 +388,11 @@ func (e *ExternalScaler) StreamIsActive(scaledObject *pb.ScaledObjectRef, epsSer } } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} + ```csharp public override async Task StreamIsActive(ScaledObjectRef request, IServerStreamWriter responseStream, ServerCallContext context) { @@ -410,49 +420,51 @@ public override async Task StreamIsActive(ScaledObjectRef request, IServerStream } } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} + ```js server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... streamIsActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { const interval = setInterval(() => { getEarthquakeCount((err, count) => { if (err) { - console.error(err) + console.error(err); } else if (count > 2) { call.write({ result: true, - }) + }); } - }) + }); }, 1000 * 60 * 60); - call.on('end', () => { - clearInterval(interval) - }) + call.on("end", () => { + clearInterval(interval); + }); } - } -}) + }, +}); ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 5. Implementing `GetMetricSpec` `GetMetricSpec` returns the `target` value for [the HPA definition for the scaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/). This scaler will define a static target of 10, but the threshold value is often specified in the metadata for other scalers. {{< collapsible "Golang" >}} + ```golang func (e *ExternalScaler) GetMetricSpec(context.Context, *pb.ScaledObjectRef) (*pb.GetMetricSpecResponse, error) { return &pb.GetMetricSpecResponse{ @@ -463,9 +475,11 @@ func (e *ExternalScaler) GetMetricSpec(context.Context, *pb.ScaledObjectRef) (*p }, nil } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} + ```csharp public override async Task GetMetricSpec(ScaledObjectRef request, ServerCallContext context) { @@ -480,31 +494,35 @@ public override async Task GetMetricSpec(ScaledObjectRef return Task.FromResult(resp); } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} + ```js server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetricSpec: (call, callback) => { callback(null, { - metricSpecs: [{ - metricName: 'earthquakeThreshold', - targetSize: 10, - }] - }) - } -}) + metricSpecs: [ + { + metricName: "earthquakeThreshold", + targetSize: 10, + }, + ], + }); + }, +}); ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 6. Implementing `GetMetrics` `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`, in this example it's `earthquakeThreshold`. {{< collapsible "Golang" >}} + ```golang func (e *ExternalScaler) GetMetrics(_ context.Context, metricRequest *pb.GetMetricsRequest) (*pb.GetMetricsResponse, error) { longitude := metricRequest.ScaledObjectRef.ScalerMetadata["longitude"] @@ -527,9 +545,11 @@ func (e *ExternalScaler) GetMetrics(_ context.Context, metricRequest *pb.GetMetr }, nil } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} + ```csharp public override async Task GetMetrics(GetMetricsRequest request, ServerCallContext context) { @@ -554,38 +574,43 @@ public override async Task GetMetrics(GetMetricsRequest requ return resp; } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} + ```js server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetrics: (call, callback) => { - const longitude = call.request.scaledObjectRef.scalerMetadata.longitude - const latitude = call.request.scaledObjectRef.scalerMetadata.latitude + const longitude = call.request.scaledObjectRef.scalerMetadata.longitude; + const latitude = call.request.scaledObjectRef.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { getEarthquakeCount((err, count) => { if (err) { callback({ code: grpc.status.INTERNAL, details: err, - }) + }); } else { callback(null, { - metricValues: [{ - metricName: 'earthquakeThreshold', - metricValue: count, - }] - }) + metricValues: [ + { + metricName: "earthquakeThreshold", + metricValue: count, + }, + ], + }); } - }) + }); } - } -}) + }, +}); ``` + {{< /collapsible >}} diff --git a/content/docs/2.3/migration.md b/content/docs/2.3/migration.md index 5ee8a6455..29e8408c8 100644 --- a/content/docs/2.3/migration.md +++ b/content/docs/2.3/migration.md @@ -11,15 +11,17 @@ Please note that you **can not** run both KEDA v1 and v2 on the same Kubernetes KEDA v2 is using a new API namespace for its Custom Resources Definitions (CRD): `keda.sh` instead of `keda.k8s.io` and introduces a new Custom Resource for scaling of Jobs. See full details on KEDA Custom Resources [here](../concepts/#custom-resources-crd). Here's an overview of what's changed: + - [Scaling of Deployments](#scaling-of-deployments) - [Scaling of Jobs](#scaling-of-jobs) - [Improved flexibility & usability of trigger metadata](#improved-flexibility--usability-of-trigger-metadata) - [Scalers](#scalers) - [TriggerAuthentication](#triggerauthentication) - ### Scaling of Deployments + In order to scale `Deployments` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Rename property `spec.scaleTargetRef.deploymentName` to `spec.scaleTargetRef.name` - Rename property `spec.scaleTargetRef.containerName` to `spec.scaleTargetRef.envSourceContainerName` @@ -27,22 +29,23 @@ In order to scale `Deployments` with KEDA v2, you need to do only a few modifica Please see the examples below or refer to the full [v2 ScaledObject Specification](../concepts/scaling-deployments/#scaledobject-spec) - **Example of v1 ScaledObject** +**Example of v1 ScaledObject** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } labels: - deploymentName: {deployment-name} + deploymentName: { deployment-name } spec: scaleTargetRef: - deploymentName: {deployment-name} - containerName: {container-name} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + deploymentName: { deployment-name } + containerName: { container-name } + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -50,18 +53,18 @@ spec: **Example of v2 ScaledObject** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed kind: ScaledObject -metadata: # <--- labels.deploymentName is not needed - name: {scaled-object-name} +metadata: # <--- labels.deploymentName is not needed + name: { scaled-object-name } spec: scaleTargetRef: - name: {deployment-name} # <--- Property name was changed - envSourceContainerName: {container-name} # <--- Property name was changed - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + name: { deployment-name } # <--- Property name was changed + envSourceContainerName: { container-name } # <--- Property name was changed + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -69,34 +72,36 @@ spec: ### Scaling of Jobs In order to scale `Jobs` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Change the value of `kind` property from `ScaledObject` to `ScaledJob` - Remove property `spec.scaleType` -- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` +- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` You can configure `successfulJobsHistoryLimit` and `failedJobsHistoryLimit`. They will remove the old job histories automatically. Please see the examples below or refer to the full [v2 ScaledJob Specification](../concepts/scaling-jobs/#scaledjob-spec) **Example of v1 ScaledObject for Jobs scaling** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } spec: scaleType: job jobTargetRef: - parallelism: 1 + parallelism: 1 completions: 1 activeDeadlineSeconds: 600 - backoffLimit: 6 + backoffLimit: 6 template: # {job template} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to create jobs} ``` @@ -104,21 +109,21 @@ spec: **Example of v2 ScaledJob** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed -kind: ScaledJob # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +kind: ScaledJob # <--- Property value was changed metadata: - name: {scaled-job-name} -spec: # <--- spec.scaleType is not needed + name: { scaled-job-name } +spec: # <--- spec.scaleType is not needed jobTargetRef: - parallelism: 1 - completions: 1 + parallelism: 1 + completions: 1 activeDeadlineSeconds: 600 backoffLimit: 6 template: # {job template} - pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed - successfulJobsHistoryLimit: 5 # <--- property is added - failedJobsHistoryLimit: 5 # <--- Property is added + pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed + successfulJobsHistoryLimit: 5 # <--- property is added + failedJobsHistoryLimit: 5 # <--- Property is added maxReplicaCount: 100 triggers: # {list of triggers to create jobs} @@ -132,68 +137,74 @@ We've introduced more options to configure trigger metadata to give users more f Here's an overview: -| Scaler | 1.x | 2.0 | -|--------|--------|--------| -| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | -| `azure-monitor` | `activeDirectoryClientId`
`activeDirectoryClientPassword` | `activeDirectoryClientId`
`activeDirectoryClientIdFromEnv`
`activeDirectoryClientPasswordFromEnv` | -| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | -| `azure-servicebus` | `connection` | `connectionFromEnv` | -| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`)
`connection` (**Default**: `EventHub`) | `storageConnectionFromEnv`
`connectionFromEnv` | -| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `kafka` | _(none)_ | _(none)_ -| `rabbitmq` | `apiHost`
`host` | ~~`apiHost`~~
`host`
`hostFromEnv` | -| `prometheus` | _(none)_ | _(none)_ | -| `cron` | _(none)_ | _(none)_ | -| `redis` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `redis-streams` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | -| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ -| `liiklus` | _(none)_ | _(none)_ | -| `stan` | _(none)_ | _(none)_ | -| `huawei-cloudeye` | | _(none)_ | _(none)_ | -| `postgresql` | `connection`
`password` | `connectionFromEnv`
`passwordFromEnv` | -| `mysql` | `connectionString`
`password` | `connectionStringFromEnv`
`passwordFromEnv` | +| Scaler | 1.x | 2.0 | +| -------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------- | +| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | +| `azure-monitor` | `activeDirectoryClientId` `activeDirectoryClientPassword` | `activeDirectoryClientId` `activeDirectoryClientIdFromEnv` `activeDirectoryClientPasswordFromEnv` | +| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | +| `azure-servicebus` | `connection` | `connectionFromEnv` | +| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`) `connection` (**Default**: `EventHub`) | `storageConnectionFromEnv` `connectionFromEnv` | +| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `kafka` | _(none)_ | _(none)_ | +| `rabbitmq` | `apiHost` `host` | ~~`apiHost`~~ `host` `hostFromEnv` | +| `prometheus` | _(none)_ | _(none)_ | +| `cron` | _(none)_ | _(none)_ | +| `redis` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `redis-streams` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | +| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ | +| `liiklus` | _(none)_ | _(none)_ | +| `stan` | _(none)_ | _(none)_ | +| `huawei-cloudeye` | | _(none)_ | _(none)_ | +| `postgresql` | `connection` `password` | `connectionFromEnv` `passwordFromEnv` | +| `mysql` | `connectionString` `password` | `connectionStringFromEnv` `passwordFromEnv` | ### Scalers **Azure Service Bus** - - `queueLength` was renamed to `messageCount` + +- `queueLength` was renamed to `messageCount` **Kafka** - - `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. + +- `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. **RabbitMQ** In KEDA 2.0 the RabbitMQ scaler has only `host` parameter, and the protocol for communication can be specified by -`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP -protocol. +`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP +protocol. Example of RabbitMQ trigger before 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - includeUnacked: 'true' - apiHost: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + includeUnacked: "true" + apiHost: "https://guest:password@localhost:443/vhostname" +``` The same trigger in 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - protocol: 'http' - host: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + protocol: "http" + host: "https://guest:password@localhost:443/vhostname" +``` ### TriggerAuthentication + In order to use Authentication via `TriggerAuthentication` with KEDA v2, you need to change: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` For more details please refer to the full diff --git a/content/docs/2.3/operate/cluster.md b/content/docs/2.3/operate/cluster.md index 4caa62f3d..f010cc0f2 100644 --- a/content/docs/2.3/operate/cluster.md +++ b/content/docs/2.3/operate/cluster.md @@ -29,12 +29,10 @@ KEDA requires to be accessible inside the cluster to be able to autoscale. Here is an overview of the required ports that need to be accessible for KEDA to work: - | Port | Why? | Remarks | | ------ | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication.

This is not applicable for Google Cloud. | +| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication. This is not applicable for Google Cloud. | | `6443` | Used by Kubernetes API server to get metrics | Only required for Google Cloud because it uses Control Plane → port 6443 on the Pod IP range for communication | - ## High Availability @@ -42,14 +40,14 @@ KEDA does not provide full support for high-availability due to upstream limitat Here is an overview of all KEDA deployments and the HA notes: -| Deployment | Support Replicas | Note | -| -------------- | ---------------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Deployment | Support Replicas | Note | +| -------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Metrics Server | 1 | You can run multiple replicas of our metrics sever, and it is recommended to add the `--enable-aggregator-routing=true` CLI flag to the kube-apiserver so that requests sent to our metrics servers are load balanced. However, [you can only run one active metric server in a Kubernetes cluster serving external.metrics.k8s.io](https://github.com/kubernetes-sigs/custom-metrics-apiserver/issues/70) which has to be the KEDA metric server. | -| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover.

This is only supported as of KEDA v2.6 if you are using our Helm chart. | +| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover.This is only supported as of KEDA v2.6 if you are using our Helm chart. | ## HTTP Timeouts -Some scalers issue HTTP requests to external servers (i.e. cloud services). Each applicable scaler uses its own dedicated HTTP client with its own connection pool, and by default each client is set to time out any HTTP request after 3 seconds. +Some scalers issue HTTP requests to external servers (i.e. cloud services). Each applicable scaler uses its own dedicated HTTP client with its own connection pool, and by default each client is set to time out any HTTP request after 3 seconds. You can override this default by setting the `KEDA_HTTP_DEFAULT_TIMEOUT` environment variable to your desired timeout in milliseconds. For example, on Linux/Mac/Windows WSL2 operating systems, you'd use this command to set to 1 second: diff --git a/content/docs/2.4/concepts/external-scalers.md b/content/docs/2.4/concepts/external-scalers.md index 27ed9e0c6..1945394d3 100644 --- a/content/docs/2.4/concepts/external-scalers.md +++ b/content/docs/2.4/concepts/external-scalers.md @@ -33,15 +33,15 @@ type PushScaler interface { ``` The `Scaler` interface defines 4 methods: + - `IsActive` is called on `pollingInterval` defined in the ScaledObject/ScaledJob CRDs and scaling to 1 happens if this returns true. - `Close` is called to allow the scaler to clean up connections or other resources. - `GetMetricSpec` returns the target value for the HPA definition for the scaler. For more details refer to [Implementing `GetMetricSpec`](#5-implementing-getmetricspec). - `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`. For more details refer to [Implementing `GetMetrics`](#6-implementing-getmetrics). -> Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA uses the metric target type `AverageValue` for external metrics. This will cause the metric value returned by the external scaler to be divided by the number of replicas. + > Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA uses the metric target type `AverageValue` for external metrics. This will cause the metric value returned by the external scaler to be divided by the number of replicas. The `PushScaler` interface adds `Run` method. The `Run` method receives a push channel (`active`), that the scaler can push `true` to any time to force scaling action independently from `pollingInterval`. - ### External Scaler GRPC interface KEDA comes with 2 external scalers [`external`](../scalers/external.md) and [`external-push`](../scalers/external-push.md). @@ -62,6 +62,7 @@ service ExternalScaler { - `StreamIsActive` maps to the `Run` method on the `PushScaler` interface. Few things to notice: + - Lack of `Close` method as the GRPC connection defines the lifetime of the scaler - `IsActive`, `StreamIsActive`, and `GetMetricsSpec` are called with a `ScaledObjectRef` that contains the scaledObject name/namespace as well as the content of `metadata` defined in the trigger. @@ -125,6 +126,7 @@ go mod init example.com/external-scaler/sample mkdir externalscaler protoc externalscaler.proto --go_out=plugins=grpc:externalscaler ``` + {{< /collapsible >}} {{< collapsible "C#" >}} @@ -161,9 +163,8 @@ mkdir Services ```bash npm install --save grpc request ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 3. Implementing `IsActive` @@ -193,6 +194,7 @@ spec: Full implementation can be found here: https://github.com/kedacore/external-scaler-samples `main.go` + ```golang func (e *ExternalScaler) IsActive(ctx context.Context, scaledObject *pb.ScaledObjectRef) (*pb.IsActiveResponse, error) { // request.Scalermetadata contains the `metadata` defined in the ScaledObject @@ -239,12 +241,14 @@ func (e *ExternalScaler) IsActive(ctx context.Context, scaledObject *pb.ScaledOb }, nil } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} Full implementation can be found here: https://github.com/kedacore/external-scaler-samples `Services/ExternalScalerService.cs` + ```csharp public class ExternalScalerService : ExternalScaler.ExternalScalerBase { @@ -277,73 +281,77 @@ public class ExternalScalerService : ExternalScaler.ExternalScalerBase } } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} `index.js` + ```js -const grpc = require('grpc') -const request = require('request') -const externalScalerProto = grpc.load('externalscaler.proto') +const grpc = require("grpc"); +const request = require("request"); +const externalScalerProto = grpc.load("externalscaler.proto"); -const server = new grpc.Server() +const server = new grpc.Server(); server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { isActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { - const now = new Date() - const yesterday = new Date(new Date().setDate(new Date().getDate()-1)); - - const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}` - const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}` - const radiusKm = 500 - const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}` - - request.get({ - url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, - json: true, - }, (err, resp, data) => { - if (err) { - callback({ - code: grpc.status.INTERNAL, - details: err, - }) - } else if (resp.statusCode !== 200) { - callback({ - code: grpc.status.INTERNAL, - details: `expected status 200, got ${resp.statusCode}` - }) - } else { - // count how many earthquakes with mag > 1.0 - let count = 0 - data.features.forEach(i => { - if (i.properties.mag > 1.0) { - count++ - } - }) - callback(null, { - result: count > 2, - }) + const now = new Date(); + const yesterday = new Date(new Date().setDate(new Date().getDate() - 1)); + + const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}`; + const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}`; + const radiusKm = 500; + const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}`; + + request.get( + { + url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, + json: true, + }, + (err, resp, data) => { + if (err) { + callback({ + code: grpc.status.INTERNAL, + details: err, + }); + } else if (resp.statusCode !== 200) { + callback({ + code: grpc.status.INTERNAL, + details: `expected status 200, got ${resp.statusCode}`, + }); + } else { + // count how many earthquakes with mag > 1.0 + let count = 0; + data.features.forEach((i) => { + if (i.properties.mag > 1.0) { + count++; + } + }); + callback(null, { + result: count > 2, + }); + } } - }) + ); } - } -}) + }, +}); -server.bind('127.0.0.1:9090', grpc.ServerCredentials.createInsecure()) -console.log('Server listening on 127.0.0.1:9090') +server.bind("127.0.0.1:9090", grpc.ServerCredentials.createInsecure()); +console.log("Server listening on 127.0.0.1:9090"); -server.start() +server.start(); ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 4. Implementing `StreamIsActive` @@ -351,8 +359,8 @@ Unlike `IsActive`, `StreamIsActive` is called once when KEDA reconciles the `Sca This implementation creates a timer and queries USGS APIs on that timer, effectively ignoring `pollingInterval` set in the scaledObject. Alternatively any other asynchronous event can be used instead of a timer, like an HTTP request, or a network connection. - {{< collapsible "Golang" >}} + ```golang func (e *ExternalScaler) StreamIsActive(scaledObject *pb.ScaledObjectRef, epsServer pb.ExternalScaler_StreamIsActiveServer) error { longitude := scaledObject.ScalerMetadata["longitude"] @@ -380,9 +388,11 @@ func (e *ExternalScaler) StreamIsActive(scaledObject *pb.ScaledObjectRef, epsSer } } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} + ```csharp public override async Task StreamIsActive(ScaledObjectRef request, IServerStreamWriter responseStream, ServerCallContext context) { @@ -410,49 +420,51 @@ public override async Task StreamIsActive(ScaledObjectRef request, IServerStream } } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} + ```js server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... streamIsActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { const interval = setInterval(() => { getEarthquakeCount((err, count) => { if (err) { - console.error(err) + console.error(err); } else if (count > 2) { call.write({ result: true, - }) + }); } - }) + }); }, 1000 * 60 * 60); - call.on('end', () => { - clearInterval(interval) - }) + call.on("end", () => { + clearInterval(interval); + }); } - } -}) + }, +}); ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 5. Implementing `GetMetricSpec` `GetMetricSpec` returns the `target` value for [the HPA definition for the scaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/). This scaler will define a static target of 10, but the threshold value is often specified in the metadata for other scalers. {{< collapsible "Golang" >}} + ```golang func (e *ExternalScaler) GetMetricSpec(context.Context, *pb.ScaledObjectRef) (*pb.GetMetricSpecResponse, error) { return &pb.GetMetricSpecResponse{ @@ -463,9 +475,11 @@ func (e *ExternalScaler) GetMetricSpec(context.Context, *pb.ScaledObjectRef) (*p }, nil } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} + ```csharp public override async Task GetMetricSpec(ScaledObjectRef request, ServerCallContext context) { @@ -480,31 +494,35 @@ public override async Task GetMetricSpec(ScaledObjectRef return Task.FromResult(resp); } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} + ```js server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetricSpec: (call, callback) => { callback(null, { - metricSpecs: [{ - metricName: 'earthquakeThreshold', - targetSize: 10, - }] - }) - } -}) + metricSpecs: [ + { + metricName: "earthquakeThreshold", + targetSize: 10, + }, + ], + }); + }, +}); ``` -{{< /collapsible >}} -
+{{< /collapsible >}} #### 6. Implementing `GetMetrics` `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`, in this example it's `earthquakeThreshold`. {{< collapsible "Golang" >}} + ```golang func (e *ExternalScaler) GetMetrics(_ context.Context, metricRequest *pb.GetMetricsRequest) (*pb.GetMetricsResponse, error) { longitude := metricRequest.ScaledObjectRef.ScalerMetadata["longitude"] @@ -527,9 +545,11 @@ func (e *ExternalScaler) GetMetrics(_ context.Context, metricRequest *pb.GetMetr }, nil } ``` + {{< /collapsible >}} {{< collapsible "C#" >}} + ```csharp public override async Task GetMetrics(GetMetricsRequest request, ServerCallContext context) { @@ -554,38 +574,43 @@ public override async Task GetMetrics(GetMetricsRequest requ return resp; } ``` + {{< /collapsible >}} {{< collapsible "Javascript" >}} + ```js server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetrics: (call, callback) => { - const longitude = call.request.scaledObjectRef.scalerMetadata.longitude - const latitude = call.request.scaledObjectRef.scalerMetadata.latitude + const longitude = call.request.scaledObjectRef.scalerMetadata.longitude; + const latitude = call.request.scaledObjectRef.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { getEarthquakeCount((err, count) => { if (err) { callback({ code: grpc.status.INTERNAL, details: err, - }) + }); } else { callback(null, { - metricValues: [{ - metricName: 'earthquakeThreshold', - metricValue: count, - }] - }) + metricValues: [ + { + metricName: "earthquakeThreshold", + metricValue: count, + }, + ], + }); } - }) + }); } - } -}) + }, +}); ``` + {{< /collapsible >}} diff --git a/content/docs/2.4/migration.md b/content/docs/2.4/migration.md index 5ee8a6455..29e8408c8 100644 --- a/content/docs/2.4/migration.md +++ b/content/docs/2.4/migration.md @@ -11,15 +11,17 @@ Please note that you **can not** run both KEDA v1 and v2 on the same Kubernetes KEDA v2 is using a new API namespace for its Custom Resources Definitions (CRD): `keda.sh` instead of `keda.k8s.io` and introduces a new Custom Resource for scaling of Jobs. See full details on KEDA Custom Resources [here](../concepts/#custom-resources-crd). Here's an overview of what's changed: + - [Scaling of Deployments](#scaling-of-deployments) - [Scaling of Jobs](#scaling-of-jobs) - [Improved flexibility & usability of trigger metadata](#improved-flexibility--usability-of-trigger-metadata) - [Scalers](#scalers) - [TriggerAuthentication](#triggerauthentication) - ### Scaling of Deployments + In order to scale `Deployments` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Rename property `spec.scaleTargetRef.deploymentName` to `spec.scaleTargetRef.name` - Rename property `spec.scaleTargetRef.containerName` to `spec.scaleTargetRef.envSourceContainerName` @@ -27,22 +29,23 @@ In order to scale `Deployments` with KEDA v2, you need to do only a few modifica Please see the examples below or refer to the full [v2 ScaledObject Specification](../concepts/scaling-deployments/#scaledobject-spec) - **Example of v1 ScaledObject** +**Example of v1 ScaledObject** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } labels: - deploymentName: {deployment-name} + deploymentName: { deployment-name } spec: scaleTargetRef: - deploymentName: {deployment-name} - containerName: {container-name} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + deploymentName: { deployment-name } + containerName: { container-name } + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -50,18 +53,18 @@ spec: **Example of v2 ScaledObject** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed kind: ScaledObject -metadata: # <--- labels.deploymentName is not needed - name: {scaled-object-name} +metadata: # <--- labels.deploymentName is not needed + name: { scaled-object-name } spec: scaleTargetRef: - name: {deployment-name} # <--- Property name was changed - envSourceContainerName: {container-name} # <--- Property name was changed - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + name: { deployment-name } # <--- Property name was changed + envSourceContainerName: { container-name } # <--- Property name was changed + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -69,34 +72,36 @@ spec: ### Scaling of Jobs In order to scale `Jobs` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Change the value of `kind` property from `ScaledObject` to `ScaledJob` - Remove property `spec.scaleType` -- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` +- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` You can configure `successfulJobsHistoryLimit` and `failedJobsHistoryLimit`. They will remove the old job histories automatically. Please see the examples below or refer to the full [v2 ScaledJob Specification](../concepts/scaling-jobs/#scaledjob-spec) **Example of v1 ScaledObject for Jobs scaling** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } spec: scaleType: job jobTargetRef: - parallelism: 1 + parallelism: 1 completions: 1 activeDeadlineSeconds: 600 - backoffLimit: 6 + backoffLimit: 6 template: # {job template} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to create jobs} ``` @@ -104,21 +109,21 @@ spec: **Example of v2 ScaledJob** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed -kind: ScaledJob # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +kind: ScaledJob # <--- Property value was changed metadata: - name: {scaled-job-name} -spec: # <--- spec.scaleType is not needed + name: { scaled-job-name } +spec: # <--- spec.scaleType is not needed jobTargetRef: - parallelism: 1 - completions: 1 + parallelism: 1 + completions: 1 activeDeadlineSeconds: 600 backoffLimit: 6 template: # {job template} - pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed - successfulJobsHistoryLimit: 5 # <--- property is added - failedJobsHistoryLimit: 5 # <--- Property is added + pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed + successfulJobsHistoryLimit: 5 # <--- property is added + failedJobsHistoryLimit: 5 # <--- Property is added maxReplicaCount: 100 triggers: # {list of triggers to create jobs} @@ -132,68 +137,74 @@ We've introduced more options to configure trigger metadata to give users more f Here's an overview: -| Scaler | 1.x | 2.0 | -|--------|--------|--------| -| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | -| `azure-monitor` | `activeDirectoryClientId`
`activeDirectoryClientPassword` | `activeDirectoryClientId`
`activeDirectoryClientIdFromEnv`
`activeDirectoryClientPasswordFromEnv` | -| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | -| `azure-servicebus` | `connection` | `connectionFromEnv` | -| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`)
`connection` (**Default**: `EventHub`) | `storageConnectionFromEnv`
`connectionFromEnv` | -| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `kafka` | _(none)_ | _(none)_ -| `rabbitmq` | `apiHost`
`host` | ~~`apiHost`~~
`host`
`hostFromEnv` | -| `prometheus` | _(none)_ | _(none)_ | -| `cron` | _(none)_ | _(none)_ | -| `redis` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `redis-streams` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | -| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ -| `liiklus` | _(none)_ | _(none)_ | -| `stan` | _(none)_ | _(none)_ | -| `huawei-cloudeye` | | _(none)_ | _(none)_ | -| `postgresql` | `connection`
`password` | `connectionFromEnv`
`passwordFromEnv` | -| `mysql` | `connectionString`
`password` | `connectionStringFromEnv`
`passwordFromEnv` | +| Scaler | 1.x | 2.0 | +| -------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------- | +| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | +| `azure-monitor` | `activeDirectoryClientId` `activeDirectoryClientPassword` | `activeDirectoryClientId` `activeDirectoryClientIdFromEnv` `activeDirectoryClientPasswordFromEnv` | +| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | +| `azure-servicebus` | `connection` | `connectionFromEnv` | +| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`) `connection` (**Default**: `EventHub`) | `storageConnectionFromEnv` `connectionFromEnv` | +| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `kafka` | _(none)_ | _(none)_ | +| `rabbitmq` | `apiHost` `host` | ~~`apiHost`~~ `host` `hostFromEnv` | +| `prometheus` | _(none)_ | _(none)_ | +| `cron` | _(none)_ | _(none)_ | +| `redis` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `redis-streams` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | +| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ | +| `liiklus` | _(none)_ | _(none)_ | +| `stan` | _(none)_ | _(none)_ | +| `huawei-cloudeye` | | _(none)_ | _(none)_ | +| `postgresql` | `connection` `password` | `connectionFromEnv` `passwordFromEnv` | +| `mysql` | `connectionString` `password` | `connectionStringFromEnv` `passwordFromEnv` | ### Scalers **Azure Service Bus** - - `queueLength` was renamed to `messageCount` + +- `queueLength` was renamed to `messageCount` **Kafka** - - `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. + +- `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. **RabbitMQ** In KEDA 2.0 the RabbitMQ scaler has only `host` parameter, and the protocol for communication can be specified by -`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP -protocol. +`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP +protocol. Example of RabbitMQ trigger before 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - includeUnacked: 'true' - apiHost: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + includeUnacked: "true" + apiHost: "https://guest:password@localhost:443/vhostname" +``` The same trigger in 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - protocol: 'http' - host: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + protocol: "http" + host: "https://guest:password@localhost:443/vhostname" +``` ### TriggerAuthentication + In order to use Authentication via `TriggerAuthentication` with KEDA v2, you need to change: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` For more details please refer to the full diff --git a/content/docs/2.4/operate/cluster.md b/content/docs/2.4/operate/cluster.md index 9c5ee2895..8ace09018 100644 --- a/content/docs/2.4/operate/cluster.md +++ b/content/docs/2.4/operate/cluster.md @@ -29,12 +29,10 @@ KEDA requires to be accessible inside the cluster to be able to autoscale. Here is an overview of the required ports that need to be accessible for KEDA to work: - | Port | Why? | Remarks | | ------ | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication.

This is not applicable for Google Cloud. | +| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication. This is not applicable for Google Cloud. | | `6443` | Used by Kubernetes API server to get metrics | Only required for Google Cloud because it uses Control Plane → port 6443 on the Pod IP range for communication | - ## High Availability @@ -42,14 +40,14 @@ KEDA does not provide full support for high-availability due to upstream limitat Here is an overview of all KEDA deployments and the HA notes: -| Deployment | Support Replicas | Note | -| -------------- | ---------------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Deployment | Support Replicas | Note | +| -------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Metrics Server | 1 | You can run multiple replicas of our metrics sever, and it is recommended to add the `--enable-aggregator-routing=true` CLI flag to the kube-apiserver so that requests sent to our metrics servers are load balanced. However, [you can only run one active metric server in a Kubernetes cluster serving external.metrics.k8s.io](https://github.com/kubernetes-sigs/custom-metrics-apiserver/issues/70) which has to be the KEDA metric server. | -| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover.

This is only supported as of KEDA v2.6 if you are using our Helm chart. | +| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover.This is only supported as of KEDA v2.6 if you are using our Helm chart. | ## HTTP Timeouts -Some scalers issue HTTP requests to external servers (i.e. cloud services). Each applicable scaler uses its own dedicated HTTP client with its own connection pool, and by default each client is set to time out any HTTP request after 3 seconds. +Some scalers issue HTTP requests to external servers (i.e. cloud services). Each applicable scaler uses its own dedicated HTTP client with its own connection pool, and by default each client is set to time out any HTTP request after 3 seconds. You can override this default by setting the `KEDA_HTTP_DEFAULT_TIMEOUT` environment variable to your desired timeout in milliseconds. For example, on Linux/Mac/Windows WSL2 operating systems, you'd use this command to set to 1 second: @@ -69,9 +67,7 @@ All applicable scalers will use this timeout. Setting a per-scaler timeout is cu The Kubernetes client config used within KEDA Metrics Adapter can be adjusted by passing the following command-line flags to the binary: -| Adapter Flag | Client Config Setting | Default Value | Description | -| -------------- | ----------------------- | ------------- | -------------------------------------------------------------- | -| kube-api-qps | cfg.QPS | 20.0 | Set the QPS rate for throttling requests sent to the apiserver | -| kube-api-burst | cfg.Burst | 30 | Set the burst for throttling requests sent to the apiserver | - - +| Adapter Flag | Client Config Setting | Default Value | Description | +| -------------- | --------------------- | ------------- | -------------------------------------------------------------- | +| kube-api-qps | cfg.QPS | 20.0 | Set the QPS rate for throttling requests sent to the apiserver | +| kube-api-burst | cfg.Burst | 30 | Set the burst for throttling requests sent to the apiserver | diff --git a/content/docs/2.5/concepts/external-scalers.md b/content/docs/2.5/concepts/external-scalers.md index 47c4a45a9..214107edc 100644 --- a/content/docs/2.5/concepts/external-scalers.md +++ b/content/docs/2.5/concepts/external-scalers.md @@ -9,7 +9,7 @@ Built-in scalers run in the KEDA process/pod, while external scalers require an This document describes the external scaler interfaces and how to implement them in Go, Node, and .NET; however for more details on GRPC refer to [the official GRPC documentation](https://grpc.io/docs/) ->Want to learn about existing external scalers? Explore our [external scaler community](https://github.com/kedacore/external-scalers). +> Want to learn about existing external scalers? Explore our [external scaler community](https://github.com/kedacore/external-scalers). ## Overview @@ -34,12 +34,12 @@ type PushScaler interface { The `Scaler` interface defines 4 methods: -- `IsActive` is called on `pollingInterval`. When `isActive` returns `true`, KEDA will scale to what is returned by `GetMetricSpec` limited by `maxReplicaCount` on the ScaledObject/ScaledJob. - When `false` is returned, KEDA will scale to `minReplicaCount` or optionally `idleReplicaCount`. More details around the defaults and how these options work together can be found on the [ScaledObjectSpec](https://keda.sh/docs/2.6/concepts/scaling-deployments/#scaledobject-spec). +- `IsActive` is called on `pollingInterval`. When `isActive` returns `true`, KEDA will scale to what is returned by `GetMetricSpec` limited by `maxReplicaCount` on the ScaledObject/ScaledJob. + When `false` is returned, KEDA will scale to `minReplicaCount` or optionally `idleReplicaCount`. More details around the defaults and how these options work together can be found on the [ScaledObjectSpec](https://keda.sh/docs/2.6/concepts/scaling-deployments/#scaledobject-spec). - `Close` is called to allow the scaler to clean up connections or other resources. - `GetMetricSpec` returns the target value for the HPA definition for the scaler. For more details refer to [Implementing `GetMetricSpec`](#5-implementing-getmetricspec). - `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`. For more details refer to [Implementing `GetMetrics`](#6-implementing-getmetrics). -> Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA uses the metric target type `AverageValue` for external metrics. This will cause the metric value returned by the external scaler to be divided by the number of replicas. + > Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA uses the metric target type `AverageValue` for external metrics. This will cause the metric value returned by the external scaler to be divided by the number of replicas. The `PushScaler` interface adds a `Run` method. This method receives a push channel (`active`), on which the scaler can send `true` at any time. The purpose of this mechanism is to initiate a scaling operation independently from `pollingInterval`. @@ -109,7 +109,7 @@ KEDA will attempt a GRPC connection to `service-address.svc.local:9090` immediat } ``` ->**Note**: KEDA will issue all of the above RPC calls except `StreamIsActive` if `spec.triggers.type` is `external`. It _must_ be `external-push` for `StreamIsActive` to be called. +> **Note**: KEDA will issue all of the above RPC calls except `StreamIsActive` if `spec.triggers.type` is `external`. It _must_ be `external-push` for `StreamIsActive` to be called. ## Implementing KEDA external scaler GRPC interface @@ -176,8 +176,6 @@ npm install --save grpc request {{< /collapsible >}} -
- #### 3. Implementing `IsActive` Just like `IsActive(ctx context.Context) (bool, error)` in the go interface, the `IsActive` method in the GRPC interface is called every `pollingInterval` with a `ScaledObjectRef` object that contains the scaledObject name, namespace, and scaler metadata. @@ -304,70 +302,71 @@ public class ExternalScalerService : ExternalScaler.ExternalScalerBase Put the following code into your `index.js` file: ```js -const grpc = require('grpc') -const request = require('request') -const externalScalerProto = grpc.load('externalscaler.proto') +const grpc = require("grpc"); +const request = require("request"); +const externalScalerProto = grpc.load("externalscaler.proto"); -const server = new grpc.Server() +const server = new grpc.Server(); server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { isActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { - const now = new Date() - const yesterday = new Date(new Date().setDate(new Date().getDate()-1)); - - const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}` - const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}` - const radiusKm = 500 - const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}` - - request.get({ - url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, - json: true, - }, (err, resp, data) => { - if (err) { - callback({ - code: grpc.status.INTERNAL, - details: err, - }) - } else if (resp.statusCode !== 200) { - callback({ - code: grpc.status.INTERNAL, - details: `expected status 200, got ${resp.statusCode}` - }) - } else { - // count how many earthquakes with mag > 1.0 - let count = 0 - data.features.forEach(i => { - if (i.properties.mag > 1.0) { - count++ - } - }) - callback(null, { - result: count > 2, - }) + const now = new Date(); + const yesterday = new Date(new Date().setDate(new Date().getDate() - 1)); + + const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}`; + const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}`; + const radiusKm = 500; + const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}`; + + request.get( + { + url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, + json: true, + }, + (err, resp, data) => { + if (err) { + callback({ + code: grpc.status.INTERNAL, + details: err, + }); + } else if (resp.statusCode !== 200) { + callback({ + code: grpc.status.INTERNAL, + details: `expected status 200, got ${resp.statusCode}`, + }); + } else { + // count how many earthquakes with mag > 1.0 + let count = 0; + data.features.forEach((i) => { + if (i.properties.mag > 1.0) { + count++; + } + }); + callback(null, { + result: count > 2, + }); + } } - }) + ); } - } -}) + }, +}); -server.bind('127.0.0.1:9090', grpc.ServerCredentials.createInsecure()) -console.log('Server listening on 127.0.0.1:9090') +server.bind("127.0.0.1:9090", grpc.ServerCredentials.createInsecure()); +console.log("Server listening on 127.0.0.1:9090"); -server.start() +server.start(); ``` {{< /collapsible >}} -
- #### 4. Implementing `StreamIsActive` Unlike `IsActive`, `StreamIsActive` is called once when KEDA reconciles the `ScaledObject`, and expects the external scaler to maintain a long-lived connection and push `IsActiveResponse` objects whenever the scaler needs KEDA to activate the deployment. @@ -444,38 +443,36 @@ public override async Task StreamIsActive(ScaledObjectRef request, IServerStream server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... streamIsActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { const interval = setInterval(() => { getEarthquakeCount((err, count) => { if (err) { - console.error(err) + console.error(err); } else if (count > 2) { call.write({ result: true, - }) + }); } - }) + }); }, 1000 * 60 * 60); - call.on('end', () => { - clearInterval(interval) - }) + call.on("end", () => { + clearInterval(interval); + }); } - } -}) + }, +}); ``` {{< /collapsible >}} -
- #### 5. Implementing `GetMetricSpec` `GetMetricSpec` returns the `target` value for [the HPA definition for the scaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/). This scaler will define a static target of 10, but the threshold value is often specified in the metadata for other scalers. @@ -521,19 +518,19 @@ server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetricSpec: (call, callback) => { callback(null, { - metricSpecs: [{ - metricName: 'earthquakeThreshold', - targetSize: 10, - }] - }) - } -}) + metricSpecs: [ + { + metricName: "earthquakeThreshold", + targetSize: 10, + }, + ], + }); + }, +}); ``` {{< /collapsible >}} -
- #### 6. Implementing `GetMetrics` `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`, in this example it's `earthquakeThreshold`. @@ -600,32 +597,34 @@ public override async Task GetMetrics(GetMetricsRequest requ server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetrics: (call, callback) => { - const longitude = call.request.scaledObjectRef.scalerMetadata.longitude - const latitude = call.request.scaledObjectRef.scalerMetadata.latitude + const longitude = call.request.scaledObjectRef.scalerMetadata.longitude; + const latitude = call.request.scaledObjectRef.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { getEarthquakeCount((err, count) => { if (err) { callback({ code: grpc.status.INTERNAL, details: err, - }) + }); } else { callback(null, { - metricValues: [{ - metricName: 'earthquakeThreshold', - metricValue: count, - }] - }) + metricValues: [ + { + metricName: "earthquakeThreshold", + metricValue: count, + }, + ], + }); } - }) + }); } - } -}) + }, +}); ``` {{< /collapsible >}} diff --git a/content/docs/2.5/migration.md b/content/docs/2.5/migration.md index 5ee8a6455..29e8408c8 100644 --- a/content/docs/2.5/migration.md +++ b/content/docs/2.5/migration.md @@ -11,15 +11,17 @@ Please note that you **can not** run both KEDA v1 and v2 on the same Kubernetes KEDA v2 is using a new API namespace for its Custom Resources Definitions (CRD): `keda.sh` instead of `keda.k8s.io` and introduces a new Custom Resource for scaling of Jobs. See full details on KEDA Custom Resources [here](../concepts/#custom-resources-crd). Here's an overview of what's changed: + - [Scaling of Deployments](#scaling-of-deployments) - [Scaling of Jobs](#scaling-of-jobs) - [Improved flexibility & usability of trigger metadata](#improved-flexibility--usability-of-trigger-metadata) - [Scalers](#scalers) - [TriggerAuthentication](#triggerauthentication) - ### Scaling of Deployments + In order to scale `Deployments` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Rename property `spec.scaleTargetRef.deploymentName` to `spec.scaleTargetRef.name` - Rename property `spec.scaleTargetRef.containerName` to `spec.scaleTargetRef.envSourceContainerName` @@ -27,22 +29,23 @@ In order to scale `Deployments` with KEDA v2, you need to do only a few modifica Please see the examples below or refer to the full [v2 ScaledObject Specification](../concepts/scaling-deployments/#scaledobject-spec) - **Example of v1 ScaledObject** +**Example of v1 ScaledObject** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } labels: - deploymentName: {deployment-name} + deploymentName: { deployment-name } spec: scaleTargetRef: - deploymentName: {deployment-name} - containerName: {container-name} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + deploymentName: { deployment-name } + containerName: { container-name } + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -50,18 +53,18 @@ spec: **Example of v2 ScaledObject** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed kind: ScaledObject -metadata: # <--- labels.deploymentName is not needed - name: {scaled-object-name} +metadata: # <--- labels.deploymentName is not needed + name: { scaled-object-name } spec: scaleTargetRef: - name: {deployment-name} # <--- Property name was changed - envSourceContainerName: {container-name} # <--- Property name was changed - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + name: { deployment-name } # <--- Property name was changed + envSourceContainerName: { container-name } # <--- Property name was changed + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -69,34 +72,36 @@ spec: ### Scaling of Jobs In order to scale `Jobs` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Change the value of `kind` property from `ScaledObject` to `ScaledJob` - Remove property `spec.scaleType` -- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` +- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` You can configure `successfulJobsHistoryLimit` and `failedJobsHistoryLimit`. They will remove the old job histories automatically. Please see the examples below or refer to the full [v2 ScaledJob Specification](../concepts/scaling-jobs/#scaledjob-spec) **Example of v1 ScaledObject for Jobs scaling** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } spec: scaleType: job jobTargetRef: - parallelism: 1 + parallelism: 1 completions: 1 activeDeadlineSeconds: 600 - backoffLimit: 6 + backoffLimit: 6 template: # {job template} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to create jobs} ``` @@ -104,21 +109,21 @@ spec: **Example of v2 ScaledJob** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed -kind: ScaledJob # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +kind: ScaledJob # <--- Property value was changed metadata: - name: {scaled-job-name} -spec: # <--- spec.scaleType is not needed + name: { scaled-job-name } +spec: # <--- spec.scaleType is not needed jobTargetRef: - parallelism: 1 - completions: 1 + parallelism: 1 + completions: 1 activeDeadlineSeconds: 600 backoffLimit: 6 template: # {job template} - pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed - successfulJobsHistoryLimit: 5 # <--- property is added - failedJobsHistoryLimit: 5 # <--- Property is added + pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed + successfulJobsHistoryLimit: 5 # <--- property is added + failedJobsHistoryLimit: 5 # <--- Property is added maxReplicaCount: 100 triggers: # {list of triggers to create jobs} @@ -132,68 +137,74 @@ We've introduced more options to configure trigger metadata to give users more f Here's an overview: -| Scaler | 1.x | 2.0 | -|--------|--------|--------| -| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | -| `azure-monitor` | `activeDirectoryClientId`
`activeDirectoryClientPassword` | `activeDirectoryClientId`
`activeDirectoryClientIdFromEnv`
`activeDirectoryClientPasswordFromEnv` | -| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | -| `azure-servicebus` | `connection` | `connectionFromEnv` | -| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`)
`connection` (**Default**: `EventHub`) | `storageConnectionFromEnv`
`connectionFromEnv` | -| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `kafka` | _(none)_ | _(none)_ -| `rabbitmq` | `apiHost`
`host` | ~~`apiHost`~~
`host`
`hostFromEnv` | -| `prometheus` | _(none)_ | _(none)_ | -| `cron` | _(none)_ | _(none)_ | -| `redis` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `redis-streams` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | -| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ -| `liiklus` | _(none)_ | _(none)_ | -| `stan` | _(none)_ | _(none)_ | -| `huawei-cloudeye` | | _(none)_ | _(none)_ | -| `postgresql` | `connection`
`password` | `connectionFromEnv`
`passwordFromEnv` | -| `mysql` | `connectionString`
`password` | `connectionStringFromEnv`
`passwordFromEnv` | +| Scaler | 1.x | 2.0 | +| -------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------- | +| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | +| `azure-monitor` | `activeDirectoryClientId` `activeDirectoryClientPassword` | `activeDirectoryClientId` `activeDirectoryClientIdFromEnv` `activeDirectoryClientPasswordFromEnv` | +| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | +| `azure-servicebus` | `connection` | `connectionFromEnv` | +| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`) `connection` (**Default**: `EventHub`) | `storageConnectionFromEnv` `connectionFromEnv` | +| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `kafka` | _(none)_ | _(none)_ | +| `rabbitmq` | `apiHost` `host` | ~~`apiHost`~~ `host` `hostFromEnv` | +| `prometheus` | _(none)_ | _(none)_ | +| `cron` | _(none)_ | _(none)_ | +| `redis` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `redis-streams` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | +| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ | +| `liiklus` | _(none)_ | _(none)_ | +| `stan` | _(none)_ | _(none)_ | +| `huawei-cloudeye` | | _(none)_ | _(none)_ | +| `postgresql` | `connection` `password` | `connectionFromEnv` `passwordFromEnv` | +| `mysql` | `connectionString` `password` | `connectionStringFromEnv` `passwordFromEnv` | ### Scalers **Azure Service Bus** - - `queueLength` was renamed to `messageCount` + +- `queueLength` was renamed to `messageCount` **Kafka** - - `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. + +- `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. **RabbitMQ** In KEDA 2.0 the RabbitMQ scaler has only `host` parameter, and the protocol for communication can be specified by -`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP -protocol. +`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP +protocol. Example of RabbitMQ trigger before 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - includeUnacked: 'true' - apiHost: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + includeUnacked: "true" + apiHost: "https://guest:password@localhost:443/vhostname" +``` The same trigger in 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - protocol: 'http' - host: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + protocol: "http" + host: "https://guest:password@localhost:443/vhostname" +``` ### TriggerAuthentication + In order to use Authentication via `TriggerAuthentication` with KEDA v2, you need to change: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` For more details please refer to the full diff --git a/content/docs/2.5/operate/cluster.md b/content/docs/2.5/operate/cluster.md index c685303b3..2c7b818ee 100644 --- a/content/docs/2.5/operate/cluster.md +++ b/content/docs/2.5/operate/cluster.md @@ -29,12 +29,10 @@ KEDA requires to be accessible inside the cluster to be able to autoscale. Here is an overview of the required ports that need to be accessible for KEDA to work: - | Port | Why? | Remarks | | ------ | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication.

This is not applicable for Google Cloud. | +| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication. This is not applicable for Google Cloud. | | `6443` | Used by Kubernetes API server to get metrics | Only required for Google Cloud because it uses Control Plane → port 6443 on the Pod IP range for communication | - ## High Availability @@ -42,14 +40,14 @@ KEDA does not provide full support for high-availability due to upstream limitat Here is an overview of all KEDA deployments and the HA notes: -| Deployment | Support Replicas | Note | -| -------------- | ---------------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Deployment | Support Replicas | Note | +| -------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Metrics Server | 1 | You can run multiple replicas of our metrics sever, and it is recommended to add the `--enable-aggregator-routing=true` CLI flag to the kube-apiserver so that requests sent to our metrics servers are load balanced. However, [you can only run one active metric server in a Kubernetes cluster serving external.metrics.k8s.io](https://github.com/kubernetes-sigs/custom-metrics-apiserver/issues/70) which has to be the KEDA metric server. | -| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover. | +| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover. | ## HTTP Timeouts -Some scalers issue HTTP requests to external servers (i.e. cloud services). Each applicable scaler uses its own dedicated HTTP client with its own connection pool, and by default each client is set to time out any HTTP request after 3 seconds. +Some scalers issue HTTP requests to external servers (i.e. cloud services). Each applicable scaler uses its own dedicated HTTP client with its own connection pool, and by default each client is set to time out any HTTP request after 3 seconds. You can override this default by setting the `KEDA_HTTP_DEFAULT_TIMEOUT` environment variable to your desired timeout in milliseconds. For example, on Linux/Mac/Windows WSL2 operating systems, you'd use this command to set to 1 second: @@ -69,16 +67,17 @@ All applicable scalers will use this timeout. Setting a per-scaler timeout is cu The Kubernetes client config used within KEDA Metrics Adapter can be adjusted by passing the following command-line flags to the binary: -| Adapter Flag | Client Config Setting | Default Value | Description | -| -------------- | ----------------------- | ------------- | -------------------------------------------------------------- | -| kube-api-qps | cfg.QPS | 20.0 | Set the QPS rate for throttling requests sent to the apiserver | -| kube-api-burst | cfg.Burst | 30 | Set the burst for throttling requests sent to the apiserver | +| Adapter Flag | Client Config Setting | Default Value | Description | +| -------------- | --------------------- | ------------- | -------------------------------------------------------------- | +| kube-api-qps | cfg.QPS | 20.0 | Set the QPS rate for throttling requests sent to the apiserver | +| kube-api-burst | cfg.Burst | 30 | Set the burst for throttling requests sent to the apiserver | ## Configure `MaxConcurrentReconciles` for Controllers To implement internal controllers KEDA uses [controller-runtime project](https://github.com/kubernetes-sigs/controller-runtime), that enables configuration of [MaxConcurrentReconciles property](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/controller#Options), ie. the maximum number of concurrent reconciles which can be run for a controller. KEDA Operator exposes properties for specifying `MaxConcurrentReconciles` for following controllers/reconcilers: + - `ScaledObjectReconciler` - responsible for watching and managing `ScaledObjects`, ie. validates input trigger specification, starts scaling logic and manages dependent HPA. - `ScaledJobReconciler` - responsible for watching and managing `ScaledJobs` and dependent Kubernetes Jobs @@ -86,8 +85,8 @@ KEDA Metrics Server exposes property for specifying `MaxConcurrentReconciles` fo To modify this properties you can set environment variables on both KEDA Operator and Metrics Server Deployments: -| Environment variable name | Deployment | Default Value | Affected reconciler | -| ------------------------------------- | -------------- | ------------- | -------------------------------------------------------------- | -| KEDA_SCALEDOBJECT_CTRL_MAX_RECONCILES | Operator | 5 | ScaledObjectReconciler | -| KEDA_SCALEDJOB_CTRL_MAX_RECONCILES | Operator | 1 | ScaledJobReconciler | -| KEDA_METRICS_CTRL_MAX_RECONCILES | Metrics Server | 1 | MetricsScaledObjectReconciler | +| Environment variable name | Deployment | Default Value | Affected reconciler | +| ------------------------------------- | -------------- | ------------- | ----------------------------- | +| KEDA_SCALEDOBJECT_CTRL_MAX_RECONCILES | Operator | 5 | ScaledObjectReconciler | +| KEDA_SCALEDJOB_CTRL_MAX_RECONCILES | Operator | 1 | ScaledJobReconciler | +| KEDA_METRICS_CTRL_MAX_RECONCILES | Metrics Server | 1 | MetricsScaledObjectReconciler | diff --git a/content/docs/2.6/concepts/external-scalers.md b/content/docs/2.6/concepts/external-scalers.md index 64d7bffb4..214107edc 100644 --- a/content/docs/2.6/concepts/external-scalers.md +++ b/content/docs/2.6/concepts/external-scalers.md @@ -9,7 +9,7 @@ Built-in scalers run in the KEDA process/pod, while external scalers require an This document describes the external scaler interfaces and how to implement them in Go, Node, and .NET; however for more details on GRPC refer to [the official GRPC documentation](https://grpc.io/docs/) ->Want to learn about existing external scalers? Explore our [external scaler community](https://github.com/kedacore/external-scalers). +> Want to learn about existing external scalers? Explore our [external scaler community](https://github.com/kedacore/external-scalers). ## Overview @@ -39,7 +39,7 @@ The `Scaler` interface defines 4 methods: - `Close` is called to allow the scaler to clean up connections or other resources. - `GetMetricSpec` returns the target value for the HPA definition for the scaler. For more details refer to [Implementing `GetMetricSpec`](#5-implementing-getmetricspec). - `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`. For more details refer to [Implementing `GetMetrics`](#6-implementing-getmetrics). -> Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA uses the metric target type `AverageValue` for external metrics. This will cause the metric value returned by the external scaler to be divided by the number of replicas. + > Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA uses the metric target type `AverageValue` for external metrics. This will cause the metric value returned by the external scaler to be divided by the number of replicas. The `PushScaler` interface adds a `Run` method. This method receives a push channel (`active`), on which the scaler can send `true` at any time. The purpose of this mechanism is to initiate a scaling operation independently from `pollingInterval`. @@ -109,7 +109,7 @@ KEDA will attempt a GRPC connection to `service-address.svc.local:9090` immediat } ``` ->**Note**: KEDA will issue all of the above RPC calls except `StreamIsActive` if `spec.triggers.type` is `external`. It _must_ be `external-push` for `StreamIsActive` to be called. +> **Note**: KEDA will issue all of the above RPC calls except `StreamIsActive` if `spec.triggers.type` is `external`. It _must_ be `external-push` for `StreamIsActive` to be called. ## Implementing KEDA external scaler GRPC interface @@ -176,8 +176,6 @@ npm install --save grpc request {{< /collapsible >}} -
- #### 3. Implementing `IsActive` Just like `IsActive(ctx context.Context) (bool, error)` in the go interface, the `IsActive` method in the GRPC interface is called every `pollingInterval` with a `ScaledObjectRef` object that contains the scaledObject name, namespace, and scaler metadata. @@ -304,70 +302,71 @@ public class ExternalScalerService : ExternalScaler.ExternalScalerBase Put the following code into your `index.js` file: ```js -const grpc = require('grpc') -const request = require('request') -const externalScalerProto = grpc.load('externalscaler.proto') +const grpc = require("grpc"); +const request = require("request"); +const externalScalerProto = grpc.load("externalscaler.proto"); -const server = new grpc.Server() +const server = new grpc.Server(); server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { isActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { - const now = new Date() - const yesterday = new Date(new Date().setDate(new Date().getDate()-1)); - - const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}` - const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}` - const radiusKm = 500 - const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}` - - request.get({ - url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, - json: true, - }, (err, resp, data) => { - if (err) { - callback({ - code: grpc.status.INTERNAL, - details: err, - }) - } else if (resp.statusCode !== 200) { - callback({ - code: grpc.status.INTERNAL, - details: `expected status 200, got ${resp.statusCode}` - }) - } else { - // count how many earthquakes with mag > 1.0 - let count = 0 - data.features.forEach(i => { - if (i.properties.mag > 1.0) { - count++ - } - }) - callback(null, { - result: count > 2, - }) + const now = new Date(); + const yesterday = new Date(new Date().setDate(new Date().getDate() - 1)); + + const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}`; + const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}`; + const radiusKm = 500; + const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}`; + + request.get( + { + url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, + json: true, + }, + (err, resp, data) => { + if (err) { + callback({ + code: grpc.status.INTERNAL, + details: err, + }); + } else if (resp.statusCode !== 200) { + callback({ + code: grpc.status.INTERNAL, + details: `expected status 200, got ${resp.statusCode}`, + }); + } else { + // count how many earthquakes with mag > 1.0 + let count = 0; + data.features.forEach((i) => { + if (i.properties.mag > 1.0) { + count++; + } + }); + callback(null, { + result: count > 2, + }); + } } - }) + ); } - } -}) + }, +}); -server.bind('127.0.0.1:9090', grpc.ServerCredentials.createInsecure()) -console.log('Server listening on 127.0.0.1:9090') +server.bind("127.0.0.1:9090", grpc.ServerCredentials.createInsecure()); +console.log("Server listening on 127.0.0.1:9090"); -server.start() +server.start(); ``` {{< /collapsible >}} -
- #### 4. Implementing `StreamIsActive` Unlike `IsActive`, `StreamIsActive` is called once when KEDA reconciles the `ScaledObject`, and expects the external scaler to maintain a long-lived connection and push `IsActiveResponse` objects whenever the scaler needs KEDA to activate the deployment. @@ -444,38 +443,36 @@ public override async Task StreamIsActive(ScaledObjectRef request, IServerStream server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... streamIsActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { const interval = setInterval(() => { getEarthquakeCount((err, count) => { if (err) { - console.error(err) + console.error(err); } else if (count > 2) { call.write({ result: true, - }) + }); } - }) + }); }, 1000 * 60 * 60); - call.on('end', () => { - clearInterval(interval) - }) + call.on("end", () => { + clearInterval(interval); + }); } - } -}) + }, +}); ``` {{< /collapsible >}} -
- #### 5. Implementing `GetMetricSpec` `GetMetricSpec` returns the `target` value for [the HPA definition for the scaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/). This scaler will define a static target of 10, but the threshold value is often specified in the metadata for other scalers. @@ -521,19 +518,19 @@ server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetricSpec: (call, callback) => { callback(null, { - metricSpecs: [{ - metricName: 'earthquakeThreshold', - targetSize: 10, - }] - }) - } -}) + metricSpecs: [ + { + metricName: "earthquakeThreshold", + targetSize: 10, + }, + ], + }); + }, +}); ``` {{< /collapsible >}} -
- #### 6. Implementing `GetMetrics` `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`, in this example it's `earthquakeThreshold`. @@ -600,32 +597,34 @@ public override async Task GetMetrics(GetMetricsRequest requ server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetrics: (call, callback) => { - const longitude = call.request.scaledObjectRef.scalerMetadata.longitude - const latitude = call.request.scaledObjectRef.scalerMetadata.latitude + const longitude = call.request.scaledObjectRef.scalerMetadata.longitude; + const latitude = call.request.scaledObjectRef.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { getEarthquakeCount((err, count) => { if (err) { callback({ code: grpc.status.INTERNAL, details: err, - }) + }); } else { callback(null, { - metricValues: [{ - metricName: 'earthquakeThreshold', - metricValue: count, - }] - }) + metricValues: [ + { + metricName: "earthquakeThreshold", + metricValue: count, + }, + ], + }); } - }) + }); } - } -}) + }, +}); ``` {{< /collapsible >}} diff --git a/content/docs/2.6/migration.md b/content/docs/2.6/migration.md index 5ee8a6455..29e8408c8 100644 --- a/content/docs/2.6/migration.md +++ b/content/docs/2.6/migration.md @@ -11,15 +11,17 @@ Please note that you **can not** run both KEDA v1 and v2 on the same Kubernetes KEDA v2 is using a new API namespace for its Custom Resources Definitions (CRD): `keda.sh` instead of `keda.k8s.io` and introduces a new Custom Resource for scaling of Jobs. See full details on KEDA Custom Resources [here](../concepts/#custom-resources-crd). Here's an overview of what's changed: + - [Scaling of Deployments](#scaling-of-deployments) - [Scaling of Jobs](#scaling-of-jobs) - [Improved flexibility & usability of trigger metadata](#improved-flexibility--usability-of-trigger-metadata) - [Scalers](#scalers) - [TriggerAuthentication](#triggerauthentication) - ### Scaling of Deployments + In order to scale `Deployments` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Rename property `spec.scaleTargetRef.deploymentName` to `spec.scaleTargetRef.name` - Rename property `spec.scaleTargetRef.containerName` to `spec.scaleTargetRef.envSourceContainerName` @@ -27,22 +29,23 @@ In order to scale `Deployments` with KEDA v2, you need to do only a few modifica Please see the examples below or refer to the full [v2 ScaledObject Specification](../concepts/scaling-deployments/#scaledobject-spec) - **Example of v1 ScaledObject** +**Example of v1 ScaledObject** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } labels: - deploymentName: {deployment-name} + deploymentName: { deployment-name } spec: scaleTargetRef: - deploymentName: {deployment-name} - containerName: {container-name} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + deploymentName: { deployment-name } + containerName: { container-name } + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -50,18 +53,18 @@ spec: **Example of v2 ScaledObject** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed kind: ScaledObject -metadata: # <--- labels.deploymentName is not needed - name: {scaled-object-name} +metadata: # <--- labels.deploymentName is not needed + name: { scaled-object-name } spec: scaleTargetRef: - name: {deployment-name} # <--- Property name was changed - envSourceContainerName: {container-name} # <--- Property name was changed - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + name: { deployment-name } # <--- Property name was changed + envSourceContainerName: { container-name } # <--- Property name was changed + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -69,34 +72,36 @@ spec: ### Scaling of Jobs In order to scale `Jobs` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Change the value of `kind` property from `ScaledObject` to `ScaledJob` - Remove property `spec.scaleType` -- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` +- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` You can configure `successfulJobsHistoryLimit` and `failedJobsHistoryLimit`. They will remove the old job histories automatically. Please see the examples below or refer to the full [v2 ScaledJob Specification](../concepts/scaling-jobs/#scaledjob-spec) **Example of v1 ScaledObject for Jobs scaling** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } spec: scaleType: job jobTargetRef: - parallelism: 1 + parallelism: 1 completions: 1 activeDeadlineSeconds: 600 - backoffLimit: 6 + backoffLimit: 6 template: # {job template} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to create jobs} ``` @@ -104,21 +109,21 @@ spec: **Example of v2 ScaledJob** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed -kind: ScaledJob # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +kind: ScaledJob # <--- Property value was changed metadata: - name: {scaled-job-name} -spec: # <--- spec.scaleType is not needed + name: { scaled-job-name } +spec: # <--- spec.scaleType is not needed jobTargetRef: - parallelism: 1 - completions: 1 + parallelism: 1 + completions: 1 activeDeadlineSeconds: 600 backoffLimit: 6 template: # {job template} - pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed - successfulJobsHistoryLimit: 5 # <--- property is added - failedJobsHistoryLimit: 5 # <--- Property is added + pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed + successfulJobsHistoryLimit: 5 # <--- property is added + failedJobsHistoryLimit: 5 # <--- Property is added maxReplicaCount: 100 triggers: # {list of triggers to create jobs} @@ -132,68 +137,74 @@ We've introduced more options to configure trigger metadata to give users more f Here's an overview: -| Scaler | 1.x | 2.0 | -|--------|--------|--------| -| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | -| `azure-monitor` | `activeDirectoryClientId`
`activeDirectoryClientPassword` | `activeDirectoryClientId`
`activeDirectoryClientIdFromEnv`
`activeDirectoryClientPasswordFromEnv` | -| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | -| `azure-servicebus` | `connection` | `connectionFromEnv` | -| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`)
`connection` (**Default**: `EventHub`) | `storageConnectionFromEnv`
`connectionFromEnv` | -| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `kafka` | _(none)_ | _(none)_ -| `rabbitmq` | `apiHost`
`host` | ~~`apiHost`~~
`host`
`hostFromEnv` | -| `prometheus` | _(none)_ | _(none)_ | -| `cron` | _(none)_ | _(none)_ | -| `redis` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `redis-streams` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | -| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ -| `liiklus` | _(none)_ | _(none)_ | -| `stan` | _(none)_ | _(none)_ | -| `huawei-cloudeye` | | _(none)_ | _(none)_ | -| `postgresql` | `connection`
`password` | `connectionFromEnv`
`passwordFromEnv` | -| `mysql` | `connectionString`
`password` | `connectionStringFromEnv`
`passwordFromEnv` | +| Scaler | 1.x | 2.0 | +| -------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------- | +| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | +| `azure-monitor` | `activeDirectoryClientId` `activeDirectoryClientPassword` | `activeDirectoryClientId` `activeDirectoryClientIdFromEnv` `activeDirectoryClientPasswordFromEnv` | +| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | +| `azure-servicebus` | `connection` | `connectionFromEnv` | +| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`) `connection` (**Default**: `EventHub`) | `storageConnectionFromEnv` `connectionFromEnv` | +| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `kafka` | _(none)_ | _(none)_ | +| `rabbitmq` | `apiHost` `host` | ~~`apiHost`~~ `host` `hostFromEnv` | +| `prometheus` | _(none)_ | _(none)_ | +| `cron` | _(none)_ | _(none)_ | +| `redis` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `redis-streams` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | +| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ | +| `liiklus` | _(none)_ | _(none)_ | +| `stan` | _(none)_ | _(none)_ | +| `huawei-cloudeye` | | _(none)_ | _(none)_ | +| `postgresql` | `connection` `password` | `connectionFromEnv` `passwordFromEnv` | +| `mysql` | `connectionString` `password` | `connectionStringFromEnv` `passwordFromEnv` | ### Scalers **Azure Service Bus** - - `queueLength` was renamed to `messageCount` + +- `queueLength` was renamed to `messageCount` **Kafka** - - `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. + +- `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. **RabbitMQ** In KEDA 2.0 the RabbitMQ scaler has only `host` parameter, and the protocol for communication can be specified by -`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP -protocol. +`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP +protocol. Example of RabbitMQ trigger before 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - includeUnacked: 'true' - apiHost: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + includeUnacked: "true" + apiHost: "https://guest:password@localhost:443/vhostname" +``` The same trigger in 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - protocol: 'http' - host: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + protocol: "http" + host: "https://guest:password@localhost:443/vhostname" +``` ### TriggerAuthentication + In order to use Authentication via `TriggerAuthentication` with KEDA v2, you need to change: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` For more details please refer to the full diff --git a/content/docs/2.6/operate/cluster.md b/content/docs/2.6/operate/cluster.md index 5932357b8..10e6a4043 100644 --- a/content/docs/2.6/operate/cluster.md +++ b/content/docs/2.6/operate/cluster.md @@ -29,12 +29,10 @@ KEDA requires to be accessible inside the cluster to be able to autoscale. Here is an overview of the required ports that need to be accessible for KEDA to work: - | Port | Why? | Remarks | | ------ | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication.

This is not applicable for Google Cloud. | +| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication. This is not applicable for Google Cloud. | | `6443` | Used by Kubernetes API server to get metrics | Only required for Google Cloud because it uses Control Plane → port 6443 on the Pod IP range for communication | - ## High Availability @@ -42,14 +40,14 @@ KEDA does not provide full support for high-availability due to upstream limitat Here is an overview of all KEDA deployments and the HA notes: -| Deployment | Support Replicas | Note | -| -------------- | ---------------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Deployment | Support Replicas | Note | +| -------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Metrics Server | 1 | You can run multiple replicas of our metrics sever, and it is recommended to add the `--enable-aggregator-routing=true` CLI flag to the kube-apiserver so that requests sent to our metrics servers are load balanced. However, [you can only run one active metric server in a Kubernetes cluster serving external.metrics.k8s.io](https://github.com/kubernetes-sigs/custom-metrics-apiserver/issues/70) which has to be the KEDA metric server. | -| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover. | +| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover. | ## HTTP Timeouts -Some scalers issue HTTP requests to external servers (i.e. cloud services). Each applicable scaler uses its own dedicated HTTP client with its own connection pool, and by default each client is set to time out any HTTP request after 3 seconds. +Some scalers issue HTTP requests to external servers (i.e. cloud services). Each applicable scaler uses its own dedicated HTTP client with its own connection pool, and by default each client is set to time out any HTTP request after 3 seconds. You can override this default by setting the `KEDA_HTTP_DEFAULT_TIMEOUT` environment variable to your desired timeout in milliseconds. For example, on Linux/Mac/Windows WSL2 operating systems, you'd use this command to set to 1 second: @@ -69,16 +67,17 @@ All applicable scalers will use this timeout. Setting a per-scaler timeout is cu The Kubernetes client config used within KEDA Metrics Adapter can be adjusted by passing the following command-line flags to the binary: -| Adapter Flag | Client Config Setting | Default Value | Description | -| -------------- | ----------------------- | ------------- | -------------------------------------------------------------- | -| kube-api-qps | cfg.QPS | 20.0 | Set the QPS rate for throttling requests sent to the apiserver | -| kube-api-burst | cfg.Burst | 30 | Set the burst for throttling requests sent to the apiserver | +| Adapter Flag | Client Config Setting | Default Value | Description | +| -------------- | --------------------- | ------------- | -------------------------------------------------------------- | +| kube-api-qps | cfg.QPS | 20.0 | Set the QPS rate for throttling requests sent to the apiserver | +| kube-api-burst | cfg.Burst | 30 | Set the burst for throttling requests sent to the apiserver | ## Configure `MaxConcurrentReconciles` for Controllers To implement internal controllers KEDA uses [controller-runtime project](https://github.com/kubernetes-sigs/controller-runtime), that enables configuration of [MaxConcurrentReconciles property](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/controller#Options), ie. the maximum number of concurrent reconciles which can be run for a controller. KEDA Operator exposes properties for specifying `MaxConcurrentReconciles` for following controllers/reconcilers: + - `ScaledObjectReconciler` - responsible for watching and managing `ScaledObjects`, ie. validates input trigger specification, starts scaling logic and manages dependent HPA. - `ScaledJobReconciler` - responsible for watching and managing `ScaledJobs` and dependent Kubernetes Jobs @@ -86,11 +85,11 @@ KEDA Metrics Server exposes property for specifying `MaxConcurrentReconciles` fo To modify this properties you can set environment variables on both KEDA Operator and Metrics Server Deployments: -| Environment variable name | Deployment | Default Value | Affected reconciler | -| ------------------------------------- | -------------- | ------------- | -------------------------------------------------------------- | -| KEDA_SCALEDOBJECT_CTRL_MAX_RECONCILES | Operator | 5 | ScaledObjectReconciler | -| KEDA_SCALEDJOB_CTRL_MAX_RECONCILES | Operator | 1 | ScaledJobReconciler | -| KEDA_METRICS_CTRL_MAX_RECONCILES | Metrics Server | 1 | MetricsScaledObjectReconciler | +| Environment variable name | Deployment | Default Value | Affected reconciler | +| ------------------------------------- | -------------- | ------------- | ----------------------------- | +| KEDA_SCALEDOBJECT_CTRL_MAX_RECONCILES | Operator | 5 | ScaledObjectReconciler | +| KEDA_SCALEDJOB_CTRL_MAX_RECONCILES | Operator | 1 | ScaledJobReconciler | +| KEDA_METRICS_CTRL_MAX_RECONCILES | Metrics Server | 1 | MetricsScaledObjectReconciler | ## Certificates used by KEDA Metrics Server @@ -99,20 +98,19 @@ By default, KEDA Metrics Server uses self-signed certificates while communicatin Certificates and CA bundle can be referenced in `args` section in KEDA Metrics Server Deployment: ```yaml -... +--- args: - - '--client-ca-file=/cabundle/service-ca.crt' - - '--tls-cert-file=/certs/tls.crt' - - '--tls-private-key-file=/certs/tls.key' -... + - "--client-ca-file=/cabundle/service-ca.crt" + - "--tls-cert-file=/certs/tls.crt" + - "--tls-private-key-file=/certs/tls.key" ``` -The custom CA bundle should be also referenced in the `v1beta1.external.metrics.k8s.io` [APIService](https://kubernetes.io/docs/reference/kubernetes-api/cluster-resources/api-service-v1/#APIServiceSpec) resource (which is created during the installation of KEDA). +The custom CA bundle should be also referenced in the `v1beta1.external.metrics.k8s.io` [APIService](https://kubernetes.io/docs/reference/kubernetes-api/cluster-resources/api-service-v1/#APIServiceSpec) resource (which is created during the installation of KEDA). You should also make sure that `insecureSkipTLSVerify` is not set to `true`. ```yaml -... +--- spec: service: namespace: keda @@ -124,5 +122,4 @@ spec: YOURCABUNDLE... groupPriorityMinimum: 100 versionPriority: 100 -... ``` diff --git a/content/docs/2.7/concepts/external-scalers.md b/content/docs/2.7/concepts/external-scalers.md index 16f721117..d360d39cd 100644 --- a/content/docs/2.7/concepts/external-scalers.md +++ b/content/docs/2.7/concepts/external-scalers.md @@ -9,7 +9,7 @@ Built-in scalers run in the KEDA process/pod, while external scalers require an This document describes the external scaler interfaces and how to implement them in Go, Node, and .NET; however for more details on GRPC refer to [the official GRPC documentation](https://grpc.io/docs/) ->Want to learn about existing external scalers? Explore our [external scaler community](https://github.com/kedacore/external-scalers). +> Want to learn about existing external scalers? Explore our [external scaler community](https://github.com/kedacore/external-scalers). ## Overview @@ -39,7 +39,7 @@ The `Scaler` interface defines 4 methods: - `Close` is called to allow the scaler to clean up connections or other resources. - `GetMetricSpec` returns the target value for the HPA definition for the scaler. For more details refer to [Implementing `GetMetricSpec`](#5-implementing-getmetricspec). - `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`. For more details refer to [Implementing `GetMetrics`](#6-implementing-getmetrics). -> Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA supports both `AverageValue` and `Value` metric target types for external metrics. When `AverageValue` (the default metric type) is used, the metric value returned by the external scaler will be divided by the number of replicas. + > Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA supports both `AverageValue` and `Value` metric target types for external metrics. When `AverageValue` (the default metric type) is used, the metric value returned by the external scaler will be divided by the number of replicas. The `PushScaler` interface adds a `Run` method. This method receives a push channel (`active`), on which the scaler can send `true` at any time. The purpose of this mechanism is to initiate a scaling operation independently from `pollingInterval`. @@ -109,7 +109,7 @@ KEDA will attempt a GRPC connection to `service-address.svc.local:9090` immediat } ``` ->**Note**: KEDA will issue all of the above RPC calls except `StreamIsActive` if `spec.triggers.type` is `external`. It _must_ be `external-push` for `StreamIsActive` to be called. +> **Note**: KEDA will issue all of the above RPC calls except `StreamIsActive` if `spec.triggers.type` is `external`. It _must_ be `external-push` for `StreamIsActive` to be called. ## Implementing KEDA external scaler GRPC interface @@ -176,8 +176,6 @@ npm install --save grpc request {{< /collapsible >}} -
- #### 3. Implementing `IsActive` Just like `IsActive(ctx context.Context) (bool, error)` in the go interface, the `IsActive` method in the GRPC interface is called every `pollingInterval` with a `ScaledObjectRef` object that contains the scaledObject name, namespace, and scaler metadata. @@ -304,70 +302,71 @@ public class ExternalScalerService : ExternalScaler.ExternalScalerBase Put the following code into your `index.js` file: ```js -const grpc = require('grpc') -const request = require('request') -const externalScalerProto = grpc.load('externalscaler.proto') +const grpc = require("grpc"); +const request = require("request"); +const externalScalerProto = grpc.load("externalscaler.proto"); -const server = new grpc.Server() +const server = new grpc.Server(); server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { isActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { - const now = new Date() - const yesterday = new Date(new Date().setDate(new Date().getDate()-1)); - - const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}` - const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}` - const radiusKm = 500 - const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}` - - request.get({ - url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, - json: true, - }, (err, resp, data) => { - if (err) { - callback({ - code: grpc.status.INTERNAL, - details: err, - }) - } else if (resp.statusCode !== 200) { - callback({ - code: grpc.status.INTERNAL, - details: `expected status 200, got ${resp.statusCode}` - }) - } else { - // count how many earthquakes with mag > 1.0 - let count = 0 - data.features.forEach(i => { - if (i.properties.mag > 1.0) { - count++ - } - }) - callback(null, { - result: count > 2, - }) + const now = new Date(); + const yesterday = new Date(new Date().setDate(new Date().getDate() - 1)); + + const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}`; + const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}`; + const radiusKm = 500; + const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}`; + + request.get( + { + url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, + json: true, + }, + (err, resp, data) => { + if (err) { + callback({ + code: grpc.status.INTERNAL, + details: err, + }); + } else if (resp.statusCode !== 200) { + callback({ + code: grpc.status.INTERNAL, + details: `expected status 200, got ${resp.statusCode}`, + }); + } else { + // count how many earthquakes with mag > 1.0 + let count = 0; + data.features.forEach((i) => { + if (i.properties.mag > 1.0) { + count++; + } + }); + callback(null, { + result: count > 2, + }); + } } - }) + ); } - } -}) + }, +}); -server.bind('127.0.0.1:9090', grpc.ServerCredentials.createInsecure()) -console.log('Server listening on 127.0.0.1:9090') +server.bind("127.0.0.1:9090", grpc.ServerCredentials.createInsecure()); +console.log("Server listening on 127.0.0.1:9090"); -server.start() +server.start(); ``` {{< /collapsible >}} -
- #### 4. Implementing `StreamIsActive` Unlike `IsActive`, `StreamIsActive` is called once when KEDA reconciles the `ScaledObject`, and expects the external scaler to maintain a long-lived connection and push `IsActiveResponse` objects whenever the scaler needs KEDA to activate the deployment. @@ -444,38 +443,36 @@ public override async Task StreamIsActive(ScaledObjectRef request, IServerStream server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... streamIsActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { const interval = setInterval(() => { getEarthquakeCount((err, count) => { if (err) { - console.error(err) + console.error(err); } else if (count > 2) { call.write({ result: true, - }) + }); } - }) + }); }, 1000 * 60 * 60); - call.on('end', () => { - clearInterval(interval) - }) + call.on("end", () => { + clearInterval(interval); + }); } - } -}) + }, +}); ``` {{< /collapsible >}} -
- #### 5. Implementing `GetMetricSpec` `GetMetricSpec` returns the `target` value for [the HPA definition for the scaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/). This scaler will define a static target of 10, but the threshold value is often specified in the metadata for other scalers. @@ -521,19 +518,19 @@ server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetricSpec: (call, callback) => { callback(null, { - metricSpecs: [{ - metricName: 'earthquakeThreshold', - targetSize: 10, - }] - }) - } -}) + metricSpecs: [ + { + metricName: "earthquakeThreshold", + targetSize: 10, + }, + ], + }); + }, +}); ``` {{< /collapsible >}} -
- #### 6. Implementing `GetMetrics` `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`, in this example it's `earthquakeThreshold`. @@ -600,32 +597,34 @@ public override async Task GetMetrics(GetMetricsRequest requ server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetrics: (call, callback) => { - const longitude = call.request.scaledObjectRef.scalerMetadata.longitude - const latitude = call.request.scaledObjectRef.scalerMetadata.latitude + const longitude = call.request.scaledObjectRef.scalerMetadata.longitude; + const latitude = call.request.scaledObjectRef.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { getEarthquakeCount((err, count) => { if (err) { callback({ code: grpc.status.INTERNAL, details: err, - }) + }); } else { callback(null, { - metricValues: [{ - metricName: 'earthquakeThreshold', - metricValue: count, - }] - }) + metricValues: [ + { + metricName: "earthquakeThreshold", + metricValue: count, + }, + ], + }); } - }) + }); } - } -}) + }, +}); ``` {{< /collapsible >}} diff --git a/content/docs/2.7/migration.md b/content/docs/2.7/migration.md index 5ee8a6455..29e8408c8 100644 --- a/content/docs/2.7/migration.md +++ b/content/docs/2.7/migration.md @@ -11,15 +11,17 @@ Please note that you **can not** run both KEDA v1 and v2 on the same Kubernetes KEDA v2 is using a new API namespace for its Custom Resources Definitions (CRD): `keda.sh` instead of `keda.k8s.io` and introduces a new Custom Resource for scaling of Jobs. See full details on KEDA Custom Resources [here](../concepts/#custom-resources-crd). Here's an overview of what's changed: + - [Scaling of Deployments](#scaling-of-deployments) - [Scaling of Jobs](#scaling-of-jobs) - [Improved flexibility & usability of trigger metadata](#improved-flexibility--usability-of-trigger-metadata) - [Scalers](#scalers) - [TriggerAuthentication](#triggerauthentication) - ### Scaling of Deployments + In order to scale `Deployments` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Rename property `spec.scaleTargetRef.deploymentName` to `spec.scaleTargetRef.name` - Rename property `spec.scaleTargetRef.containerName` to `spec.scaleTargetRef.envSourceContainerName` @@ -27,22 +29,23 @@ In order to scale `Deployments` with KEDA v2, you need to do only a few modifica Please see the examples below or refer to the full [v2 ScaledObject Specification](../concepts/scaling-deployments/#scaledobject-spec) - **Example of v1 ScaledObject** +**Example of v1 ScaledObject** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } labels: - deploymentName: {deployment-name} + deploymentName: { deployment-name } spec: scaleTargetRef: - deploymentName: {deployment-name} - containerName: {container-name} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + deploymentName: { deployment-name } + containerName: { container-name } + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -50,18 +53,18 @@ spec: **Example of v2 ScaledObject** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed kind: ScaledObject -metadata: # <--- labels.deploymentName is not needed - name: {scaled-object-name} +metadata: # <--- labels.deploymentName is not needed + name: { scaled-object-name } spec: scaleTargetRef: - name: {deployment-name} # <--- Property name was changed - envSourceContainerName: {container-name} # <--- Property name was changed - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + name: { deployment-name } # <--- Property name was changed + envSourceContainerName: { container-name } # <--- Property name was changed + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -69,34 +72,36 @@ spec: ### Scaling of Jobs In order to scale `Jobs` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Change the value of `kind` property from `ScaledObject` to `ScaledJob` - Remove property `spec.scaleType` -- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` +- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` You can configure `successfulJobsHistoryLimit` and `failedJobsHistoryLimit`. They will remove the old job histories automatically. Please see the examples below or refer to the full [v2 ScaledJob Specification](../concepts/scaling-jobs/#scaledjob-spec) **Example of v1 ScaledObject for Jobs scaling** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } spec: scaleType: job jobTargetRef: - parallelism: 1 + parallelism: 1 completions: 1 activeDeadlineSeconds: 600 - backoffLimit: 6 + backoffLimit: 6 template: # {job template} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to create jobs} ``` @@ -104,21 +109,21 @@ spec: **Example of v2 ScaledJob** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed -kind: ScaledJob # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +kind: ScaledJob # <--- Property value was changed metadata: - name: {scaled-job-name} -spec: # <--- spec.scaleType is not needed + name: { scaled-job-name } +spec: # <--- spec.scaleType is not needed jobTargetRef: - parallelism: 1 - completions: 1 + parallelism: 1 + completions: 1 activeDeadlineSeconds: 600 backoffLimit: 6 template: # {job template} - pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed - successfulJobsHistoryLimit: 5 # <--- property is added - failedJobsHistoryLimit: 5 # <--- Property is added + pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed + successfulJobsHistoryLimit: 5 # <--- property is added + failedJobsHistoryLimit: 5 # <--- Property is added maxReplicaCount: 100 triggers: # {list of triggers to create jobs} @@ -132,68 +137,74 @@ We've introduced more options to configure trigger metadata to give users more f Here's an overview: -| Scaler | 1.x | 2.0 | -|--------|--------|--------| -| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | -| `azure-monitor` | `activeDirectoryClientId`
`activeDirectoryClientPassword` | `activeDirectoryClientId`
`activeDirectoryClientIdFromEnv`
`activeDirectoryClientPasswordFromEnv` | -| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | -| `azure-servicebus` | `connection` | `connectionFromEnv` | -| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`)
`connection` (**Default**: `EventHub`) | `storageConnectionFromEnv`
`connectionFromEnv` | -| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `kafka` | _(none)_ | _(none)_ -| `rabbitmq` | `apiHost`
`host` | ~~`apiHost`~~
`host`
`hostFromEnv` | -| `prometheus` | _(none)_ | _(none)_ | -| `cron` | _(none)_ | _(none)_ | -| `redis` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `redis-streams` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | -| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ -| `liiklus` | _(none)_ | _(none)_ | -| `stan` | _(none)_ | _(none)_ | -| `huawei-cloudeye` | | _(none)_ | _(none)_ | -| `postgresql` | `connection`
`password` | `connectionFromEnv`
`passwordFromEnv` | -| `mysql` | `connectionString`
`password` | `connectionStringFromEnv`
`passwordFromEnv` | +| Scaler | 1.x | 2.0 | +| -------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------- | +| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | +| `azure-monitor` | `activeDirectoryClientId` `activeDirectoryClientPassword` | `activeDirectoryClientId` `activeDirectoryClientIdFromEnv` `activeDirectoryClientPasswordFromEnv` | +| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | +| `azure-servicebus` | `connection` | `connectionFromEnv` | +| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`) `connection` (**Default**: `EventHub`) | `storageConnectionFromEnv` `connectionFromEnv` | +| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `kafka` | _(none)_ | _(none)_ | +| `rabbitmq` | `apiHost` `host` | ~~`apiHost`~~ `host` `hostFromEnv` | +| `prometheus` | _(none)_ | _(none)_ | +| `cron` | _(none)_ | _(none)_ | +| `redis` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `redis-streams` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | +| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ | +| `liiklus` | _(none)_ | _(none)_ | +| `stan` | _(none)_ | _(none)_ | +| `huawei-cloudeye` | | _(none)_ | _(none)_ | +| `postgresql` | `connection` `password` | `connectionFromEnv` `passwordFromEnv` | +| `mysql` | `connectionString` `password` | `connectionStringFromEnv` `passwordFromEnv` | ### Scalers **Azure Service Bus** - - `queueLength` was renamed to `messageCount` + +- `queueLength` was renamed to `messageCount` **Kafka** - - `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. + +- `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. **RabbitMQ** In KEDA 2.0 the RabbitMQ scaler has only `host` parameter, and the protocol for communication can be specified by -`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP -protocol. +`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP +protocol. Example of RabbitMQ trigger before 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - includeUnacked: 'true' - apiHost: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + includeUnacked: "true" + apiHost: "https://guest:password@localhost:443/vhostname" +``` The same trigger in 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - protocol: 'http' - host: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + protocol: "http" + host: "https://guest:password@localhost:443/vhostname" +``` ### TriggerAuthentication + In order to use Authentication via `TriggerAuthentication` with KEDA v2, you need to change: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` For more details please refer to the full diff --git a/content/docs/2.7/operate/cluster.md b/content/docs/2.7/operate/cluster.md index dc1a201d6..dfb78df81 100644 --- a/content/docs/2.7/operate/cluster.md +++ b/content/docs/2.7/operate/cluster.md @@ -29,12 +29,10 @@ KEDA requires to be accessible inside the cluster to be able to autoscale. Here is an overview of the required ports that need to be accessible for KEDA to work: - | Port | Why? | Remarks | | ------ | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication.

This is not applicable for Google Cloud. | +| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication. This is not applicable for Google Cloud. | | `6443` | Used by Kubernetes API server to get metrics | Only required for Google Cloud because it uses Control Plane → port 6443 on the Pod IP range for communication | - ## High Availability @@ -42,14 +40,14 @@ KEDA does not provide full support for high-availability due to upstream limitat Here is an overview of all KEDA deployments and the HA notes: -| Deployment | Support Replicas | Note | -| -------------- | ---------------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Deployment | Support Replicas | Note | +| -------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Metrics Server | 1 | You can run multiple replicas of our metrics sever, and it is recommended to add the `--enable-aggregator-routing=true` CLI flag to the kube-apiserver so that requests sent to our metrics servers are load balanced. However, [you can only run one active metric server in a Kubernetes cluster serving external.metrics.k8s.io](https://github.com/kubernetes-sigs/custom-metrics-apiserver/issues/70) which has to be the KEDA metric server. | -| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover. | +| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover. | ## HTTP Timeouts -Some scalers issue HTTP requests to external servers (i.e. cloud services). Each applicable scaler uses its own dedicated HTTP client with its own connection pool, and by default each client is set to time out any HTTP request after 3 seconds. +Some scalers issue HTTP requests to external servers (i.e. cloud services). Each applicable scaler uses its own dedicated HTTP client with its own connection pool, and by default each client is set to time out any HTTP request after 3 seconds. You can override this default by setting the `KEDA_HTTP_DEFAULT_TIMEOUT` environment variable to your desired timeout in milliseconds. For example, on Linux/Mac/Windows WSL2 operating systems, you'd use this command to set to 1 second: @@ -80,16 +78,17 @@ Some scalers issue HTTP requests to external servers (i.e. cloud services). As c The Kubernetes client config used within KEDA Metrics Adapter can be adjusted by passing the following command-line flags to the binary: -| Adapter Flag | Client Config Setting | Default Value | Description | -| -------------- | ----------------------- | ------------- | -------------------------------------------------------------- | -| kube-api-qps | cfg.QPS | 20.0 | Set the QPS rate for throttling requests sent to the apiserver | -| kube-api-burst | cfg.Burst | 30 | Set the burst for throttling requests sent to the apiserver | +| Adapter Flag | Client Config Setting | Default Value | Description | +| -------------- | --------------------- | ------------- | -------------------------------------------------------------- | +| kube-api-qps | cfg.QPS | 20.0 | Set the QPS rate for throttling requests sent to the apiserver | +| kube-api-burst | cfg.Burst | 30 | Set the burst for throttling requests sent to the apiserver | ## Configure `MaxConcurrentReconciles` for Controllers To implement internal controllers KEDA uses [controller-runtime project](https://github.com/kubernetes-sigs/controller-runtime), that enables configuration of [MaxConcurrentReconciles property](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/controller#Options), ie. the maximum number of concurrent reconciles which can be run for a controller. KEDA Operator exposes properties for specifying `MaxConcurrentReconciles` for following controllers/reconcilers: + - `ScaledObjectReconciler` - responsible for watching and managing `ScaledObjects`, ie. validates input trigger specification, starts scaling logic and manages dependent HPA. - `ScaledJobReconciler` - responsible for watching and managing `ScaledJobs` and dependent Kubernetes Jobs @@ -97,11 +96,11 @@ KEDA Metrics Server exposes property for specifying `MaxConcurrentReconciles` fo To modify this properties you can set environment variables on both KEDA Operator and Metrics Server Deployments: -| Environment variable name | Deployment | Default Value | Affected reconciler | -| ------------------------------------- | -------------- | ------------- | -------------------------------------------------------------- | -| KEDA_SCALEDOBJECT_CTRL_MAX_RECONCILES | Operator | 5 | ScaledObjectReconciler | -| KEDA_SCALEDJOB_CTRL_MAX_RECONCILES | Operator | 1 | ScaledJobReconciler | -| KEDA_METRICS_CTRL_MAX_RECONCILES | Metrics Server | 1 | MetricsScaledObjectReconciler | +| Environment variable name | Deployment | Default Value | Affected reconciler | +| ------------------------------------- | -------------- | ------------- | ----------------------------- | +| KEDA_SCALEDOBJECT_CTRL_MAX_RECONCILES | Operator | 5 | ScaledObjectReconciler | +| KEDA_SCALEDJOB_CTRL_MAX_RECONCILES | Operator | 1 | ScaledJobReconciler | +| KEDA_METRICS_CTRL_MAX_RECONCILES | Metrics Server | 1 | MetricsScaledObjectReconciler | ## Certificates used by KEDA Metrics Server @@ -110,20 +109,19 @@ By default, KEDA Metrics Server uses self-signed certificates while communicatin Certificates and CA bundle can be referenced in `args` section in KEDA Metrics Server Deployment: ```yaml -... +--- args: - - '--client-ca-file=/cabundle/service-ca.crt' - - '--tls-cert-file=/certs/tls.crt' - - '--tls-private-key-file=/certs/tls.key' -... + - "--client-ca-file=/cabundle/service-ca.crt" + - "--tls-cert-file=/certs/tls.crt" + - "--tls-private-key-file=/certs/tls.key" ``` -The custom CA bundle should be also referenced in the `v1beta1.external.metrics.k8s.io` [APIService](https://kubernetes.io/docs/reference/kubernetes-api/cluster-resources/api-service-v1/#APIServiceSpec) resource (which is created during the installation of KEDA). +The custom CA bundle should be also referenced in the `v1beta1.external.metrics.k8s.io` [APIService](https://kubernetes.io/docs/reference/kubernetes-api/cluster-resources/api-service-v1/#APIServiceSpec) resource (which is created during the installation of KEDA). You should also make sure that `insecureSkipTLSVerify` is not set to `true`. ```yaml -... +--- spec: service: namespace: keda @@ -135,5 +133,4 @@ spec: YOURCABUNDLE... groupPriorityMinimum: 100 versionPriority: 100 -... ``` diff --git a/content/docs/2.8/concepts/external-scalers.md b/content/docs/2.8/concepts/external-scalers.md index 16f721117..d360d39cd 100644 --- a/content/docs/2.8/concepts/external-scalers.md +++ b/content/docs/2.8/concepts/external-scalers.md @@ -9,7 +9,7 @@ Built-in scalers run in the KEDA process/pod, while external scalers require an This document describes the external scaler interfaces and how to implement them in Go, Node, and .NET; however for more details on GRPC refer to [the official GRPC documentation](https://grpc.io/docs/) ->Want to learn about existing external scalers? Explore our [external scaler community](https://github.com/kedacore/external-scalers). +> Want to learn about existing external scalers? Explore our [external scaler community](https://github.com/kedacore/external-scalers). ## Overview @@ -39,7 +39,7 @@ The `Scaler` interface defines 4 methods: - `Close` is called to allow the scaler to clean up connections or other resources. - `GetMetricSpec` returns the target value for the HPA definition for the scaler. For more details refer to [Implementing `GetMetricSpec`](#5-implementing-getmetricspec). - `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`. For more details refer to [Implementing `GetMetrics`](#6-implementing-getmetrics). -> Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA supports both `AverageValue` and `Value` metric target types for external metrics. When `AverageValue` (the default metric type) is used, the metric value returned by the external scaler will be divided by the number of replicas. + > Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA supports both `AverageValue` and `Value` metric target types for external metrics. When `AverageValue` (the default metric type) is used, the metric value returned by the external scaler will be divided by the number of replicas. The `PushScaler` interface adds a `Run` method. This method receives a push channel (`active`), on which the scaler can send `true` at any time. The purpose of this mechanism is to initiate a scaling operation independently from `pollingInterval`. @@ -109,7 +109,7 @@ KEDA will attempt a GRPC connection to `service-address.svc.local:9090` immediat } ``` ->**Note**: KEDA will issue all of the above RPC calls except `StreamIsActive` if `spec.triggers.type` is `external`. It _must_ be `external-push` for `StreamIsActive` to be called. +> **Note**: KEDA will issue all of the above RPC calls except `StreamIsActive` if `spec.triggers.type` is `external`. It _must_ be `external-push` for `StreamIsActive` to be called. ## Implementing KEDA external scaler GRPC interface @@ -176,8 +176,6 @@ npm install --save grpc request {{< /collapsible >}} -
- #### 3. Implementing `IsActive` Just like `IsActive(ctx context.Context) (bool, error)` in the go interface, the `IsActive` method in the GRPC interface is called every `pollingInterval` with a `ScaledObjectRef` object that contains the scaledObject name, namespace, and scaler metadata. @@ -304,70 +302,71 @@ public class ExternalScalerService : ExternalScaler.ExternalScalerBase Put the following code into your `index.js` file: ```js -const grpc = require('grpc') -const request = require('request') -const externalScalerProto = grpc.load('externalscaler.proto') +const grpc = require("grpc"); +const request = require("request"); +const externalScalerProto = grpc.load("externalscaler.proto"); -const server = new grpc.Server() +const server = new grpc.Server(); server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { isActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { - const now = new Date() - const yesterday = new Date(new Date().setDate(new Date().getDate()-1)); - - const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}` - const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}` - const radiusKm = 500 - const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}` - - request.get({ - url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, - json: true, - }, (err, resp, data) => { - if (err) { - callback({ - code: grpc.status.INTERNAL, - details: err, - }) - } else if (resp.statusCode !== 200) { - callback({ - code: grpc.status.INTERNAL, - details: `expected status 200, got ${resp.statusCode}` - }) - } else { - // count how many earthquakes with mag > 1.0 - let count = 0 - data.features.forEach(i => { - if (i.properties.mag > 1.0) { - count++ - } - }) - callback(null, { - result: count > 2, - }) + const now = new Date(); + const yesterday = new Date(new Date().setDate(new Date().getDate() - 1)); + + const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}`; + const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}`; + const radiusKm = 500; + const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}`; + + request.get( + { + url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, + json: true, + }, + (err, resp, data) => { + if (err) { + callback({ + code: grpc.status.INTERNAL, + details: err, + }); + } else if (resp.statusCode !== 200) { + callback({ + code: grpc.status.INTERNAL, + details: `expected status 200, got ${resp.statusCode}`, + }); + } else { + // count how many earthquakes with mag > 1.0 + let count = 0; + data.features.forEach((i) => { + if (i.properties.mag > 1.0) { + count++; + } + }); + callback(null, { + result: count > 2, + }); + } } - }) + ); } - } -}) + }, +}); -server.bind('127.0.0.1:9090', grpc.ServerCredentials.createInsecure()) -console.log('Server listening on 127.0.0.1:9090') +server.bind("127.0.0.1:9090", grpc.ServerCredentials.createInsecure()); +console.log("Server listening on 127.0.0.1:9090"); -server.start() +server.start(); ``` {{< /collapsible >}} -
- #### 4. Implementing `StreamIsActive` Unlike `IsActive`, `StreamIsActive` is called once when KEDA reconciles the `ScaledObject`, and expects the external scaler to maintain a long-lived connection and push `IsActiveResponse` objects whenever the scaler needs KEDA to activate the deployment. @@ -444,38 +443,36 @@ public override async Task StreamIsActive(ScaledObjectRef request, IServerStream server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... streamIsActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { const interval = setInterval(() => { getEarthquakeCount((err, count) => { if (err) { - console.error(err) + console.error(err); } else if (count > 2) { call.write({ result: true, - }) + }); } - }) + }); }, 1000 * 60 * 60); - call.on('end', () => { - clearInterval(interval) - }) + call.on("end", () => { + clearInterval(interval); + }); } - } -}) + }, +}); ``` {{< /collapsible >}} -
- #### 5. Implementing `GetMetricSpec` `GetMetricSpec` returns the `target` value for [the HPA definition for the scaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/). This scaler will define a static target of 10, but the threshold value is often specified in the metadata for other scalers. @@ -521,19 +518,19 @@ server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetricSpec: (call, callback) => { callback(null, { - metricSpecs: [{ - metricName: 'earthquakeThreshold', - targetSize: 10, - }] - }) - } -}) + metricSpecs: [ + { + metricName: "earthquakeThreshold", + targetSize: 10, + }, + ], + }); + }, +}); ``` {{< /collapsible >}} -
- #### 6. Implementing `GetMetrics` `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`, in this example it's `earthquakeThreshold`. @@ -600,32 +597,34 @@ public override async Task GetMetrics(GetMetricsRequest requ server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetrics: (call, callback) => { - const longitude = call.request.scaledObjectRef.scalerMetadata.longitude - const latitude = call.request.scaledObjectRef.scalerMetadata.latitude + const longitude = call.request.scaledObjectRef.scalerMetadata.longitude; + const latitude = call.request.scaledObjectRef.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { getEarthquakeCount((err, count) => { if (err) { callback({ code: grpc.status.INTERNAL, details: err, - }) + }); } else { callback(null, { - metricValues: [{ - metricName: 'earthquakeThreshold', - metricValue: count, - }] - }) + metricValues: [ + { + metricName: "earthquakeThreshold", + metricValue: count, + }, + ], + }); } - }) + }); } - } -}) + }, +}); ``` {{< /collapsible >}} diff --git a/content/docs/2.8/migration.md b/content/docs/2.8/migration.md index 5ee8a6455..29e8408c8 100644 --- a/content/docs/2.8/migration.md +++ b/content/docs/2.8/migration.md @@ -11,15 +11,17 @@ Please note that you **can not** run both KEDA v1 and v2 on the same Kubernetes KEDA v2 is using a new API namespace for its Custom Resources Definitions (CRD): `keda.sh` instead of `keda.k8s.io` and introduces a new Custom Resource for scaling of Jobs. See full details on KEDA Custom Resources [here](../concepts/#custom-resources-crd). Here's an overview of what's changed: + - [Scaling of Deployments](#scaling-of-deployments) - [Scaling of Jobs](#scaling-of-jobs) - [Improved flexibility & usability of trigger metadata](#improved-flexibility--usability-of-trigger-metadata) - [Scalers](#scalers) - [TriggerAuthentication](#triggerauthentication) - ### Scaling of Deployments + In order to scale `Deployments` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Rename property `spec.scaleTargetRef.deploymentName` to `spec.scaleTargetRef.name` - Rename property `spec.scaleTargetRef.containerName` to `spec.scaleTargetRef.envSourceContainerName` @@ -27,22 +29,23 @@ In order to scale `Deployments` with KEDA v2, you need to do only a few modifica Please see the examples below or refer to the full [v2 ScaledObject Specification](../concepts/scaling-deployments/#scaledobject-spec) - **Example of v1 ScaledObject** +**Example of v1 ScaledObject** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } labels: - deploymentName: {deployment-name} + deploymentName: { deployment-name } spec: scaleTargetRef: - deploymentName: {deployment-name} - containerName: {container-name} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + deploymentName: { deployment-name } + containerName: { container-name } + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -50,18 +53,18 @@ spec: **Example of v2 ScaledObject** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed kind: ScaledObject -metadata: # <--- labels.deploymentName is not needed - name: {scaled-object-name} +metadata: # <--- labels.deploymentName is not needed + name: { scaled-object-name } spec: scaleTargetRef: - name: {deployment-name} # <--- Property name was changed - envSourceContainerName: {container-name} # <--- Property name was changed - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + name: { deployment-name } # <--- Property name was changed + envSourceContainerName: { container-name } # <--- Property name was changed + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -69,34 +72,36 @@ spec: ### Scaling of Jobs In order to scale `Jobs` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Change the value of `kind` property from `ScaledObject` to `ScaledJob` - Remove property `spec.scaleType` -- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` +- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` You can configure `successfulJobsHistoryLimit` and `failedJobsHistoryLimit`. They will remove the old job histories automatically. Please see the examples below or refer to the full [v2 ScaledJob Specification](../concepts/scaling-jobs/#scaledjob-spec) **Example of v1 ScaledObject for Jobs scaling** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } spec: scaleType: job jobTargetRef: - parallelism: 1 + parallelism: 1 completions: 1 activeDeadlineSeconds: 600 - backoffLimit: 6 + backoffLimit: 6 template: # {job template} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to create jobs} ``` @@ -104,21 +109,21 @@ spec: **Example of v2 ScaledJob** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed -kind: ScaledJob # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +kind: ScaledJob # <--- Property value was changed metadata: - name: {scaled-job-name} -spec: # <--- spec.scaleType is not needed + name: { scaled-job-name } +spec: # <--- spec.scaleType is not needed jobTargetRef: - parallelism: 1 - completions: 1 + parallelism: 1 + completions: 1 activeDeadlineSeconds: 600 backoffLimit: 6 template: # {job template} - pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed - successfulJobsHistoryLimit: 5 # <--- property is added - failedJobsHistoryLimit: 5 # <--- Property is added + pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed + successfulJobsHistoryLimit: 5 # <--- property is added + failedJobsHistoryLimit: 5 # <--- Property is added maxReplicaCount: 100 triggers: # {list of triggers to create jobs} @@ -132,68 +137,74 @@ We've introduced more options to configure trigger metadata to give users more f Here's an overview: -| Scaler | 1.x | 2.0 | -|--------|--------|--------| -| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | -| `azure-monitor` | `activeDirectoryClientId`
`activeDirectoryClientPassword` | `activeDirectoryClientId`
`activeDirectoryClientIdFromEnv`
`activeDirectoryClientPasswordFromEnv` | -| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | -| `azure-servicebus` | `connection` | `connectionFromEnv` | -| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`)
`connection` (**Default**: `EventHub`) | `storageConnectionFromEnv`
`connectionFromEnv` | -| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `kafka` | _(none)_ | _(none)_ -| `rabbitmq` | `apiHost`
`host` | ~~`apiHost`~~
`host`
`hostFromEnv` | -| `prometheus` | _(none)_ | _(none)_ | -| `cron` | _(none)_ | _(none)_ | -| `redis` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `redis-streams` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | -| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ -| `liiklus` | _(none)_ | _(none)_ | -| `stan` | _(none)_ | _(none)_ | -| `huawei-cloudeye` | | _(none)_ | _(none)_ | -| `postgresql` | `connection`
`password` | `connectionFromEnv`
`passwordFromEnv` | -| `mysql` | `connectionString`
`password` | `connectionStringFromEnv`
`passwordFromEnv` | +| Scaler | 1.x | 2.0 | +| -------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------- | +| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | +| `azure-monitor` | `activeDirectoryClientId` `activeDirectoryClientPassword` | `activeDirectoryClientId` `activeDirectoryClientIdFromEnv` `activeDirectoryClientPasswordFromEnv` | +| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | +| `azure-servicebus` | `connection` | `connectionFromEnv` | +| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`) `connection` (**Default**: `EventHub`) | `storageConnectionFromEnv` `connectionFromEnv` | +| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `kafka` | _(none)_ | _(none)_ | +| `rabbitmq` | `apiHost` `host` | ~~`apiHost`~~ `host` `hostFromEnv` | +| `prometheus` | _(none)_ | _(none)_ | +| `cron` | _(none)_ | _(none)_ | +| `redis` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `redis-streams` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | +| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ | +| `liiklus` | _(none)_ | _(none)_ | +| `stan` | _(none)_ | _(none)_ | +| `huawei-cloudeye` | | _(none)_ | _(none)_ | +| `postgresql` | `connection` `password` | `connectionFromEnv` `passwordFromEnv` | +| `mysql` | `connectionString` `password` | `connectionStringFromEnv` `passwordFromEnv` | ### Scalers **Azure Service Bus** - - `queueLength` was renamed to `messageCount` + +- `queueLength` was renamed to `messageCount` **Kafka** - - `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. + +- `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. **RabbitMQ** In KEDA 2.0 the RabbitMQ scaler has only `host` parameter, and the protocol for communication can be specified by -`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP -protocol. +`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP +protocol. Example of RabbitMQ trigger before 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - includeUnacked: 'true' - apiHost: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + includeUnacked: "true" + apiHost: "https://guest:password@localhost:443/vhostname" +``` The same trigger in 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - protocol: 'http' - host: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + protocol: "http" + host: "https://guest:password@localhost:443/vhostname" +``` ### TriggerAuthentication + In order to use Authentication via `TriggerAuthentication` with KEDA v2, you need to change: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` For more details please refer to the full diff --git a/content/docs/2.8/operate/cluster.md b/content/docs/2.8/operate/cluster.md index 47365ca41..01a4f368d 100644 --- a/content/docs/2.8/operate/cluster.md +++ b/content/docs/2.8/operate/cluster.md @@ -29,12 +29,10 @@ KEDA requires to be accessible inside the cluster to be able to autoscale. Here is an overview of the required ports that need to be accessible for KEDA to work: - | Port | Why? | Remarks | | ------ | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication.

This is not applicable for Google Cloud. | +| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication. This is not applicable for Google Cloud. | | `6443` | Used by Kubernetes API server to get metrics | Only required for Google Cloud because it uses Control Plane → port 6443 on the Pod IP range for communication | - ## High Availability @@ -42,10 +40,10 @@ KEDA does not provide full support for high-availability due to upstream limitat Here is an overview of all KEDA deployments and the HA notes: -| Deployment | Support Replicas | Note | -| -------------- | ---------------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Deployment | Support Replicas | Note | +| -------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Metrics Server | 1 | You can run multiple replicas of our metrics sever, and it is recommended to add the `--enable-aggregator-routing=true` CLI flag to the kube-apiserver so that requests sent to our metrics servers are load balanced. However, [you can only run one active metric server in a Kubernetes cluster serving external.metrics.k8s.io](https://github.com/kubernetes-sigs/custom-metrics-apiserver/issues/70) which has to be the KEDA metric server. | -| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover. | +| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover. | ## HTTP Timeouts @@ -80,16 +78,17 @@ Some scalers issue HTTP requests to external servers (i.e. cloud services). As c The Kubernetes client config used within KEDA Metrics Adapter can be adjusted by passing the following command-line flags to the binary: -| Adapter Flag | Client Config Setting | Default Value | Description | -| -------------- | ----------------------- | ------------- | -------------------------------------------------------------- | -| kube-api-qps | cfg.QPS | 20.0 | Set the QPS rate for throttling requests sent to the apiserver | -| kube-api-burst | cfg.Burst | 30 | Set the burst for throttling requests sent to the apiserver | +| Adapter Flag | Client Config Setting | Default Value | Description | +| -------------- | --------------------- | ------------- | -------------------------------------------------------------- | +| kube-api-qps | cfg.QPS | 20.0 | Set the QPS rate for throttling requests sent to the apiserver | +| kube-api-burst | cfg.Burst | 30 | Set the burst for throttling requests sent to the apiserver | ## Configure `MaxConcurrentReconciles` for Controllers To implement internal controllers KEDA uses the [controller-runtime project](https://github.com/kubernetes-sigs/controller-runtime), that enables configuration of [MaxConcurrentReconciles property](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/controller#Options), ie. the maximum number of concurrent reconciles which can be run for a controller. KEDA Operator exposes properties for specifying `MaxConcurrentReconciles` for following controllers/reconcilers: + - `ScaledObjectReconciler` - responsible for watching and managing `ScaledObjects`, ie. validates input trigger specification, starts scaling logic and manages dependent HPA. - `ScaledJobReconciler` - responsible for watching and managing `ScaledJobs` and dependent Kubernetes Jobs @@ -97,15 +96,16 @@ KEDA Metrics Server exposes property for specifying `MaxConcurrentReconciles` fo To modify this properties you can set environment variables on both KEDA Operator and Metrics Server Deployments: -| Environment variable name | Deployment | Default Value | Affected reconciler | -| ------------------------------------- | -------------- | ------------- | -------------------------------------------------------------- | -| KEDA_SCALEDOBJECT_CTRL_MAX_RECONCILES | Operator | 5 | ScaledObjectReconciler | -| KEDA_SCALEDJOB_CTRL_MAX_RECONCILES | Operator | 1 | ScaledJobReconciler | -| KEDA_METRICS_CTRL_MAX_RECONCILES | Metrics Server | 1 | MetricsScaledObjectReconciler | +| Environment variable name | Deployment | Default Value | Affected reconciler | +| ------------------------------------- | -------------- | ------------- | ----------------------------- | +| KEDA_SCALEDOBJECT_CTRL_MAX_RECONCILES | Operator | 5 | ScaledObjectReconciler | +| KEDA_SCALEDJOB_CTRL_MAX_RECONCILES | Operator | 1 | ScaledJobReconciler | +| KEDA_METRICS_CTRL_MAX_RECONCILES | Metrics Server | 1 | MetricsScaledObjectReconciler | ## Configure Leader Election Like reconciliation, KEDA also uses the [controller-runtime project](https://github.com/kubernetes-sigs/controller-runtime) for electing the leader replica. The following properties can be configured for either the Operator and Metrics Server Deployment: + - [`LeaseDuration`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options.LeaseDuration) - [`RenewDeadline`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options.RenewDeadline) - [`RetryPeriod`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options.RetryPeriod) @@ -128,20 +128,19 @@ By default, KEDA Metrics Server uses self-signed certificates while communicatin Certificates and CA bundle can be referenced in `args` section in KEDA Metrics Server Deployment: ```yaml -... +--- args: - - '--client-ca-file=/cabundle/service-ca.crt' - - '--tls-cert-file=/certs/tls.crt' - - '--tls-private-key-file=/certs/tls.key' -... + - "--client-ca-file=/cabundle/service-ca.crt" + - "--tls-cert-file=/certs/tls.crt" + - "--tls-private-key-file=/certs/tls.key" ``` -The custom CA bundle should be also referenced in the `v1beta1.external.metrics.k8s.io` [APIService](https://kubernetes.io/docs/reference/kubernetes-api/cluster-resources/api-service-v1/#APIServiceSpec) resource (which is created during the installation of KEDA). +The custom CA bundle should be also referenced in the `v1beta1.external.metrics.k8s.io` [APIService](https://kubernetes.io/docs/reference/kubernetes-api/cluster-resources/api-service-v1/#APIServiceSpec) resource (which is created during the installation of KEDA). You should also make sure that `insecureSkipTLSVerify` is not set to `true`. ```yaml -... +--- spec: service: namespace: keda @@ -153,5 +152,4 @@ spec: YOURCABUNDLE... groupPriorityMinimum: 100 versionPriority: 100 -... ``` diff --git a/content/docs/2.9/concepts/external-scalers.md b/content/docs/2.9/concepts/external-scalers.md index 5badde098..aa00a18a0 100644 --- a/content/docs/2.9/concepts/external-scalers.md +++ b/content/docs/2.9/concepts/external-scalers.md @@ -9,7 +9,7 @@ Built-in scalers run in the KEDA process/pod, while external scalers require an This document describes the external scaler interfaces and how to implement them in Go, Node, and .NET; however for more details on GRPC refer to [the official GRPC documentation](https://grpc.io/docs/) ->Want to learn about existing external scalers? Explore our [external scaler community](https://github.com/kedacore/external-scalers). +> Want to learn about existing external scalers? Explore our [external scaler community](https://github.com/kedacore/external-scalers). ## Overview @@ -45,7 +45,7 @@ The `Scaler` interface defines 3 methods: - `GetMetricSpecForScaling` returns the target value for the HPA definition for the scaler. For more details refer to [Implementing `GetMetricSpec`](#5-implementing-getmetricspec). - `GetMetricsAndActivity` is called on `pollingInterval` and. When activity returns `true`, KEDA will scale to what is returned by the metric limited by `maxReplicaCount` on the ScaledObject/ScaledJob. When `false` is returned, KEDA will scale to `minReplicaCount` or optionally `idleReplicaCount`. More details around the defaults and how these options work together can be found on the [ScaledObjectSpec](https://keda.sh/docs/latest/concepts/scaling-deployments/#scaledobject-spec). -> Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA supports both `AverageValue` and `Value` metric target types for external metrics. When `AverageValue` (the default metric type) is used, the metric value returned by the external scaler will be divided by the number of replicas. + > Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA supports both `AverageValue` and `Value` metric target types for external metrics. When `AverageValue` (the default metric type) is used, the metric value returned by the external scaler will be divided by the number of replicas. The `PushScaler` interface adds a `Run` method. This method receives a push channel (`active`), on which the scaler can send `true` at any time. The purpose of this mechanism is to initiate a scaling operation independently from `pollingInterval`. @@ -115,7 +115,7 @@ KEDA will attempt a GRPC connection to `service-address.svc.local:9090` immediat } ``` ->**Note**: KEDA will issue all of the above RPC calls except `StreamIsActive` if `spec.triggers.type` is `external`. It _must_ be `external-push` for `StreamIsActive` to be called. +> **Note**: KEDA will issue all of the above RPC calls except `StreamIsActive` if `spec.triggers.type` is `external`. It _must_ be `external-push` for `StreamIsActive` to be called. ## Implementing KEDA external scaler GRPC interface @@ -182,8 +182,6 @@ npm install --save grpc request {{< /collapsible >}} -
- #### 3. Implementing `IsActive` Just like `IsActive(ctx context.Context) (bool, error)` in the go interface, the `IsActive` method in the GRPC interface is called every `pollingInterval` with a `ScaledObjectRef` object that contains the scaledObject name, namespace, and scaler metadata. @@ -310,70 +308,71 @@ public class ExternalScalerService : ExternalScaler.ExternalScalerBase Put the following code into your `index.js` file: ```js -const grpc = require('grpc') -const request = require('request') -const externalScalerProto = grpc.load('externalscaler.proto') +const grpc = require("grpc"); +const request = require("request"); +const externalScalerProto = grpc.load("externalscaler.proto"); -const server = new grpc.Server() +const server = new grpc.Server(); server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { isActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { - const now = new Date() - const yesterday = new Date(new Date().setDate(new Date().getDate()-1)); - - const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}` - const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}` - const radiusKm = 500 - const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}` - - request.get({ - url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, - json: true, - }, (err, resp, data) => { - if (err) { - callback({ - code: grpc.status.INTERNAL, - details: err, - }) - } else if (resp.statusCode !== 200) { - callback({ - code: grpc.status.INTERNAL, - details: `expected status 200, got ${resp.statusCode}` - }) - } else { - // count how many earthquakes with mag > 1.0 - let count = 0 - data.features.forEach(i => { - if (i.properties.mag > 1.0) { - count++ - } - }) - callback(null, { - result: count > 2, - }) + const now = new Date(); + const yesterday = new Date(new Date().setDate(new Date().getDate() - 1)); + + const startTime = `${yesterday.getUTCFullYear()}-${yesterday.getUTCMonth()}-${yesterday.getUTCDay()}`; + const endTime = `${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDay()}`; + const radiusKm = 500; + const query = `format=geojson&starttime=${startTime}&endtime=${endTime}&longitude=${longitude}&latitude=${latitude}&maxradiuskm=${radiusKm}`; + + request.get( + { + url: `https://earthquake.usgs.gov/fdsnws/event/1/query?${query}`, + json: true, + }, + (err, resp, data) => { + if (err) { + callback({ + code: grpc.status.INTERNAL, + details: err, + }); + } else if (resp.statusCode !== 200) { + callback({ + code: grpc.status.INTERNAL, + details: `expected status 200, got ${resp.statusCode}`, + }); + } else { + // count how many earthquakes with mag > 1.0 + let count = 0; + data.features.forEach((i) => { + if (i.properties.mag > 1.0) { + count++; + } + }); + callback(null, { + result: count > 2, + }); + } } - }) + ); } - } -}) + }, +}); -server.bind('127.0.0.1:9090', grpc.ServerCredentials.createInsecure()) -console.log('Server listening on 127.0.0.1:9090') +server.bind("127.0.0.1:9090", grpc.ServerCredentials.createInsecure()); +console.log("Server listening on 127.0.0.1:9090"); -server.start() +server.start(); ``` {{< /collapsible >}} -
- #### 4. Implementing `StreamIsActive` Unlike `IsActive`, `StreamIsActive` is called once when KEDA reconciles the `ScaledObject`, and expects the external scaler to maintain a long-lived connection and push `IsActiveResponse` objects whenever the scaler needs KEDA to activate the deployment. @@ -450,38 +449,36 @@ public override async Task StreamIsActive(ScaledObjectRef request, IServerStream server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... streamIsActive: (call, callback) => { - const longitude = call.request.scalerMetadata.longitude - const latitude = call.request.scalerMetadata.latitude + const longitude = call.request.scalerMetadata.longitude; + const latitude = call.request.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { const interval = setInterval(() => { getEarthquakeCount((err, count) => { if (err) { - console.error(err) + console.error(err); } else if (count > 2) { call.write({ result: true, - }) + }); } - }) + }); }, 1000 * 60 * 60); - call.on('end', () => { - clearInterval(interval) - }) + call.on("end", () => { + clearInterval(interval); + }); } - } -}) + }, +}); ``` {{< /collapsible >}} -
- #### 5. Implementing `GetMetricSpec` `GetMetricSpec` returns the `target` value for [the HPA definition for the scaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/). This scaler will define a static target of 10, but the threshold value is often specified in the metadata for other scalers. @@ -527,19 +524,19 @@ server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetricSpec: (call, callback) => { callback(null, { - metricSpecs: [{ - metricName: 'earthquakeThreshold', - targetSize: 10, - }] - }) - } -}) + metricSpecs: [ + { + metricName: "earthquakeThreshold", + targetSize: 10, + }, + ], + }); + }, +}); ``` {{< /collapsible >}} -
- #### 6. Implementing `GetMetrics` `GetMetrics` returns the value of the metric referred to from `GetMetricSpec`, in this example it's `earthquakeThreshold`. @@ -606,32 +603,34 @@ public override async Task GetMetrics(GetMetricsRequest requ server.addService(externalScalerProto.externalscaler.ExternalScaler.service, { // ... getMetrics: (call, callback) => { - const longitude = call.request.scaledObjectRef.scalerMetadata.longitude - const latitude = call.request.scaledObjectRef.scalerMetadata.latitude + const longitude = call.request.scaledObjectRef.scalerMetadata.longitude; + const latitude = call.request.scaledObjectRef.scalerMetadata.latitude; if (!longitude || !latitude) { callback({ code: grpc.status.INVALID_ARGUMENT, - details: 'longitude and latitude must be specified', - }) + details: "longitude and latitude must be specified", + }); } else { getEarthquakeCount((err, count) => { if (err) { callback({ code: grpc.status.INTERNAL, details: err, - }) + }); } else { callback(null, { - metricValues: [{ - metricName: 'earthquakeThreshold', - metricValue: count, - }] - }) + metricValues: [ + { + metricName: "earthquakeThreshold", + metricValue: count, + }, + ], + }); } - }) + }); } - } -}) + }, +}); ``` {{< /collapsible >}} diff --git a/content/docs/2.9/migration.md b/content/docs/2.9/migration.md index 5ee8a6455..29e8408c8 100644 --- a/content/docs/2.9/migration.md +++ b/content/docs/2.9/migration.md @@ -11,15 +11,17 @@ Please note that you **can not** run both KEDA v1 and v2 on the same Kubernetes KEDA v2 is using a new API namespace for its Custom Resources Definitions (CRD): `keda.sh` instead of `keda.k8s.io` and introduces a new Custom Resource for scaling of Jobs. See full details on KEDA Custom Resources [here](../concepts/#custom-resources-crd). Here's an overview of what's changed: + - [Scaling of Deployments](#scaling-of-deployments) - [Scaling of Jobs](#scaling-of-jobs) - [Improved flexibility & usability of trigger metadata](#improved-flexibility--usability-of-trigger-metadata) - [Scalers](#scalers) - [TriggerAuthentication](#triggerauthentication) - ### Scaling of Deployments + In order to scale `Deployments` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Rename property `spec.scaleTargetRef.deploymentName` to `spec.scaleTargetRef.name` - Rename property `spec.scaleTargetRef.containerName` to `spec.scaleTargetRef.envSourceContainerName` @@ -27,22 +29,23 @@ In order to scale `Deployments` with KEDA v2, you need to do only a few modifica Please see the examples below or refer to the full [v2 ScaledObject Specification](../concepts/scaling-deployments/#scaledobject-spec) - **Example of v1 ScaledObject** +**Example of v1 ScaledObject** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } labels: - deploymentName: {deployment-name} + deploymentName: { deployment-name } spec: scaleTargetRef: - deploymentName: {deployment-name} - containerName: {container-name} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + deploymentName: { deployment-name } + containerName: { container-name } + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -50,18 +53,18 @@ spec: **Example of v2 ScaledObject** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed kind: ScaledObject -metadata: # <--- labels.deploymentName is not needed - name: {scaled-object-name} +metadata: # <--- labels.deploymentName is not needed + name: { scaled-object-name } spec: scaleTargetRef: - name: {deployment-name} # <--- Property name was changed - envSourceContainerName: {container-name} # <--- Property name was changed - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + name: { deployment-name } # <--- Property name was changed + envSourceContainerName: { container-name } # <--- Property name was changed + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to activate the deployment} ``` @@ -69,34 +72,36 @@ spec: ### Scaling of Jobs In order to scale `Jobs` with KEDA v2, you need to do only a few modifications to existing v1 `ScaledObjects` definitions, so they comply with v2: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` - Change the value of `kind` property from `ScaledObject` to `ScaledJob` - Remove property `spec.scaleType` -- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` +- Remove properties `spec.cooldownPeriod` and `spec.minReplicaCount` You can configure `successfulJobsHistoryLimit` and `failedJobsHistoryLimit`. They will remove the old job histories automatically. Please see the examples below or refer to the full [v2 ScaledJob Specification](../concepts/scaling-jobs/#scaledjob-spec) **Example of v1 ScaledObject for Jobs scaling** + ```yaml apiVersion: keda.k8s.io/v1alpha1 kind: ScaledObject metadata: - name: {scaled-object-name} + name: { scaled-object-name } spec: scaleType: job jobTargetRef: - parallelism: 1 + parallelism: 1 completions: 1 activeDeadlineSeconds: 600 - backoffLimit: 6 + backoffLimit: 6 template: # {job template} - pollingInterval: 30 - cooldownPeriod: 300 - minReplicaCount: 0 - maxReplicaCount: 100 + pollingInterval: 30 + cooldownPeriod: 300 + minReplicaCount: 0 + maxReplicaCount: 100 triggers: # {list of triggers to create jobs} ``` @@ -104,21 +109,21 @@ spec: **Example of v2 ScaledJob** ```yaml -apiVersion: keda.sh/v1alpha1 # <--- Property value was changed -kind: ScaledJob # <--- Property value was changed +apiVersion: keda.sh/v1alpha1 # <--- Property value was changed +kind: ScaledJob # <--- Property value was changed metadata: - name: {scaled-job-name} -spec: # <--- spec.scaleType is not needed + name: { scaled-job-name } +spec: # <--- spec.scaleType is not needed jobTargetRef: - parallelism: 1 - completions: 1 + parallelism: 1 + completions: 1 activeDeadlineSeconds: 600 backoffLimit: 6 template: # {job template} - pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed - successfulJobsHistoryLimit: 5 # <--- property is added - failedJobsHistoryLimit: 5 # <--- Property is added + pollingInterval: 30 # <--- spec.cooldownPeriod and spec.minReplicaCount are not needed + successfulJobsHistoryLimit: 5 # <--- property is added + failedJobsHistoryLimit: 5 # <--- Property is added maxReplicaCount: 100 triggers: # {list of triggers to create jobs} @@ -132,68 +137,74 @@ We've introduced more options to configure trigger metadata to give users more f Here's an overview: -| Scaler | 1.x | 2.0 | -|--------|--------|--------| -| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | -| `azure-monitor` | `activeDirectoryClientId`
`activeDirectoryClientPassword` | `activeDirectoryClientId`
`activeDirectoryClientIdFromEnv`
`activeDirectoryClientPasswordFromEnv` | -| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | -| `azure-servicebus` | `connection` | `connectionFromEnv` | -| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`)
`connection` (**Default**: `EventHub`) | `storageConnectionFromEnv`
`connectionFromEnv` | -| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`)
`awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID`
`awsAccessKeyIDFromEnv`
`awsSecretAccessKeyFromEnv` | -| `kafka` | _(none)_ | _(none)_ -| `rabbitmq` | `apiHost`
`host` | ~~`apiHost`~~
`host`
`hostFromEnv` | -| `prometheus` | _(none)_ | _(none)_ | -| `cron` | _(none)_ | _(none)_ | -| `redis` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `redis-streams` | `address`
`host`
`port`
`password` | `address`
`addressFromEnv`
`host`
`hostFromEnv`
~~`port`~~
`passwordFromEnv` -| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | -| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ -| `liiklus` | _(none)_ | _(none)_ | -| `stan` | _(none)_ | _(none)_ | -| `huawei-cloudeye` | | _(none)_ | _(none)_ | -| `postgresql` | `connection`
`password` | `connectionFromEnv`
`passwordFromEnv` | -| `mysql` | `connectionString`
`password` | `connectionStringFromEnv`
`passwordFromEnv` | +| Scaler | 1.x | 2.0 | +| -------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------- | +| `azure-blob` | `connection` (**Default**: `AzureWebJobsStorage`) | `connectionFromEnv` | +| `azure-monitor` | `activeDirectoryClientId` `activeDirectoryClientPassword` | `activeDirectoryClientId` `activeDirectoryClientIdFromEnv` `activeDirectoryClientPasswordFromEnv` | +| `azure-queue` | `connection` (**Default**: AzureWebJobsStorage) | `connectionFromEnv` | +| `azure-servicebus` | `connection` | `connectionFromEnv` | +| `azure-eventhub` | `storageConnection` (**Default**: `AzureWebJobsStorage`) `connection` (**Default**: `EventHub`) | `storageConnectionFromEnv` `connectionFromEnv` | +| `aws-cloudwatch` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-kinesis-stream` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `aws-sqs-queue` | `awsAccessKeyID` (**Default**: `AWS_ACCESS_KEY_ID`) `awsSecretAccessKey` (**Default**: `AWS_SECRET_ACCESS_KEY`) | `awsAccessKeyID` `awsAccessKeyIDFromEnv` `awsSecretAccessKeyFromEnv` | +| `kafka` | _(none)_ | _(none)_ | +| `rabbitmq` | `apiHost` `host` | ~~`apiHost`~~ `host` `hostFromEnv` | +| `prometheus` | _(none)_ | _(none)_ | +| `cron` | _(none)_ | _(none)_ | +| `redis` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `redis-streams` | `address` `host` `port` `password` | `address` `addressFromEnv` `host` `hostFromEnv` ~~`port`~~ `passwordFromEnv` | +| `gcp-pubsub` | `credentials` | `credentialsFromEnv` | +| `external` | _(any matching value)_ | _(any matching value with `FromEnv` suffix)_ | +| `liiklus` | _(none)_ | _(none)_ | +| `stan` | _(none)_ | _(none)_ | +| `huawei-cloudeye` | | _(none)_ | _(none)_ | +| `postgresql` | `connection` `password` | `connectionFromEnv` `passwordFromEnv` | +| `mysql` | `connectionString` `password` | `connectionStringFromEnv` `passwordFromEnv` | ### Scalers **Azure Service Bus** - - `queueLength` was renamed to `messageCount` + +- `queueLength` was renamed to `messageCount` **Kafka** - - `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. + +- `authMode` property was replaced with `sasl` and `tls` properties. Please refer [documentation](../scalers/apache-kafka/#authentication-parameters) for Kafka Authentication Parameters details. **RabbitMQ** In KEDA 2.0 the RabbitMQ scaler has only `host` parameter, and the protocol for communication can be specified by -`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP -protocol. +`protocol` (http or amqp). The default value is `amqp`. The behavior changes only for scalers that were using HTTP +protocol. Example of RabbitMQ trigger before 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - includeUnacked: 'true' - apiHost: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + includeUnacked: "true" + apiHost: "https://guest:password@localhost:443/vhostname" +``` The same trigger in 2.0: + ```yaml triggers: -- type: rabbitmq - metadata: - queueLength: '20' - queueName: testqueue - protocol: 'http' - host: 'https://guest:password@localhost:443/vhostname' -``` + - type: rabbitmq + metadata: + queueLength: "20" + queueName: testqueue + protocol: "http" + host: "https://guest:password@localhost:443/vhostname" +``` ### TriggerAuthentication + In order to use Authentication via `TriggerAuthentication` with KEDA v2, you need to change: + - Change the value of `apiVersion` property from `keda.k8s.io/v1alpha1` to `keda.sh/v1alpha1` For more details please refer to the full diff --git a/content/docs/2.9/operate/cluster.md b/content/docs/2.9/operate/cluster.md index 5cc6024bb..18bca5f61 100644 --- a/content/docs/2.9/operate/cluster.md +++ b/content/docs/2.9/operate/cluster.md @@ -14,11 +14,11 @@ However, maintainers can decide to extend this by supporting more minor versions As a reference, this compatibility matrix shows supported k8s versions per KEDA version: -| KEDA | Kubernetes | -|-----------|---------------| -| v2.9 | v1.23 - v1.25 | -| v2.8 | v1.17 - v1.25 | -| v2.7 | v1.17 - v1.25 | +| KEDA | Kubernetes | +| ---- | ------------- | +| v2.9 | v1.23 - v1.25 | +| v2.8 | v1.17 - v1.25 | +| v2.7 | v1.17 - v1.25 | ### Cluster Capacity @@ -39,12 +39,10 @@ KEDA requires to be accessible inside the cluster to be able to autoscale. Here is an overview of the required ports that need to be accessible for KEDA to work: - | Port | Why? | Remarks | | ------ | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication.

This is not applicable for Google Cloud. | +| `443` | Used by Kubernetes API server to get metrics | Required for all platforms because it uses Control Plane → port 443 on the Service IP range communication. This is not applicable for Google Cloud. | | `6443` | Used by Kubernetes API server to get metrics | Only required for Google Cloud because it uses Control Plane → port 6443 on the Pod IP range for communication | - ## High Availability @@ -52,10 +50,10 @@ KEDA does not provide full support for high-availability due to upstream limitat Here is an overview of all KEDA deployments and the HA notes: -| Deployment | Support Replicas | Note | -| -------------- | ---------------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Deployment | Support Replicas | Note | +| -------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Metrics Server | 1 | You can run multiple replicas of our metrics sever, and it is recommended to add the `--enable-aggregator-routing=true` CLI flag to the kube-apiserver so that requests sent to our metrics servers are load balanced. However, [you can only run one active metric server in a Kubernetes cluster serving external.metrics.k8s.io](https://github.com/kubernetes-sigs/custom-metrics-apiserver/issues/70) which has to be the KEDA metric server. | -| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover. | +| Operator | 2 | While you can run multiple replicas of our operator, only one operator instance will be active. The rest will be standing by, which may reduce downtime during a failure. Multiple replicas will not improve the performance of KEDA, it could only reduce a downtime during a failover. | ## HTTP Timeouts @@ -77,7 +75,7 @@ All applicable scalers will use this timeout. Setting a per-scaler timeout is cu ## HTTP connection disable keep alive -Keep alive behaviour is enabled by default for every HTTP connection, this could stack a huge amount of connections (one per scaler) in some scenarios. +Keep alive behaviour is enabled by default for every HTTP connection, this could stack a huge amount of connections (one per scaler) in some scenarios. You can disable keep alive for every HTTP connection by adding the relevant environment variable to both the KEDA Operator, and KEDA Metrics Server deployments: @@ -103,17 +101,18 @@ Some scalers issue HTTP requests to external servers (i.e. cloud services). As c The Kubernetes client config used within KEDA Operator and KEDA Metrics Adapter can be adjusted by passing the following command-line flags to the binary: -| Adapter Flag | Client Config Setting | Default Value | Description | -| ------------------- | ----------------------- | ------------- | -------------------------------------------------------------- | -| kube-api-qps | cfg.QPS | 20.0 | Set the QPS rate for throttling requests sent to the apiserver | -| kube-api-burst | cfg.Burst | 30 | Set the burst for throttling requests sent to the apiserver | -| disable-compression | cfg.DisableCompression | true | Disable compression for response in k8s restAPI in client-go, see [this Kubernetes issue](https://github.com/kubernetes/kubernetes/issues/112296) for details | +| Adapter Flag | Client Config Setting | Default Value | Description | +| ------------------- | ---------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| kube-api-qps | cfg.QPS | 20.0 | Set the QPS rate for throttling requests sent to the apiserver | +| kube-api-burst | cfg.Burst | 30 | Set the burst for throttling requests sent to the apiserver | +| disable-compression | cfg.DisableCompression | true | Disable compression for response in k8s restAPI in client-go, see [this Kubernetes issue](https://github.com/kubernetes/kubernetes/issues/112296) for details | ## Configure `MaxConcurrentReconciles` for Controllers To implement internal controllers KEDA uses the [controller-runtime project](https://github.com/kubernetes-sigs/controller-runtime), that enables configuration of [MaxConcurrentReconciles property](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/controller#Options), ie. the maximum number of concurrent reconciles which can be run for a controller. KEDA Operator exposes properties for specifying `MaxConcurrentReconciles` for following controllers/reconcilers: + - `ScaledObjectReconciler` - responsible for watching and managing `ScaledObjects`, ie. validates input trigger specification, starts scaling logic and manages dependent HPA. - `ScaledJobReconciler` - responsible for watching and managing `ScaledJobs` and dependent Kubernetes Jobs @@ -121,15 +120,16 @@ KEDA Metrics Server exposes property for specifying `MaxConcurrentReconciles` fo To modify this properties you can set environment variables on both KEDA Operator and Metrics Server Deployments: -| Environment variable name | Deployment | Default Value | Affected reconciler | -| ------------------------------------- | -------------- | ------------- | -------------------------------------------------------------- | -| KEDA_SCALEDOBJECT_CTRL_MAX_RECONCILES | Operator | 5 | ScaledObjectReconciler | -| KEDA_SCALEDJOB_CTRL_MAX_RECONCILES | Operator | 1 | ScaledJobReconciler | -| KEDA_METRICS_CTRL_MAX_RECONCILES | Metrics Server | 1 | MetricsScaledObjectReconciler | +| Environment variable name | Deployment | Default Value | Affected reconciler | +| ------------------------------------- | -------------- | ------------- | ----------------------------- | +| KEDA_SCALEDOBJECT_CTRL_MAX_RECONCILES | Operator | 5 | ScaledObjectReconciler | +| KEDA_SCALEDJOB_CTRL_MAX_RECONCILES | Operator | 1 | ScaledJobReconciler | +| KEDA_METRICS_CTRL_MAX_RECONCILES | Metrics Server | 1 | MetricsScaledObjectReconciler | ## Configure Leader Election Like reconciliation, KEDA also uses the [controller-runtime project](https://github.com/kubernetes-sigs/controller-runtime) for electing the leader replica. The following properties can be configured for either the Operator and Metrics Server Deployment: + - [`LeaseDuration`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options.LeaseDuration) - [`RenewDeadline`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options.RenewDeadline) - [`RetryPeriod`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options.RetryPeriod) @@ -152,20 +152,19 @@ By default KEDA Metrics Server uses self-signed certificates while communicating Certificates and CA bundle can be referenced in `args` section in KEDA Metrics Server Deployment: ```yaml -... +--- args: - - '--client-ca-file=/cabundle/service-ca.crt' - - '--tls-cert-file=/certs/tls.crt' - - '--tls-private-key-file=/certs/tls.key' -... + - "--client-ca-file=/cabundle/service-ca.crt" + - "--tls-cert-file=/certs/tls.crt" + - "--tls-private-key-file=/certs/tls.key" ``` -The custom CA bundle should be also referenced in the `v1beta1.external.metrics.k8s.io` [APIService](https://kubernetes.io/docs/reference/kubernetes-api/cluster-resources/api-service-v1/#APIServiceSpec) resource (which is created during the installation of KEDA). +The custom CA bundle should be also referenced in the `v1beta1.external.metrics.k8s.io` [APIService](https://kubernetes.io/docs/reference/kubernetes-api/cluster-resources/api-service-v1/#APIServiceSpec) resource (which is created during the installation of KEDA). You should also make sure that `insecureSkipTLSVerify` is not set to `true`. ```yaml -... +--- spec: service: namespace: keda @@ -177,31 +176,34 @@ spec: YOURCABUNDLE... groupPriorityMinimum: 100 versionPriority: 100 -... ``` ## Restrict Secret Access By default, KEDA requires adding `secrets` to the cluster role as following: + ```yaml - apiGroups: - - "" + - "" resources: - - external - - pods - - secrets - - services + - external + - pods + - secrets + - services verbs: - - get - - list - - watch + - get + - list + - watch ``` + However, this might lead to security risk (especially in production environment) since it will grant permission to read `secrets` from all namespaces. To restrict `secret` access and limited to KEDA namespace, you could add `KEDA_RESTRICT_SECRET_ACCESS` as environment variable to both KEDA Operator and KEDA Metrics Server: + ```yaml env: - name: KEDA_RESTRICT_SECRET_ACCESS value: "true" ``` + This allows you to omit `secrets` from the cluster role, which will disallow `TriggerAuthentication` to be used for your triggers if the `TriggerAuthentication` is using secrets. You can, however, still use `ClusterTriggerAuthentication`. From eba4f5343112e8f0b05a3b5328b826cf70fee7e1 Mon Sep 17 00:00:00 2001 From: Dave Welsch <116022979+dwelsch-esi@users.noreply.github.com> Date: Fri, 28 Jun 2024 06:07:32 -0700 Subject: [PATCH 11/33] Added Reference section, Glossary, removed non-inclusive language. (#1389) Co-authored-by: Dave Welsch <116022979+dwelsch-esi@users.noreply.github.com> Co-authored-by: Tom Kerkhove Co-authored-by: Nate W Co-authored-by: thisisobate Signed-off-by: shubhusion --- config.toml | 2 +- content/docs/2.14/operate/cloud-events.md | 116 +++++++ content/docs/2.14/reference/_index.md | 13 + content/docs/2.14/reference/events.md | 28 ++ content/docs/{2.15 => 2.14/reference}/faq.md | 1 + content/docs/2.14/reference/glossary.md | 88 ++++++ content/docs/2.14/reference/scaledjob-spec.md | 236 ++++++++++++++ .../docs/2.14/reference/scaledobject-spec.md | 254 +++++++++++++++ content/docs/2.15/_index.md | 17 +- .../docs/2.15/authentication-providers/aws.md | 6 +- .../docs/2.15/concepts/external-scalers.md | 4 +- .../docs/2.15/concepts/scaling-deployments.md | 293 ++---------------- content/docs/2.15/concepts/scaling-jobs.md | 247 +-------------- content/docs/2.15/deploy.md | 12 +- content/docs/2.15/migration.md | 4 +- content/docs/2.15/operate/_index.md | 6 +- content/docs/2.15/operate/cloud-events.md | 116 +++++++ content/docs/2.15/operate/events.md | 144 --------- content/docs/2.15/operate/metrics-server.md | 2 +- content/docs/2.15/reference/_index.md | 13 + content/docs/2.15/reference/events.md | 28 ++ content/docs/2.15/reference/faq.md | 6 + content/docs/2.15/reference/glossary.md | 88 ++++++ content/docs/2.15/reference/scaledjob-spec.md | 236 ++++++++++++++ .../docs/2.15/reference/scaledobject-spec.md | 254 +++++++++++++++ content/docs/2.15/scalers/aws-sqs.md | 4 +- content/docs/2.15/scalers/azure-pipelines.md | 2 +- .../docs/2.15/scalers/azure-service-bus.md | 4 +- content/docs/2.15/scalers/datadog.md | 4 +- .../docs/2.15/scalers/redis-sentinel-lists.md | 8 +- .../2.15/scalers/redis-sentinel-streams.md | 10 +- 31 files changed, 1570 insertions(+), 676 deletions(-) create mode 100644 content/docs/2.14/operate/cloud-events.md create mode 100644 content/docs/2.14/reference/_index.md create mode 100644 content/docs/2.14/reference/events.md rename content/docs/{2.15 => 2.14/reference}/faq.md (72%) create mode 100644 content/docs/2.14/reference/glossary.md create mode 100644 content/docs/2.14/reference/scaledjob-spec.md create mode 100644 content/docs/2.14/reference/scaledobject-spec.md create mode 100644 content/docs/2.15/operate/cloud-events.md delete mode 100644 content/docs/2.15/operate/events.md create mode 100644 content/docs/2.15/reference/_index.md create mode 100644 content/docs/2.15/reference/events.md create mode 100644 content/docs/2.15/reference/faq.md create mode 100644 content/docs/2.15/reference/glossary.md create mode 100644 content/docs/2.15/reference/scaledjob-spec.md create mode 100644 content/docs/2.15/reference/scaledobject-spec.md diff --git a/config.toml b/config.toml index 3407abf04..fe27d32f0 100644 --- a/config.toml +++ b/config.toml @@ -188,7 +188,7 @@ parent = "docs" weight = 5 [[menu.docs]] -url = "/docs/faq/" +url = "/docs/reference/faq/" name = "FAQ" parent = "docs" weight = 6 diff --git a/content/docs/2.14/operate/cloud-events.md b/content/docs/2.14/operate/cloud-events.md new file mode 100644 index 000000000..e07dc0505 --- /dev/null +++ b/content/docs/2.14/operate/cloud-events.md @@ -0,0 +1,116 @@ ++++ +title = "CloudEvent Support" +description = "Experimental support for cloud events" +weight = 100 ++++ + +## Subscribing to events with `CloudEventSource` +`CloudEventSource` resource can be used in KEDA for subscribing to events that are emitted to the user's defined CloudEvent sink. + +> 📝 Event will be emitted to both Kubernetes Events and CloudEvents Destination if CloudEventSource resource is created. + +Here is a the schema of the `CloudEventSource` CRD: + +```yaml +apiVersion: eventing.keda.sh/v1alpha1 +kind: CloudEventSource +metadata: + name: {cloud-event-name} +spec: + clusterName: {cluster-name} #Optional. Will be used in the source/subject to specify where the event comes from. The default value is 'kubernetes-default' and it can also be set during the installation of KEDA with --k8sClusterName. This one will overwrite others if set. + authenticationRef: + name: {trigger-authentication-name} #Optional. Used to reference a `TriggerAuthentication` for authentication. + kind: TriggerAuthentication # Optional. Used to choose the authentication scopes. https://keda.sh/docs/latest/concepts/authentication/#authentication-scopes-namespace-vs-cluster + destination: + http: + uri: http://foo.bar + azureEventGridTopic: + endpoint: https://my-topic.eastus-1.eventgrid.azure.net/api/events + + eventSubscription: #Optional. Submit included/excluded event types will filter events when emitting events. + includedEventTypes: #Optional. Only events in this section will be emitted. + - keda.scaledobject.failed.v1 + excludedEventTypes: #Optional. Events in this section will not be emitted. + - keda.scaledobject.ready.v1 +``` + +In general, an event emitted by KEDA would fundamentally come down to the following structure: +```json +{ + "specversion" : "1.0", + "type" : "com.cloudeventsource.keda", + "source" : "/{cluster-name}/{keda-namespace}/keda", + "subject" : "/{cluster-name}/{namespace}/{object-type}/{object-name}", + "id" : "", + "time" : "2018-04-05T17:31:00Z", + "datacontenttype" : "application/json", + "data" : { + "reason":"", + "message":"" + } +} +``` + +## Event Sinks + +There will be multiple types of destination to emit KEDA events to. + +Here is an overview of the supported destinations: + +- [HTTP endpoint](#http-endpoint). +- [Azure Event Grid endpoint](#azure-event-grid). + +### HTTP endpoint +```yaml + destination: + http: + uri: http://foo.bar #An http endpoint that can receive cloudevent +``` + +### Azure Event Grid + +```yaml + destination: + azureEventGrid: + endpoint: foo.bar #endpoint from AzureEventGrid Topic +``` + +Authentication information must be provided by using `authenticationRef` which allows you to provide the access key or managed identity for Azure Event Grid authentication by providing a `TriggerAuthentication`. + +Here is an overview of the supported authentication types: + +#### Connection String Authentication + +- `accessKey` - Access key string for the Azure Event Grid connection auth. + +#### Pod identity based authentication +[Azure AD Workload Identity](https://azure.github.io/azure-workload-identity/docs/) providers can be used. + +```yaml +apiVersion: keda.sh/v1alpha1 +kind: TriggerAuthentication +metadata: + name: nameOfTriggerAuth + namespace: default +spec: + podIdentity: + provider: azure-workload +``` + +## Event Filter + +You can include filter(s) to define what event types you are interested in, or want to ignore. This is done by using `includedEventTypes` or `excludedEventTypes` respectively for a given sink. + +```yaml +eventSubscription: #Optional. Submit included/excluded event types will filter events when emitting events. + includedEventTypes: #Optional. Only events in this section will be emitted. + - keda.scaledobject.failed.v1 + excludedEventTypes: #Optional. Events in this section will not be emitted. + - keda.scaledobject.ready.v1 +``` + +## Supported Event List +| Event Type | Scenario Description | +|-------------------------------|-----------------------------------------------------------------------------------------------------------------------------| +| `keda.scaledobject.ready.v1` | On the first time a ScaledObject is ready, or if the previous ready condition status of the object was `Unknown` or `False` | +| `keda.scaledobject.failed.v1` | If the check validation for a ScaledObject fails | diff --git a/content/docs/2.14/reference/_index.md b/content/docs/2.14/reference/_index.md new file mode 100644 index 000000000..987370371 --- /dev/null +++ b/content/docs/2.14/reference/_index.md @@ -0,0 +1,13 @@ ++++ +title = "Reference" +weight = 2 ++++ + +Reference information for the KEDA autoscaler. + +- [ScaledObject specification](./scaledobject-spec) +- [ScaledJob specification](./scaledjob-spec) +- [Events](./events) +- [Firewall requirements](../operate/cluster#firewall) +- [FAQ](./faq.md) +- [Glossary](./glossary.md) \ No newline at end of file diff --git a/content/docs/2.14/reference/events.md b/content/docs/2.14/reference/events.md new file mode 100644 index 000000000..aa264c0d8 --- /dev/null +++ b/content/docs/2.14/reference/events.md @@ -0,0 +1,28 @@ ++++ +title = "Events reference" +description = "Kubernetes Events emitted by KEDA" +weight = 2500 ++++ + +KEDA emits the following [Kubernetes Events](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#event-v1-core): + +| Event | Type | Description | +|---------------------------------------|-----------|-----------------------------------------------------------------------------------------------------------------------------| +| `ScaledObjectReady` | `Normal` | On the first time a ScaledObject is ready, or if the previous ready condition status of the object was `Unknown` or `False` | +| `ScaledJobReady` | `Normal` | On the first time a ScaledJob is ready, or if the previous ready condition status of the object was `Unknown` or `False` | +| `ScaledObjectCheckFailed` | `Warning` | If the check validation for a ScaledObject fails | | +| `ScaledJobCheckFailed` | `Warning` | If the check validation for a ScaledJob fails | | +| `ScaledObjectDeleted` | `Normal` | When a ScaledObject is deleted and removed from KEDA watch | | +| `ScaledJobDeleted` | `Normal` | When a ScaledJob is deleted and removed from KEDA watch | | +| `KEDAScalersStarted` | `Normal` | When Scalers watch loop have started for a ScaledObject or ScaledJob | | +| `KEDAScalersStopped` | `Normal` | When Scalers watch loop have stopped for a ScaledObject or a ScaledJob | | +| `KEDAScalerFailed` | `Warning` | When a Scaler fails to create or check its event source | | +| `KEDAScaleTargetActivated` | `Normal` | When the scale target (Deployment, StatefulSet, etc) of a ScaledObject is scaled to 1, triggered by {scalers1;scalers2;...} | | +| `KEDAScaleTargetDeactivated` | `Normal` | When the scale target (Deployment, StatefulSet, etc) of a ScaledObject is scaled to 0 | | +| `KEDAScaleTargetActivationFailed` | `Warning` | When KEDA fails to scale the scale target of a ScaledObject to 1 | | +| `KEDAScaleTargetDeactivationFailed` | `Warning` | When KEDA fails to scale the scale target of a ScaledObject to 0 | | +| `KEDAJobsCreated` | `Normal` | When KEDA creates jobs for a ScaledJob | | +| `TriggerAuthenticationAdded` | `Normal` | When a new TriggerAuthentication is added | | +| `TriggerAuthenticationDeleted` | `Normal` | When a TriggerAuthentication is deleted | | +| `ClusterTriggerAuthenticationAdded` | `Normal` | When a new ClusterTriggerAuthentication is added | | +| `ClusterTriggerAuthenticationDeleted` | `Normal` | When a ClusterTriggerAuthentication is deleted | | diff --git a/content/docs/2.15/faq.md b/content/docs/2.14/reference/faq.md similarity index 72% rename from content/docs/2.15/faq.md rename to content/docs/2.14/reference/faq.md index d012d6767..df75bbe78 100644 --- a/content/docs/2.15/faq.md +++ b/content/docs/2.14/reference/faq.md @@ -1,5 +1,6 @@ +++ title = "FAQ" +weight = 2000 +++ {{< faq20 >}} diff --git a/content/docs/2.14/reference/glossary.md b/content/docs/2.14/reference/glossary.md new file mode 100644 index 000000000..fa8ecf689 --- /dev/null +++ b/content/docs/2.14/reference/glossary.md @@ -0,0 +1,88 @@ ++++ +title = "Glossary" +weight = 1000 ++++ + +This document defines the various terms needed to understand the documentation and set up and use KEDA. + +## Admission Webhook + +[In Kubernetes](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/), an HTTP callback that handle admission requests. KEDA uses an admission webhook to validate and mutate ScaledObject resources. + +## Agent + +A primary role held by the KEDA operator. The Agent activates and deactivates Kubernetes Deployments to scale to and from zero. + +## Cluster + +[In Kubernetes](https://kubernetes.io/docs/reference/glossary/?fundamental=true#term-cluster), a set of one or more nodes that run containerized applications. + +## CRD + +Custom Resource Definition. [In Kubernetes](https://kubernetes.io/docs/reference/glossary/?fundamental=true#term-CustomResourceDefinition), a custom resource that extends the Kubernetes API with custom resources like ScaledObjects that have custom fields and behavior. + +## Event + +A notable occurrence captured by an event source that KEDA may use as a trigger to scale a container or deployment. + +## Event Source + +An external system like Kafka, RabbitMQ, that generates events that KEDA can monitor using a scaler. + +## Grafana + +An open-source monitoring platform that can visualize metrics collected by KEDA. + +## GRPC + +Go Remote Procedure Call. An open-source remote procedure call framework used by KEDA components to communicate. + +## HPA + +Horizontal Pod Autoscaler. Kubernetes autoscaler. By default, scales based on CPU/memory usage. KEDA uses HPA to scale Kubernetes clusters and deployments. + +## KEDA + +Kubernetes Event-Driven Autoscaling. A single-purpose, lightweight autoscaler that can scale a Kubernetes workload based on event metrics. + +## Metric + +Measurement of an event source such as queue length or response lag that KEDA uses to determine scaling. + +## OpenTelemetry + +An observability framework used by KEDA to instrument applications and collect metrics. + +## Operator + +The core KEDA component that monitors metrics and scales workloads accordingly. + +## Prometheus + +An open-source monitoring system that can scrape and store metrics from KEDA. + +## Scaled Object + +A custom resource that defines how KEDA should scale a workload based on events. + +## Scaled Job + +A custom resource KEDA uses to scale an application. + +## Scaler + +A component that integrates KEDA with a specific event source to collect metrics. + +## Stateful Set + +A Kubernetes workload with persistent data. KEDA can scale stateful sets. + +## TLS + +Transport Layer Security. KEDA uses TLS to encrypt communications between KEDA components. + +## Webhook + +An HTTP callback used to notify KEDA of events from external sources. + +[In Kubernetes](https://kubernetes.io/docs/reference/access-authn-authz/webhook/), an HTTP callback used as an event notification mechanism. diff --git a/content/docs/2.14/reference/scaledjob-spec.md b/content/docs/2.14/reference/scaledjob-spec.md new file mode 100644 index 000000000..dbc33680b --- /dev/null +++ b/content/docs/2.14/reference/scaledjob-spec.md @@ -0,0 +1,236 @@ ++++ +title = "ScaledJob specification" +weight = 4000 ++++ + +## Overview + +This specification describes the `ScaledJob` custom resource definition that defines the triggers and scaling behaviors use by KEDA + +to scale jobs. The `.spec.ScaleTargetRef` section holds the reference to the job, defined in [_scaledjob_types.go_](https://github.com/kedacore/keda/blob/main/apis/keda/v1alpha1/scaledjob_types.go). + +```yaml +apiVersion: keda.sh/v1alpha1 +kind: ScaledJob +metadata: + name: {scaled-job-name} + labels: + my-label: {my-label-value} # Optional. ScaledJob labels are applied to child Jobs + annotations: + autoscaling.keda.sh/paused: true # Optional. Use to pause autoscaling of Jobs + my-annotation: {my-annotation-value} # Optional. ScaledJob annotations are applied to child Jobs +spec: + jobTargetRef: + parallelism: 1 # [max number of desired pods](https://kubernetes.io/docs/concepts/workloads/controllers/job/#controlling-parallelism) + completions: 1 # [desired number of successfully finished pods](https://kubernetes.io/docs/concepts/workloads/controllers/job/#controlling-parallelism) + activeDeadlineSeconds: 600 # Specifies the duration in seconds relative to the startTime that the job may be active before the system tries to terminate it; value must be positive integer + backoffLimit: 6 # Specifies the number of retries before marking this job failed. Defaults to 6 + template: + # describes the [job template](https://kubernetes.io/docs/concepts/workloads/controllers/job) + pollingInterval: 30 # Optional. Default: 30 seconds + successfulJobsHistoryLimit: 5 # Optional. Default: 100. How many completed jobs should be kept. + failedJobsHistoryLimit: 5 # Optional. Default: 100. How many failed jobs should be kept. + envSourceContainerName: {container-name} # Optional. Default: .spec.JobTargetRef.template.spec.containers[0] + minReplicaCount: 10 # Optional. Default: 0 + maxReplicaCount: 100 # Optional. Default: 100 + rolloutStrategy: gradual # Deprecated: Use rollout.strategy instead (see below). + rollout: + strategy: gradual # Optional. Default: default. Which Rollout Strategy KEDA will use. + propagationPolicy: foreground # Optional. Default: background. Kubernetes propagation policy for cleaning up existing jobs during rollout. + scalingStrategy: + strategy: "custom" # Optional. Default: default. Which Scaling Strategy to use. + customScalingQueueLengthDeduction: 1 # Optional. A parameter to optimize custom ScalingStrategy. + customScalingRunningJobPercentage: "0.5" # Optional. A parameter to optimize custom ScalingStrategy. + pendingPodConditions: # Optional. A parameter to calculate pending job count per the specified pod conditions + - "Ready" + - "PodScheduled" + - "AnyOtherCustomPodCondition" + multipleScalersCalculation : "max" # Optional. Default: max. Specifies how to calculate the target metrics when multiple scalers are defined. + triggers: + # {list of triggers to create jobs} +``` + +You can find all supported triggers [here](../scalers). + +## jobTargetRef + +```yaml + jobTargetRef: + parallelism: 1 # Optional. Max number of desired instances ([docs](https://kubernetes.io/docs/concepts/workloads/controllers/job/#controlling-parallelism)) + completions: 1 # Optional. Desired number of successfully finished instances ([docs](https://kubernetes.io/docs/concepts/workloads/controllers/job/#controlling-parallelism)) + activeDeadlineSeconds: 600 # Optional. Specifies the duration in seconds relative to the startTime that the job may be active before the system tries to terminate it; value must be positive integer + backoffLimit: 6 # Optional. Specifies the number of retries before marking this job failed. Defaults to 6 +``` + +The `jobTargetRef` is a batch/v1 `JobSpec` object; refer to the Kubernetes API for [more details](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/job-v1/#JobSpec) about the fields. The `template` field is required. + + +## pollingInterval + +```yaml + pollingInterval: 30 # Optional. Default: 30 seconds +``` + +This is the interval to check each trigger on. By default, KEDA will check each trigger source on every ScaledJob every 30 seconds. + + +## successfulJobsHistoryLimit, failedJobsHistoryLimit + +```yaml + successfulJobsHistoryLimit: 5 # Optional. Default: 100. How many completed jobs should be kept. + failedJobsHistoryLimit: 5 # Optional. Default: 100. How many failed jobs should be kept. +``` + +The `successfulJobsHistoryLimit` and `failedJobsHistoryLimit` fields are optional. These fields specify how many completed and failed jobs should be kept. By default, they are set to 100. + +This concept is similar to [Jobs History Limits](https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/#jobs-history-limits) allowing you to learn what the outcomes of your jobs are. + +The actual number of jobs could exceed the limit in a short time. However, it is going to resolve in the cleanup period. Currently, the cleanup period is the same as the Polling interval. + + +## envSourceContainerName + +```yaml + envSourceContainerName: {container-name} # Optional. Default: .spec.JobTargetRef.template.spec.containers[0] +``` + +This optional property specifies the name of container in the Job, from which KEDA should try to get environment properties holding secrets etc. If it is not defined it, KEDA will try to get environment properties from the first Container, ie. from `.spec.JobTargetRef.template.spec.containers[0]`. + +___ +## minReplicaCount + +```yaml + minReplicaCount: 10 # Optional. Default: 0 +``` + +The min number of jobs that is created by default. This can be useful to avoid bootstrapping time of new jobs. If minReplicaCount is greater than maxReplicaCount, minReplicaCount will be set to maxReplicaCount. + +New messages may create new jobs - within the limits imposed by maxReplicaCount - in order to reach the state where minReplicaCount jobs are always running. For example, if one sets minReplicaCount to 2 then there will be 2 jobs running permanently. Using a targetValue of 1, if 3 new messages are sent, 2 of those messages will be processed on the already running jobs but another 3 jobs will be created in order to fulfill the desired state dictated by the minReplicaCount parameter that is set to 2. + +## maxReplicaCount + +```yaml + maxReplicaCount: 100 # Optional. Default: 100 +``` + +The max number of pods that is created within a single polling period. If there are running jobs, the number of running jobs will be deducted. This table is an example of the scaling logic. + +| Queue Length | Max Replica Count | Target Average Value | Running Job Count | Number of the Scale | +|--------------|-------------------|----------------------|-------------------|---------------------| +| 10 | 3 | 1 | 0 | 3 | +| 10 | 3 | 2 | 0 | 3 | +| 10 | 3 | 1 | 1 | 2 | +| 10 | 100 | 1 | 0 | 10 | +| 4 | 3 | 5 | 0 | 1 | + +* **Queue Length:** The number of items in the queue. +* **Target Average Value:** The number of messages that will be consumed on a job. It is defined on the scaler side. e.g. `queueLength` on `Azure Storage Queue` scaler. +* **Running Job Count:** How many jobs are running. +* **Number of the Scale:** The number of the job that is created. + + +## rollout + +```yaml + rollout: + strategy: gradual # Optional. Default: default. Which Rollout Strategy KEDA will use. + propagationPolicy: foreground # Optional. Default: background. Kubernetes propagation policy for cleaning up existing jobs during +``` + +The optional property rollout.strategy specifies the rollout strategy KEDA will use while updating an existing ScaledJob. +Possible values are `default` or `gradual`. \ +When using the `default` rolloutStrategy, KEDA will terminate existing Jobs whenever a ScaledJob is being updated. Then, it will recreate those Jobs with the latest specs. The order in which this termination happens can be configured via the rollout.propagationPolicy property. By default, the kubernetes background propagation is used. To change this behavior specify set propagationPolicy to `foreground`. For further information see [Kubernetes Documentation](https://kubernetes.io/docs/tasks/administer-cluster/use-cascading-deletion/#use-foreground-cascading-deletion). +On the `gradual` rolloutStartegy, whenever a ScaledJob is being updated, KEDA will not delete existing Jobs. Only new Jobs will be created with the latest specs. + + +## scalingStrategy + +```yaml +scalingStrategy: + strategy: "default" # Optional. Default: default. Which Scaling Strategy to use. +``` + +Select a Scaling Strategy. Possible values are `default`, `custom`, or `accurate`. The default value is `default`. + +> 💡 **NOTE:** +> +>`maxScale` is not the running Job count. It is measured as follows: + >```go + >maxScale = min(scaledJob.MaxReplicaCount(), divideWithCeil(queueLength, targetAverageValue)) + >``` + >That means it will use the value of `queueLength` divided by `targetAvarageValue` unless it is exceeding the `MaxReplicaCount`. +> +>`RunningJobCount` represents the number of jobs that are currently running or have not finished yet. +> +>It is measured as follows: +>```go +>if !e.isJobFinished(&job) { +> runningJobs++ +>} +>``` +>`PendingJobCount` provides an indication of the amount of jobs that are in pending state. Pending jobs can be calculated in two ways: +> - Default behavior - Job that have not finished yet **and** the underlying pod is either not running or has not been completed yet +> - Setting `pendingPodConditions` - Job that has not finished yet **and** all specified pod conditions of the underlying pod mark as `true` by kubernetes. +> +>It is measured as follows: +>```go +>if !e.isJobFinished(&job) { +> if len(scaledJob.Spec.ScalingStrategy.PendingPodConditions) > 0 { +> if !e.areAllPendingPodConditionsFulfilled(&job, scaledJob.Spec.ScalingStrategy.PendingPodConditions) { +> pendingJobs++ +> } +> } else { +> if !e.isAnyPodRunningOrCompleted(&job) { +> pendingJobs++ +> } +> } +>} +>``` + +**default** +This logic is the same as Job for V1. The number of the scale will be calculated as follows. + +_The number of the scale_ + +```go +maxScale - runningJobCount +``` + +**custom** +You can customize the default scale logic. You need to configure the following parameters. If you don't configure it, then the strategy will be `default.` + +```yaml +customScalingQueueLengthDeduction: 1 # Optional. A parameter to optimize custom ScalingStrategy. +customScalingRunningJobPercentage: "0.5" # Optional. A parameter to optimize custom ScalingStrategy. +``` + +_The number of the scale_ + +```go +min(maxScale-int64(*s.CustomScalingQueueLengthDeduction)-int64(float64(runningJobCount)*(*s.CustomScalingRunningJobPercentage)), maxReplicaCount) +``` + +**accurate** +If the scaler returns `queueLength` (number of items in the queue) that does not include the number of locked messages, this strategy is recommended. `Azure Storage Queue` is one example. You can use this strategy if you delete a message once your app consumes it. + +```go +if (maxScale + runningJobCount) > maxReplicaCount { + return maxReplicaCount - runningJobCount + } + return maxScale - pendingJobCount +``` +For more details, you can refer to [this PR](https://github.com/kedacore/keda/pull/1227). + + +### multipleScalersCalculation + +```yaml +scalingStrategy: + multipleScalersCalculation : "max" # Optional. Default: max. Specifies how to calculate the target metrics (`queueLength` and `maxScale`) when multiple scalers are defined. +``` +Select a behavior if you have multiple triggers. Possible values are `max`, `min`, `avg`, or `sum`. The default value is `max`. + +* **max:** - Use metrics from the scaler that has the max number of `queueLength`. (default) +* **min:** - Use metrics from the scaler that has the min number of `queueLength`. +* **avg:** - Sum up all the active scalers metrics and divide by the number of active scalers. +* **sum:** - Sum up all the active scalers metrics. diff --git a/content/docs/2.14/reference/scaledobject-spec.md b/content/docs/2.14/reference/scaledobject-spec.md new file mode 100644 index 000000000..391a968c8 --- /dev/null +++ b/content/docs/2.14/reference/scaledobject-spec.md @@ -0,0 +1,254 @@ + ++++ +title = "ScaledObject specification" +weight = 3000 ++++ + +## Overview + +This specification describes the `ScaledObject` Custom Resource definition that defines the triggers and scaling behaviors used by KEDA to scale `Deployment`, `StatefulSet` and `Custom Resource` target resources. The `.spec.ScaleTargetRef` section holds the reference to the target resource, defined in [_scaledobject_types.go_](https://github.com/kedacore/keda/blob/main/apis/keda/v1alpha1/scaledobject_types.go). + +```yaml +apiVersion: keda.sh/v1alpha1 +kind: ScaledObject +metadata: + name: {scaled-object-name} + annotations: + scaledobject.keda.sh/transfer-hpa-ownership: "true" # Optional. Use to transfer an existing HPA ownership to this ScaledObject + validations.keda.sh/hpa-ownership: "true" # Optional. Use to disable HPA ownership validation on this ScaledObject + autoscaling.keda.sh/paused: "true" # Optional. Use to pause autoscaling of objects explicitly +spec: + scaleTargetRef: + apiVersion: {api-version-of-target-resource} # Optional. Default: apps/v1 + kind: {kind-of-target-resource} # Optional. Default: Deployment + name: {name-of-target-resource} # Mandatory. Must be in the same namespace as the ScaledObject + envSourceContainerName: {container-name} # Optional. Default: .spec.template.spec.containers[0] + pollingInterval: 30 # Optional. Default: 30 seconds + cooldownPeriod: 300 # Optional. Default: 300 seconds + idleReplicaCount: 0 # Optional. Default: ignored, must be less than minReplicaCount + minReplicaCount: 1 # Optional. Default: 0 + maxReplicaCount: 100 # Optional. Default: 100 + fallback: # Optional. Section to specify fallback options + failureThreshold: 3 # Mandatory if fallback section is included + replicas: 6 # Mandatory if fallback section is included + advanced: # Optional. Section to specify advanced options + restoreToOriginalReplicaCount: true/false # Optional. Default: false + horizontalPodAutoscalerConfig: # Optional. Section to specify HPA related options + name: {name-of-hpa-resource} # Optional. Default: keda-hpa-{scaled-object-name} + behavior: # Optional. Use to modify HPA's scaling behavior + scaleDown: + stabilizationWindowSeconds: 300 + policies: + - type: Percent + value: 100 + periodSeconds: 15 + triggers: + # {list of triggers to activate scaling of the target resource} +``` + +## scaleTargetRef + +```yaml + scaleTargetRef: + apiVersion: {api-version-of-target-resource} # Optional. Default: apps/v1 + kind: {kind-of-target-resource} # Optional. Default: Deployment + name: {name-of-target-resource} # Mandatory. Must be in the same namespace as the ScaledObject + envSourceContainerName: {container-name} # Optional. Default: .spec.template.spec.containers[0] +``` + +The reference to the resource this ScaledObject is configured for. This is the resource KEDA will scale up/down and set up an HPA for, based on the triggers defined in `triggers:`. + +To scale Kubernetes Deployments only `name` need be specified. To scale a different resource such as StatefulSet or Custom Resource (that defines `/scale` subresource), appropriate `apiVersion` (following standard Kubernetes convention, ie. `{api}/{version}`) and `kind` need to be specified. + +`envSourceContainerName` is an optional property that specifies the name of container in the target resource, from which KEDA should try to get environment properties holding secrets etc. If it is not defined, KEDA will try to get environment properties from the first Container, ie. from `.spec.template.spec.containers[0]`. + +**Assumptions:** Resource referenced by `name` (and `apiVersion`, `kind`) is in the same namespace as the ScaledObject + + +## pollingInterval +```yaml + pollingInterval: 30 # Optional. Default: 30 seconds +``` + +This is the interval to check each trigger on. By default, KEDA will check each trigger source on every ScaledObject every 30 seconds. + +**Example:** in a queue scenario, KEDA will check the queueLength every `pollingInterval`, and scale the resource up or down accordingly. + + +## cooldownPeriod +```yaml + cooldownPeriod: 300 # Optional. Default: 300 seconds +``` + +The period to wait after the last trigger reported active before scaling the resource back to 0, in seconds. By default, it's 300 (5 minutes). + +The `cooldownPeriod` only applies after a trigger occurs; when you first create your `Deployment` (or `StatefulSet`/`CustomResource`), KEDA will immediately scale it to `minReplicaCount`. Additionally, the KEDA `cooldownPeriod` only applies when scaling to 0; scaling from 1 to N replicas is handled by the [Kubernetes Horizontal Pod Autoscaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/../concepts/scaling-deployments.md#support-for-cooldowndelay). + +**Example:** wait 5 minutes after the last time KEDA checked the queue and it was empty. (this is obviously dependent on `pollingInterval`) + + +## initialCooldownPeriod +```yaml + InitialCooldownPeriod: 120 # Optional. Default: 0 seconds +``` +The delay before the `cooldownPeriod` starts after the initial creation of the `ScaledObject`, in seconds. By default, it's 0, meaning the `cooldownPeriod` begins immediately upon creation. If set to a value such as 120 seconds, the `cooldownPeriod` will only start after the `ScaledObject` has been active for that duration. + +This parameter is particularly useful for managing the scale-down behavior during the initial phase of a `ScaledObject`. For instance, if `InitialCooldownPeriod` is set to 120 seconds, KEDA will not scale the resource back to 0 until 120 seconds have passed since the `ScaledObject` creation, regardless of the activity triggers. This allows for a grace period in situations where immediate scaling down after creation is not desirable. + +**Example:** Wait 120 seconds after the `ScaledObject` is created before starting the `cooldownPeriod`. For instance, if the `InitialCooldownPeriod` is set to 120 seconds, KEDA will not initiate the cooldown process until 120 seconds have passed since the `ScaledObject` was first created, regardless of the triggers' activity. This ensures a buffer period where the resource won’t be scaled down immediately after creation. (Note: This setting is independent of the `pollingInterval`.) + + +## idleReplicaCount + +```yaml + idleReplicaCount: 0 # Optional. Default: ignored, must be less than minReplicaCount +``` + +> 💡 **NOTE:** Due to limitations in HPA controller the only supported value for this property is 0, it will not work correctly otherwise. See this [issue](https://github.com/kedacore/keda/issues/2314) for more details. +> +> In some cases, you always need at least `n` pod running. Thus, you can omit this property and set `minReplicaCount` to `n`. +> +> **Example** You set `minReplicaCount` to 1 and `maxReplicaCount` to 10. If there’s no activity on triggers, the target resource is scaled down to `minReplicaCount` (1). Once there are activities, the target resource will scale base on the HPA rule. If there’s no activity on triggers, the resource is again scaled down to `minReplicaCount` (1). + +If this property is set, KEDA will scale the resource down to this number of replicas. If there's some activity on target triggers KEDA will scale the target resource immediately to `minReplicaCount` and then will be scaling handled by HPA. When there is no activity, the target resource is again scaled down to `idleReplicaCount`. This setting must be less than `minReplicaCount`. + +**Example:** If there's no activity on triggers the target resource is scaled down to `idleReplicaCount` (0), once there is an activity the target resource is immediately scaled to `minReplicaCount` (10) and then up to `maxReplicaCount` (100) as needed. If there's no activity on triggers the resource is again scaled down to `idleReplicaCount` (0). + + +## minReplicaCount + +```yaml + minReplicaCount: 1 # Optional. Default: 0 +``` + +Minimum number of replicas KEDA will scale the resource down to. By default, it's scale to zero, but you can use it with some other value as well. + +## maxReplicaCount + +```yaml + maxReplicaCount: 100 # Optional. Default: 100 +``` +This setting is passed to the HPA definition that KEDA will create for a given resource and holds the maximum number of replicas of the target resource. + + +## fallback +```yaml + fallback: # Optional. Section to specify fallback options + failureThreshold: 3 # Mandatory if fallback section is included + replicas: 6 # Mandatory if fallback section is included +``` + +The `fallback` section is optional. It defines a number of replicas to fall back to if a scaler is in an error state. + +KEDA will keep track of the number of consecutive times each scaler has failed to get metrics from its source. Once that value passes the `failureThreshold`, instead of not propagating a metric to the HPA (the default error behaviour), the scaler will, instead, return a normalised metric using the formula: +``` +target metric value * fallback replicas +``` +Due to the HPA metric being of type `AverageValue` (see below), this will have the effect of the HPA scaling the deployment to the defined number of fallback replicas. + +**Example:** When my instance of prometheus is unavailable 3 consecutive times, KEDA will change the HPA metric such that the deployment will scale to 6 replicas. + +There are a few limitations to using a fallback: + - It only supports scalers whose target is an `AverageValue` metric. Thus, it is **not** supported by the CPU & memory scalers, or by scalers whose metric target type is `Value`. In these cases, it will assume that fallback is disabled. + - It is only supported by `ScaledObjects` **not** `ScaledJobs`. + + +## advanced + +### restoreToOriginalReplicaCount + +```yaml +advanced: + restoreToOriginalReplicaCount: true/false # Optional. Default: false +``` + +This property specifies whether the target resource (`Deployment`, `StatefulSet`,...) should be scaled back to original replicas count, after the `ScaledObject` is deleted. +Default behavior is to keep the replica count at the same number as it is in the moment of `ScaledObject's` deletion. + +For example a `Deployment` with `3 replicas` is created, then `ScaledObject` is created and the `Deployment` is scaled by KEDA to `10 replicas`. Then `ScaledObject` is deleted: + 1. if `restoreToOriginalReplicaCount = false` (default behavior) then `Deployment` replicas count is `10` + 2. if `restoreToOriginalReplicaCount = true` then `Deployment` replicas count is set back to `3` (the original value) + + +### horizontalPodAutoscalerConfig + +```yaml +advanced: + horizontalPodAutoscalerConfig: # Optional. Section to specify HPA related options + name: {name-of-hpa-resource} # Optional. Default: keda-hpa-{scaled-object-name} + behavior: # Optional. Use to modify HPA's scaling behavior + scaleDown: + stabilizationWindowSeconds: 300 + policies: + - type: Percent + value: 100 + periodSeconds: 15 +``` + +#### horizontalPodAutoscalerConfig.name + +The name of the HPA resource KEDA will create. By default, it's `keda-hpa-{scaled-object-name}` + +#### horizontalPodAutoscalerConfig.behavior + +Starting from Kubernetes v1.18 the autoscaling API allows scaling behavior to be configured through the HPA behavior field. This way one can directly affect scaling of 1<->N replicas, which is internally being handled by HPA. KEDA would feed values from this section directly to the HPA's `behavior` field. Please follow [Kubernetes documentation](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/../concepts/scaling-deployments.md#configurable-scaling-behavior) for details. + +**Assumptions:** KEDA must be running on Kubernetes cluster v1.18+, in order to be able to benefit from this setting. + + + +```yaml +advanced: + scalingModifiers: # Optional. Section to specify scaling modifiers + target: {target-value-to-scale-on} # Mandatory. New target if metrics are anyhow composed together + activationTarget: {activation-target-value-to-scale-on} # Optional. New activation target if metrics are anyhow composed together + metricType: {metric-tipe-for-the-modifier} # Optional. Metric type to be used if metrics are anyhow composed together + formula: {formula-for-fetched-metrics} # Mandatory. Formula for calculation +``` + +### scalingModifiers + +The `scalingModifiers` is optional and **experimental**. If defined, both `target` and `formula` are mandatory. Using this structure creates `composite-metric` for the HPA that will replace all requests for external metrics and handle them internally. With `scalingModifiers` each trigger used in the `formula` **must** have a name defined. + +#### scalingModifiers.target + +`target` defines new target value to scale on for the composed metric. + +#### scalingModifiers.activationTarget + +`activationTarget` defines a new [activation target value](../concepts/scaling-deployments.md#activating-and-scaling-thresholds) to scale on for the composed metric. (Default: `0`, Optional) + +#### scalingModifiers.metricType + +`metricType` defines metric type used for this new `composite-metric`. (Values: `AverageValue`, `Value`, Default: `AverageValue`, Optional) + +#### scalingModifiers.formula + + `formula` composes metrics together and allows them to be modified/manipulated. It accepts mathematical/conditional statements using [this external project](https://github.com/antonmedv/expr). If the `fallback` scaling feature is in effect, the `formula` will NOT modify its metrics (therefore it modifies metrics only when all of their triggers are healthy). Complete language definition of `expr` package can be found [here](https://expr.medv.io/docs/Language-Definition). Formula must return a single value (not boolean). + +For examples of this feature see section [Scaling Modifiers](../concepts/scaling-deployments.md#scaling-modifiers-experimental). + + +## triggers + +```yaml + triggers: + # {list of triggers to activate scaling of the target resource} +``` + +> 💡 **NOTE:** You can find all supported triggers [here](../scalers). + +Trigger fields: +- **type**: The type of trigger to use. (Mandatory) +- **metadata**: The configuration parameters that the trigger requires. (Mandatory) +- **name**: Name for this trigger. This value can be used to easily distinguish this specific trigger and its metrics when consuming [Prometheus metrics](../operate/prometheus.md). By default, the name is generated from the trigger type. (Optional) +- **useCachedMetrics**: Enables caching of metric values during polling interval (as specified in `.spec.pollingInterval`). For more information, see ["Caching Metrics"](../concepts/scaling-deployments.md#caching-metrics). (Values: `false`, `true`, Default: `false`, Optional) +- **authenticationRef**: A reference to the `TriggerAuthentication` or `ClusterTriggerAuthentication` object that is used to authenticate the scaler with the environment. + - More details can be found [here](../concepts/authentication). (Optional) +- **metricType**: The type of metric that should be used. (Values: `AverageValue`, `Value`, `Utilization`, Default: `AverageValue`, Optional) + - Learn more about how the [Horizontal Pod Autoscaler (HPA) calculates `replicaCount`](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) based on metric type and value. + - To show the differences between the metric types, let's assume we want to scale a deployment with 3 running replicas based on a queue of messages: + - With `AverageValue` metric type, we can control how many messages, on average, each replica will handle. If our metric is the queue size, the threshold is 5 messages, and the current message count in the queue is 20, HPA will scale the deployment to 20 / 5 = 4 replicas, regardless of the current replica count. + - The `Value` metric type, on the other hand, can be used when we don't want to take the average of the given metric across all replicas. For example, with the `Value` type, we can control the average time of messages in the queue. If our metric is average time in the queue, the threshold is 5 milliseconds, and the current average time is 20 milliseconds, HPA will scale the deployment to 3 * 20 / 5 = 12. + +> ⚠️ **NOTE:** All scalers, except CPU and Memory, support metric types `AverageValue` and `Value` while CPU and Memory scalers both support `AverageValue` and `Utilization`. diff --git a/content/docs/2.15/_index.md b/content/docs/2.15/_index.md index a3c18da2f..3dce1ff48 100644 --- a/content/docs/2.15/_index.md +++ b/content/docs/2.15/_index.md @@ -1,8 +1,19 @@ +++ -title = "The KEDA Documentation" +title = "Getting Started" weight = 1 +++ -Welcome to the documentation for **KEDA**, the Kubernetes Event-driven Autoscaler. Use the navigation to the left to learn more about how to use KEDA and its components. +Welcome to the documentation for **KEDA**, the Kubernetes Event-driven Autoscaler. -Additions and contributions to these docs are managed on [the keda-docs GitHub repo](https://github.com/kedacore/keda-docs). +Use the navigation bar on the left to learn more about KEDA's architecture and how to deploy and use KEDA. + +## Where to go + +What is your involvement with KEDA? + +| Role | Documentation | +|---------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------| +| User | This documentation is for users who want to deploy KEDA to scale Kubernetes. | +| Core Contributor | To contribute to the core KEDA project see the [KEDA GitHub repo](https://github.com/kedacore/keda). | +| Documentation Contributor | To add or contribute to these docs, or to build and serve the documentation locally, see the [keda-docs GitHub repo](https://github.com/kedacore/keda-docs). | +| Other Contributor | See the [KEDA project on GitHub](https://github.com/kedacore/) for other KEDA repos, including project governance, testing, and external scalers. | diff --git a/content/docs/2.15/authentication-providers/aws.md b/content/docs/2.15/authentication-providers/aws.md index c78d64b10..f47cc38c2 100644 --- a/content/docs/2.15/authentication-providers/aws.md +++ b/content/docs/2.15/authentication-providers/aws.md @@ -35,15 +35,15 @@ If you would like to use the same IAM credentials as your workload is currently ## AssumeRole or AssumeRoleWithWebIdentity? -This authentication uses automatically both, doing a fallback from [AssumeRoleWithWebIdentity](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html) to [AssumeRole](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) if the first one fails. This extends the capabilities because KEDA doesn't need `sts:AssumeRole` permission if you are already working with [WebIdentities](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc.html), you just need to add KEDA service account to the trusted relations of the role. +This authentication automatically uses both, falling back from [AssumeRoleWithWebIdentity](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html) to [AssumeRole](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) if the first one fails. This extends the capabilities because KEDA doesn't need `sts:AssumeRole` permission if you are already working with [WebIdentities](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc.html); in this case, you can add a KEDA service account to the trusted relations of the role. ## Setting up KEDA role and policy -The [official AWS docs](https://aws.amazon.com/es/blogs/opensource/introducing-fine-grained-iam-roles-service-accounts/) explain how to set up a a basic configuration for an IRSA role. The policy changes depend if you are using the KEDA role (`podIdentity.roleArn` is not set) or workload role (`podIdentity.roleArn` sets a RoleArn or `podIdentity.identityOwner` sets to `workload`). +The [official AWS docs](https://aws.amazon.com/es/blogs/opensource/introducing-fine-grained-iam-roles-service-accounts/) explain how to set up a basic configuration for an IRSA role. The policy changes depending on if you are using the KEDA role (`podIdentity.roleArn` is not set) or workload role (`podIdentity.roleArn` sets a RoleArn or `podIdentity.identityOwner` sets to `workload`). ### Using KEDA role to access infrastructure -This is the easiest case and you just need to attach to KEDA's role the desired policy/policies, granting the access permissions that you want to provide. For example, this could be a policy to use with SQS: +Attach the desired policies to KEDA's role, granting the access permissions that you want to provide. For example, this could be a policy to use with SQS: ```json { diff --git a/content/docs/2.15/concepts/external-scalers.md b/content/docs/2.15/concepts/external-scalers.md index aa00a18a0..d58ffe06d 100644 --- a/content/docs/2.15/concepts/external-scalers.md +++ b/content/docs/2.15/concepts/external-scalers.md @@ -44,8 +44,8 @@ The `Scaler` interface defines 3 methods: - `Close` is called to allow the scaler to clean up connections or other resources. - `GetMetricSpecForScaling` returns the target value for the HPA definition for the scaler. For more details refer to [Implementing `GetMetricSpec`](#5-implementing-getmetricspec). - `GetMetricsAndActivity` is called on `pollingInterval` and. When activity returns `true`, KEDA will scale to what is returned by the metric limited by `maxReplicaCount` on the ScaledObject/ScaledJob. - When `false` is returned, KEDA will scale to `minReplicaCount` or optionally `idleReplicaCount`. More details around the defaults and how these options work together can be found on the [ScaledObjectSpec](https://keda.sh/docs/latest/concepts/scaling-deployments/#scaledobject-spec). - > Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA supports both `AverageValue` and `Value` metric target types for external metrics. When `AverageValue` (the default metric type) is used, the metric value returned by the external scaler will be divided by the number of replicas. + When `false` is returned, KEDA will scale to `minReplicaCount` or optionally `idleReplicaCount`. More details around the defaults and how these options work together can be found on the [ScaledObjectSpec](../reference/scaledobject-spec). +> Refer to the [HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) for how HPA calculates `replicaCount` based on metric value and target value. KEDA supports both `AverageValue` and `Value` metric target types for external metrics. When `AverageValue` (the default metric type) is used, the metric value returned by the external scaler will be divided by the number of replicas. The `PushScaler` interface adds a `Run` method. This method receives a push channel (`active`), on which the scaler can send `true` at any time. The purpose of this mechanism is to initiate a scaling operation independently from `pollingInterval`. diff --git a/content/docs/2.15/concepts/scaling-deployments.md b/content/docs/2.15/concepts/scaling-deployments.md index 94594d562..6d0d90271 100644 --- a/content/docs/2.15/concepts/scaling-deployments.md +++ b/content/docs/2.15/concepts/scaling-deployments.md @@ -3,9 +3,15 @@ title = "Scaling Deployments, StatefulSets & Custom Resources" weight = 200 +++ -## Overview +This page describes the deployment scaling behavior of KEDA. -### Scaling of Deployments and StatefulSets +# Specification + +See the [Scaled Object specification](../reference/scaledobject-spec.md) for details on how to set the behaviors described below. + +# Scaling objects + +## Scaling Deployments and StatefulSets Deployments and StatefulSets are the most common way to scale workloads with KEDA. @@ -21,270 +27,30 @@ For example, if you wanted to use KEDA with an Apache Kafka topic as event sourc * As more messages arrive at the Kafka Topic, KEDA can feed this data to the HPA to drive scale out. * Each replica of the deployment is actively processing messages. Very likely, each replica is processing a batch of messages in a distributed manner. -### Scaling of Custom Resources +## Scaling Custom Resources With KEDA you can scale any workload defined as any `Custom Resource` (for example `ArgoRollout` [resource](https://argoproj.github.io/argo-rollouts/)). The scaling behaves the same way as scaling for arbitrary Kubernetes `Deployment` or `StatefulSet`. The only constraint is that the target `Custom Resource` must define `/scale` [subresource](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#scale-subresource). -## ScaledObject spec - -This specification describes the `ScaledObject` Custom Resource definition which is used to define how KEDA should scale your application and what the triggers are. The `.spec.ScaleTargetRef` section holds the reference to the target resource, ie. `Deployment`, `StatefulSet` or `Custom Resource`. - -[`scaledobject_types.go`](https://github.com/kedacore/keda/blob/main/apis/keda/v1alpha1/scaledobject_types.go) - -```yaml -apiVersion: keda.sh/v1alpha1 -kind: ScaledObject -metadata: - name: {scaled-object-name} - annotations: - scaledobject.keda.sh/transfer-hpa-ownership: "true" # Optional. Use to transfer an existing HPA ownership to this ScaledObject - validations.keda.sh/hpa-ownership: "true" # Optional. Use to disable HPA ownership validation on this ScaledObject - autoscaling.keda.sh/paused: "true" # Optional. Use to pause autoscaling of objects explicitly -spec: - scaleTargetRef: - apiVersion: {api-version-of-target-resource} # Optional. Default: apps/v1 - kind: {kind-of-target-resource} # Optional. Default: Deployment - name: {name-of-target-resource} # Mandatory. Must be in the same namespace as the ScaledObject - envSourceContainerName: {container-name} # Optional. Default: .spec.template.spec.containers[0] - pollingInterval: 30 # Optional. Default: 30 seconds - cooldownPeriod: 300 # Optional. Default: 300 seconds - idleReplicaCount: 0 # Optional. Default: ignored, must be less than minReplicaCount - minReplicaCount: 1 # Optional. Default: 0 - maxReplicaCount: 100 # Optional. Default: 100 - fallback: # Optional. Section to specify fallback options - failureThreshold: 3 # Mandatory if fallback section is included - replicas: 6 # Mandatory if fallback section is included - advanced: # Optional. Section to specify advanced options - restoreToOriginalReplicaCount: true/false # Optional. Default: false - horizontalPodAutoscalerConfig: # Optional. Section to specify HPA related options - name: {name-of-hpa-resource} # Optional. Default: keda-hpa-{scaled-object-name} - behavior: # Optional. Use to modify HPA's scaling behavior - scaleDown: - stabilizationWindowSeconds: 300 - policies: - - type: Percent - value: 100 - periodSeconds: 15 - triggers: - # {list of triggers to activate scaling of the target resource} -``` - -### Details -```yaml - scaleTargetRef: - apiVersion: {api-version-of-target-resource} # Optional. Default: apps/v1 - kind: {kind-of-target-resource} # Optional. Default: Deployment - name: {name-of-target-resource} # Mandatory. Must be in the same namespace as the ScaledObject - envSourceContainerName: {container-name} # Optional. Default: .spec.template.spec.containers[0] -``` - -The reference to the resource this ScaledObject is configured for. This is the resource KEDA will scale up/down and setup an HPA for, based on the triggers defined in `triggers:`. - -To scale Kubernetes Deployments only `name` is needed to be specified, if one wants to scale a different resource such as StatefulSet or Custom Resource (that defines `/scale` subresource), appropriate `apiVersion` (following standard Kubernetes convention, ie. `{api}/{version}`) and `kind` need to be specified. - -`envSourceContainerName` is an optional property that specifies the name of container in the target resource, from which KEDA should try to get environment properties holding secrets etc. If it is not defined, KEDA will try to get environment properties from the first Container, ie. from `.spec.template.spec.containers[0]`. - -**Assumptions:** Resource referenced by `name` (and `apiVersion`, `kind`) is in the same namespace as the ScaledObject - ---- -#### pollingInterval -```yaml - pollingInterval: 30 # Optional. Default: 30 seconds -``` - -This is the interval to check each trigger on. By default, KEDA will check each trigger source on every ScaledObject every 30 seconds. - -**Example:** in a queue scenario, KEDA will check the queueLength every `pollingInterval`, and scale the resource up or down accordingly. - ---- -#### cooldownPeriod -```yaml - cooldownPeriod: 300 # Optional. Default: 300 seconds -``` - -The period to wait after the last trigger reported active before scaling the resource back to 0. By default, it's 5 minutes (300 seconds). - -The `cooldownPeriod` only applies after a trigger occurs; when you first create your `Deployment` (or `StatefulSet`/`CustomResource`), KEDA will immediately scale it to `minReplicaCount`. Additionally, the KEDA `cooldownPeriod` only applies when scaling to 0; scaling from 1 to N replicas is handled by the [Kubernetes Horizontal Pod Autoscaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#support-for-cooldowndelay). - -**Example:** wait 5 minutes after the last time KEDA checked the queue and it was empty. (this is obviously dependent on `pollingInterval`) - ---- -#### initialCooldownPeriod -```yaml - initialCooldownPeriod: 120 # Optional. Default: 0 seconds -``` -The delay before the `cooldownPeriod` starts after the initial creation of the `ScaledObject`. By default, this is 0 seconds, meaning the `cooldownPeriod` begins immediately upon creation. If set to a value such as 120 seconds, the `cooldownPeriod` will only start after the `ScaledObject` has been active for that duration. - -This parameter is particularly useful for managing the scale-down behavior during the initial phase of a `ScaledObject`. For instance, if `initialCooldownPeriod` is set to 120 seconds, KEDA will not scale the resource back to 0 until 120 seconds have passed since the `ScaledObject` creation, regardless of the activity triggers. This allows for a grace period in situations where immediate scaling down after creation is not desirable. - -**Example:** Wait 120 seconds after the `ScaledObject` is created before starting the `cooldownPeriod`. For instance, if the `initialCooldownPeriod` is set to 120 seconds, KEDA will not initiate the cooldown process until 120 seconds have passed since the `ScaledObject` was first created, regardless of the triggers' activity. This ensures a buffer period where the resource won’t be scaled down immediately after creation. (Note: This setting is independent of the `pollingInterval`.) - ---- -#### idleReplicaCount - -```yaml - idleReplicaCount: 0 # Optional. Default: ignored, must be less than minReplicaCount -``` - -> 💡 **NOTE:** Due to limitations in HPA controller the only supported value for this property is 0, it will not work correctly otherwise. See this [issue](https://github.com/kedacore/keda/issues/2314) for more details. -> -> In some cases, you always need at least `n` pod running. Thus, you can omit this property and set `minReplicaCount` to `n`. -> -> **Example** You set `minReplicaCount` to 1 and `maxReplicaCount` to 10. If there’s no activity on triggers, the target resource is scaled down to `minReplicaCount` (1). Once there are activities, the target resource will scale base on the HPA rule. If there’s no activity on triggers, the resource is again scaled down to `minReplicaCount` (1). - -If this property is set, KEDA will scale the resource down to this number of replicas. If there's some activity on target triggers KEDA will scale the target resource immediately to `minReplicaCount` and then will be scaling handled by HPA. When there is no activity, the target resource is again scaled down to `idleReplicaCount`. This setting must be less than `minReplicaCount`. - -**Example:** If there's no activity on triggers the target resource is scaled down to `idleReplicaCount` (0), once there is an activity the target resource is immediately scaled to `minReplicaCount` (10) and then up to `maxReplicaCount` (100) as needed. If there's no activity on triggers the resource is again scaled down to `idleReplicaCount` (0). - ---- -#### minReplicaCount -```yaml - minReplicaCount: 1 # Optional. Default: 0 -``` - -Minimum number of replicas KEDA will scale the resource down to. By default, it's scale to zero, but you can use it with some other value as well. - ---- -#### maxReplicaCount -```yaml - maxReplicaCount: 100 # Optional. Default: 100 -``` - -This setting is passed to the HPA definition that KEDA will create for a given resource and holds the maximum number of replicas of the target resource. - ---- -#### fallback -```yaml - fallback: # Optional. Section to specify fallback options - failureThreshold: 3 # Mandatory if fallback section is included - replicas: 6 # Mandatory if fallback section is included -``` - -The `fallback` section is optional. It defines a number of replicas to fall back to if a scaler is in an error state. - -KEDA will keep track of the number of consecutive times each scaler has failed to get metrics from its source. Once that value passes the `failureThreshold`, instead of not propagating a metric to the HPA (the default error behaviour), the scaler will, instead, return a normalised metric using the formula: -``` -target metric value * fallback replicas -``` -Due to the HPA metric being of type `AverageValue` (see below), this will have the effect of the HPA scaling the deployment to the defined number of fallback replicas. - -**Example:** When my instance of prometheus is unavailable 3 consecutive times, KEDA will change the HPA metric such that the deployment will scale to 6 replicas. - -There are a few limitations to using a fallback: - - It only supports scalers whose target is an `AverageValue` metric. Thus, it is **not** supported by the CPU & memory scalers, or by scalers whose metric target type is `Value`. In these cases, it will assume that fallback is disabled. - - It is only supported by `ScaledObjects` **not** `ScaledJobs`. - ---- -#### advanced -```yaml -advanced: - restoreToOriginalReplicaCount: true/false # Optional. Default: false -``` - -This property specifies whether the target resource (`Deployment`, `StatefulSet`,...) should be scaled back to original replicas count, after the `ScaledObject` is deleted. -Default behavior is to keep the replica count at the same number as it is in the moment of `ScaledObject's` deletion. - -For example a `Deployment` with `3 replicas` is created, then `ScaledObject` is created and the `Deployment` is scaled by KEDA to `10 replicas`. Then `ScaledObject` is deleted: - 1. if `restoreToOriginalReplicaCount = false` (default behavior) then `Deployment` replicas count is `10` - 2. if `restoreToOriginalReplicaCount = true` then `Deployment` replicas count is set back to `3` (the original value) - ---- - -```yaml -advanced: - horizontalPodAutoscalerConfig: # Optional. Section to specify HPA related options - name: {name-of-hpa-resource} # Optional. Default: keda-hpa-{scaled-object-name} - behavior: # Optional. Use to modify HPA's scaling behavior - scaleDown: - stabilizationWindowSeconds: 300 - policies: - - type: Percent - value: 100 - periodSeconds: 15 -``` - -##### `horizontalPodAutoscalerConfig:` - -###### `horizontalPodAutoscalerConfig.name` - -The name of the HPA resource KEDA will create. By default, it's `keda-hpa-{scaled-object-name}` - -###### `horizontalPodAutoscalerConfig.behavior` - -Starting from Kubernetes v1.18 the autoscaling API allows scaling behavior to be configured through the HPA behavior field. This way one can directly affect scaling of 1<->N replicas, which is internally being handled by HPA. KEDA would feed values from this section directly to the HPA's `behavior` field. Please follow [Kubernetes documentation](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#configurable-scaling-behavior) for details. - -**Assumptions:** KEDA must be running on Kubernetes cluster v1.18+, in order to be able to benefit from this setting. +# Features ---- +## Caching Metrics -```yaml -advanced: - scalingModifiers: # Optional. Section to specify scaling modifiers - target: {target-value-to-scale-on} # Mandatory. New target if metrics are anyhow composed together - activationTarget: {activation-target-value-to-scale-on} # Optional. New activation target if metrics are anyhow composed together - metricType: {metric-tipe-for-the-modifier} # Optional. Metric type to be used if metrics are anyhow composed together - formula: {formula-for-fetched-metrics} # Mandatory. Formula for calculation -``` - -##### `scalingModifiers` - -The `scalingModifiers` is optional and **experimental**. If defined, both `target` and `formula` are mandatory. Using this structure creates `composite-metric` for the HPA that will replace all requests for external metrics and handle them internally. With `scalingModifiers` each trigger used in the `formula` **must** have a name defined. - -###### `scalingModifiers.target` - -`target` defines new target value to scale on for the composed metric. - -###### `scalingModifiers.activationTarget` - -`activationTarget` defines new [activation target value](./scaling-deployments.md#activating-and-scaling-thresholds) to scale on for the composed metric. (Default: `0`, Optional) - -###### `scalingModifiers.metricType` - -`metricType` defines metric type used for this new `composite-metric`. (Values: `AverageValue`, `Value`, Default: `AverageValue`, Optional) - -###### `scalingModifiers.formula` - - `formula` composes metrics together and allows them to be modified/manipulated. It accepts mathematical/conditional statements using [this external project](https://github.com/antonmedv/expr). If the `fallback` scaling feature is in effect, the `formula` will NOT modify its metrics (therefore it modifies metrics only when all of their triggers are healthy). Complete language definition of `expr` package can be found [here](https://expr.medv.io/docs/Language-Definition). Formula must return a single value (not boolean). +This feature enables caching of metric values during polling interval (as specified in `.spec.pollingInterval`). Kubernetes (HPA controller) asks for a metric every few seconds (as defined by `--horizontal-pod-autoscaler-sync-period`, usually 15s), then this request is routed to KEDA Metrics Server, that by default queries the scaler and reads the metric values. Enabling this feature changes this behavior such that KEDA Metrics Server tries to read metric from the cache first. This cache is updated periodically during the polling interval. -For examples of this feature see section [Scaling Modifiers](#scaling-modifiers-experimental) below. - ---- -#### triggers -```yaml - triggers: - # {list of triggers to activate scaling of the target resource} -``` - -> 💡 **NOTE:** You can find all supported triggers [here](/scalers). - -Trigger fields: -- **type**: The type of trigger to use. (Mandatory) -- **metadata**: The configuration parameters that the trigger requires. (Mandatory) -- **name**: Name for this trigger. This value can be used to easily distinguish this specific trigger and its metrics when consuming [Prometheus metrics](../operate/prometheus.md). By default, the name is generated from the trigger type. (Optional) -- **useCachedMetrics**: Enables caching of metric values during polling interval (as specified in `.spec.pollingInterval`). For more information, see ["Caching Metrics"](#caching-metrics). (Values: `false`, `true`, Default: `false`, Optional) -- **authenticationRef**: A reference to the `TriggerAuthentication` or `ClusterTriggerAuthentication` object that is used to authenticate the scaler with the environment. - - More details can be found [here](./authentication). (Optional) -- **metricType**: The type of metric that should be used. (Values: `AverageValue`, `Value`, `Utilization`, Default: `AverageValue`, Optional) - - Learn more about how the [Horizontal Pod Autoscaler (HPA) calculates `replicaCount`](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) based on metric type and value. - - To show the differences between the metric types, let's assume we want to scale a deployment with 3 running replicas based on a queue of messages: - - With `AverageValue` metric type, we can control how many messages, on average, each replica will handle. If our metric is the queue size, the threshold is 5 messages, and the current message count in the queue is 20, HPA will scale the deployment to 20 / 5 = 4 replicas, regardless of the current replica count. - - The `Value` metric type, on the other hand, can be used when we don't want to take the average of the given metric across all replicas. For example, with the `Value` type, we can control the average time of messages in the queue. If our metric is average time in the queue, the threshold is 5 milliseconds, and the current average time is 20 milliseconds, HPA will scale the deployment to 3 * 20 / 5 = 12. - -> ⚠️ **NOTE:** All scalers, except CPU and Memory, support metric types `AverageValue` and `Value` while CPU and Memory scalers both support `AverageValue` and `Utilization`. +Enabling this feature can significantly reduce the load on the scaler service. -### Caching Metrics +This feature is not supported for `cpu`, `memory` or `cron` scaler. -This feature enables caching of metric values during polling interval (as specified in `.spec.pollingInterval`). Kubernetes (HPA controller) asks for a metric every few seconds (as defined by `--horizontal-pod-autoscaler-sync-period`, usually 15s), then this request is routed to KEDA Metrics Server, that by default queries the scaler and reads the metric values. Enabling this feature changes this behavior, KEDA Metrics Server tries to read metric from the cache first. This cache is being updated periodically during the polling interval. +## Pausing autoscaling -Enabling this feature can significantly reduce the load on the scaler service. +It can be useful to instruct KEDA to pause the autoscaling of objects, to do to cluster maintenance or to avoid resource starvation by removing non-mission-critical workloads. -This feature is not supported for `cpu`, `memory` or `cron` scaler. +This is preferable to deleting the resource because it removes the instances it is running from operation without touching the applications themselves. When ready, you can then reenable scaling. -### Pause autoscaling +You can pause autoscaling by adding this annotation to your `ScaledObject` definition: -It can be useful to instruct KEDA to pause autoscaling of objects, if you want to do to cluster maintenance or you want to avoid resource starvation by removing non-mission-critical workloads. You can enable this by adding the below annotation to your `ScaledObject` definition: ```yaml metadata: @@ -299,10 +65,10 @@ The annotation `autoscaling.keda.sh/paused` will pause scaling immediately and u Typically, either one or the other is being used given they serve a different purpose/scenario. However, if both `paused` and `paused-replicas` are set, KEDA will scale your current workload to the number specified count in `paused-replicas` and then pause autoscaling. -To enable/unpause autoscaling again, simply remove all paused annotations from the `ScaledObject` definition. If you paused with `autoscaling.keda.sh/paused`, you can also set the annotation to `false` to unpause. +To unpause (reenable) autoscaling again, remove all paused annotations from the `ScaledObject` definition. If you paused with `autoscaling.keda.sh/paused`, you can unpause by setting the annotation to `false`. -### Scaling Modifiers (Experimental) +## Scaling Modifiers (Experimental) **Example: compose average value** @@ -370,15 +136,14 @@ Conditions can be used within another condition as well. If value of `trig_one` is less than 2 AND `trig_one`+`trig_two` is at least 2 then return 5, if only the first is true return 10, if the first condition is false then return 0. Complete language definition of `expr` package can be found [here](https://expr.medv.io/docs/Language-Definition). Formula must return a single value (not boolean). All formulas are internally wrapped with float cast. -### Activating and Scaling thresholds -To give a consistent solution to this problem, KEDA has 2 different phases during the autoscaling process. +## Activating and Scaling thresholds + +KEDA has 2 different phases during the autoscaling process. - **Activation phase:** The activating (or deactivating) phase is the moment when KEDA (operator) has to decide if the workload should be scaled from/to zero. KEDA takes responsibility for this action based on the result of the scaler `IsActive` function and only applies to 0<->1 scaling. There are use-cases where the activating value (0-1 and 1-0) is totally different than 0, such as workloads scaled with the Prometheus scaler where the values go from -X to X. - **Scaling phase:** The scaling phase is the moment when KEDA has decided to scale out to 1 instance and now it is the HPA controller who takes the scaling decisions based on the configuration defined in the generated HPA (from ScaledObject data) and the metrics exposed by KEDA (metrics server). This phase applies the to 1<->N scaling. -#### Managing Activation & Scaling Thresholds - KEDA allows you to specify different values for each scenario: - **Activation:** Defines when the scaler is active or not and scales from/to 0 based on it. @@ -397,7 +162,7 @@ There are some important topics to take into account: > ⚠️ **NOTE:** If a scaler doesn't define "activation" parameter (a property that starts with `activation` prefix), then this specific scaler doesn't support configurable activation value and the activation value is always 0. -## Transfer ownership of an existing HPA +## Transferring ownership of an existing HPA If your environment already operates using kubernetes HPA, you can transfer the ownership of this resource to a new ScaledObject: @@ -413,7 +178,7 @@ spec: > ⚠️ **NOTE:** You need to specify a custom HPA name in your ScaledObject matching the existing HPA name you want it to manage. -## Disable validations on an existing HPA +## Disabling validations on an existing HPA You are allowed to disable admission webhooks validations with the following snippet. It grants you better flexibility but also brings vulnerabilities. Do it **at your own risk**. @@ -423,13 +188,13 @@ metadata: validations.keda.sh/hpa-ownership: "true" ``` -## Long-running executions +### Long-running executions One important consideration to make is how this pattern can work with long-running executions. Imagine a deployment triggers on a RabbitMQ queue message. Each message takes 3 hours to process. It's possible that if many queue messages arrive, KEDA will help drive scaling out to many replicas - let's say 4. Now the HPA makes a decision to scale down from 4 replicas to 2. There is no way to control which of the 2 replicas get terminated to scale down. That means the HPA may attempt to terminate a replica that is 2.9 hours into processing a 3 hour queue message. There are two main ways to handle this scenario. -### Leverage the container lifecycle +#### Leverage the container lifecycle Kubernetes provides a few [lifecycle hooks](https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/) that can be leveraged to delay termination. Imagine a replica is scheduled for termination and is 2.9 hours into processing a 3 hour message. Kubernetes will send a [`SIGTERM`](https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html) to signal the intent to terminate. Rather than immediately terminating, a deployment can delay termination until processing the current batch of messages has completed. Kubernetes will wait for a `SIGTERM` response or the `terminationGracePeriodSeconds` before killing the replica. @@ -437,6 +202,6 @@ Kubernetes provides a few [lifecycle hooks](https://kubernetes.io/docs/concepts/ Using this method can preserve a replica and enable long-running executions. However, one downside of this approach is while delaying termination, the pod phase will remain in the `Terminating` state. That means a pod that is delaying termination for a very long duration may show `Terminating` during that entire period of delay. -### Run as jobs +#### Run as jobs -The other alternative to handling long-running executions is by running the event driven code in Kubernetes Jobs instead of Deployments or Custom Resources. This approach is discussed [in the next section](../scaling-jobs). +The other alternative to handling long-running executions is by running the event driven code in Kubernetes Jobs instead of Deployments or Custom Resources. This approach is discussed [in the next section](./scaling-jobs). diff --git a/content/docs/2.15/concepts/scaling-jobs.md b/content/docs/2.15/concepts/scaling-jobs.md index 9a5c58595..2f9029332 100644 --- a/content/docs/2.15/concepts/scaling-jobs.md +++ b/content/docs/2.15/concepts/scaling-jobs.md @@ -3,10 +3,12 @@ title = "Scaling Jobs" weight = 300 +++ +This page describes the job scaling behavior of KEDA. See the [Scaled Job specification](../reference/scaledjob-spec.md) for details on how to set the behaviors described below. -## Overview -As an alternate to [scaling event-driven code as deployments](../scaling-deployments) you can also run and scale your code as Kubernetes Jobs. The primary reason to consider this option is to handle processing long-running executions. Rather than processing multiple events within a deployment, for each detected event a single Kubernetes Job is scheduled. That job will initialize, pull a single event from the message source, and process to completion and terminate. +# Overview + +As an alternate to [scaling event-driven code as deployments](./scaling-deployments) you can also run and scale your code as Kubernetes Jobs. The primary reason to consider this option is to handle processing long-running executions. Rather than processing multiple events within a deployment, for each detected event a single Kubernetes Job is scheduled. That job will initialize, pull a single event from the message source, and process to completion and terminate. For example, if you wanted to use KEDA to run a job for each message that lands on a RabbitMQ queue, the flow may be: @@ -16,250 +18,33 @@ For example, if you wanted to use KEDA to run a job for each message that lands 1. As additional messages arrive, additional jobs are created. Each job processes a single message to completion. 1. Periodically remove completed/failed job by the `SuccessfulJobsHistoryLimit` and `FailedJobsHistoryLimit.` -## ScaledJob spec - -This specification describes the `ScaledJob` custom resource definition which is used to define how KEDA should scale your application and what the triggers are. - -[`scaledjob_types.go`](https://github.com/kedacore/keda/blob/main/apis/keda/v1alpha1/scaledjob_types.go) - -```yaml -apiVersion: keda.sh/v1alpha1 -kind: ScaledJob -metadata: - name: {scaled-job-name} - labels: - my-label: {my-label-value} # Optional. ScaledJob labels are applied to child Jobs - annotations: - autoscaling.keda.sh/paused: true # Optional. Use to pause autoscaling of Jobs - my-annotation: {my-annotation-value} # Optional. ScaledJob annotations are applied to child Jobs -spec: - jobTargetRef: - parallelism: 1 # [max number of desired pods](https://kubernetes.io/docs/concepts/workloads/controllers/job/#controlling-parallelism) - completions: 1 # [desired number of successfully finished pods](https://kubernetes.io/docs/concepts/workloads/controllers/job/#controlling-parallelism) - activeDeadlineSeconds: 600 # Specifies the duration in seconds relative to the startTime that the job may be active before the system tries to terminate it; value must be positive integer - backoffLimit: 6 # Specifies the number of retries before marking this job failed. Defaults to 6 - template: - # describes the [job template](https://kubernetes.io/docs/concepts/workloads/controllers/job) - pollingInterval: 30 # Optional. Default: 30 seconds - successfulJobsHistoryLimit: 5 # Optional. Default: 100. How many completed jobs should be kept. - failedJobsHistoryLimit: 5 # Optional. Default: 100. How many failed jobs should be kept. - envSourceContainerName: {container-name} # Optional. Default: .spec.JobTargetRef.template.spec.containers[0] - minReplicaCount: 10 # Optional. Default: 0 - maxReplicaCount: 100 # Optional. Default: 100 - rolloutStrategy: gradual # Deprecated: Use rollout.strategy instead (see below). - rollout: - strategy: gradual # Optional. Default: default. Which Rollout Strategy KEDA will use. - propagationPolicy: foreground # Optional. Default: background. Kubernetes propagation policy for cleaning up existing jobs during rollout. - scalingStrategy: - strategy: "custom" # Optional. Default: default. Which Scaling Strategy to use. - customScalingQueueLengthDeduction: 1 # Optional. A parameter to optimize custom ScalingStrategy. - customScalingRunningJobPercentage: "0.5" # Optional. A parameter to optimize custom ScalingStrategy. - pendingPodConditions: # Optional. A parameter to calculate pending job count per the specified pod conditions - - "Ready" - - "PodScheduled" - - "AnyOtherCustomPodCondition" - multipleScalersCalculation : "max" # Optional. Default: max. Specifies how to calculate the target metrics when multiple scalers are defined. - triggers: - # {list of triggers to create jobs} -``` - -You can find all supported triggers [here](../scalers). - -## Details - -```yaml - jobTargetRef: - parallelism: 1 # Optional. Max number of desired instances ([docs](https://kubernetes.io/docs/concepts/workloads/controllers/job/#controlling-parallelism)) - completions: 1 # Optional. Desired number of successfully finished instances ([docs](https://kubernetes.io/docs/concepts/workloads/controllers/job/#controlling-parallelism)) - activeDeadlineSeconds: 600 # Optional. Specifies the duration in seconds relative to the startTime that the job may be active before the system tries to terminate it; value must be positive integer - backoffLimit: 6 # Optional. Specifies the number of retries before marking this job failed. Defaults to 6 -``` - -The `jobTargetRef` is a batch/v1 `JobSpec` object; refer to the Kubernetes API for [more details](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/job-v1/#JobSpec) about the fields. The `template` field is required. - ---- - -```yaml - pollingInterval: 30 # Optional. Default: 30 seconds -``` - -This is the interval to check each trigger on. By default, KEDA will check each trigger source on every ScaledJob every 30 seconds. - ---- - -```yaml - successfulJobsHistoryLimit: 5 # Optional. Default: 100. How many completed jobs should be kept. - failedJobsHistoryLimit: 5 # Optional. Default: 100. How many failed jobs should be kept. -``` - -The `successfulJobsHistoryLimit` and `failedJobsHistoryLimit` fields are optional. These fields specify how many completed and failed jobs should be kept. By default, they are set to 100. - -This concept is similar to [Jobs History Limits](https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/#jobs-history-limits) allowing you to learn what the outcomes of your jobs are. - -The actual number of jobs could exceed the limit in a short time. However, it is going to resolve in the cleanup period. Currently, the cleanup period is the same as the Polling interval. - ---- - - -```yaml - envSourceContainerName: {container-name} # Optional. Default: .spec.JobTargetRef.template.spec.containers[0] -``` - -This optional property specifies the name of container in the Job, from which KEDA should try to get environment properties holding secrets etc. If it is not defined it, KEDA will try to get environment properties from the first Container, ie. from `.spec.JobTargetRef.template.spec.containers[0]`. - -___ -```yaml - minReplicaCount: 10 # Optional. Default: 0 -``` - -The min number of jobs that is created by default. This can be useful to avoid bootstrapping time of new jobs. If minReplicaCount is greater than maxReplicaCount, minReplicaCount will be set to maxReplicaCount. - -New messages may create new jobs - within the limits imposed by maxReplicaCount - in order to reach the state where minReplicaCount jobs are always running. For example, if one sets minReplicaCount to 2 then there will be 2 jobs running permanently. Using a targetValue of 1, if 3 new messages are sent, 2 of those messages will be processed on the already running jobs but another 3 jobs will be created in order to fulfill the desired state dictated by the minReplicaCount parameter that is set to 2. -___ - ---- - -```yaml - maxReplicaCount: 100 # Optional. Default: 100 -``` - -The max number of pods that is created within a single polling period. If there are running jobs, the number of running jobs will be deducted. This table is an example of the scaling logic. - -| Queue Length | Max Replica Count | Target Average Value | Running Job Count | Number of the Scale | -| ------- | ------ | ------- | ------ | ----- | -| 10 | 3 | 1 | 0 | 3 | -| 10 | 3 | 2 | 0 | 3 | -| 10 | 3 | 1 | 1 | 2 | -| 10 | 100 | 1 | 0 | 10 | -| 4 | 3 | 5 | 0 | 1 | - -* **Queue Length:** The number of items in the queue. -* **Target Average Value:** The number of messages that will be consumed on a job. It is defined on the scaler side. e.g. `queueLength` on `Azure Storage Queue` scaler. -* **Running Job Count:** How many jobs are running. -* **Number of the Scale:** The number of the job that is created. - ---- - -```yaml - rollout: - strategy: gradual # Optional. Default: default. Which Rollout Strategy KEDA will use. - propagationPolicy: foreground # Optional. Default: background. Kubernetes propagation policy for cleaning up existing jobs during -``` - -The optional property rollout.strategy specifies the rollout strategy KEDA will use while updating an existing ScaledJob. -Possible values are `default` or `gradual`. \ -When using the `default` rolloutStrategy, KEDA will terminate existing Jobs whenever a ScaledJob is being updated. Then, it will recreate those Jobs with the latest specs. The order in which this termination happens can be configured via the rollout.propagationPolicy property. By default, the kubernetes background propagation is used. To change this behavior specify set propagationPolicy to `foreground`. For further information see [Kubernetes Documentation](https://kubernetes.io/docs/tasks/administer-cluster/use-cascading-deletion/#use-foreground-cascading-deletion). -On the `gradual` rolloutStartegy, whenever a ScaledJob is being updated, KEDA will not delete existing Jobs. Only new Jobs will be created with the latest specs. - - ---- - -```yaml -scalingStrategy: - strategy: "default" # Optional. Default: default. Which Scaling Strategy to use. -``` -Select a Scaling Strategy. Possible values are `default`, `custom`, or `accurate`. The default value is `default`. +# Pausing autoscaling -> 💡 **NOTE:** -> ->`maxScale` is not the running Job count. It is measured as follows: - >```go - >maxScale = min(scaledJob.MaxReplicaCount(), divideWithCeil(queueLength, targetAverageValue)) - >``` - >That means it will use the value of `queueLength` divided by `targetAvarageValue` unless it is exceeding the `MaxReplicaCount`. -> ->`RunningJobCount` represents the number of jobs that are currently running or have not finished yet. -> ->It is measured as follows: ->```go ->if !e.isJobFinished(&job) { -> runningJobs++ ->} ->``` ->`PendingJobCount` provides an indication of the amount of jobs that are in pending state. Pending jobs can be calculated in two ways: -> - Default behavior - Job that have not finished yet **and** the underlying pod is either not running or has not been completed yet -> - Setting `pendingPodConditions` - Job that has not finished yet **and** all specified pod conditions of the underlying pod mark as `true` by kubernetes. -> ->It is measured as follows: ->```go ->if !e.isJobFinished(&job) { -> if len(scaledJob.Spec.ScalingStrategy.PendingPodConditions) > 0 { -> if !e.areAllPendingPodConditionsFulfilled(&job, scaledJob.Spec.ScalingStrategy.PendingPodConditions) { -> pendingJobs++ -> } -> } else { -> if !e.isAnyPodRunningOrCompleted(&job) { -> pendingJobs++ -> } -> } ->} ->``` +It can be useful to instruct KEDA to pause the autoscaling of objects, to do to cluster maintenance or to avoid resource starvation by removing non-mission-critical workloads. -**default** -This logic is the same as Job for V1. The number of the scale will be calculated as follows. +This is preferable to deleting the resource because it removes the instances it is running from operation without touching the applications themselves. When ready, you can then reenable scaling. -_The number of the scale_ - -```go -maxScale - runningJobCount -``` - -**custom** -You can customize the default scale logic. You need to configure the following parameters. If you don't configure it, then the strategy will be `default.` +You can pause autoscaling by adding this annotation to your `ScaledJob` definition: ```yaml -customScalingQueueLengthDeduction: 1 # Optional. A parameter to optimize custom ScalingStrategy. -customScalingRunningJobPercentage: "0.5" # Optional. A parameter to optimize custom ScalingStrategy. -``` - -_The number of the scale_ - -```go -min(maxScale-int64(*s.CustomScalingQueueLengthDeduction)-int64(float64(runningJobCount)*(*s.CustomScalingRunningJobPercentage)), maxReplicaCount) -``` - -**accurate** -If the scaler returns `queueLength` (number of items in the queue) that does not include the number of locked messages, this strategy is recommended. `Azure Storage Queue` is one example. You can use this strategy if you delete a message once your app consumes it. - -```go -if (maxScale + runningJobCount) > maxReplicaCount { - return maxReplicaCount - runningJobCount - } - return maxScale - pendingJobCount -``` -For more details, you can refer to [this PR](https://github.com/kedacore/keda/pull/1227). - ---- - -```yaml -scalingStrategy: - multipleScalersCalculation : "max" # Optional. Default: max. Specifies how to calculate the target metrics (`queueLength` and `maxScale`) when multiple scalers are defined. +metadata: + annotations: + autoscaling.keda.sh/paused: true ``` -Select a behavior if you have multiple triggers. Possible values are `max`, `min`, `avg`, or `sum`. The default value is `max`. - -* **max:** - Use metrics from the scaler that has the max number of `queueLength`. (default) -* **min:** - Use metrics from the scaler that has the min number of `queueLength`. -* **avg:** - Sum up all the active scalers metrics and divide by the number of active scalers. -* **sum:** - Sum up all the active scalers metrics. -### Pause autoscaling - -It can be useful to instruct KEDA to pause the autoscaling of objects, if you want to do to cluster maintenance or you want to avoid resource starvation by removing non-mission-critical workloads. - -This is a great alternative to deleting the resource, because we do not want to touch the applications themselves but simply remove the instances it is running from an operational perspective. Once everything is good to go, we can enable it to scale again. - -You can enable this by adding the below annotation to your `ScaledJob` definition: +To reenable autoscaling, remove the annotation from the `ScaledJob` definition or set the value to `false`. ```yaml metadata: annotations: - autoscaling.keda.sh/paused: true + autoscaling.keda.sh/paused: false ``` -The above annotation will pause autoscaling. To enable autoscaling again, simply remove the annotation from the `ScaledJob` definition or set the value to `false`. -# Sample +## Example + +An example configuration for autoscaling jobs using a RabbitMQ scaler is given below. ```yaml apiVersion: v1 diff --git a/content/docs/2.15/deploy.md b/content/docs/2.15/deploy.md index 0ebec231f..4e78035e4 100644 --- a/content/docs/2.15/deploy.md +++ b/content/docs/2.15/deploy.md @@ -4,9 +4,9 @@ title = "Deploying KEDA" We provide a few approaches to deploy KEDA runtime in your Kubernetes clusters: -- [Helm charts](#helm) -- [Operator Hub](#operatorhub) -- [YAML declarations](#yaml) +- Helm charts +- Operator Hub +- YAML declarations > 💡 **NOTE:** KEDA requires Kubernetes cluster version 1.27 and higher @@ -16,7 +16,7 @@ Don't see what you need? Feel free to [create an issue](https://github.com/kedac ### Install -Deploying KEDA with Helm is very simple: +To deploy KEDA with Helm: 1. Add Helm repo @@ -147,7 +147,7 @@ VERSION=2.15.0 make undeploy ### Install -If you want to try KEDA v2 on [MicroK8s](https://microk8s.io/) from `1.20` channel, KEDA is included into MicroK8s addons. +If you want to try KEDA v2 on [MicroK8s](https://microk8s.io/) from `1.20` channel, KEDA is included into MicroK8s add-ons. ```sh microk8s enable keda @@ -155,7 +155,7 @@ microk8s enable keda ### Uninstall -To uninstall KEDA in MicroK8s, simply disable the addon as shown below. +To uninstall KEDA in MicroK8s, disable the add-on as shown below. ```sh microk8s disable keda diff --git a/content/docs/2.15/migration.md b/content/docs/2.15/migration.md index 29e8408c8..3e52fd485 100644 --- a/content/docs/2.15/migration.md +++ b/content/docs/2.15/migration.md @@ -27,7 +27,7 @@ In order to scale `Deployments` with KEDA v2, you need to do only a few modifica - Rename property `spec.scaleTargetRef.containerName` to `spec.scaleTargetRef.envSourceContainerName` - Label `deploymentName` (in `metadata.labels.`) is no longer needed to be specified on v2 ScaledObject (it was mandatory on older versions of v1) -Please see the examples below or refer to the full [v2 ScaledObject Specification](../concepts/scaling-deployments/#scaledobject-spec) +Please see the examples below or refer to the full [v2 ScaledObject Specification](./reference/scaledobject-spec) **Example of v1 ScaledObject** @@ -80,7 +80,7 @@ In order to scale `Jobs` with KEDA v2, you need to do only a few modifications t You can configure `successfulJobsHistoryLimit` and `failedJobsHistoryLimit`. They will remove the old job histories automatically. -Please see the examples below or refer to the full [v2 ScaledJob Specification](../concepts/scaling-jobs/#scaledjob-spec) +Please see the examples below or refer to the full [v2 ScaledJob Specification](./reference/scaledjob-spec/) **Example of v1 ScaledObject for Jobs scaling** diff --git a/content/docs/2.15/operate/_index.md b/content/docs/2.15/operate/_index.md index e7604a0cf..dac7c02f2 100644 --- a/content/docs/2.15/operate/_index.md +++ b/content/docs/2.15/operate/_index.md @@ -1,14 +1,14 @@ +++ title = "Operate" -description = "Guidance & requirements for operating KEDA" +description = "Guidance and requirements for operating KEDA" weight = 1 +++ -We provide guidance & requirements around various areas to operate KEDA: +We provide guidance and requirements around various areas to operate KEDA: - Admission Webhooks ([link](./admission-webhooks)) - Cluster ([link](./cluster)) -- Kubernetes Events ([link](./events)) +- Kubernetes Events ([link](../reference/events)) - KEDA Metrics Server ([link](./metrics-server)) - Integrate with Prometheus ([link](./prometheus)) - Integrate with OpenTelemetry Collector (Experimental) ([link](./opentelemetry)) diff --git a/content/docs/2.15/operate/cloud-events.md b/content/docs/2.15/operate/cloud-events.md new file mode 100644 index 000000000..e07dc0505 --- /dev/null +++ b/content/docs/2.15/operate/cloud-events.md @@ -0,0 +1,116 @@ ++++ +title = "CloudEvent Support" +description = "Experimental support for cloud events" +weight = 100 ++++ + +## Subscribing to events with `CloudEventSource` +`CloudEventSource` resource can be used in KEDA for subscribing to events that are emitted to the user's defined CloudEvent sink. + +> 📝 Event will be emitted to both Kubernetes Events and CloudEvents Destination if CloudEventSource resource is created. + +Here is a the schema of the `CloudEventSource` CRD: + +```yaml +apiVersion: eventing.keda.sh/v1alpha1 +kind: CloudEventSource +metadata: + name: {cloud-event-name} +spec: + clusterName: {cluster-name} #Optional. Will be used in the source/subject to specify where the event comes from. The default value is 'kubernetes-default' and it can also be set during the installation of KEDA with --k8sClusterName. This one will overwrite others if set. + authenticationRef: + name: {trigger-authentication-name} #Optional. Used to reference a `TriggerAuthentication` for authentication. + kind: TriggerAuthentication # Optional. Used to choose the authentication scopes. https://keda.sh/docs/latest/concepts/authentication/#authentication-scopes-namespace-vs-cluster + destination: + http: + uri: http://foo.bar + azureEventGridTopic: + endpoint: https://my-topic.eastus-1.eventgrid.azure.net/api/events + + eventSubscription: #Optional. Submit included/excluded event types will filter events when emitting events. + includedEventTypes: #Optional. Only events in this section will be emitted. + - keda.scaledobject.failed.v1 + excludedEventTypes: #Optional. Events in this section will not be emitted. + - keda.scaledobject.ready.v1 +``` + +In general, an event emitted by KEDA would fundamentally come down to the following structure: +```json +{ + "specversion" : "1.0", + "type" : "com.cloudeventsource.keda", + "source" : "/{cluster-name}/{keda-namespace}/keda", + "subject" : "/{cluster-name}/{namespace}/{object-type}/{object-name}", + "id" : "", + "time" : "2018-04-05T17:31:00Z", + "datacontenttype" : "application/json", + "data" : { + "reason":"", + "message":"" + } +} +``` + +## Event Sinks + +There will be multiple types of destination to emit KEDA events to. + +Here is an overview of the supported destinations: + +- [HTTP endpoint](#http-endpoint). +- [Azure Event Grid endpoint](#azure-event-grid). + +### HTTP endpoint +```yaml + destination: + http: + uri: http://foo.bar #An http endpoint that can receive cloudevent +``` + +### Azure Event Grid + +```yaml + destination: + azureEventGrid: + endpoint: foo.bar #endpoint from AzureEventGrid Topic +``` + +Authentication information must be provided by using `authenticationRef` which allows you to provide the access key or managed identity for Azure Event Grid authentication by providing a `TriggerAuthentication`. + +Here is an overview of the supported authentication types: + +#### Connection String Authentication + +- `accessKey` - Access key string for the Azure Event Grid connection auth. + +#### Pod identity based authentication +[Azure AD Workload Identity](https://azure.github.io/azure-workload-identity/docs/) providers can be used. + +```yaml +apiVersion: keda.sh/v1alpha1 +kind: TriggerAuthentication +metadata: + name: nameOfTriggerAuth + namespace: default +spec: + podIdentity: + provider: azure-workload +``` + +## Event Filter + +You can include filter(s) to define what event types you are interested in, or want to ignore. This is done by using `includedEventTypes` or `excludedEventTypes` respectively for a given sink. + +```yaml +eventSubscription: #Optional. Submit included/excluded event types will filter events when emitting events. + includedEventTypes: #Optional. Only events in this section will be emitted. + - keda.scaledobject.failed.v1 + excludedEventTypes: #Optional. Events in this section will not be emitted. + - keda.scaledobject.ready.v1 +``` + +## Supported Event List +| Event Type | Scenario Description | +|-------------------------------|-----------------------------------------------------------------------------------------------------------------------------| +| `keda.scaledobject.ready.v1` | On the first time a ScaledObject is ready, or if the previous ready condition status of the object was `Unknown` or `False` | +| `keda.scaledobject.failed.v1` | If the check validation for a ScaledObject fails | diff --git a/content/docs/2.15/operate/events.md b/content/docs/2.15/operate/events.md deleted file mode 100644 index a4bf08ff1..000000000 --- a/content/docs/2.15/operate/events.md +++ /dev/null @@ -1,144 +0,0 @@ -+++ -title = "Events" -description = "Kubernetes Events emitted by KEDA" -weight = 100 -+++ - -## Kubernetes Events emitted by KEDA - -KEDA emits the following [Kubernetes Events](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#event-v1-core): - -| Event | Type | Description | -| ------------------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------- | -| `ScaledObjectReady` | `Normal` | On the first time a ScaledObject is ready, or if the previous ready condition status of the object was `Unknown` or `False` | -| `ScaledJobReady` | `Normal` | On the first time a ScaledJob is ready, or if the previous ready condition status of the object was `Unknown` or `False` | -| `ScaledObjectCheckFailed` | `Warning` | If the check validation for a ScaledObject fails | | -| `ScaledJobCheckFailed` | `Warning` | If the check validation for a ScaledJob fails | | -| `ScaledObjectDeleted` | `Normal` | When a ScaledObject is deleted and removed from KEDA watch | | -| `ScaledJobDeleted` | `Normal` | When a ScaledJob is deleted and removed from KEDA watch | | -| `KEDAScalersStarted` | `Normal` | When Scalers watch loop have started for a ScaledObject or ScaledJob | | -| `KEDAScalersStopped` | `Normal` | When Scalers watch loop have stopped for a ScaledObject or a ScaledJob | | -| `KEDAScalerFailed` | `Warning` | When a Scaler fails to create or check its event source| | -| `KEDAScaleTargetActivated` | `Normal` | When the scale target (Deployment, StatefulSet, etc) of a ScaledObject is scaled to 1, triggered by {scalers1;scalers2;...}| | -| `KEDAScaleTargetDeactivated` | `Normal` | When the scale target (Deployment, StatefulSet, etc) of a ScaledObject is scaled to 0 | | -| `KEDAScaleTargetActivationFailed` | `Warning` | When KEDA fails to scale the scale target of a ScaledObject to 1| | -| `KEDAScaleTargetDeactivationFailed` | `Warning` | When KEDA fails to scale the scale target of a ScaledObject to 0| | -| `KEDAJobsCreated` | `Normal` | When KEDA creates jobs for a ScaledJob | | -| `TriggerAuthenticationAdded` | `Normal` | When a new TriggerAuthentication is added| | -| `TriggerAuthenticationDeleted` | `Normal` | When a TriggerAuthentication is deleted| | -| `ClusterTriggerAuthenticationAdded` | `Normal` | When a new ClusterTriggerAuthentication is added| | -| `ClusterTriggerAuthenticationDeleted` | `Normal` | When a ClusterTriggerAuthentication is deleted| | - - -## CloudEvent Support (Experimental) - -### Subscribing to events with `CloudEventSource` -`CloudEventSource` resource can be used in KEDA for subscribing to events that are emitted to the user's defined CloudEvent sink. - -> 📝 Event will be emitted to both Kubernetes Events and CloudEvents Destination if CloudEventSource resource is created. - -Here is a the schema of the `CloudEventSource` CRD: - -```yaml -apiVersion: eventing.keda.sh/v1alpha1 -kind: CloudEventSource -metadata: - name: {cloud-event-name} -spec: - clusterName: {cluster-name} #Optional. Will be used in the source/subject to specify where the event comes from. The default value is 'kubernetes-default' and it can also be set during the installation of KEDA with --k8sClusterName. This one will overwrite others if set. - authenticationRef: - name: {trigger-authentication-name} #Optional. Used to reference a `TriggerAuthentication` for authentication. - kind: TriggerAuthentication # Optional. Used to choose the authentication scopes. https://keda.sh/docs/latest/concepts/authentication/#authentication-scopes-namespace-vs-cluster - destination: - http: - uri: http://foo.bar - azureEventGridTopic: - endpoint: https://my-topic.eastus-1.eventgrid.azure.net/api/events - - eventSubscription: #Optional. Submit included/excluded event types will filter events when emitting events. - includedEventTypes: #Optional. Only events in this section will be emitted. - - keda.scaledobject.failed.v1 - excludedEventTypes: #Optional. Events in this section will not be emitted. - - keda.scaledobject.ready.v1 -``` - -In general, an event emitted by KEDA would fundamentally come down to the following structure: -```json -{ - "specversion" : "1.0", - "type" : "com.cloudeventsource.keda", - "source" : "/{cluster-name}/{keda-namespace}/keda", - "subject" : "/{cluster-name}/{namespace}/{object-type}/{object-name}", - "id" : "", - "time" : "2018-04-05T17:31:00Z", - "datacontenttype" : "application/json", - "data" : { - "reason":"", - "message":"" - } -} -``` - -### Event Sinks - -There will be multiple types of destination to emit KEDA events to. - -Here is an overview of the supported destinations: - -- [HTTP endpoint](#http-endpoint). -- [Azure Event Grid endpoint](#azure-event-grid). - -#### HTTP endpoint -```yaml - destination: - http: - uri: http://foo.bar #An http endpoint that can receive cloudevent -``` - -#### Azure Event Grid - -```yaml - destination: - azureEventGrid: - endpoint: foo.bar #endpoint from AzureEventGrid Topic -``` - -Authentication information must be provided by using `authenticationRef` which allows you to provide the access key or managed identity for Azure Event Grid authentication by providing a `TriggerAuthentication`. - -Here is an overview of the supported authentication types: - -##### Connection String Authentication - -- `accessKey` - Access key string for the Azure Event Grid connection auth. - -##### Pod identity based authentication -[Azure AD Workload Identity](https://azure.github.io/azure-workload-identity/docs/) providers can be used. - -```yaml -apiVersion: keda.sh/v1alpha1 -kind: TriggerAuthentication -metadata: - name: nameOfTriggerAuth - namespace: default -spec: - podIdentity: - provider: azure-workload -``` - -### Event Filter - -You can include filter(s) to define what event types you are interested in, or want to ignore. This is done by using `includedEventTypes` or `excludedEventTypes` respectively for a given sink. - -```yaml -eventSubscription: #Optional. Submit included/excluded event types will filter events when emitting events. - includedEventTypes: #Optional. Only events in this section will be emitted. - - keda.scaledobject.failed.v1 - excludedEventTypes: #Optional. Events in this section will not be emitted. - - keda.scaledobject.ready.v1 -``` - -### Supported Event List -| Event Type | Scenario Description | -| ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | -| `keda.scaledobject.ready.v1` | On the first time a ScaledObject is ready, or if the previous ready condition status of the object was `Unknown` or `False` | -| `keda.scaledobject.failed.v1` | If the check validation for a ScaledObject fails | \ No newline at end of file diff --git a/content/docs/2.15/operate/metrics-server.md b/content/docs/2.15/operate/metrics-server.md index 6977e990e..45e9699fa 100644 --- a/content/docs/2.15/operate/metrics-server.md +++ b/content/docs/2.15/operate/metrics-server.md @@ -11,7 +11,7 @@ The metrics exposed by KEDA Metrics Server can be queried directly using `kubect kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1" ``` -This will return a json with the list of metrics exposed by KEDA (just an external metric): +This will return a json with the list of metrics exposed by KEDA (external metrics only): ```json { "kind": "APIResourceList", diff --git a/content/docs/2.15/reference/_index.md b/content/docs/2.15/reference/_index.md new file mode 100644 index 000000000..82fc53448 --- /dev/null +++ b/content/docs/2.15/reference/_index.md @@ -0,0 +1,13 @@ ++++ +title = "Reference" +weight = 2 ++++ + +Reference information for the KEDA autoscaler. + +- [ScaledObject specification](./scaledobject-spec) +- [ScaledJob specification](./scaledjob-spec) +- [Kubernetes Events](./events) +- [Firewall requirements] +- [FAQ](./faq.md) +- [Glossary](./glossary.md) \ No newline at end of file diff --git a/content/docs/2.15/reference/events.md b/content/docs/2.15/reference/events.md new file mode 100644 index 000000000..aa264c0d8 --- /dev/null +++ b/content/docs/2.15/reference/events.md @@ -0,0 +1,28 @@ ++++ +title = "Events reference" +description = "Kubernetes Events emitted by KEDA" +weight = 2500 ++++ + +KEDA emits the following [Kubernetes Events](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#event-v1-core): + +| Event | Type | Description | +|---------------------------------------|-----------|-----------------------------------------------------------------------------------------------------------------------------| +| `ScaledObjectReady` | `Normal` | On the first time a ScaledObject is ready, or if the previous ready condition status of the object was `Unknown` or `False` | +| `ScaledJobReady` | `Normal` | On the first time a ScaledJob is ready, or if the previous ready condition status of the object was `Unknown` or `False` | +| `ScaledObjectCheckFailed` | `Warning` | If the check validation for a ScaledObject fails | | +| `ScaledJobCheckFailed` | `Warning` | If the check validation for a ScaledJob fails | | +| `ScaledObjectDeleted` | `Normal` | When a ScaledObject is deleted and removed from KEDA watch | | +| `ScaledJobDeleted` | `Normal` | When a ScaledJob is deleted and removed from KEDA watch | | +| `KEDAScalersStarted` | `Normal` | When Scalers watch loop have started for a ScaledObject or ScaledJob | | +| `KEDAScalersStopped` | `Normal` | When Scalers watch loop have stopped for a ScaledObject or a ScaledJob | | +| `KEDAScalerFailed` | `Warning` | When a Scaler fails to create or check its event source | | +| `KEDAScaleTargetActivated` | `Normal` | When the scale target (Deployment, StatefulSet, etc) of a ScaledObject is scaled to 1, triggered by {scalers1;scalers2;...} | | +| `KEDAScaleTargetDeactivated` | `Normal` | When the scale target (Deployment, StatefulSet, etc) of a ScaledObject is scaled to 0 | | +| `KEDAScaleTargetActivationFailed` | `Warning` | When KEDA fails to scale the scale target of a ScaledObject to 1 | | +| `KEDAScaleTargetDeactivationFailed` | `Warning` | When KEDA fails to scale the scale target of a ScaledObject to 0 | | +| `KEDAJobsCreated` | `Normal` | When KEDA creates jobs for a ScaledJob | | +| `TriggerAuthenticationAdded` | `Normal` | When a new TriggerAuthentication is added | | +| `TriggerAuthenticationDeleted` | `Normal` | When a TriggerAuthentication is deleted | | +| `ClusterTriggerAuthenticationAdded` | `Normal` | When a new ClusterTriggerAuthentication is added | | +| `ClusterTriggerAuthenticationDeleted` | `Normal` | When a ClusterTriggerAuthentication is deleted | | diff --git a/content/docs/2.15/reference/faq.md b/content/docs/2.15/reference/faq.md new file mode 100644 index 000000000..df75bbe78 --- /dev/null +++ b/content/docs/2.15/reference/faq.md @@ -0,0 +1,6 @@ ++++ +title = "FAQ" +weight = 2000 ++++ + +{{< faq20 >}} diff --git a/content/docs/2.15/reference/glossary.md b/content/docs/2.15/reference/glossary.md new file mode 100644 index 000000000..2451000bf --- /dev/null +++ b/content/docs/2.15/reference/glossary.md @@ -0,0 +1,88 @@ ++++ +title = "Glossary" +weight = 1000 ++++ + +This document defines the various terms needed to understand the documentation and set up and use KEDA. + +## Admission Webhook + +[In Kubernetes](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/), an HTTP callback that handle admission requests. KEDA uses an admission webhook to validate and mutate ScaledObject resources. + +## Agent + +A primary role held by the KEDA operator. The Agent activates and deactivates Kubernetes Deployments to scale to and from zero. + +## Cluster + +[In Kubernetes](https://kubernetes.io/docs/reference/glossary/?fundamental=true#term-cluster), a set of one or more nodes that run containerized applications. + +## CRD + +Custom Resource Definition. [In Kubernetes](https://kubernetes.io/docs/reference/glossary/?fundamental=true#term-CustomResourceDefinition), a custom resource that extends the Kubernetes API with custom resources like ScaledObjects that have custom fields and behavior. + +## Event + +A notable occurrence captured by an event source that KEDA may use as a trigger to scale a container or deployment. + +## Event Source + +An external system like Kafka, RabbitMQ, that generates events that KEDA can monitor using a scaler. + +## Grafana + +An open-source monitoring platform that can visualize metrics collected by KEDA. + +## gRPC Remote Procedure Calls (gRPC) + +gRPC Remote Procedure Calls (gRPC). An open-source remote procedure call framework used by KEDA components to communicate. + +## HPA + +Horizontal Pod Autoscaler. Kubernetes autoscaler. By default, scales based on CPU/memory usage. KEDA uses HPA to scale Kubernetes clusters and deployments. + +## KEDA + +Kubernetes Event-Driven Autoscaling. A single-purpose, lightweight autoscaler that can scale a Kubernetes workload based on event metrics. + +## Metric + +Measurement of an event source such as queue length or response lag that KEDA uses to determine scaling. + +## OpenTelemetry + +An observability framework used by KEDA to instrument applications and collect metrics. + +## Operator + +The core KEDA component that monitors metrics and scales workloads accordingly. + +## Prometheus + +An open-source monitoring system that can scrape and store metrics from KEDA. + +## Scaled Object + +A custom resource that defines how KEDA should scale a workload based on events. + +## Scaled Job + +A custom resource KEDA uses to scale an application. + +## Scaler + +A component that integrates KEDA with a specific event source to collect metrics. + +## Stateful Set + +A Kubernetes workload with persistent data. KEDA can scale stateful sets. + +## TLS + +Transport Layer Security. KEDA uses TLS to encrypt communications between KEDA components. + +## Webhook + +An HTTP callback used to notify KEDA of events from external sources. + +[In Kubernetes](https://kubernetes.io/docs/reference/access-authn-authz/webhook/), an HTTP callback used as an event notification mechanism. diff --git a/content/docs/2.15/reference/scaledjob-spec.md b/content/docs/2.15/reference/scaledjob-spec.md new file mode 100644 index 000000000..dbc33680b --- /dev/null +++ b/content/docs/2.15/reference/scaledjob-spec.md @@ -0,0 +1,236 @@ ++++ +title = "ScaledJob specification" +weight = 4000 ++++ + +## Overview + +This specification describes the `ScaledJob` custom resource definition that defines the triggers and scaling behaviors use by KEDA + +to scale jobs. The `.spec.ScaleTargetRef` section holds the reference to the job, defined in [_scaledjob_types.go_](https://github.com/kedacore/keda/blob/main/apis/keda/v1alpha1/scaledjob_types.go). + +```yaml +apiVersion: keda.sh/v1alpha1 +kind: ScaledJob +metadata: + name: {scaled-job-name} + labels: + my-label: {my-label-value} # Optional. ScaledJob labels are applied to child Jobs + annotations: + autoscaling.keda.sh/paused: true # Optional. Use to pause autoscaling of Jobs + my-annotation: {my-annotation-value} # Optional. ScaledJob annotations are applied to child Jobs +spec: + jobTargetRef: + parallelism: 1 # [max number of desired pods](https://kubernetes.io/docs/concepts/workloads/controllers/job/#controlling-parallelism) + completions: 1 # [desired number of successfully finished pods](https://kubernetes.io/docs/concepts/workloads/controllers/job/#controlling-parallelism) + activeDeadlineSeconds: 600 # Specifies the duration in seconds relative to the startTime that the job may be active before the system tries to terminate it; value must be positive integer + backoffLimit: 6 # Specifies the number of retries before marking this job failed. Defaults to 6 + template: + # describes the [job template](https://kubernetes.io/docs/concepts/workloads/controllers/job) + pollingInterval: 30 # Optional. Default: 30 seconds + successfulJobsHistoryLimit: 5 # Optional. Default: 100. How many completed jobs should be kept. + failedJobsHistoryLimit: 5 # Optional. Default: 100. How many failed jobs should be kept. + envSourceContainerName: {container-name} # Optional. Default: .spec.JobTargetRef.template.spec.containers[0] + minReplicaCount: 10 # Optional. Default: 0 + maxReplicaCount: 100 # Optional. Default: 100 + rolloutStrategy: gradual # Deprecated: Use rollout.strategy instead (see below). + rollout: + strategy: gradual # Optional. Default: default. Which Rollout Strategy KEDA will use. + propagationPolicy: foreground # Optional. Default: background. Kubernetes propagation policy for cleaning up existing jobs during rollout. + scalingStrategy: + strategy: "custom" # Optional. Default: default. Which Scaling Strategy to use. + customScalingQueueLengthDeduction: 1 # Optional. A parameter to optimize custom ScalingStrategy. + customScalingRunningJobPercentage: "0.5" # Optional. A parameter to optimize custom ScalingStrategy. + pendingPodConditions: # Optional. A parameter to calculate pending job count per the specified pod conditions + - "Ready" + - "PodScheduled" + - "AnyOtherCustomPodCondition" + multipleScalersCalculation : "max" # Optional. Default: max. Specifies how to calculate the target metrics when multiple scalers are defined. + triggers: + # {list of triggers to create jobs} +``` + +You can find all supported triggers [here](../scalers). + +## jobTargetRef + +```yaml + jobTargetRef: + parallelism: 1 # Optional. Max number of desired instances ([docs](https://kubernetes.io/docs/concepts/workloads/controllers/job/#controlling-parallelism)) + completions: 1 # Optional. Desired number of successfully finished instances ([docs](https://kubernetes.io/docs/concepts/workloads/controllers/job/#controlling-parallelism)) + activeDeadlineSeconds: 600 # Optional. Specifies the duration in seconds relative to the startTime that the job may be active before the system tries to terminate it; value must be positive integer + backoffLimit: 6 # Optional. Specifies the number of retries before marking this job failed. Defaults to 6 +``` + +The `jobTargetRef` is a batch/v1 `JobSpec` object; refer to the Kubernetes API for [more details](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/job-v1/#JobSpec) about the fields. The `template` field is required. + + +## pollingInterval + +```yaml + pollingInterval: 30 # Optional. Default: 30 seconds +``` + +This is the interval to check each trigger on. By default, KEDA will check each trigger source on every ScaledJob every 30 seconds. + + +## successfulJobsHistoryLimit, failedJobsHistoryLimit + +```yaml + successfulJobsHistoryLimit: 5 # Optional. Default: 100. How many completed jobs should be kept. + failedJobsHistoryLimit: 5 # Optional. Default: 100. How many failed jobs should be kept. +``` + +The `successfulJobsHistoryLimit` and `failedJobsHistoryLimit` fields are optional. These fields specify how many completed and failed jobs should be kept. By default, they are set to 100. + +This concept is similar to [Jobs History Limits](https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/#jobs-history-limits) allowing you to learn what the outcomes of your jobs are. + +The actual number of jobs could exceed the limit in a short time. However, it is going to resolve in the cleanup period. Currently, the cleanup period is the same as the Polling interval. + + +## envSourceContainerName + +```yaml + envSourceContainerName: {container-name} # Optional. Default: .spec.JobTargetRef.template.spec.containers[0] +``` + +This optional property specifies the name of container in the Job, from which KEDA should try to get environment properties holding secrets etc. If it is not defined it, KEDA will try to get environment properties from the first Container, ie. from `.spec.JobTargetRef.template.spec.containers[0]`. + +___ +## minReplicaCount + +```yaml + minReplicaCount: 10 # Optional. Default: 0 +``` + +The min number of jobs that is created by default. This can be useful to avoid bootstrapping time of new jobs. If minReplicaCount is greater than maxReplicaCount, minReplicaCount will be set to maxReplicaCount. + +New messages may create new jobs - within the limits imposed by maxReplicaCount - in order to reach the state where minReplicaCount jobs are always running. For example, if one sets minReplicaCount to 2 then there will be 2 jobs running permanently. Using a targetValue of 1, if 3 new messages are sent, 2 of those messages will be processed on the already running jobs but another 3 jobs will be created in order to fulfill the desired state dictated by the minReplicaCount parameter that is set to 2. + +## maxReplicaCount + +```yaml + maxReplicaCount: 100 # Optional. Default: 100 +``` + +The max number of pods that is created within a single polling period. If there are running jobs, the number of running jobs will be deducted. This table is an example of the scaling logic. + +| Queue Length | Max Replica Count | Target Average Value | Running Job Count | Number of the Scale | +|--------------|-------------------|----------------------|-------------------|---------------------| +| 10 | 3 | 1 | 0 | 3 | +| 10 | 3 | 2 | 0 | 3 | +| 10 | 3 | 1 | 1 | 2 | +| 10 | 100 | 1 | 0 | 10 | +| 4 | 3 | 5 | 0 | 1 | + +* **Queue Length:** The number of items in the queue. +* **Target Average Value:** The number of messages that will be consumed on a job. It is defined on the scaler side. e.g. `queueLength` on `Azure Storage Queue` scaler. +* **Running Job Count:** How many jobs are running. +* **Number of the Scale:** The number of the job that is created. + + +## rollout + +```yaml + rollout: + strategy: gradual # Optional. Default: default. Which Rollout Strategy KEDA will use. + propagationPolicy: foreground # Optional. Default: background. Kubernetes propagation policy for cleaning up existing jobs during +``` + +The optional property rollout.strategy specifies the rollout strategy KEDA will use while updating an existing ScaledJob. +Possible values are `default` or `gradual`. \ +When using the `default` rolloutStrategy, KEDA will terminate existing Jobs whenever a ScaledJob is being updated. Then, it will recreate those Jobs with the latest specs. The order in which this termination happens can be configured via the rollout.propagationPolicy property. By default, the kubernetes background propagation is used. To change this behavior specify set propagationPolicy to `foreground`. For further information see [Kubernetes Documentation](https://kubernetes.io/docs/tasks/administer-cluster/use-cascading-deletion/#use-foreground-cascading-deletion). +On the `gradual` rolloutStartegy, whenever a ScaledJob is being updated, KEDA will not delete existing Jobs. Only new Jobs will be created with the latest specs. + + +## scalingStrategy + +```yaml +scalingStrategy: + strategy: "default" # Optional. Default: default. Which Scaling Strategy to use. +``` + +Select a Scaling Strategy. Possible values are `default`, `custom`, or `accurate`. The default value is `default`. + +> 💡 **NOTE:** +> +>`maxScale` is not the running Job count. It is measured as follows: + >```go + >maxScale = min(scaledJob.MaxReplicaCount(), divideWithCeil(queueLength, targetAverageValue)) + >``` + >That means it will use the value of `queueLength` divided by `targetAvarageValue` unless it is exceeding the `MaxReplicaCount`. +> +>`RunningJobCount` represents the number of jobs that are currently running or have not finished yet. +> +>It is measured as follows: +>```go +>if !e.isJobFinished(&job) { +> runningJobs++ +>} +>``` +>`PendingJobCount` provides an indication of the amount of jobs that are in pending state. Pending jobs can be calculated in two ways: +> - Default behavior - Job that have not finished yet **and** the underlying pod is either not running or has not been completed yet +> - Setting `pendingPodConditions` - Job that has not finished yet **and** all specified pod conditions of the underlying pod mark as `true` by kubernetes. +> +>It is measured as follows: +>```go +>if !e.isJobFinished(&job) { +> if len(scaledJob.Spec.ScalingStrategy.PendingPodConditions) > 0 { +> if !e.areAllPendingPodConditionsFulfilled(&job, scaledJob.Spec.ScalingStrategy.PendingPodConditions) { +> pendingJobs++ +> } +> } else { +> if !e.isAnyPodRunningOrCompleted(&job) { +> pendingJobs++ +> } +> } +>} +>``` + +**default** +This logic is the same as Job for V1. The number of the scale will be calculated as follows. + +_The number of the scale_ + +```go +maxScale - runningJobCount +``` + +**custom** +You can customize the default scale logic. You need to configure the following parameters. If you don't configure it, then the strategy will be `default.` + +```yaml +customScalingQueueLengthDeduction: 1 # Optional. A parameter to optimize custom ScalingStrategy. +customScalingRunningJobPercentage: "0.5" # Optional. A parameter to optimize custom ScalingStrategy. +``` + +_The number of the scale_ + +```go +min(maxScale-int64(*s.CustomScalingQueueLengthDeduction)-int64(float64(runningJobCount)*(*s.CustomScalingRunningJobPercentage)), maxReplicaCount) +``` + +**accurate** +If the scaler returns `queueLength` (number of items in the queue) that does not include the number of locked messages, this strategy is recommended. `Azure Storage Queue` is one example. You can use this strategy if you delete a message once your app consumes it. + +```go +if (maxScale + runningJobCount) > maxReplicaCount { + return maxReplicaCount - runningJobCount + } + return maxScale - pendingJobCount +``` +For more details, you can refer to [this PR](https://github.com/kedacore/keda/pull/1227). + + +### multipleScalersCalculation + +```yaml +scalingStrategy: + multipleScalersCalculation : "max" # Optional. Default: max. Specifies how to calculate the target metrics (`queueLength` and `maxScale`) when multiple scalers are defined. +``` +Select a behavior if you have multiple triggers. Possible values are `max`, `min`, `avg`, or `sum`. The default value is `max`. + +* **max:** - Use metrics from the scaler that has the max number of `queueLength`. (default) +* **min:** - Use metrics from the scaler that has the min number of `queueLength`. +* **avg:** - Sum up all the active scalers metrics and divide by the number of active scalers. +* **sum:** - Sum up all the active scalers metrics. diff --git a/content/docs/2.15/reference/scaledobject-spec.md b/content/docs/2.15/reference/scaledobject-spec.md new file mode 100644 index 000000000..391a968c8 --- /dev/null +++ b/content/docs/2.15/reference/scaledobject-spec.md @@ -0,0 +1,254 @@ + ++++ +title = "ScaledObject specification" +weight = 3000 ++++ + +## Overview + +This specification describes the `ScaledObject` Custom Resource definition that defines the triggers and scaling behaviors used by KEDA to scale `Deployment`, `StatefulSet` and `Custom Resource` target resources. The `.spec.ScaleTargetRef` section holds the reference to the target resource, defined in [_scaledobject_types.go_](https://github.com/kedacore/keda/blob/main/apis/keda/v1alpha1/scaledobject_types.go). + +```yaml +apiVersion: keda.sh/v1alpha1 +kind: ScaledObject +metadata: + name: {scaled-object-name} + annotations: + scaledobject.keda.sh/transfer-hpa-ownership: "true" # Optional. Use to transfer an existing HPA ownership to this ScaledObject + validations.keda.sh/hpa-ownership: "true" # Optional. Use to disable HPA ownership validation on this ScaledObject + autoscaling.keda.sh/paused: "true" # Optional. Use to pause autoscaling of objects explicitly +spec: + scaleTargetRef: + apiVersion: {api-version-of-target-resource} # Optional. Default: apps/v1 + kind: {kind-of-target-resource} # Optional. Default: Deployment + name: {name-of-target-resource} # Mandatory. Must be in the same namespace as the ScaledObject + envSourceContainerName: {container-name} # Optional. Default: .spec.template.spec.containers[0] + pollingInterval: 30 # Optional. Default: 30 seconds + cooldownPeriod: 300 # Optional. Default: 300 seconds + idleReplicaCount: 0 # Optional. Default: ignored, must be less than minReplicaCount + minReplicaCount: 1 # Optional. Default: 0 + maxReplicaCount: 100 # Optional. Default: 100 + fallback: # Optional. Section to specify fallback options + failureThreshold: 3 # Mandatory if fallback section is included + replicas: 6 # Mandatory if fallback section is included + advanced: # Optional. Section to specify advanced options + restoreToOriginalReplicaCount: true/false # Optional. Default: false + horizontalPodAutoscalerConfig: # Optional. Section to specify HPA related options + name: {name-of-hpa-resource} # Optional. Default: keda-hpa-{scaled-object-name} + behavior: # Optional. Use to modify HPA's scaling behavior + scaleDown: + stabilizationWindowSeconds: 300 + policies: + - type: Percent + value: 100 + periodSeconds: 15 + triggers: + # {list of triggers to activate scaling of the target resource} +``` + +## scaleTargetRef + +```yaml + scaleTargetRef: + apiVersion: {api-version-of-target-resource} # Optional. Default: apps/v1 + kind: {kind-of-target-resource} # Optional. Default: Deployment + name: {name-of-target-resource} # Mandatory. Must be in the same namespace as the ScaledObject + envSourceContainerName: {container-name} # Optional. Default: .spec.template.spec.containers[0] +``` + +The reference to the resource this ScaledObject is configured for. This is the resource KEDA will scale up/down and set up an HPA for, based on the triggers defined in `triggers:`. + +To scale Kubernetes Deployments only `name` need be specified. To scale a different resource such as StatefulSet or Custom Resource (that defines `/scale` subresource), appropriate `apiVersion` (following standard Kubernetes convention, ie. `{api}/{version}`) and `kind` need to be specified. + +`envSourceContainerName` is an optional property that specifies the name of container in the target resource, from which KEDA should try to get environment properties holding secrets etc. If it is not defined, KEDA will try to get environment properties from the first Container, ie. from `.spec.template.spec.containers[0]`. + +**Assumptions:** Resource referenced by `name` (and `apiVersion`, `kind`) is in the same namespace as the ScaledObject + + +## pollingInterval +```yaml + pollingInterval: 30 # Optional. Default: 30 seconds +``` + +This is the interval to check each trigger on. By default, KEDA will check each trigger source on every ScaledObject every 30 seconds. + +**Example:** in a queue scenario, KEDA will check the queueLength every `pollingInterval`, and scale the resource up or down accordingly. + + +## cooldownPeriod +```yaml + cooldownPeriod: 300 # Optional. Default: 300 seconds +``` + +The period to wait after the last trigger reported active before scaling the resource back to 0, in seconds. By default, it's 300 (5 minutes). + +The `cooldownPeriod` only applies after a trigger occurs; when you first create your `Deployment` (or `StatefulSet`/`CustomResource`), KEDA will immediately scale it to `minReplicaCount`. Additionally, the KEDA `cooldownPeriod` only applies when scaling to 0; scaling from 1 to N replicas is handled by the [Kubernetes Horizontal Pod Autoscaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/../concepts/scaling-deployments.md#support-for-cooldowndelay). + +**Example:** wait 5 minutes after the last time KEDA checked the queue and it was empty. (this is obviously dependent on `pollingInterval`) + + +## initialCooldownPeriod +```yaml + InitialCooldownPeriod: 120 # Optional. Default: 0 seconds +``` +The delay before the `cooldownPeriod` starts after the initial creation of the `ScaledObject`, in seconds. By default, it's 0, meaning the `cooldownPeriod` begins immediately upon creation. If set to a value such as 120 seconds, the `cooldownPeriod` will only start after the `ScaledObject` has been active for that duration. + +This parameter is particularly useful for managing the scale-down behavior during the initial phase of a `ScaledObject`. For instance, if `InitialCooldownPeriod` is set to 120 seconds, KEDA will not scale the resource back to 0 until 120 seconds have passed since the `ScaledObject` creation, regardless of the activity triggers. This allows for a grace period in situations where immediate scaling down after creation is not desirable. + +**Example:** Wait 120 seconds after the `ScaledObject` is created before starting the `cooldownPeriod`. For instance, if the `InitialCooldownPeriod` is set to 120 seconds, KEDA will not initiate the cooldown process until 120 seconds have passed since the `ScaledObject` was first created, regardless of the triggers' activity. This ensures a buffer period where the resource won’t be scaled down immediately after creation. (Note: This setting is independent of the `pollingInterval`.) + + +## idleReplicaCount + +```yaml + idleReplicaCount: 0 # Optional. Default: ignored, must be less than minReplicaCount +``` + +> 💡 **NOTE:** Due to limitations in HPA controller the only supported value for this property is 0, it will not work correctly otherwise. See this [issue](https://github.com/kedacore/keda/issues/2314) for more details. +> +> In some cases, you always need at least `n` pod running. Thus, you can omit this property and set `minReplicaCount` to `n`. +> +> **Example** You set `minReplicaCount` to 1 and `maxReplicaCount` to 10. If there’s no activity on triggers, the target resource is scaled down to `minReplicaCount` (1). Once there are activities, the target resource will scale base on the HPA rule. If there’s no activity on triggers, the resource is again scaled down to `minReplicaCount` (1). + +If this property is set, KEDA will scale the resource down to this number of replicas. If there's some activity on target triggers KEDA will scale the target resource immediately to `minReplicaCount` and then will be scaling handled by HPA. When there is no activity, the target resource is again scaled down to `idleReplicaCount`. This setting must be less than `minReplicaCount`. + +**Example:** If there's no activity on triggers the target resource is scaled down to `idleReplicaCount` (0), once there is an activity the target resource is immediately scaled to `minReplicaCount` (10) and then up to `maxReplicaCount` (100) as needed. If there's no activity on triggers the resource is again scaled down to `idleReplicaCount` (0). + + +## minReplicaCount + +```yaml + minReplicaCount: 1 # Optional. Default: 0 +``` + +Minimum number of replicas KEDA will scale the resource down to. By default, it's scale to zero, but you can use it with some other value as well. + +## maxReplicaCount + +```yaml + maxReplicaCount: 100 # Optional. Default: 100 +``` +This setting is passed to the HPA definition that KEDA will create for a given resource and holds the maximum number of replicas of the target resource. + + +## fallback +```yaml + fallback: # Optional. Section to specify fallback options + failureThreshold: 3 # Mandatory if fallback section is included + replicas: 6 # Mandatory if fallback section is included +``` + +The `fallback` section is optional. It defines a number of replicas to fall back to if a scaler is in an error state. + +KEDA will keep track of the number of consecutive times each scaler has failed to get metrics from its source. Once that value passes the `failureThreshold`, instead of not propagating a metric to the HPA (the default error behaviour), the scaler will, instead, return a normalised metric using the formula: +``` +target metric value * fallback replicas +``` +Due to the HPA metric being of type `AverageValue` (see below), this will have the effect of the HPA scaling the deployment to the defined number of fallback replicas. + +**Example:** When my instance of prometheus is unavailable 3 consecutive times, KEDA will change the HPA metric such that the deployment will scale to 6 replicas. + +There are a few limitations to using a fallback: + - It only supports scalers whose target is an `AverageValue` metric. Thus, it is **not** supported by the CPU & memory scalers, or by scalers whose metric target type is `Value`. In these cases, it will assume that fallback is disabled. + - It is only supported by `ScaledObjects` **not** `ScaledJobs`. + + +## advanced + +### restoreToOriginalReplicaCount + +```yaml +advanced: + restoreToOriginalReplicaCount: true/false # Optional. Default: false +``` + +This property specifies whether the target resource (`Deployment`, `StatefulSet`,...) should be scaled back to original replicas count, after the `ScaledObject` is deleted. +Default behavior is to keep the replica count at the same number as it is in the moment of `ScaledObject's` deletion. + +For example a `Deployment` with `3 replicas` is created, then `ScaledObject` is created and the `Deployment` is scaled by KEDA to `10 replicas`. Then `ScaledObject` is deleted: + 1. if `restoreToOriginalReplicaCount = false` (default behavior) then `Deployment` replicas count is `10` + 2. if `restoreToOriginalReplicaCount = true` then `Deployment` replicas count is set back to `3` (the original value) + + +### horizontalPodAutoscalerConfig + +```yaml +advanced: + horizontalPodAutoscalerConfig: # Optional. Section to specify HPA related options + name: {name-of-hpa-resource} # Optional. Default: keda-hpa-{scaled-object-name} + behavior: # Optional. Use to modify HPA's scaling behavior + scaleDown: + stabilizationWindowSeconds: 300 + policies: + - type: Percent + value: 100 + periodSeconds: 15 +``` + +#### horizontalPodAutoscalerConfig.name + +The name of the HPA resource KEDA will create. By default, it's `keda-hpa-{scaled-object-name}` + +#### horizontalPodAutoscalerConfig.behavior + +Starting from Kubernetes v1.18 the autoscaling API allows scaling behavior to be configured through the HPA behavior field. This way one can directly affect scaling of 1<->N replicas, which is internally being handled by HPA. KEDA would feed values from this section directly to the HPA's `behavior` field. Please follow [Kubernetes documentation](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/../concepts/scaling-deployments.md#configurable-scaling-behavior) for details. + +**Assumptions:** KEDA must be running on Kubernetes cluster v1.18+, in order to be able to benefit from this setting. + + + +```yaml +advanced: + scalingModifiers: # Optional. Section to specify scaling modifiers + target: {target-value-to-scale-on} # Mandatory. New target if metrics are anyhow composed together + activationTarget: {activation-target-value-to-scale-on} # Optional. New activation target if metrics are anyhow composed together + metricType: {metric-tipe-for-the-modifier} # Optional. Metric type to be used if metrics are anyhow composed together + formula: {formula-for-fetched-metrics} # Mandatory. Formula for calculation +``` + +### scalingModifiers + +The `scalingModifiers` is optional and **experimental**. If defined, both `target` and `formula` are mandatory. Using this structure creates `composite-metric` for the HPA that will replace all requests for external metrics and handle them internally. With `scalingModifiers` each trigger used in the `formula` **must** have a name defined. + +#### scalingModifiers.target + +`target` defines new target value to scale on for the composed metric. + +#### scalingModifiers.activationTarget + +`activationTarget` defines a new [activation target value](../concepts/scaling-deployments.md#activating-and-scaling-thresholds) to scale on for the composed metric. (Default: `0`, Optional) + +#### scalingModifiers.metricType + +`metricType` defines metric type used for this new `composite-metric`. (Values: `AverageValue`, `Value`, Default: `AverageValue`, Optional) + +#### scalingModifiers.formula + + `formula` composes metrics together and allows them to be modified/manipulated. It accepts mathematical/conditional statements using [this external project](https://github.com/antonmedv/expr). If the `fallback` scaling feature is in effect, the `formula` will NOT modify its metrics (therefore it modifies metrics only when all of their triggers are healthy). Complete language definition of `expr` package can be found [here](https://expr.medv.io/docs/Language-Definition). Formula must return a single value (not boolean). + +For examples of this feature see section [Scaling Modifiers](../concepts/scaling-deployments.md#scaling-modifiers-experimental). + + +## triggers + +```yaml + triggers: + # {list of triggers to activate scaling of the target resource} +``` + +> 💡 **NOTE:** You can find all supported triggers [here](../scalers). + +Trigger fields: +- **type**: The type of trigger to use. (Mandatory) +- **metadata**: The configuration parameters that the trigger requires. (Mandatory) +- **name**: Name for this trigger. This value can be used to easily distinguish this specific trigger and its metrics when consuming [Prometheus metrics](../operate/prometheus.md). By default, the name is generated from the trigger type. (Optional) +- **useCachedMetrics**: Enables caching of metric values during polling interval (as specified in `.spec.pollingInterval`). For more information, see ["Caching Metrics"](../concepts/scaling-deployments.md#caching-metrics). (Values: `false`, `true`, Default: `false`, Optional) +- **authenticationRef**: A reference to the `TriggerAuthentication` or `ClusterTriggerAuthentication` object that is used to authenticate the scaler with the environment. + - More details can be found [here](../concepts/authentication). (Optional) +- **metricType**: The type of metric that should be used. (Values: `AverageValue`, `Value`, `Utilization`, Default: `AverageValue`, Optional) + - Learn more about how the [Horizontal Pod Autoscaler (HPA) calculates `replicaCount`](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) based on metric type and value. + - To show the differences between the metric types, let's assume we want to scale a deployment with 3 running replicas based on a queue of messages: + - With `AverageValue` metric type, we can control how many messages, on average, each replica will handle. If our metric is the queue size, the threshold is 5 messages, and the current message count in the queue is 20, HPA will scale the deployment to 20 / 5 = 4 replicas, regardless of the current replica count. + - The `Value` metric type, on the other hand, can be used when we don't want to take the average of the given metric across all replicas. For example, with the `Value` type, we can control the average time of messages in the queue. If our metric is average time in the queue, the threshold is 5 milliseconds, and the current average time is 20 milliseconds, HPA will scale the deployment to 3 * 20 / 5 = 12. + +> ⚠️ **NOTE:** All scalers, except CPU and Memory, support metric types `AverageValue` and `Value` while CPU and Memory scalers both support `AverageValue` and `Utilization`. diff --git a/content/docs/2.15/scalers/aws-sqs.md b/content/docs/2.15/scalers/aws-sqs.md index 95eb2387c..ec059ba86 100644 --- a/content/docs/2.15/scalers/aws-sqs.md +++ b/content/docs/2.15/scalers/aws-sqs.md @@ -30,8 +30,8 @@ triggers: **Parameter list:** -- `queueURL` - Full URL for the SQS Queue. The simple name of the queue can be used in case there's no ambiguity. (Optional, You can use this instead of `queueURLFromEnv` parameter) -- `queueURLFromEnv` - Name of the environment variable on the scale target to read the queue URL from. (Optional, You can use this instead of `queueURL` parameter) +- `queueURL` - Full URL for the SQS Queue. The short name of the queue can be used if there's no ambiguity. (Optional. Only one of `queueURL` and `queueURLFromEnv` is required. If both are provided, `queueURL` is used.) +- `queueURLFromEnv` - Name of the environment variable on the scale target to read the queue URL from. (Optional. Only one of `queueURL` and `queueURLFromEnv` is required.) - `queueLength` - Target value for queue length passed to the scaler. Example: if one pod can handle 10 messages, set the queue length target to 10. If the actual messages in the SQS Queue is 30, the scaler scales to 3 pods. (default: 5) - `activationQueueLength` - Target value for activating the scaler. Learn more about activation [here](./../concepts/scaling-deployments.md#activating-and-scaling-thresholds). (Default: `0`, Optional) diff --git a/content/docs/2.15/scalers/azure-pipelines.md b/content/docs/2.15/scalers/azure-pipelines.md index 4933bfae4..3f8fa4373 100644 --- a/content/docs/2.15/scalers/azure-pipelines.md +++ b/content/docs/2.15/scalers/azure-pipelines.md @@ -79,7 +79,7 @@ Finally, it is also possible get the pool ID from the response of a HTTP request ### Supporting demands in agents -By default, if you do not wish to use demands in your agent scaler then it will scale based simply on the pool's queue length. +By default, if you do not use demands in your agent scaler then it scales based on the pool's queue length. Demands (Capabilities) are useful when you have multiple agents with different capabilities existing within the same pool, for instance in a kube cluster you may have an agent supporting dotnet5, dotnet6, java or maven; diff --git a/content/docs/2.15/scalers/azure-service-bus.md b/content/docs/2.15/scalers/azure-service-bus.md index ca498fbc9..e7b9c6bf3 100644 --- a/content/docs/2.15/scalers/azure-service-bus.md +++ b/content/docs/2.15/scalers/azure-service-bus.md @@ -36,7 +36,7 @@ triggers: **Parameter list:** - `messageCount` - Amount of active messages in your Azure Service Bus queue or topic to scale on. -- `activationMessageCount` - Target value for activating the scaler. Learn more about activation [here](./../concepts/scaling-deployments.md#activating-and-scaling-thresholds). (Default: `0`, Optional) +- `activationMessageCount` - Target value for activating the scaler. Learn more about activation [here](../concepts/scaling-deployments#activating-and-scaling-thresholds). (Default: `0`, Optional) - `queueName` - Name of the Azure Service Bus queue to scale on. (Optional) - `topicName` - Name of the Azure Service Bus topic to scale on. (Optional) - `subscriptionName` - Name of the Azure Service Bus queue to scale on. (Optional*, Required when `topicName` is specified) @@ -118,4 +118,4 @@ When KEDA logs show errors similar to `invalid queue runtime properties: no Coun Consider applying one of the following mitigations: - Scaling the Azure Service Bus namespace to a higher SKU, or use premium - Increase the polling interval of the ScaledObject/ScaledJob -- Use [caching of metrics](./../concepts/scaling-deployments/#caching-metrics) +- Use [caching of metrics](../concepts/scaling-deployments/#caching-metrics) diff --git a/content/docs/2.15/scalers/datadog.md b/content/docs/2.15/scalers/datadog.md index cf7e01d24..540fa96f5 100644 --- a/content/docs/2.15/scalers/datadog.md +++ b/content/docs/2.15/scalers/datadog.md @@ -37,7 +37,7 @@ triggers: - `query` - The Datadog query to run. - `queryValue` - Value to reach to start scaling (This value can be a float). -- `activationQueryValue` - Target value for activating the scaler. Learn more about activation [here](./../concepts/scaling-deployments.md#activating-and-scaling-thresholds).(Default: `0`, Optional, This value can be a float) +- `activationQueryValue` - Target value for activating the scaler. Learn more about activation [here](../concepts/scaling-deployments#activating-and-scaling-thresholds).(Default: `0`, Optional, This value can be a float) - `queryAggregator` - When `query` is multiple queries, comma-seperated, this sets how to aggregate the multiple results. (Values: `max`, `average`, Required only when `query` contains multiple queries) - `type` - Whether to start scaling based on the value or the average between pods. (Values: `average`, `global`, Default:`average`, Optional) - `age`: The time window (in seconds) to retrieve metrics from Datadog. (Default: `90`, Optional) @@ -133,7 +133,7 @@ often (per `ScaledObject`) we query Datadog for a metric. When scaling from 0 to 1, the polling interval is controlled by KEDA, using [the `spec.pollingInterval` parameter in the `ScaledObject` -definition](../concepts/scaling-deployments/#pollinginterval). For example, if +definition](../reference/scaledobject-spec/#pollinginterval). For example, if this parameter is set to `60`, KEDA will poll Datadog for a metric value every 60 seconds while the number of replicas is 0. diff --git a/content/docs/2.15/scalers/redis-sentinel-lists.md b/content/docs/2.15/scalers/redis-sentinel-lists.md index 07bf4b25e..1ce8b9805 100644 --- a/content/docs/2.15/scalers/redis-sentinel-lists.md +++ b/content/docs/2.15/scalers/redis-sentinel-lists.md @@ -42,7 +42,7 @@ triggers: - Both the hostname, username and password fields need to be set to the names of the environment variables in the target deployment that contain the host name, username and password respectively. - `sentinelUsernameFromEnv` - Environment variable to read the authentication username from to authenticate with the Redis Sentinel server. - `sentinelPasswordFromEnv` - Environment variable to read the authentication password from to authenticate with the Redis Sentinel server. -- `sentinelMaster` - The name of the master in Sentinel to get the Redis server address for. +- sentinelMaster - The name of the primary (still referred to as the 'master' in Sentinel) to get the Redis server address for. - `listName` - Name of the Redis List that you want to monitor. - `listLength` - Average target value to trigger scaling actions. - `activationListLength` - Target value for activating the scaler. Learn more about activation [here](./../concepts/scaling-deployments.md#activating-and-scaling-thresholds). (Default: `0`, Optional) @@ -55,7 +55,7 @@ Some parameters could be provided using environmental variables, instead of sett - `addressesFromEnv` - The hosts and their respective ports of the Redis Sentinel nodes, similar to `addresses`, but reads it from an environment variable on the scale target. - `hostsFromEnv` - The hosts of the Redis Sentinel nodes, similar to `hosts`, but reads it from an environment variable on the scale target. - `portsFromEnv` - The corresponding ports for the hosts of the Redis Sentinel nodes, similar to `ports`, but reads it from an environment variable on the scale target. -- `sentinelMasterFromEnv` - The name of the master in Sentinel to get the Redis server address for, similar to `sentinelMaster`, but reads it from an environment variable on the scale target. +- `sentinelMasterFromEnv` - The name of the primary (still referred to as the 'master' in Sentinel) to get the Redis server address for; similar to `sentinelMaster`, but reads it from an environment variable on the scale target. ### Authentication Parameters @@ -66,7 +66,7 @@ You can authenticate by using a password. - `addresses` - Comma separated list of host:port format. - `hosts` - Comma separated list of hostname of the Redis Sentinel nodes. If specified, the `ports` should also be specified. - `ports` - Comma separated list of ports of the Redis Sentinel nodes. If specified, the `hosts` should also be specified. -- `sentinelMaster` - The name of the master in Sentinel to get the Redis server address for. +- `sentinelMaster` - The name of the primary (still referred to as the 'master' in Sentinel) to get the Redis server address for. **Authentication:** @@ -134,7 +134,7 @@ spec: addresses: node1:26379, node2:26379, node3:26379 listName: mylist listLength: "10" - sentinelMaster: "mymaster" + sentinelMaster: "myprimary" authenticationRef: name: keda-trigger-auth-redis-secret ``` diff --git a/content/docs/2.15/scalers/redis-sentinel-streams.md b/content/docs/2.15/scalers/redis-sentinel-streams.md index 0070884d9..95db3210d 100644 --- a/content/docs/2.15/scalers/redis-sentinel-streams.md +++ b/content/docs/2.15/scalers/redis-sentinel-streams.md @@ -64,7 +64,7 @@ triggers: - `sentinelUsernameFromEnv` - Name of the environment variable your deployment uses to get the Redis Sentinel username. (Optional) - `sentinelPasswordFromEnv` - Name of the environment variable your deployment uses to get the Redis Sentinel password. (Optional) -- `sentinelMaster` - The name of the master in Sentinel to get the Redis server address for. +- `sentinelMaster` - The name of the primary (still referred to as the 'master' in Sentinel) in Sentinel to get the Redis server address for. - `stream` - Name of the Redis Stream. - `consumerGroup` - Name of the Consumer group associated with Redis Stream. > Setting the `consumerGroup` causes the scaler to operate on `pendingEntriesCount`. Lack of `consumerGroup` will cause the scaler to be based on `streamLength` @@ -81,7 +81,7 @@ Some parameters could be provided using environmental variables, instead of sett - `addressesFromEnv` - The hosts and corresponding ports of Redis Sentinel nodes, similar to `addresses`, but reads it from an environment variable on the scale target. Name of the environment variable your deployment uses to get the URLs of Redis Sentinel nodes. The resolved hosts should follow a format like `node1:26379, node2:26379, node3:26379 ...`. - `hostsFromEnv` - The hosts of the Redis Sentinel nodes, similar to `hosts`, but reads it from an environment variable on the scale target. - `portsFromEnv` - The corresponding ports for the hosts of Redis Sentinel nodes, similar to `ports`, but reads it from an environment variable on the scale target. -- `sentinelMasterFromEnv` - The name of the master in Sentinel to get the Redis server address for, similar to `sentinelMaster`, but reads it from an environment variable on the scale target. +- `sentinelMasterFromEnv` - The name of the primary (still referred to as the 'master' in Sentinel) in Sentinel to get the Redis server address for, similar to `sentinelMaster`, but reads it from an environment variable on the scale target. ### Authentication Parameters @@ -117,7 +117,7 @@ spec: stream: my-stream consumerGroup: consumer-group-1 pendingEntriesCount: "10" - sentinelMaster: "mymaster" + sentinelMaster: "myprimary" ``` #### Using `TriggerAuthentication` @@ -197,7 +197,7 @@ spec: stream: my-stream consumerGroup: consumer-group-1 pendingEntriesCount: "10" - sentinelMaster: "mymaster" + sentinelMaster: "myprimary" authenticationRef: name: keda-redis-stream-triggerauth # name of the TriggerAuthentication resource ``` @@ -227,7 +227,7 @@ spec: passwordFromEnv: REDIS_PASSWORD # name of the environment variable in the Deployment stream: my-stream streamLength: "50" - sentinelMaster: "mymaster" + sentinelMaster: "myprimary" ``` #### Using `lagCount` From 8f8bb08025569f73907f0616416022d42e3e0c9e Mon Sep 17 00:00:00 2001 From: shubhusion Date: Tue, 30 Jul 2024 20:55:56 +0530 Subject: [PATCH 12/33] Added a Note Signed-off-by: shubhusion --- content/docs/2.14/operate/setupscaler.md | 6 +++++- content/docs/2.15/operate/setupscaler.md | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/content/docs/2.14/operate/setupscaler.md b/content/docs/2.14/operate/setupscaler.md index 7279354e3..a56feb769 100644 --- a/content/docs/2.14/operate/setupscaler.md +++ b/content/docs/2.14/operate/setupscaler.md @@ -26,7 +26,11 @@ KEDA supports various scalers that correspond to different event sources or trig 1. Visit the [KEDA Scalers documentation](https://keda.sh/docs/2.14/scalers/) and browse through the list of available scalers. 2. Identify the scaler that matches the event source you want to use for scaling your application. For example: - - If you want to scale based on incoming HTTP traffic, you would need the **HTTP scaler**. + - If you want to scale based on incoming HTTP traffic, you would need the **HTTP Add-on**. + + > **Note:** + > The HTTP Add-on is still in beta stage and may not provide the full functionality or stability expected in a production environment. + - If you want to scale based on messages in a RabbitMQ queue, you would need the **RabbitMQ scaler**. - If you want to scale based on a cron schedule, you would need the **Cron scaler**. 3. Open the documentation page for your chosen scaler and familiarize yourself with its specific requirements and configuration options. diff --git a/content/docs/2.15/operate/setupscaler.md b/content/docs/2.15/operate/setupscaler.md index 7279354e3..a56feb769 100644 --- a/content/docs/2.15/operate/setupscaler.md +++ b/content/docs/2.15/operate/setupscaler.md @@ -26,7 +26,11 @@ KEDA supports various scalers that correspond to different event sources or trig 1. Visit the [KEDA Scalers documentation](https://keda.sh/docs/2.14/scalers/) and browse through the list of available scalers. 2. Identify the scaler that matches the event source you want to use for scaling your application. For example: - - If you want to scale based on incoming HTTP traffic, you would need the **HTTP scaler**. + - If you want to scale based on incoming HTTP traffic, you would need the **HTTP Add-on**. + + > **Note:** + > The HTTP Add-on is still in beta stage and may not provide the full functionality or stability expected in a production environment. + - If you want to scale based on messages in a RabbitMQ queue, you would need the **RabbitMQ scaler**. - If you want to scale based on a cron schedule, you would need the **Cron scaler**. 3. Open the documentation page for your chosen scaler and familiarize yourself with its specific requirements and configuration options. From fc9e3a070fb76e4d2c91f39401d95c1c33a1c3ed Mon Sep 17 00:00:00 2001 From: rxg8255 <105524324+rxg8255@users.noreply.github.com> Date: Mon, 1 Jul 2024 06:54:48 -0500 Subject: [PATCH 13/33] Add support for cassandra tls under v2.15 (#1390) Signed-off-by: Ranjith Gopal Co-authored-by: Ranjith Gopal Signed-off-by: shubhusion --- content/docs/2.15/scalers/cassandra.md | 101 ++++++++++++++++++++++++- 1 file changed, 100 insertions(+), 1 deletion(-) diff --git a/content/docs/2.15/scalers/cassandra.md b/content/docs/2.15/scalers/cassandra.md index d662388d3..04c151c3f 100644 --- a/content/docs/2.15/scalers/cassandra.md +++ b/content/docs/2.15/scalers/cassandra.md @@ -45,8 +45,11 @@ You can authenticate by using a password via `TriggerAuthentication` configurati **Password Authentication:** - `password` - Password for configured user to log in to the Cassandra instance. +- `tls` - To enable SSL auth for Cassandra session, set this to enable. If not set, TLS for Cassandra is not used. (Values: enable, disable, Default: disable, Optional). +- `cert` - Certificate path for client authentication. Mandatory if tls enabled. (Optional) +- `key` - Key path for client authentication. Mandatory if tls enabled. (Optional) -### Example +### Example with no TLS auth ```yaml apiVersion: v1 @@ -87,3 +90,99 @@ spec: authenticationRef: name: keda-trigger-auth-cassandra-secret ``` + +### Example with TLS auth + +Since we are passing Cert and Key content as inputs to the scaler, we have to supply writable location for required GSSAPI configurations for the `keda-operator` container. + +##### `sasl/gssapi` in manager.yaml + +If you use YAML declarations to deploy KEDA, add below volume mount and volume to supply writable location for required GSSAPI configurations for the `keda-operator` container. + +``` + volumeMounts: + - mountPath: /tmp/cassandra + name: temp-cassandra-vol + readOnly: false + + volumes: + - name: temp-cassandra-vol + emptyDir: + medium: Memory +``` + +##### `sasl/gssapi` in keda-charts + +If you use Helm Charts to deploy KEDA, add below volume mount and volume to supply writable location for required gssapi configurations. + +``` +volumes.keda.extraVolumeMounts +- mountPath: /tmp/cassandra + name: temp-cassandra-vol + readOnly: false + +volumes.keda.extraVolumes +- name: temp-cassandra-vol + emptyDir: + medium: Memory +``` + +Once we have the writable mount path set up for the certificates and keys. + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: cassandra-secrets +type: Opaque +data: + cassandra_password: CASSANDRA_PASSWORD + tls: enable + cert: + key: + ## Optional parameter ca ## + ca: +--- +apiVersion: keda.sh/v1alpha1 +kind: TriggerAuthentication +metadata: + name: keda-trigger-auth-cassandra-secret +spec: + secretTargetRef: + - parameter: password + name: cassandra-secrets + key: cassandra_password + - parameter: tls + name: cassandra-secrets + key: tls + - parameter: cert + name: cassandra-secrets + key: cert + - parameter: key + name: cassandra-secrets + key: key + ## Optional parameter ca ## + - parameter: ca + name: cassandra-secrets + key: ca +--- +apiVersion: keda.sh/v1alpha1 +kind: ScaledObject +metadata: + name: cassandra-scaledobject +spec: + scaleTargetRef: + name: nginx-deployment + triggers: + - type: cassandra + metadata: + username: "cassandra" + port: "9042" + clusterIPAddress: "cassandra.default" + consistency: "Quorum" + protocolVersion: "4" + query: "SELECT COUNT(*) FROM test_keyspace.test_table;" + targetQueryValue: "1" + authenticationRef: + name: keda-trigger-auth-cassandra-secret +``` From 0927db294a4e55bf7bd423289cbf835addee4068 Mon Sep 17 00:00:00 2001 From: Caleb Lemoine <21261388+circa10a@users.noreply.github.com> Date: Wed, 3 Jul 2024 00:53:55 -0700 Subject: [PATCH 14/33] feat: splunk scaler docs (#1413) Signed-off-by: shubhusion --- .htmltest.yml | 1 + content/docs/2.15/scalers/splunk.md | 292 ++++++++++++++++++++++++++++ 2 files changed, 293 insertions(+) create mode 100644 content/docs/2.15/scalers/splunk.md diff --git a/.htmltest.yml b/.htmltest.yml index afd8fd6cd..3628b12af 100644 --- a/.htmltest.yml +++ b/.htmltest.yml @@ -4,3 +4,4 @@ CheckExternal: false IgnoreAltMissing: true IgnoreEmptyHref: true IgnoreInternalURLs: + - /docs/2.14/scalers/splunk/ diff --git a/content/docs/2.15/scalers/splunk.md b/content/docs/2.15/scalers/splunk.md new file mode 100644 index 000000000..beee29ea8 --- /dev/null +++ b/content/docs/2.15/scalers/splunk.md @@ -0,0 +1,292 @@ ++++ +title = "Splunk" +availability = "v2.15+" +maintainer = "Community" +category = "Data & Storage" +description = "Scale applications based on Splunk saved search results." +go_file = "splunk_scaler" ++++ + +### Trigger Specification + +This specification describes the `splunk` trigger that scales based on the result of a [saved search](https://docs.splunk.com/Documentation/Splunk/9.2.1/Search/Savingsearches). + +The trigger always requires the following information: + +```yaml +triggers: + - type: splunk + metadata: + host: https://splunk.default.svc.cluster.local:8089 + targetValue: "1" + activationValue: "10" + savedSearchName: my-saved-search-name + valueField: count +``` + +**Parameter list:** + +- `host` - Search API host and port. Example: `https://localhost:8089`. +- `unsafeSsl` - Whether to trust invalid certificates or not. (Values: `"true"`, `"false"`, Default: `"false"`, Optional) +- `targetValue` - Value to reach to start scaling (This value can be a integer or float). +- `activationValue` - Target value for activating the scaler. Learn more about activation [here](./../concepts/scaling-deployments.md#activating-and-scaling-thresholds). +- `savedSearchName` - Name of saved search that returns metric data for scaling. +- `valueField` - The name of the field in the search results containing the metric value. Example: `index=_internal | tail | stats count`, the `valueField` is `count`. + +### Authentication Parameters + +You can authenticate by using a username/password or an API token. You will need to use `TriggerAuthentication` CRD to configure the authentication. + +> **Note:** +> +> `TriggerAuthentication` is required to use this scaler due to the hard requirement of providing a `username` for the Splunk API. + +**Parameter list:** + +- `username` - Splunk username authorized to access the search API. +- `apiToken` - Splunk API token for supplied `username`. Conflicts with `password`. +- `password` - Password for supplied `username`. Conflicts with `apiToken`. + +The user will need access to the saved search. + +### Examples + +### Username/password + +```yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: splunk-creds +data: + username: YWRtaW4= # "admin" + password: cGFzc3dvcmQ= # "password" +--- +apiVersion: keda.sh/v1alpha1 +kind: TriggerAuthentication +metadata: + name: splunk-auth +spec: + secretTargetRef: + - parameter: username + name: splunk-creds + key: username + - parameter: password + name: splunk-creds + key: password +--- +apiVersion: keda.sh/v1alpha1 +kind: ScaledObject +metadata: + name: splunk-scaledobject +spec: + pollingInterval: 15 + minReplicaCount: 1 + maxReplicaCount: 3 + scaleTargetRef: + name: nginx + triggers: + - type: splunk + authenticationRef: + name: splunk-auth + metadata: + host: https://splunk.default.svc.cluster.local:8089 + targetValue: "11" + activationValue: "15" + savedSearchName: my-saved-search-name + valueField: count +``` + +### API Token + +```yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: splunk-creds +data: + username: YWRtaW4= # admin + apiToken: +--- +apiVersion: keda.sh/v1alpha1 +kind: TriggerAuthentication +metadata: + name: splunk-auth +spec: + secretTargetRef: + - parameter: username + name: splunk-creds + key: username + - parameter: apiToken + name: splunk-creds + key: apiToken +--- +apiVersion: keda.sh/v1alpha1 +kind: ScaledObject +metadata: + name: splunk-scaledobject +spec: + pollingInterval: 15 + minReplicaCount: 1 + maxReplicaCount: 3 + scaleTargetRef: + name: nginx + triggers: + - type: splunk + authenticationRef: + name: splunk-auth + metadata: + host: https://splunk.default.svc.cluster.local:8089 + targetValue: "11" + activationValue: "15" + savedSearchName: my-saved-search-name + valueField: count +``` + +### Full example using Splunk deployment + +```yaml +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: splunkconf +data: + default.yml: | + splunk: + conf: + - key: savedsearches + value: + directory: /opt/splunk/etc/users/admin/search/local + content: + my-saved-search-name: + action.email.useNSSubject: 1 + action.webhook.enable_allowlist: 0 + alert.track: 0 + cron_schedule: '*/1 * * * *' + dispatch.earliest_time: -15m + dispatch.latest_time: now + display.general.type: statistics + display.page.search.tab: statistics + display.visualizations.show: 0 + enableSched: 1 + request.ui_dispatch_app: search + request.ui_dispatch_view: search + search: index=_internal | tail | stats count +--- +apiVersion: v1 +kind: Secret +metadata: + name: splunk-creds +data: + username: YWRtaW4= # "admin" + password: cGFzc3dvcmQ= # "password" +--- +apiVersion: keda.sh/v1alpha1 +kind: TriggerAuthentication +metadata: + name: splunk-auth +spec: + secretTargetRef: + - parameter: username + name: splunk-creds + key: username + - parameter: password + name: splunk-creds + key: password +--- +apiVersion: v1 +kind: Service +metadata: + name: splunk +spec: + ports: + - port: 8000 + targetPort: web + name: web-svc + - port: 8089 + targetPort: 8089 + name: api-svc + selector: + app: splunk +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: splunk + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app: splunk + template: + metadata: + labels: + app: splunk + spec: + containers: + - name: splunk + image: splunk/splunk:9.2 + ports: + - containerPort: 8000 + name: web + - containerPort: 8089 + name: api + env: + - name: SPLUNK_START_ARGS + value: --accept-license + - name: SPLUNK_PASSWORD + value: password + volumeMounts: + - name: splunkconf-volume + mountPath: /tmp/defaults + volumes: + - name: splunkconf-volume + configMap: + name: splunkconf +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx +spec: + selector: + matchLabels: + app: nginx + replicas: 1 + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx + ports: + - containerPort: 8080 +--- +apiVersion: keda.sh/v1alpha1 +kind: ScaledObject +metadata: + name: splunk-scaledobject +spec: + pollingInterval: 15 + minReplicaCount: 1 + maxReplicaCount: 3 + scaleTargetRef: + name: nginx + triggers: + - type: splunk + authenticationRef: + name: splunk-auth + metadata: + host: https://splunk.default.svc.cluster.local:8089 + unsafeSsl: "true" + targetValue: "5" + activationValue: "5" + savedSearchName: my-saved-search-name + valueField: count +``` From 704e541e501a596dfdb8f4d1790f260a02ae4fc1 Mon Sep 17 00:00:00 2001 From: Uchechukwu Obasi Date: Thu, 4 Jul 2024 14:45:17 +0100 Subject: [PATCH 15/33] Feat: version faq docs (#1416) Signed-off-by: shubhusion --- CONTRIBUTING.md | 113 ++++++++++----- content/docs/2.0/faq.md | 2 +- content/docs/2.1/faq.md | 2 +- content/docs/2.10/faq.md | 2 +- content/docs/2.11/faq.md | 2 +- content/docs/2.12/faq.md | 2 +- content/docs/2.13/faq.md | 2 +- content/docs/2.14/faq.md | 2 +- content/docs/2.14/reference/faq.md | 2 +- content/docs/2.15/reference/faq.md | 2 +- content/docs/2.2/faq.md | 2 +- content/docs/2.3/faq.md | 2 +- content/docs/2.4/faq.md | 2 +- content/docs/2.5/faq.md | 2 +- content/docs/2.6/faq.md | 2 +- content/docs/2.7/faq.md | 2 +- content/docs/2.8/faq.md | 2 +- content/docs/2.9/faq.md | 2 +- data/faq2_14.toml | 217 +++++++++++++++++++++++++++++ data/faq2_15.toml | 217 +++++++++++++++++++++++++++++ layouts/shortcodes/faq20.html | 8 +- 21 files changed, 534 insertions(+), 55 deletions(-) create mode 100644 data/faq2_14.toml create mode 100644 data/faq2_15.toml diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d909a47ea..8068d73d1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,20 +8,32 @@ Our documentation is versioned so it's important to make the changes for the cor ## Getting Help -If you have a question about KEDA or how best to contribute, the [#KEDA](https://kubernetes.slack.com/archives/CKZJ36A5D) channel on the Kubernetes slack channel ([get an invite if you don't have one already](https://slack.k8s.io/)) is a good place to start. We also have regular [community stand-ups](https://github.com/kedacore/keda#community) to track ongoing work and discuss areas of contribution. For any issues with the product you can [create an issue](https://github.com/kedacore/keda/issues/new) in this repo. +If you have a question about KEDA or how best to contribute, the [#KEDA](https://kubernetes.slack.com/archives/CKZJ36A5D) channel on the Kubernetes slack channel ([get an invite if you don't have one already](https://slack.k8s.io/)) is a good place to start. We also have regular [community stand-ups](https://github.com/kedacore/keda#community) to track ongoing work and discuss areas of contribution. For any issues with the product you can [create an issue](https://github.com/kedacore/keda/issues/new) in this repo. ## Contributing New Documentation We provide easy ways to introduce new content: -- [Adding new blog post](#adding-blog-post) -- [Adding new Frequently Asked Question (FAQ)](#add-new-frequently-asked-question-faq) -- [Adding new scaler documentation](#adding-scaler-documentation) -- [Adding new troubleshooting guidance](#add-new-troubleshooting-guidance) -- [Become a listed KEDA user!](#become-a-listed-KEDA-user) -- [Become a listed KEDA commercial offering!](#become-a-listed-KEDA-commercial-offering) -- [Writing documentation for a scaler](#writing-documentation-for-a-new-authentication-provider) -- [Writing documentation for a scaler](#writing-documentation-for-a-scaler) +- [Contributing to KEDA](#contributing-to-keda) + - [Getting Help](#getting-help) + - [Contributing New Documentation](#contributing-new-documentation) + - [Become a listed KEDA user!](#become-a-listed-keda-user) + - [Become a listed KEDA commercial offering!](#become-a-listed-keda-commercial-offering) + - [Adding blog post](#adding-blog-post) + - [Adding scaler documentation](#adding-scaler-documentation) + - [Writing documentation for a new authentication provider](#writing-documentation-for-a-new-authentication-provider) + - [Add new Frequently Asked Question (FAQ)](#add-new-frequently-asked-question-faq) + - [Add new troubleshooting guidance](#add-new-troubleshooting-guidance) + - [Writing documentation for a scaler](#writing-documentation-for-a-scaler) + - [Working with documentation versions](#working-with-documentation-versions) + - [Preparing a new version](#preparing-a-new-version) + - [Publishing a new version](#publishing-a-new-version) + - [Developer Certificate of Origin: Signing your work](#developer-certificate-of-origin-signing-your-work) + - [Every commit needs to be signed](#every-commit-needs-to-be-signed) + - [I didn't sign my commit, now what?!](#i-didnt-sign-my-commit-now-what) + - [Changing the website](#changing-the-website) + - [Creating and building a local environment](#creating-and-building-a-local-environment) + - [Adding a new filter option](#adding-a-new-filter-option) Learn more how to [create and build a local environment](#creating-and-building-a-local-environment). @@ -30,6 +42,7 @@ Learn more how to [create and build a local environment](#creating-and-building- Are you using KEDA in production? Do you want to become a [listed user](https://keda.sh/community/#users)? Say no more! You can easily get listed by following these steps: + 1. Upload your logo to `static/img/logos/` _(350x180)_ 2. Configure your company as a new user in `config.toml` _(sorted alphabetically)_ @@ -46,6 +59,7 @@ Here's a good example of [Coralogix becoming a listed user](https://github.com/k Do you offer commercial support for KEDA and want to become a [listed commercial offering](https://keda.sh/support/#commercial-support)? Say no more! You can easily get listed by following these steps: + 1. Upload your logo to `static/img/logos/` _(350x180)_ 2. Configure your company as a new user in `config.toml` _(sorted alphabetically)_ @@ -66,9 +80,9 @@ $ hugo new blog/my-new-post.md This creates a boilerplate Markdown file in `content/blog/my-new-post.md` whose contents you can modify. The following fields are required: -* `title` -* `date` (in `YYYY-MM-DD` format) -* `author` +- `title` +- `date` (in `YYYY-MM-DD` format) +- `author` ### Adding scaler documentation @@ -82,10 +96,10 @@ This creates a boilerplate Markdown file in `content/docs//scalers/my-new-scaler.md` whose contents you can modify. Make sure to update the following metadata fields: -* `title` -* `availability` -* `maintainer` -* `description` +- `title` +- `availability` +- `maintainer` +- `description` ### Writing documentation for a new authentication provider @@ -99,7 +113,7 @@ This creates a boilerplate Markdown file in `content/docs//providers/my-new-provider.md` whose contents you can modify. Make sure to update the following metadata fields: -* `title` +- `title` ### Add new Frequently Asked Question (FAQ) @@ -143,13 +157,34 @@ Here are a few examples: ## Working with documentation versions The KEDA documentation is versioned. Each version has its own subdirectory under -[content/docs](content/docs). To add a new version, copy the directory for -the most recent version. Here's an example: +[content/docs](content/docs). To add a new version, follow these steps: + +1. Copy the directory for the most recent version. Here's an example: ```console $ cp -rf content/docs/ content/docs/ ``` +2. Copy the file for the most recent faq data in the `data` directory. Here's an example: + +```console +$ cp -rf data/faq data/faq +``` + +3. Navigate to the new faq file: + +```console +$ cd content/docs//reference/faq.md +``` + +4. Update the versionData option + +``` +{{< faq20 versionData="NEW_FAQ_FILE_NAME" >}} +``` + +Replace `NEW_FAQ_FILE_NAME` with the file name of the faq data for the new version. + By default, new documentation versions are not listed as available version so it's safe to make changes to them. After every release, the version will be published as new version. @@ -169,7 +204,7 @@ Ensure that compatibility matrix on `content/docs/{next-version}/operate/cluster Once a version is ready to be published, we must add the version to the `params.versions.docs` list in [config.toml](config.toml). -More recent versions should be placed first in the list (ordering *does* matter +More recent versions should be placed first in the list (ordering _does_ matter because the first element in that list is considered the latest version). > Note: Remember to [prepare the next version](#preparing-a-new-version). @@ -179,6 +214,7 @@ because the first element in that list is considered the latest version). ### Every commit needs to be signed The Developer Certificate of Origin (DCO) is a lightweight way for contributors to certify that they wrote or otherwise have the right to submit the code they are contributing to the project. Here is the full text of the DCO, reformatted for readability: + ``` By making a contribution to this project, I certify that: @@ -198,12 +234,14 @@ This is my commit message Signed-off-by: Random J Developer ``` + Git even has a `-s` command line option to append this automatically to your commit message: + ``` $ git commit -s -m 'This is my commit message' ``` -Each Pull Request is checked whether or not commits in a Pull Request do contain a valid Signed-off-by line. +Each Pull Request is checked whether or not commits in a Pull Request do contain a valid Signed-off-by line. ### I didn't sign my commit, now what?! @@ -259,7 +297,7 @@ FILTER_NAME = "filter_value" Replace FILTER_NAME with any desired name of your choice. Same applies to the value. 3. Navigate to the `list.lunr.json` file to edit: `cd layouts/_default/list.lunr.json`. -4. Open the file and go down to line 3. You will notice the format of the data represented in a key/value pair. Just before the closing parenthesis, append your new option like this: `"FILTER_NAME" $scalers.Params.FILTER_NAME`. +4. Open the file and go down to line 3. You will notice the format of the data represented in a key/value pair. Just before the closing parenthesis, append your new option like this: `"FILTER_NAME" $scalers.Params.FILTER_NAME`. Replace FILTER_NAME with the same name represented in the frontmatter (see step 2 above for reference). @@ -276,7 +314,7 @@ params = ["availability", "maintainer", "category", "type", "FILTER_NAME"] this.field("FILTER_NAME", { boost: 5, }); -``` +``` Replace FILTER_NAME with the same name represented in the frontmatter (see step 2 above for reference). @@ -291,7 +329,7 @@ parse[doc.title] = { availability: doc.availability, category: doc.category, type: doc.type, - FILTER_NAME: doc.FILTER_NAME + FILTER_NAME: doc.FILTER_NAME, }; ``` @@ -300,21 +338,22 @@ parse[doc.title] = { ```html
FILTER_NAME
- {{ $FILTER_NAME := slice }} - {{ range $scalers := where site.RegularPages ".CurrentSection.Title" "Scalers" }} - {{ with $scalers.Params.FILTER_NAME }} - {{ $FILTER_NAME = $categories | append ($scalers.Params.FILTER_NAME) }} - {{ $FILTER_NAME = uniq $FILTER_NAME }} - {{ end }} - {{ end }} - {{ range $FILTER_NAME }} - {{ $item := . }} + {{ $FILTER_NAME := slice }} {{ range $scalers := where site.RegularPages + ".CurrentSection.Title" "Scalers" }} {{ with $scalers.Params.FILTER_NAME }} {{ + $FILTER_NAME = $categories | append ($scalers.Params.FILTER_NAME) }} {{ + $FILTER_NAME = uniq $FILTER_NAME }} {{ end }} {{ end }} {{ range $FILTER_NAME + }} {{ $item := . }}
- - + +
{{ end }} -
+ ``` Replace FILTER_NAME with the same name represented in the frontmatter (see step 2 above for reference). @@ -324,4 +363,4 @@ Replace FILTER_NAME with the same name represented in the frontmatter (see step [localhost:8888]: http://localhost:8888 [LTS release]: https://nodejs.org/en/about/releases/ [Netlify]: https://netlify.com -[nvm]: https://github.com/nvm-sh/nvm/blob/master/README.md#installing-and-updating \ No newline at end of file +[nvm]: https://github.com/nvm-sh/nvm/blob/master/README.md#installing-and-updating diff --git a/content/docs/2.0/faq.md b/content/docs/2.0/faq.md index d012d6767..df84af22c 100644 --- a/content/docs/2.0/faq.md +++ b/content/docs/2.0/faq.md @@ -2,4 +2,4 @@ title = "FAQ" +++ -{{< faq20 >}} +{{< faq20 versionData="faq20" >}} diff --git a/content/docs/2.1/faq.md b/content/docs/2.1/faq.md index d012d6767..df84af22c 100644 --- a/content/docs/2.1/faq.md +++ b/content/docs/2.1/faq.md @@ -2,4 +2,4 @@ title = "FAQ" +++ -{{< faq20 >}} +{{< faq20 versionData="faq20" >}} diff --git a/content/docs/2.10/faq.md b/content/docs/2.10/faq.md index d012d6767..df84af22c 100644 --- a/content/docs/2.10/faq.md +++ b/content/docs/2.10/faq.md @@ -2,4 +2,4 @@ title = "FAQ" +++ -{{< faq20 >}} +{{< faq20 versionData="faq20" >}} diff --git a/content/docs/2.11/faq.md b/content/docs/2.11/faq.md index d012d6767..df84af22c 100644 --- a/content/docs/2.11/faq.md +++ b/content/docs/2.11/faq.md @@ -2,4 +2,4 @@ title = "FAQ" +++ -{{< faq20 >}} +{{< faq20 versionData="faq20" >}} diff --git a/content/docs/2.12/faq.md b/content/docs/2.12/faq.md index d012d6767..df84af22c 100644 --- a/content/docs/2.12/faq.md +++ b/content/docs/2.12/faq.md @@ -2,4 +2,4 @@ title = "FAQ" +++ -{{< faq20 >}} +{{< faq20 versionData="faq20" >}} diff --git a/content/docs/2.13/faq.md b/content/docs/2.13/faq.md index d012d6767..df84af22c 100644 --- a/content/docs/2.13/faq.md +++ b/content/docs/2.13/faq.md @@ -2,4 +2,4 @@ title = "FAQ" +++ -{{< faq20 >}} +{{< faq20 versionData="faq20" >}} diff --git a/content/docs/2.14/faq.md b/content/docs/2.14/faq.md index d012d6767..cffb0bd53 100644 --- a/content/docs/2.14/faq.md +++ b/content/docs/2.14/faq.md @@ -2,4 +2,4 @@ title = "FAQ" +++ -{{< faq20 >}} +{{< faq20 versionData="faq2_14" >}} diff --git a/content/docs/2.14/reference/faq.md b/content/docs/2.14/reference/faq.md index df75bbe78..995bfb24d 100644 --- a/content/docs/2.14/reference/faq.md +++ b/content/docs/2.14/reference/faq.md @@ -3,4 +3,4 @@ title = "FAQ" weight = 2000 +++ -{{< faq20 >}} +{{< faq20 versionData="faq2_14" >}} diff --git a/content/docs/2.15/reference/faq.md b/content/docs/2.15/reference/faq.md index df75bbe78..95365417f 100644 --- a/content/docs/2.15/reference/faq.md +++ b/content/docs/2.15/reference/faq.md @@ -3,4 +3,4 @@ title = "FAQ" weight = 2000 +++ -{{< faq20 >}} +{{< faq20 versionData="faq2_15" >}} diff --git a/content/docs/2.2/faq.md b/content/docs/2.2/faq.md index d012d6767..df84af22c 100644 --- a/content/docs/2.2/faq.md +++ b/content/docs/2.2/faq.md @@ -2,4 +2,4 @@ title = "FAQ" +++ -{{< faq20 >}} +{{< faq20 versionData="faq20" >}} diff --git a/content/docs/2.3/faq.md b/content/docs/2.3/faq.md index d012d6767..df84af22c 100644 --- a/content/docs/2.3/faq.md +++ b/content/docs/2.3/faq.md @@ -2,4 +2,4 @@ title = "FAQ" +++ -{{< faq20 >}} +{{< faq20 versionData="faq20" >}} diff --git a/content/docs/2.4/faq.md b/content/docs/2.4/faq.md index d012d6767..df84af22c 100644 --- a/content/docs/2.4/faq.md +++ b/content/docs/2.4/faq.md @@ -2,4 +2,4 @@ title = "FAQ" +++ -{{< faq20 >}} +{{< faq20 versionData="faq20" >}} diff --git a/content/docs/2.5/faq.md b/content/docs/2.5/faq.md index d012d6767..df84af22c 100644 --- a/content/docs/2.5/faq.md +++ b/content/docs/2.5/faq.md @@ -2,4 +2,4 @@ title = "FAQ" +++ -{{< faq20 >}} +{{< faq20 versionData="faq20" >}} diff --git a/content/docs/2.6/faq.md b/content/docs/2.6/faq.md index d012d6767..df84af22c 100644 --- a/content/docs/2.6/faq.md +++ b/content/docs/2.6/faq.md @@ -2,4 +2,4 @@ title = "FAQ" +++ -{{< faq20 >}} +{{< faq20 versionData="faq20" >}} diff --git a/content/docs/2.7/faq.md b/content/docs/2.7/faq.md index d012d6767..df84af22c 100644 --- a/content/docs/2.7/faq.md +++ b/content/docs/2.7/faq.md @@ -2,4 +2,4 @@ title = "FAQ" +++ -{{< faq20 >}} +{{< faq20 versionData="faq20" >}} diff --git a/content/docs/2.8/faq.md b/content/docs/2.8/faq.md index d012d6767..df84af22c 100644 --- a/content/docs/2.8/faq.md +++ b/content/docs/2.8/faq.md @@ -2,4 +2,4 @@ title = "FAQ" +++ -{{< faq20 >}} +{{< faq20 versionData="faq20" >}} diff --git a/content/docs/2.9/faq.md b/content/docs/2.9/faq.md index d012d6767..df84af22c 100644 --- a/content/docs/2.9/faq.md +++ b/content/docs/2.9/faq.md @@ -2,4 +2,4 @@ title = "FAQ" +++ -{{< faq20 >}} +{{< faq20 versionData="faq20" >}} diff --git a/data/faq2_14.toml b/data/faq2_14.toml new file mode 100644 index 000000000..95d1089e0 --- /dev/null +++ b/data/faq2_14.toml @@ -0,0 +1,217 @@ +[[qna]] +q = "What is KEDA and why is it useful?" +a = "KEDA stands for Kubernetes Event-driven Autoscaler. It is built to be able to activate a Kubernetes deployment (i.e. no pods to a single pod) and subsequently to more pods based on events from various event sources." +type = "General" + +[[qna]] +q = "What are the prerequisites for using KEDA?" +a = """ +KEDA is designed, tested and is supported to be run on any Kubernetes cluster that runs Kubernetes v1.17.0 or above. + +It uses a CRD (custom resource definition) and the Kubernetes metric server so you will have to use a Kubernetes version which supports these. + +> 💡 Kubernetes v1.16 is supported with KEDA v2.4.0 or below +""" +type = "General" + +[[qna]] +q = "Can KEDA be used in production?" +a = "Yes! KEDA v2.0 is suited for production workloads, but we still support v1.5 if you are running that as well.." +type = "General" + +[[qna]] +q = "What does it cost?" +a = "There is no charge for using KEDA itself, we just ask people to [become a listed user](https://github.com/kedacore/keda-docs#become-a-listed-keda-user) when possible." +type = "General" + +[[qna]] +q = "Can I scale HTTP workloads with KEDA and Kubernetes?" +a = """ +KEDA will scale a container using metrics from a scaler, but unfortunately there is no scaler today for HTTP workloads out-of-the-box. + +We do, however, provide some alternative approaches: +- Use our HTTP add-on scaler which is currently in experimental stage ([GitHub](https://github.com/kedacore/http-add-on)) +- Use [Prometheus scaler](/docs/latest/scalers/prometheus/) to create scale rule based on metrics around HTTP events + - Read [Anirudh Garg's blog post](https://dev.to/anirudhgarg_99/scale-up-and-down-a-http-triggered-function-app-in-kubernetes-using-keda-4m42) to learn more. +""" +type = "Features" + +[[qna]] +q = "Is short polling intervals a problem?" +a = "Polling interval really only impacts the time-to-activation (scaling from 0 to 1) but once scaled to one it's really up to the HPA (horizontal pod autoscaler) which polls KEDA." +type = "Features" + +[[qna]] +q = "Using multiple triggers for the same scale target" +a = """ +KEDA allows you to use multiple triggers as part of the same `ScaledObject` or `ScaledJob`. + +By doing this, your autoscaling becomes better: +- All your autoscaling rules are in one place +- You will not have multiple `ScaledObject`'s or `ScaledJob`'s interfering with each other + +KEDA will start scaling as soon as when one of the triggers meets the criteria. Horizontal Pod Autoscaler (HPA) will calculate metrics for every scaler and use the highest desired replica count to scale the workload to. +""" +type = "Best Practices" + +[[qna]] +q = "Don't combine `ScaledObject` with Horizontal Pod Autoscaler (HPA)" +a = """ +We recommend not to combine using KEDA's `ScaledObject` with a Horizontal Pod Autoscaler (HPA) to scale the same workload. + +They will compete with each other resulting given KEDA uses Horizontal Pod Autoscaler (HPA) under the hood and will result in odd scaling behavior. + +If you are using a Horizontal Pod Autoscaler (HPA) to scale on CPU and/or memory, we recommend using the [CPU scaler](/docs/latest/scalers/cpu/) & [Memory scaler](/docs/latest/scalers/memory/) scalers instead. +""" +type = "Best Practices" + +[[qna]] +q = "What does the target metric value in the Horizontal Pod Autoscaler (HPA) represent?" +a = """ +The target metric value is used by the Horizontal Pod Autoscaler (HPA) to make scaling decisions. + +The current target value on the Horizontal Pod Autoscaler (HPA) often does not match with the metrics on the system you are scaling on. This is because of how the Horizontal Pod Autoscaler's (HPA) [scaling algorithm](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#algorithm-details) works. + +By default, KEDA scalers use average metrics (the `AverageValue` metric type). This means that the HPA will use the average value of the metric between the total amount of pods. As of KEDA v2.7, ScaledObjects also support the `Value` metric type. You can learn more about it [here](https://keda.sh/docs/latest/concepts/scaling-deployments/#triggers). +""" +type = "Kubernetes" + +[[qna]] +q = "Why does KEDA use external metrics and not custom metrics instead?" +a = """ +Kubernetes allows you to autoscale based on custom & external metrics which are fundamentally different: +- **Custom metrics** are metrics that come from applications solely running on the Kubernetes cluster (Prometheus) +- **External metrics** are metrics that represent the state of an application/service that is running outside of the Kubernetes cluster (AWS, Azure, GCP, Datadog, etc.) + +Because KEDA primarily serves metrics for metric sources outside of the Kubernetes cluster, it uses external metrics and not custom metrics. + +This is why KEDA registers the `v1beta1.external.metrics.k8s.io` namespace in the API service. However, this is just an implementation detail as both offer the same functionality. + +Read [about the different metric APIs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#support-for-metrics-apis) or [this article](https://cloud.google.com/kubernetes-engine/docs/concepts/custom-and-external-metrics) by Google Cloud to learn more. +""" +type = "Kubernetes" + +[[qna]] +q = "Can I run multiple metric servers serving external metrics in the same cluster?" +a = """ +Unfortunately, you cannot do that. + +Kubernetes currently only supports one metric server serving `external.metrics.k8s.io` metrics per cluster. This is because only one API Service can be registered to handle external metrics. + +If you want to know what external metric server is currently registered, you can use the following command: + +```shell +~ kubectl get APIService/v1beta1.external.metrics.k8s.io +NAME SERVICE AVAILABLE AGE +v1beta1.external.metrics.k8s.io keda-system/keda-operator-metrics-apiserver True 457d +``` + +Once a new metric server is installed, it will overwrite the existing API Server registration and take over the `v1beta1.external.metrics.k8s.io` namespace. This will cause the previously installed metric server to be ignored. + +There is an [open proposal](https://github.com/kubernetes-sigs/custom-metrics-apiserver/issues/70) to allow multiple metric servers in the same cluster, but it's not implemented yet. +""" +type = "Kubernetes" + +[[qna]] +q = "Can I run multiple installations of KEDA in the same cluster?" +a = """ +Unfortunately, you cannot do that. + +This is a limitation that is because Kubernetes does not allow you to run multiple metric servers in the same cluster that serve external metrics. + +Also, KEDA does not allow you to share a single metric server across multiple operator installations. + +Learn more in the "Can I run multiple metric servers serving external metrics in the same cluster?" FAQ entry. +""" +type = "Kubernetes" + +[[qna]] +q = "How can I get involved?" +a = """ +There are several ways to get involved. + +* Pick up an issue to work on. A good place to start might be issues which are marked as [Good First Issue](https://github.com/kedacore/keda/labels/good%20first%20issue) or [Help Wanted](https://github.com/kedacore/keda/labels/help%20wanted) +* We are always looking to add more scalers. +* We are always looking for more samples, documentation, etc. +* Please join us in our [weekly standup](https://github.com/kedacore/keda#community). +""" +type = "Community" + +[[qna]] +q = "Where can I get to the code for the Scalers?" +a = "All scalers have their code [here](https://github.com/kedacore/keda/tree/main/pkg/scalers)." +type = "Community" + +[[qna]] +q = "How do I access KEDA resources using `client-go`?" +a = """KEDA client-go is exported as part of the KEDA repository.""" + +[[qna]] +q = "How do I run KEDA with `readOnlyRootFilesystem=true`?" +a = """ +As default, KEDA v2.10 or above sets `readOnlyRootFilesystem=true` as default without any other manual intervention. + +If you are running KEDA v2.9 or below, you can't run KEDA with `readOnlyRootFilesystem=true` as default because Metrics adapter generates self-signed certificates during deployment and stores them on the root file system. +To overcome this, you can create a secret/configmap with a valid CA, cert and key and then mount it to the Metrics Deployment. +To use your certificate, you need to reference it in the container `args` section, e.g.: +``` +args: + - '--client-ca-file=/cabundle/service-ca.crt' + - '--tls-cert-file=/certs/tls.crt' + - '--tls-private-key-file=/certs/tls.key' +``` +It is also possible to run KEDA with `readOnlyRootFilesystem=true` by creating an emptyDir volume and mounting it to the path where, +by default, metrics server writes its generated cert. The corresponding helm command is: +``` +helm install keda kedacore/keda --namespace keda \ + --set 'volumes.metricsApiServer.extraVolumes[0].name=keda-volume' \ + --set 'volumes.metricsApiServer.extraVolumeMounts[0].name=keda-volume' \ + --set 'volumes.metricsApiServer.extraVolumeMounts[0].mountPath=/apiserver.local.config/certificates/' \ + --set 'securityContext.metricServer.readOnlyRootFilesystem=true' +``` +""" +type = "Features" + +[[qna]] +q = "How do I run KEDA with TLS v1.3 only?" +a = """ +By default, Keda listens on TLS v1.1 and TLSv1.2, with the default Golang ciphersuites. +In some environments, these ciphers may be considered less secure, for example CBC ciphers. + +As an alternative, you can configure the minimum TLS version to be v1.3 to increase security. +Since all modern clients support this version, there should be no impact in most scenarios. + +You can set this with args - e.g.: +``` +args: + - '--tls-min-version=VersionTLS13' +``` +""" +type = "Features" + +[[qna]] +q = "Does KEDA depend on any Azure service?" +a = "No, KEDA only takes a dependency on standard Kubernetes constructs and can run on any Kubernetes cluster whether in OpenShift, AKS, GKE, EKS or your own infrastructure." +type = "Azure" + +[[qna]] +q = "Does KEDA only work with Azure Functions?" +a = "No, KEDA can scale up/down any container that you specify in your deployment. There has been work done in the Azure Functions tooling to make it easy to scale an Azure Function container." +type = "Azure" + +[[qna]] +q = "Why should we use KEDA if we are already using Azure Functions in Azure?" +a = """ +There are a few reasons for this: + +* Run functions on-premises (potentially in something like an 'intelligent edge' architecture) +* Run functions alongside other Kubernetes apps (maybe in a restricted network, app mesh, custom environment, etc.) +* Run functions outside of Azure (no vendor lock-in) +* Specific need for more control (GPU enabled compute clusters, policies, etc.) +""" +type = "Azure" + +[[qna]] +q = "Does scaler search support wildcard search?" +a = "Yes. The search actually supports wildcard search. We've made our search to automatically perform wildcard filtering on the fly so you don't have to append special symbols within your search query." +type = "Website" diff --git a/data/faq2_15.toml b/data/faq2_15.toml new file mode 100644 index 000000000..95d1089e0 --- /dev/null +++ b/data/faq2_15.toml @@ -0,0 +1,217 @@ +[[qna]] +q = "What is KEDA and why is it useful?" +a = "KEDA stands for Kubernetes Event-driven Autoscaler. It is built to be able to activate a Kubernetes deployment (i.e. no pods to a single pod) and subsequently to more pods based on events from various event sources." +type = "General" + +[[qna]] +q = "What are the prerequisites for using KEDA?" +a = """ +KEDA is designed, tested and is supported to be run on any Kubernetes cluster that runs Kubernetes v1.17.0 or above. + +It uses a CRD (custom resource definition) and the Kubernetes metric server so you will have to use a Kubernetes version which supports these. + +> 💡 Kubernetes v1.16 is supported with KEDA v2.4.0 or below +""" +type = "General" + +[[qna]] +q = "Can KEDA be used in production?" +a = "Yes! KEDA v2.0 is suited for production workloads, but we still support v1.5 if you are running that as well.." +type = "General" + +[[qna]] +q = "What does it cost?" +a = "There is no charge for using KEDA itself, we just ask people to [become a listed user](https://github.com/kedacore/keda-docs#become-a-listed-keda-user) when possible." +type = "General" + +[[qna]] +q = "Can I scale HTTP workloads with KEDA and Kubernetes?" +a = """ +KEDA will scale a container using metrics from a scaler, but unfortunately there is no scaler today for HTTP workloads out-of-the-box. + +We do, however, provide some alternative approaches: +- Use our HTTP add-on scaler which is currently in experimental stage ([GitHub](https://github.com/kedacore/http-add-on)) +- Use [Prometheus scaler](/docs/latest/scalers/prometheus/) to create scale rule based on metrics around HTTP events + - Read [Anirudh Garg's blog post](https://dev.to/anirudhgarg_99/scale-up-and-down-a-http-triggered-function-app-in-kubernetes-using-keda-4m42) to learn more. +""" +type = "Features" + +[[qna]] +q = "Is short polling intervals a problem?" +a = "Polling interval really only impacts the time-to-activation (scaling from 0 to 1) but once scaled to one it's really up to the HPA (horizontal pod autoscaler) which polls KEDA." +type = "Features" + +[[qna]] +q = "Using multiple triggers for the same scale target" +a = """ +KEDA allows you to use multiple triggers as part of the same `ScaledObject` or `ScaledJob`. + +By doing this, your autoscaling becomes better: +- All your autoscaling rules are in one place +- You will not have multiple `ScaledObject`'s or `ScaledJob`'s interfering with each other + +KEDA will start scaling as soon as when one of the triggers meets the criteria. Horizontal Pod Autoscaler (HPA) will calculate metrics for every scaler and use the highest desired replica count to scale the workload to. +""" +type = "Best Practices" + +[[qna]] +q = "Don't combine `ScaledObject` with Horizontal Pod Autoscaler (HPA)" +a = """ +We recommend not to combine using KEDA's `ScaledObject` with a Horizontal Pod Autoscaler (HPA) to scale the same workload. + +They will compete with each other resulting given KEDA uses Horizontal Pod Autoscaler (HPA) under the hood and will result in odd scaling behavior. + +If you are using a Horizontal Pod Autoscaler (HPA) to scale on CPU and/or memory, we recommend using the [CPU scaler](/docs/latest/scalers/cpu/) & [Memory scaler](/docs/latest/scalers/memory/) scalers instead. +""" +type = "Best Practices" + +[[qna]] +q = "What does the target metric value in the Horizontal Pod Autoscaler (HPA) represent?" +a = """ +The target metric value is used by the Horizontal Pod Autoscaler (HPA) to make scaling decisions. + +The current target value on the Horizontal Pod Autoscaler (HPA) often does not match with the metrics on the system you are scaling on. This is because of how the Horizontal Pod Autoscaler's (HPA) [scaling algorithm](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#algorithm-details) works. + +By default, KEDA scalers use average metrics (the `AverageValue` metric type). This means that the HPA will use the average value of the metric between the total amount of pods. As of KEDA v2.7, ScaledObjects also support the `Value` metric type. You can learn more about it [here](https://keda.sh/docs/latest/concepts/scaling-deployments/#triggers). +""" +type = "Kubernetes" + +[[qna]] +q = "Why does KEDA use external metrics and not custom metrics instead?" +a = """ +Kubernetes allows you to autoscale based on custom & external metrics which are fundamentally different: +- **Custom metrics** are metrics that come from applications solely running on the Kubernetes cluster (Prometheus) +- **External metrics** are metrics that represent the state of an application/service that is running outside of the Kubernetes cluster (AWS, Azure, GCP, Datadog, etc.) + +Because KEDA primarily serves metrics for metric sources outside of the Kubernetes cluster, it uses external metrics and not custom metrics. + +This is why KEDA registers the `v1beta1.external.metrics.k8s.io` namespace in the API service. However, this is just an implementation detail as both offer the same functionality. + +Read [about the different metric APIs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#support-for-metrics-apis) or [this article](https://cloud.google.com/kubernetes-engine/docs/concepts/custom-and-external-metrics) by Google Cloud to learn more. +""" +type = "Kubernetes" + +[[qna]] +q = "Can I run multiple metric servers serving external metrics in the same cluster?" +a = """ +Unfortunately, you cannot do that. + +Kubernetes currently only supports one metric server serving `external.metrics.k8s.io` metrics per cluster. This is because only one API Service can be registered to handle external metrics. + +If you want to know what external metric server is currently registered, you can use the following command: + +```shell +~ kubectl get APIService/v1beta1.external.metrics.k8s.io +NAME SERVICE AVAILABLE AGE +v1beta1.external.metrics.k8s.io keda-system/keda-operator-metrics-apiserver True 457d +``` + +Once a new metric server is installed, it will overwrite the existing API Server registration and take over the `v1beta1.external.metrics.k8s.io` namespace. This will cause the previously installed metric server to be ignored. + +There is an [open proposal](https://github.com/kubernetes-sigs/custom-metrics-apiserver/issues/70) to allow multiple metric servers in the same cluster, but it's not implemented yet. +""" +type = "Kubernetes" + +[[qna]] +q = "Can I run multiple installations of KEDA in the same cluster?" +a = """ +Unfortunately, you cannot do that. + +This is a limitation that is because Kubernetes does not allow you to run multiple metric servers in the same cluster that serve external metrics. + +Also, KEDA does not allow you to share a single metric server across multiple operator installations. + +Learn more in the "Can I run multiple metric servers serving external metrics in the same cluster?" FAQ entry. +""" +type = "Kubernetes" + +[[qna]] +q = "How can I get involved?" +a = """ +There are several ways to get involved. + +* Pick up an issue to work on. A good place to start might be issues which are marked as [Good First Issue](https://github.com/kedacore/keda/labels/good%20first%20issue) or [Help Wanted](https://github.com/kedacore/keda/labels/help%20wanted) +* We are always looking to add more scalers. +* We are always looking for more samples, documentation, etc. +* Please join us in our [weekly standup](https://github.com/kedacore/keda#community). +""" +type = "Community" + +[[qna]] +q = "Where can I get to the code for the Scalers?" +a = "All scalers have their code [here](https://github.com/kedacore/keda/tree/main/pkg/scalers)." +type = "Community" + +[[qna]] +q = "How do I access KEDA resources using `client-go`?" +a = """KEDA client-go is exported as part of the KEDA repository.""" + +[[qna]] +q = "How do I run KEDA with `readOnlyRootFilesystem=true`?" +a = """ +As default, KEDA v2.10 or above sets `readOnlyRootFilesystem=true` as default without any other manual intervention. + +If you are running KEDA v2.9 or below, you can't run KEDA with `readOnlyRootFilesystem=true` as default because Metrics adapter generates self-signed certificates during deployment and stores them on the root file system. +To overcome this, you can create a secret/configmap with a valid CA, cert and key and then mount it to the Metrics Deployment. +To use your certificate, you need to reference it in the container `args` section, e.g.: +``` +args: + - '--client-ca-file=/cabundle/service-ca.crt' + - '--tls-cert-file=/certs/tls.crt' + - '--tls-private-key-file=/certs/tls.key' +``` +It is also possible to run KEDA with `readOnlyRootFilesystem=true` by creating an emptyDir volume and mounting it to the path where, +by default, metrics server writes its generated cert. The corresponding helm command is: +``` +helm install keda kedacore/keda --namespace keda \ + --set 'volumes.metricsApiServer.extraVolumes[0].name=keda-volume' \ + --set 'volumes.metricsApiServer.extraVolumeMounts[0].name=keda-volume' \ + --set 'volumes.metricsApiServer.extraVolumeMounts[0].mountPath=/apiserver.local.config/certificates/' \ + --set 'securityContext.metricServer.readOnlyRootFilesystem=true' +``` +""" +type = "Features" + +[[qna]] +q = "How do I run KEDA with TLS v1.3 only?" +a = """ +By default, Keda listens on TLS v1.1 and TLSv1.2, with the default Golang ciphersuites. +In some environments, these ciphers may be considered less secure, for example CBC ciphers. + +As an alternative, you can configure the minimum TLS version to be v1.3 to increase security. +Since all modern clients support this version, there should be no impact in most scenarios. + +You can set this with args - e.g.: +``` +args: + - '--tls-min-version=VersionTLS13' +``` +""" +type = "Features" + +[[qna]] +q = "Does KEDA depend on any Azure service?" +a = "No, KEDA only takes a dependency on standard Kubernetes constructs and can run on any Kubernetes cluster whether in OpenShift, AKS, GKE, EKS or your own infrastructure." +type = "Azure" + +[[qna]] +q = "Does KEDA only work with Azure Functions?" +a = "No, KEDA can scale up/down any container that you specify in your deployment. There has been work done in the Azure Functions tooling to make it easy to scale an Azure Function container." +type = "Azure" + +[[qna]] +q = "Why should we use KEDA if we are already using Azure Functions in Azure?" +a = """ +There are a few reasons for this: + +* Run functions on-premises (potentially in something like an 'intelligent edge' architecture) +* Run functions alongside other Kubernetes apps (maybe in a restricted network, app mesh, custom environment, etc.) +* Run functions outside of Azure (no vendor lock-in) +* Specific need for more control (GPU enabled compute clusters, policies, etc.) +""" +type = "Azure" + +[[qna]] +q = "Does scaler search support wildcard search?" +a = "Yes. The search actually supports wildcard search. We've made our search to automatically perform wildcard filtering on the fly so you don't have to append special symbols within your search query." +type = "Website" diff --git a/layouts/shortcodes/faq20.html b/layouts/shortcodes/faq20.html index 75c294338..c26bdcd69 100644 --- a/layouts/shortcodes/faq20.html +++ b/layouts/shortcodes/faq20.html @@ -1,4 +1,10 @@ -{{ $faq20 := site.Data.faq20.qna }} +{{ $filename := .Get "versionData" }} +{{ range index .Site.Data $filename }} + {{ $.Scratch.Add "faq20" . }} +{{ end }} + +{{ $faq20 := $.Scratch.Get "faq20" }} +

General

From ddd894deaf34e797e51fd39fea77184f2479e3aa Mon Sep 17 00:00:00 2001 From: Zbynek Roubalik Date: Mon, 8 Jul 2024 19:32:07 +0200 Subject: [PATCH 16/33] Update Kedify link (#1421) Signed-off-by: Zbynek Roubalik Signed-off-by: shubhusion --- config.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.toml b/config.toml index fe27d32f0..30e16a5af 100644 --- a/config.toml +++ b/config.toml @@ -643,5 +643,5 @@ logo = "vendors/azure-kubernetes-service.png" [[params.vendors]] name = "Kedify" -url = "https://kedify.io" +url = "https://kedify.io/?utm_source=keda_oss_site" logo = "vendors/kedify.png" From 7f49ce0ce2773a75b4582422ba7637e1f67bebe6 Mon Sep 17 00:00:00 2001 From: Tom Kerkhove Date: Tue, 9 Jul 2024 09:25:04 +0200 Subject: [PATCH 17/33] fix: Align Kedify links (#1422) Signed-off-by: Tom Kerkhove Signed-off-by: shubhusion --- config.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.toml b/config.toml index 30e16a5af..4e9a32197 100644 --- a/config.toml +++ b/config.toml @@ -593,7 +593,7 @@ logo = "zapier.png" # "Partners" section on the Community page [[params.partners]] -url = "https://kedify.io" +url = "https://kedify.io/?utm_source=keda_oss_site" logo = "kedify.png" [[params.partners]] From eedd10ebd10cb6f4f4156f579854776b7368de98 Mon Sep 17 00:00:00 2001 From: Uchechukwu Obasi Date: Wed, 10 Jul 2024 13:39:57 +0100 Subject: [PATCH 18/33] chore: fix faq version dropdown in older versions (#1423) Signed-off-by: shubhusion --- content/docs/1.4/{ => reference}/faq.md | 0 content/docs/1.5/{ => reference}/faq.md | 0 content/docs/2.0/{ => reference}/faq.md | 0 content/docs/2.1/{ => reference}/faq.md | 0 content/docs/2.10/{ => reference}/faq.md | 0 content/docs/2.11/{ => reference}/faq.md | 0 content/docs/2.12/{ => reference}/faq.md | 0 content/docs/2.13/{ => reference}/faq.md | 0 content/docs/2.2/{ => reference}/faq.md | 0 content/docs/2.3/{ => reference}/faq.md | 0 content/docs/2.4/{ => reference}/faq.md | 0 content/docs/2.5/{ => reference}/faq.md | 0 content/docs/2.6/{ => reference}/faq.md | 0 content/docs/2.7/{ => reference}/faq.md | 0 content/docs/2.8/{ => reference}/faq.md | 0 content/docs/2.9/{ => reference}/faq.md | 0 layouts/shortcodes/faq20.html | 1 - 17 files changed, 1 deletion(-) rename content/docs/1.4/{ => reference}/faq.md (100%) rename content/docs/1.5/{ => reference}/faq.md (100%) rename content/docs/2.0/{ => reference}/faq.md (100%) rename content/docs/2.1/{ => reference}/faq.md (100%) rename content/docs/2.10/{ => reference}/faq.md (100%) rename content/docs/2.11/{ => reference}/faq.md (100%) rename content/docs/2.12/{ => reference}/faq.md (100%) rename content/docs/2.13/{ => reference}/faq.md (100%) rename content/docs/2.2/{ => reference}/faq.md (100%) rename content/docs/2.3/{ => reference}/faq.md (100%) rename content/docs/2.4/{ => reference}/faq.md (100%) rename content/docs/2.5/{ => reference}/faq.md (100%) rename content/docs/2.6/{ => reference}/faq.md (100%) rename content/docs/2.7/{ => reference}/faq.md (100%) rename content/docs/2.8/{ => reference}/faq.md (100%) rename content/docs/2.9/{ => reference}/faq.md (100%) diff --git a/content/docs/1.4/faq.md b/content/docs/1.4/reference/faq.md similarity index 100% rename from content/docs/1.4/faq.md rename to content/docs/1.4/reference/faq.md diff --git a/content/docs/1.5/faq.md b/content/docs/1.5/reference/faq.md similarity index 100% rename from content/docs/1.5/faq.md rename to content/docs/1.5/reference/faq.md diff --git a/content/docs/2.0/faq.md b/content/docs/2.0/reference/faq.md similarity index 100% rename from content/docs/2.0/faq.md rename to content/docs/2.0/reference/faq.md diff --git a/content/docs/2.1/faq.md b/content/docs/2.1/reference/faq.md similarity index 100% rename from content/docs/2.1/faq.md rename to content/docs/2.1/reference/faq.md diff --git a/content/docs/2.10/faq.md b/content/docs/2.10/reference/faq.md similarity index 100% rename from content/docs/2.10/faq.md rename to content/docs/2.10/reference/faq.md diff --git a/content/docs/2.11/faq.md b/content/docs/2.11/reference/faq.md similarity index 100% rename from content/docs/2.11/faq.md rename to content/docs/2.11/reference/faq.md diff --git a/content/docs/2.12/faq.md b/content/docs/2.12/reference/faq.md similarity index 100% rename from content/docs/2.12/faq.md rename to content/docs/2.12/reference/faq.md diff --git a/content/docs/2.13/faq.md b/content/docs/2.13/reference/faq.md similarity index 100% rename from content/docs/2.13/faq.md rename to content/docs/2.13/reference/faq.md diff --git a/content/docs/2.2/faq.md b/content/docs/2.2/reference/faq.md similarity index 100% rename from content/docs/2.2/faq.md rename to content/docs/2.2/reference/faq.md diff --git a/content/docs/2.3/faq.md b/content/docs/2.3/reference/faq.md similarity index 100% rename from content/docs/2.3/faq.md rename to content/docs/2.3/reference/faq.md diff --git a/content/docs/2.4/faq.md b/content/docs/2.4/reference/faq.md similarity index 100% rename from content/docs/2.4/faq.md rename to content/docs/2.4/reference/faq.md diff --git a/content/docs/2.5/faq.md b/content/docs/2.5/reference/faq.md similarity index 100% rename from content/docs/2.5/faq.md rename to content/docs/2.5/reference/faq.md diff --git a/content/docs/2.6/faq.md b/content/docs/2.6/reference/faq.md similarity index 100% rename from content/docs/2.6/faq.md rename to content/docs/2.6/reference/faq.md diff --git a/content/docs/2.7/faq.md b/content/docs/2.7/reference/faq.md similarity index 100% rename from content/docs/2.7/faq.md rename to content/docs/2.7/reference/faq.md diff --git a/content/docs/2.8/faq.md b/content/docs/2.8/reference/faq.md similarity index 100% rename from content/docs/2.8/faq.md rename to content/docs/2.8/reference/faq.md diff --git a/content/docs/2.9/faq.md b/content/docs/2.9/reference/faq.md similarity index 100% rename from content/docs/2.9/faq.md rename to content/docs/2.9/reference/faq.md diff --git a/layouts/shortcodes/faq20.html b/layouts/shortcodes/faq20.html index c26bdcd69..79be1a78a 100644 --- a/layouts/shortcodes/faq20.html +++ b/layouts/shortcodes/faq20.html @@ -5,7 +5,6 @@ {{ $faq20 := $.Scratch.Get "faq20" }} -

General

{{ range where $faq20 ".type" "==" "General" }} From cabfc599ec5439dd9064e4ca9d8fd352354fa97c Mon Sep 17 00:00:00 2001 From: SpiritZhou Date: Thu, 11 Jul 2024 14:39:46 +0800 Subject: [PATCH 19/33] Update (#1420) Signed-off-by: SpiritZhou Signed-off-by: shubhusion --- content/docs/2.15/operate/cloud-events.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/content/docs/2.15/operate/cloud-events.md b/content/docs/2.15/operate/cloud-events.md index e07dc0505..ad46c74f1 100644 --- a/content/docs/2.15/operate/cloud-events.md +++ b/content/docs/2.15/operate/cloud-events.md @@ -113,4 +113,5 @@ eventSubscription: #Optional. Submit included/excluded event types will filter e | Event Type | Scenario Description | |-------------------------------|-----------------------------------------------------------------------------------------------------------------------------| | `keda.scaledobject.ready.v1` | On the first time a ScaledObject is ready, or if the previous ready condition status of the object was `Unknown` or `False` | -| `keda.scaledobject.failed.v1` | If the check validation for a ScaledObject fails | +| `keda.scaledobject.failed.v1` | If the check validation for a ScaledObject fails | +| `keda.scaledobject.removed.v1`| When a ScaledObject is deleted | From c868e70e5647449848cfab3d6dd278f9dbc3b606 Mon Sep 17 00:00:00 2001 From: Zbynek Roubalik Date: Fri, 12 Jul 2024 11:13:40 +0200 Subject: [PATCH 20/33] Add lightweight Scarf analytics pixel to thewebsite (#1426) Signed-off-by: shubhusion --- layouts/index.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/layouts/index.html b/layouts/index.html index 66857cddc..b51911fde 100644 --- a/layouts/index.html +++ b/layouts/index.html @@ -17,4 +17,6 @@ {{ partial "home/get-involved.html" . }} {{ partial "home/cncf.html" . }} + + {{ end -}} From 4c84e5e7cf8c00a44d6f01de67d991954cbae4d4 Mon Sep 17 00:00:00 2001 From: Zbynek Roubalik Date: Fri, 12 Jul 2024 19:29:28 +0200 Subject: [PATCH 21/33] put tracking pixel into correct location (#1427) Signed-off-by: Zbynek Roubalik Signed-off-by: shubhusion --- layouts/partials/footer.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layouts/partials/footer.html b/layouts/partials/footer.html index e29de702a..b76a955b5 100644 --- a/layouts/partials/footer.html +++ b/layouts/partials/footer.html @@ -40,7 +40,7 @@

© KEDA Authors 2014-{{ $year }} | Documentation Distributed under CC-BY-4.0

- +

From 4080c9174429f9a2790afb4a4c498125007dc763 Mon Sep 17 00:00:00 2001 From: Zbynek Roubalik Date: Tue, 16 Jul 2024 17:07:26 +0200 Subject: [PATCH 22/33] navbar + hero refactor (#1428) Signed-off-by: shubhusion --- config.toml | 25 +++++++++++++++++++++---- layouts/partials/navbar.html | 4 ++-- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/config.toml b/config.toml index 4e9a32197..5ddbe7389 100644 --- a/config.toml +++ b/config.toml @@ -175,29 +175,41 @@ name = "Architecture" parent = "docs" weight = 3 +[[menu.docs]] +url = "/docs/scalers" +name = "Scalers" +parent = "docs" +weight = 4 + [[menu.docs]] url = "/docs/operate/" name = "Operate" parent = "docs" -weight = 4 +weight = 5 + +[[menu.docs]] +url = "/docs/authentication-providers" +name = "Auth providers" +parent = "docs" +weight = 6 [[menu.docs]] url = "/docs/migration/" name = "Migration Guide" parent = "docs" -weight = 5 +weight = 7 [[menu.docs]] url = "/docs/reference/faq/" name = "FAQ" parent = "docs" -weight = 6 +weight = 8 [[menu.docs]] url = "/docs/troubleshooting/" name = "Troubleshooting" parent = "docs" -weight = 7 +weight = 9 [[menu.main]] url = "/blog" @@ -328,6 +340,11 @@ name = "Merch" parent = "project" weight = 12 +[[menu.main]] +url = "/support/" +name = "Support" +weight = 5 + # "Features" section on the main page [[params.features]] title = "Autoscaling Made Simple" diff --git a/layouts/partials/navbar.html b/layouts/partials/navbar.html index 09372c3e2..2d1cc8dbc 100644 --- a/layouts/partials/navbar.html +++ b/layouts/partials/navbar.html @@ -33,13 +33,13 @@

-