From 4fec9528439d9229e81d4c0c14a05623799e9029 Mon Sep 17 00:00:00 2001
From: Tapajit Chandra Paul <33987732+tapojit047@users.noreply.github.com>
Date: Thu, 14 Nov 2024 14:09:03 +0600
Subject: [PATCH] Add Druid Complete Docs (#699)
* Add druid concepts
Signed-off-by: Tapajit Chandra Paul
---
docs/guides/README.md | 2 +-
docs/guides/druid/README.md | 60 +-
docs/guides/druid/autoscaler/_index.md | 10 +
.../guides/druid/autoscaler/compute/_index.md | 10 +
docs/guides/druid/autoscaler/compute/guide.md | 864 +++++++++
.../compute/images/compute-autoscaling.png | Bin 0 -> 65595 bytes
.../druid/autoscaler/compute/overview.md | 55 +
.../compute/yamls/deep-storage-config.yaml | 16 +
.../compute/yamls/druid-autoscaler.yaml | 31 +
.../compute/yamls/druid-cluster.yaml | 31 +
.../guides/druid/autoscaler/storage/_index.md | 10 +
docs/guides/druid/autoscaler/storage/guide.md | 896 ++++++++++
.../storage/images/storage-autoscaling.png | Bin 0 -> 66996 bytes
.../druid/autoscaler/storage/overview.md | 55 +
.../storage/yamls/deep-storage-config.yaml | 16 +
.../storage/yamls/druid-cluster.yaml | 40 +
.../yamls/druid-storage-autoscaler.yaml | 19 +
docs/guides/druid/backup/_index.md | 2 +-
.../druid/backup/application-level/index.md | 3 +-
docs/guides/druid/backup/auto-backup/index.md | 2 +-
.../backup/cross-ns-dependencies/index.md | 2 +-
docs/guides/druid/backup/logical/index.md | 2 +-
docs/guides/druid/backup/overview/index.md | 2 +-
docs/guides/druid/clustering/_index.md | 10 +
docs/guides/druid/clustering/guide/index.md | 925 ++++++++++
.../guide/yamls/deep-storage-config.yaml | 16 +
.../clustering/guide/yamls/druid-cluster.yaml | 15 +
.../overview/images/druid-architecture.svg | 19 +
.../guides/druid/clustering/overview/index.md | 115 ++
docs/guides/druid/concepts/_index.md | 2 +-
docs/guides/druid/concepts/appbinding.md | 277 +--
docs/guides/druid/concepts/catalog.md | 111 --
docs/guides/druid/concepts/druid.md | 679 +++++---
docs/guides/druid/concepts/druidautoscaler.md | 132 ++
docs/guides/druid/concepts/druidopsrequest.md | 473 +++++
docs/guides/druid/concepts/druidversion.md | 102 ++
docs/guides/druid/configuration/_index.md | 10 +
.../config-file/images/druid-updated-ui.png | Bin 0 -> 48477 bytes
.../druid/configuration/config-file/index.md | 284 +++
.../config-file/yamls/config-secret.yaml | 10 +
.../yamls/deep-storage-config.yaml | 16 +
.../config-file/yamls/druid-with-config.yaml | 17 +
.../configuration/podtemplating/index.md | 618 +++++++
.../yamls/deep-storage-config.yaml | 16 +
.../podtemplating/yamls/druid-cluster.yaml | 43 +
.../yamls/druid-node-selector.yaml | 20 +
.../yamls/druid-with-tolerations.yaml | 58 +
.../yamls/druid-without-tolerations.yaml | 15 +
docs/guides/druid/monitoring/_index.md | 10 +
.../monitoring/images/druid-monitoring.png | Bin 0 -> 68080 bytes
.../monitoring/images/druid-prometheus.png | Bin 0 -> 209966 bytes
docs/guides/druid/monitoring/overview.md | 139 ++
.../monitoring/using-builtin-prometheus.md | 372 ++++
.../monitoring/using-prometheus-operator.md | 343 ++++
.../monitoring/yamls/deep-storage-config.yaml | 16 +
.../yamls/druid-monitoring-builtin.yaml | 24 +
.../yamls/druid-with-monitoring.yaml | 23 +
docs/guides/druid/quickstart/_index.md | 2 +-
.../quickstart/{overview => guide}/index.md | 12 +-
docs/guides/druid/reconfigure-tls/_index.md | 10 +
docs/guides/druid/reconfigure-tls/guide.md | 1539 +++++++++++++++++
.../druid/reconfigure-tls/images/druid-ui.png | Bin 0 -> 46148 bytes
.../reconfigure-tls/images/druid-with-tls.png | Bin 0 -> 99499 bytes
.../images/druid-without-tls.png | Bin 0 -> 114409 bytes
.../images/reconfigure-tls.png | Bin 0 -> 37055 bytes
docs/guides/druid/reconfigure-tls/overview.md | 54 +
.../yamls/deep-storage-config.yaml | 16 +
.../reconfigure-tls/yamls/drops-add-tls.yaml | 23 +
.../reconfigure-tls/yamls/drops-remove.yaml | 11 +
.../reconfigure-tls/yamls/drops-rotate.yaml | 11 +
.../yamls/druid-ca-issuer.yaml | 8 +
.../reconfigure-tls/yamls/druid-cluster.yaml | 16 +
.../yamls/druid-new-issuer.yaml | 8 +
.../yamls/druid-update-tls-issuer.yaml | 14 +
docs/guides/druid/reconfigure/_index.md | 10 +
docs/guides/druid/reconfigure/guide.md | 704 ++++++++
.../druid/reconfigure/images/druid-ui.png | Bin 0 -> 47241 bytes
.../druid/reconfigure/images/reconfigure.svg | 120 ++
docs/guides/druid/reconfigure/overview.md | 54 +
.../reconfigure/yamls/config-secret.yaml | 10 +
.../yamls/deep-storage-config.yaml | 16 +
.../reconfigure/yamls/druid-cluster.yaml | 15 +
.../yamls/reconfigure-druid-ops.yaml | 12 +
docs/guides/druid/restart/_index.md | 10 +
docs/guides/druid/restart/guide.md | 283 +++
.../restart/yamls/deep-storage-config.yaml | 16 +
.../druid/restart/yamls/druid-cluster.yaml | 16 +
docs/guides/druid/restart/yamls/restart.yaml | 11 +
docs/guides/druid/scaling/_index.md | 10 +
.../scaling/horizontal-scaling/_index.md | 10 +
.../druid/scaling/horizontal-scaling/guide.md | 603 +++++++
.../images/dr-horizontal-scaling.png | Bin 0 -> 68725 bytes
.../images/druid-ui-scaled-up.png | Bin 0 -> 52430 bytes
.../horizontal-scaling/images/druid-ui.png | Bin 0 -> 46148 bytes
.../scaling/horizontal-scaling/overview.md | 54 +
.../yamls/deep-storage-config.yaml | 16 +
.../yamls/druid-cluster.yaml | 16 +
.../yamls/druid-hscale-down.yaml | 13 +
.../yamls/druid-hscale-up.yaml | 13 +
.../druid/scaling/vertical-scaling/_index.md | 10 +
.../druid/scaling/vertical-scaling/guide.md | 454 +++++
.../images/dr-vertical-scaling.png | Bin 0 -> 73609 bytes
.../scaling/vertical-scaling/overview.md | 54 +
.../yamls/deep-storage-config.yaml | 16 +
.../vertical-scaling/yamls/druid-cluster.yaml | 15 +
.../vertical-scaling/yamls/druid-vscale.yaml | 28 +
docs/guides/druid/tls/_index.md | 10 +
docs/guides/druid/tls/guide.md | 307 ++++
docs/guides/druid/tls/images/druid-ui.png | Bin 0 -> 99499 bytes
docs/guides/druid/tls/images/tls.png | Bin 0 -> 41254 bytes
docs/guides/druid/tls/overview.md | 70 +
.../druid/tls/yamls/deep-storage-config.yaml | 16 +
.../druid/tls/yamls/druid-ca-issuer.yaml | 8 +
.../druid/tls/yamls/druid-cluster-tls.yaml | 21 +
docs/guides/druid/update-version/_index.md | 10 +
docs/guides/druid/update-version/guide.md | 448 +++++
.../images/dr-update-version.png | Bin 0 -> 73376 bytes
.../update-version/images/druid-ui-28.png | Bin 0 -> 46732 bytes
.../update-version/images/druid-ui-30.png | Bin 0 -> 48517 bytes
docs/guides/druid/update-version/overview.md | 53 +
.../yamls/deep-storage-config.yaml | 16 +
.../update-version/yamls/druid-cluster.yaml | 15 +
.../yamls/update-version-ops.yaml | 13 +
docs/guides/druid/volume-expansion/_index.md | 10 +
docs/guides/druid/volume-expansion/guide.md | 498 ++++++
.../images/druid-volume-expansion.png | Bin 0 -> 76116 bytes
.../guides/druid/volume-expansion/overview.md | 56 +
.../yamls/deep-storage-config.yaml | 16 +
.../volume-expansion/yamls/druid-cluster.yaml | 34 +
.../yamls/volume-expansion-ops.yaml | 13 +
130 files changed, 12370 insertions(+), 595 deletions(-)
create mode 100644 docs/guides/druid/autoscaler/_index.md
create mode 100644 docs/guides/druid/autoscaler/compute/_index.md
create mode 100644 docs/guides/druid/autoscaler/compute/guide.md
create mode 100644 docs/guides/druid/autoscaler/compute/images/compute-autoscaling.png
create mode 100644 docs/guides/druid/autoscaler/compute/overview.md
create mode 100644 docs/guides/druid/autoscaler/compute/yamls/deep-storage-config.yaml
create mode 100644 docs/guides/druid/autoscaler/compute/yamls/druid-autoscaler.yaml
create mode 100644 docs/guides/druid/autoscaler/compute/yamls/druid-cluster.yaml
create mode 100644 docs/guides/druid/autoscaler/storage/_index.md
create mode 100644 docs/guides/druid/autoscaler/storage/guide.md
create mode 100644 docs/guides/druid/autoscaler/storage/images/storage-autoscaling.png
create mode 100644 docs/guides/druid/autoscaler/storage/overview.md
create mode 100644 docs/guides/druid/autoscaler/storage/yamls/deep-storage-config.yaml
create mode 100644 docs/guides/druid/autoscaler/storage/yamls/druid-cluster.yaml
create mode 100644 docs/guides/druid/autoscaler/storage/yamls/druid-storage-autoscaler.yaml
create mode 100644 docs/guides/druid/clustering/_index.md
create mode 100644 docs/guides/druid/clustering/guide/index.md
create mode 100644 docs/guides/druid/clustering/guide/yamls/deep-storage-config.yaml
create mode 100644 docs/guides/druid/clustering/guide/yamls/druid-cluster.yaml
create mode 100644 docs/guides/druid/clustering/overview/images/druid-architecture.svg
create mode 100644 docs/guides/druid/clustering/overview/index.md
delete mode 100644 docs/guides/druid/concepts/catalog.md
create mode 100644 docs/guides/druid/concepts/druidautoscaler.md
create mode 100644 docs/guides/druid/concepts/druidopsrequest.md
create mode 100644 docs/guides/druid/concepts/druidversion.md
create mode 100644 docs/guides/druid/configuration/_index.md
create mode 100644 docs/guides/druid/configuration/config-file/images/druid-updated-ui.png
create mode 100644 docs/guides/druid/configuration/config-file/index.md
create mode 100644 docs/guides/druid/configuration/config-file/yamls/config-secret.yaml
create mode 100644 docs/guides/druid/configuration/config-file/yamls/deep-storage-config.yaml
create mode 100644 docs/guides/druid/configuration/config-file/yamls/druid-with-config.yaml
create mode 100644 docs/guides/druid/configuration/podtemplating/index.md
create mode 100644 docs/guides/druid/configuration/podtemplating/yamls/deep-storage-config.yaml
create mode 100644 docs/guides/druid/configuration/podtemplating/yamls/druid-cluster.yaml
create mode 100644 docs/guides/druid/configuration/podtemplating/yamls/druid-node-selector.yaml
create mode 100644 docs/guides/druid/configuration/podtemplating/yamls/druid-with-tolerations.yaml
create mode 100644 docs/guides/druid/configuration/podtemplating/yamls/druid-without-tolerations.yaml
create mode 100755 docs/guides/druid/monitoring/_index.md
create mode 100644 docs/guides/druid/monitoring/images/druid-monitoring.png
create mode 100644 docs/guides/druid/monitoring/images/druid-prometheus.png
create mode 100644 docs/guides/druid/monitoring/overview.md
create mode 100644 docs/guides/druid/monitoring/using-builtin-prometheus.md
create mode 100644 docs/guides/druid/monitoring/using-prometheus-operator.md
create mode 100644 docs/guides/druid/monitoring/yamls/deep-storage-config.yaml
create mode 100644 docs/guides/druid/monitoring/yamls/druid-monitoring-builtin.yaml
create mode 100644 docs/guides/druid/monitoring/yamls/druid-with-monitoring.yaml
rename docs/guides/druid/quickstart/{overview => guide}/index.md (97%)
create mode 100644 docs/guides/druid/reconfigure-tls/_index.md
create mode 100644 docs/guides/druid/reconfigure-tls/guide.md
create mode 100644 docs/guides/druid/reconfigure-tls/images/druid-ui.png
create mode 100644 docs/guides/druid/reconfigure-tls/images/druid-with-tls.png
create mode 100644 docs/guides/druid/reconfigure-tls/images/druid-without-tls.png
create mode 100644 docs/guides/druid/reconfigure-tls/images/reconfigure-tls.png
create mode 100644 docs/guides/druid/reconfigure-tls/overview.md
create mode 100644 docs/guides/druid/reconfigure-tls/yamls/deep-storage-config.yaml
create mode 100644 docs/guides/druid/reconfigure-tls/yamls/drops-add-tls.yaml
create mode 100644 docs/guides/druid/reconfigure-tls/yamls/drops-remove.yaml
create mode 100644 docs/guides/druid/reconfigure-tls/yamls/drops-rotate.yaml
create mode 100644 docs/guides/druid/reconfigure-tls/yamls/druid-ca-issuer.yaml
create mode 100644 docs/guides/druid/reconfigure-tls/yamls/druid-cluster.yaml
create mode 100644 docs/guides/druid/reconfigure-tls/yamls/druid-new-issuer.yaml
create mode 100644 docs/guides/druid/reconfigure-tls/yamls/druid-update-tls-issuer.yaml
create mode 100644 docs/guides/druid/reconfigure/_index.md
create mode 100644 docs/guides/druid/reconfigure/guide.md
create mode 100644 docs/guides/druid/reconfigure/images/druid-ui.png
create mode 100644 docs/guides/druid/reconfigure/images/reconfigure.svg
create mode 100644 docs/guides/druid/reconfigure/overview.md
create mode 100644 docs/guides/druid/reconfigure/yamls/config-secret.yaml
create mode 100644 docs/guides/druid/reconfigure/yamls/deep-storage-config.yaml
create mode 100644 docs/guides/druid/reconfigure/yamls/druid-cluster.yaml
create mode 100644 docs/guides/druid/reconfigure/yamls/reconfigure-druid-ops.yaml
create mode 100644 docs/guides/druid/restart/_index.md
create mode 100644 docs/guides/druid/restart/guide.md
create mode 100644 docs/guides/druid/restart/yamls/deep-storage-config.yaml
create mode 100644 docs/guides/druid/restart/yamls/druid-cluster.yaml
create mode 100644 docs/guides/druid/restart/yamls/restart.yaml
create mode 100644 docs/guides/druid/scaling/_index.md
create mode 100644 docs/guides/druid/scaling/horizontal-scaling/_index.md
create mode 100644 docs/guides/druid/scaling/horizontal-scaling/guide.md
create mode 100644 docs/guides/druid/scaling/horizontal-scaling/images/dr-horizontal-scaling.png
create mode 100644 docs/guides/druid/scaling/horizontal-scaling/images/druid-ui-scaled-up.png
create mode 100644 docs/guides/druid/scaling/horizontal-scaling/images/druid-ui.png
create mode 100644 docs/guides/druid/scaling/horizontal-scaling/overview.md
create mode 100644 docs/guides/druid/scaling/horizontal-scaling/yamls/deep-storage-config.yaml
create mode 100644 docs/guides/druid/scaling/horizontal-scaling/yamls/druid-cluster.yaml
create mode 100644 docs/guides/druid/scaling/horizontal-scaling/yamls/druid-hscale-down.yaml
create mode 100644 docs/guides/druid/scaling/horizontal-scaling/yamls/druid-hscale-up.yaml
create mode 100644 docs/guides/druid/scaling/vertical-scaling/_index.md
create mode 100644 docs/guides/druid/scaling/vertical-scaling/guide.md
create mode 100644 docs/guides/druid/scaling/vertical-scaling/images/dr-vertical-scaling.png
create mode 100644 docs/guides/druid/scaling/vertical-scaling/overview.md
create mode 100644 docs/guides/druid/scaling/vertical-scaling/yamls/deep-storage-config.yaml
create mode 100644 docs/guides/druid/scaling/vertical-scaling/yamls/druid-cluster.yaml
create mode 100644 docs/guides/druid/scaling/vertical-scaling/yamls/druid-vscale.yaml
create mode 100755 docs/guides/druid/tls/_index.md
create mode 100644 docs/guides/druid/tls/guide.md
create mode 100644 docs/guides/druid/tls/images/druid-ui.png
create mode 100644 docs/guides/druid/tls/images/tls.png
create mode 100644 docs/guides/druid/tls/overview.md
create mode 100644 docs/guides/druid/tls/yamls/deep-storage-config.yaml
create mode 100644 docs/guides/druid/tls/yamls/druid-ca-issuer.yaml
create mode 100644 docs/guides/druid/tls/yamls/druid-cluster-tls.yaml
create mode 100644 docs/guides/druid/update-version/_index.md
create mode 100644 docs/guides/druid/update-version/guide.md
create mode 100644 docs/guides/druid/update-version/images/dr-update-version.png
create mode 100644 docs/guides/druid/update-version/images/druid-ui-28.png
create mode 100644 docs/guides/druid/update-version/images/druid-ui-30.png
create mode 100644 docs/guides/druid/update-version/overview.md
create mode 100644 docs/guides/druid/update-version/yamls/deep-storage-config.yaml
create mode 100644 docs/guides/druid/update-version/yamls/druid-cluster.yaml
create mode 100644 docs/guides/druid/update-version/yamls/update-version-ops.yaml
create mode 100644 docs/guides/druid/volume-expansion/_index.md
create mode 100644 docs/guides/druid/volume-expansion/guide.md
create mode 100644 docs/guides/druid/volume-expansion/images/druid-volume-expansion.png
create mode 100644 docs/guides/druid/volume-expansion/overview.md
create mode 100644 docs/guides/druid/volume-expansion/yamls/deep-storage-config.yaml
create mode 100644 docs/guides/druid/volume-expansion/yamls/druid-cluster.yaml
create mode 100644 docs/guides/druid/volume-expansion/yamls/volume-expansion-ops.yaml
diff --git a/docs/guides/README.md b/docs/guides/README.md
index e7f0486867..065bc32b01 100644
--- a/docs/guides/README.md
+++ b/docs/guides/README.md
@@ -16,7 +16,7 @@ aliases:
# Guides
Guides to show you how to perform tasks with KubeDB:
-- [Druid](/docs/guides/kafka/README.md). Shows how to manage Druid using KubeDB.
+- [Druid](/docs/guides/druid/README.md). Shows how to manage Druid using KubeDB.
- [Elasticsearch](/docs/guides/elasticsearch/README.md). Shows how to manage Elasticsearch & OpenSearch using KubeDB.
- [Kafka](/docs/guides/kafka/README.md). Shows how to manage Kafka using KubeDB.
- [FerretDB](/docs/guides/ferretdb/README.md). Shows how to manage FerretDB using KubeDB.
diff --git a/docs/guides/druid/README.md b/docs/guides/druid/README.md
index 3117d47cb3..e1f9c98d61 100644
--- a/docs/guides/druid/README.md
+++ b/docs/guides/druid/README.md
@@ -15,23 +15,35 @@ aliases:
> New to KubeDB? Please start [here](/docs/README.md).
+## Overview
+
+Apache Druid is a real-time analytics database designed for fast slice-and-dice analytics ("OLAP" queries) on large data sets. Druid is most often used as a database for powering use cases where real-time ingest, fast query performance, and high uptime are important. As such, Druid is commonly used for powering GUIs of analytical applications, or as a backend for highly-concurrent APIs that need fast aggregations. Druid works best with event-oriented data.
+
## Supported Druid Features
-| Features | Availability |
-|----------------------------------------------------------------------------|:------------:|
-| Clustering | ✓ |
-| Druid Dependency Management (MySQL, PostgreSQL and ZooKeeper) | ✓ |
-| Authentication & Authorization | ✓ |
-| Custom Configuration | ✓ |
-| Backup/Recovery: Instant, Scheduled ( [KubeStash](https://kubestash.com/)) | ✓ |
-| Monitoring with Prometheus & Grafana | ✓ |
-| Builtin Prometheus Discovery | ✓ |
-| Using Prometheus operator | ✓ |
-| Externally manageable Auth Secret | ✓ |
-| Reconfigurable Health Checker | ✓ |
-| Persistent volume | ✓ |
-| Dashboard ( Druid Web Console ) | ✓ |
+| Features | Availability |
+|------------------------------------------------------------------------------------|:-----:|
+| Clustering | ✓ |
+| Druid Dependency Management (MySQL, PostgreSQL and ZooKeeper) | ✓ |
+| Authentication & Authorization | ✓ |
+| Custom Configuration | ✓ |
+| Backup/Recovery: Instant, Scheduled ( [KubeStash](https://kubestash.com/)) | ✓ |
+| Monitoring with Prometheus & Grafana | ✓ |
+| Builtin Prometheus Discovery | ✓ |
+| Using Prometheus operator | ✓ |
+| Externally manageable Auth Secret | ✓ |
+| Reconfigurable Health Checker | ✓ |
+| Persistent volume | ✓ |
+| Dashboard ( Druid Web Console ) | ✓ |
+| Automated Version Update | ✓ |
+| Automatic Vertical Scaling | ✓ |
+| Automated Horizontal Scaling | ✓ |
+| Automated db-configure Reconfiguration | ✓ |
+| TLS: Add, Remove, Update, Rotate ( [Cert Manager](https://cert-manager.io/docs/) ) | ✓ |
+| Automated Reprovision | ✓ |
+| Automated Volume Expansion | ✓ |
+| Autoscaling (vertically) | ✓ |
## Supported Druid Versions
@@ -39,7 +51,7 @@ KubeDB supports The following Druid versions.
- `28.0.1`
- `30.0.1`
-> The listed DruidVersions are tested and provided as a part of the installation process (ie. catalog chart), but you are open to create your own [DruidVersion](/docs/guides/druid/concepts/catalog.md) object with your custom Druid image.
+> The listed DruidVersions are tested and provided as a part of the installation process (ie. catalog chart), but you are open to create your own [DruidVersion](/docs/guides/druid/concepts/druidversion.md) object with your custom Druid image.
## Lifecycle of Druid Object
@@ -52,14 +64,12 @@ ref : https://cacoo.com/diagrams/bbB63L6KRIbPLl95/9A5B0
## User Guide
-- [Quickstart Druid](/docs/guides/druid/quickstart/overview/index.md) with KubeDB Operator.
-
-[//]: # (- Druid Clustering supported by KubeDB)
-
-[//]: # ( - [Topology Clustering](/docs/guides/druid/clustering/topology-cluster/index.md))
-
-[//]: # (- Use [kubedb cli](/docs/guides/druid/cli/cli.md) to manage databases like kubectl for Kubernetes.)
-
+- [Quickstart Druid](/docs/guides/druid/quickstart/guide/index.md) with KubeDB Operator.
+- [Druid Clustering](/docs/guides/druid/clustering/overview/index.md) with KubeDB Operator.
+- [Backup & Restore](/docs/guides/druid/backup/overview/index.md) Druid databases using KubeStash.
+- Start [Druid with Custom Config](/docs/guides/druid/configuration/_index.md).
+- Monitor your Druid database with KubeDB using [out-of-the-box Prometheus operator](/docs/guides/druid/monitoring/using-prometheus-operator.md).
+- Monitor your Druid database with KubeDB using [out-of-the-box builtin-Prometheus](/docs/guides/druid/monitoring/using-builtin-prometheus.md).
- Detail concepts of [Druid object](/docs/guides/druid/concepts/druid.md).
-
-[//]: # (- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md).)
\ No newline at end of file
+- Detail concepts of [DruidVersion object](/docs/guides/druid/concepts/druidversion.md).
+- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md).
\ No newline at end of file
diff --git a/docs/guides/druid/autoscaler/_index.md b/docs/guides/druid/autoscaler/_index.md
new file mode 100644
index 0000000000..a39f2bfba3
--- /dev/null
+++ b/docs/guides/druid/autoscaler/_index.md
@@ -0,0 +1,10 @@
+---
+title: Autoscaling
+menu:
+ docs_{{ .version }}:
+ identifier: guides-druid-autoscaler
+ name: Autoscaling
+ parent: guides-druid
+ weight: 100
+menu_name: docs_{{ .version }}
+---
\ No newline at end of file
diff --git a/docs/guides/druid/autoscaler/compute/_index.md b/docs/guides/druid/autoscaler/compute/_index.md
new file mode 100644
index 0000000000..c2c1eea280
--- /dev/null
+++ b/docs/guides/druid/autoscaler/compute/_index.md
@@ -0,0 +1,10 @@
+---
+title: Compute Autoscaling
+menu:
+ docs_{{ .version }}:
+ identifier: guides-druid-autoscaler-compute
+ name: Compute Autoscaling
+ parent: guides-druid-autoscaler
+ weight: 46
+menu_name: docs_{{ .version }}
+---
diff --git a/docs/guides/druid/autoscaler/compute/guide.md b/docs/guides/druid/autoscaler/compute/guide.md
new file mode 100644
index 0000000000..b0810f67b2
--- /dev/null
+++ b/docs/guides/druid/autoscaler/compute/guide.md
@@ -0,0 +1,864 @@
+---
+title: Druid Topology Autoscaling
+menu:
+ docs_{{ .version }}:
+ identifier: guides-druid-autoscaler-compute-guide
+ name: Druid Compute Autoscaling
+ parent: guides-druid-autoscaler-compute
+ weight: 20
+menu_name: docs_{{ .version }}
+section_menu_id: guides
+---
+
+> New to KubeDB? Please start [here](/docs/README.md).
+
+# Autoscaling the Compute Resource of a Druid Topology Cluster
+
+This guide will show you how to use `KubeDB` to autoscale compute resources i.e. cpu and memory of a Druid topology cluster.
+
+## Before You Begin
+
+- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster.
+
+- Install `KubeDB` Provisioner, Ops-manager and Autoscaler operator in your cluster following the steps [here](/docs/setup/README.md).
+
+- Install `Metrics Server` from [here](https://github.com/kubernetes-sigs/metrics-server#installation)
+
+- You should be familiar with the following `KubeDB` concepts:
+ - [Druid](/docs/guides/druid/concepts/druid.md)
+ - [DruidAutoscaler](/docs/guides/druid/concepts/druidautoscaler.md)
+ - [DruidOpsRequest](/docs/guides/druid/concepts/druidopsrequest.md)
+ - [Compute Resource Autoscaling Overview](/docs/guides/druid/autoscaler/compute/overview.md)
+
+To keep everything isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+> **Note:** YAML files used in this tutorial are stored in [docs/examples/druid](/docs/examples/druid) directory of [kubedb/docs](https://github.com/kubedb/docs) repository.
+
+## Autoscaling of Topology Cluster
+
+Here, we are going to deploy a `Druid` Topology Cluster using a supported version by `KubeDB` operator. Then we are going to apply `DruidAutoscaler` to set up autoscaling.
+
+### Create External Dependency (Deep Storage)
+
+Before proceeding further, we need to prepare deep storage, which is one of the external dependency of Druid and used for storing the segments. It is a storage mechanism that Apache Druid does not provide. **Amazon S3**, **Google Cloud Storage**, or **Azure Blob Storage**, **S3-compatible storage** (like **Minio**), or **HDFS** are generally convenient options for deep storage.
+
+In this tutorial, we will run a `minio-server` as deep storage in our local `kind` cluster using `minio-operator` and create a bucket named `druid` in it, which the deployed druid database will use.
+
+```bash
+$ helm repo add minio https://operator.min.io/
+$ helm repo update minio
+$ helm upgrade --install --namespace "minio-operator" --create-namespace "minio-operator" minio/operator --set operator.replicaCount=1
+
+$ helm upgrade --install --namespace "demo" --create-namespace druid-minio minio/tenant \
+--set tenant.pools[0].servers=1 \
+--set tenant.pools[0].volumesPerServer=1 \
+--set tenant.pools[0].size=1Gi \
+--set tenant.certificate.requestAutoCert=false \
+--set tenant.buckets[0].name="druid" \
+--set tenant.pools[0].name="default"
+
+```
+
+Now we need to create a `Secret` named `deep-storage-config`. It contains the necessary connection information using which the druid database will connect to the deep storage.
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: deep-storage-config
+ namespace: demo
+stringData:
+ druid.storage.type: "s3"
+ druid.storage.bucket: "druid"
+ druid.storage.baseKey: "druid/segments"
+ druid.s3.accessKey: "minio"
+ druid.s3.secretKey: "minio123"
+ druid.s3.protocol: "http"
+ druid.s3.enablePathStyleAccess: "true"
+ druid.s3.endpoint.signingRegion: "us-east-1"
+ druid.s3.endpoint.url: "http://myminio-hl.demo.svc.cluster.local:9000/"
+```
+
+Let’s create the `deep-storage-config` Secret shown above:
+
+```bash
+$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/guides/druid/autoscaler/compute/yamls/deep-storage-config.yaml
+secret/deep-storage-config created
+```
+
+Now, we are going to deploy a `Druid` combined cluster with version `28.0.1`.
+
+### Deploy Druid Cluster
+
+In this section, we are going to deploy a Druid Topology cluster with version `28.0.1`. Then, in the next section we will set up autoscaling for this database using `DruidAutoscaler` CRD. Below is the YAML of the `Druid` CR that we are going to create,
+
+```yaml
+apiVersion: kubedb.com/v1alpha2
+kind: Druid
+metadata:
+ name: druid-cluster
+ namespace: demo
+spec:
+ version: 28.0.1
+ deepStorage:
+ type: s3
+ configSecret:
+ name: deep-storage-config
+ topology:
+ routers:
+ replicas: 1
+ deletionPolicy: WipeOut
+```
+
+Let's create the `Druid` CRO we have shown above,
+
+```bash
+$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/guides/druid/autoscaler/compute/yamls/druid-cluster.yaml
+druid.kubedb.com/druid-cluster created
+```
+
+Now, wait until `druid-cluster` has status `Ready`. i.e,
+
+```bash
+$ kubectl get kf -n demo -w
+NAME TYPE VERSION STATUS AGE
+druid-cluster kubedb.com/v1alpha2 28.0.1 Provisioning 0s
+druid-cluster kubedb.com/v1alpha2 28.0.1 Provisioning 24s
+.
+.
+druid-cluster kubedb.com/v1alpha2 28.0.1 Ready 118s
+```
+
+## Druid Topology Autoscaler
+
+Let's check the Druid resources for coordinators and historicals,
+
+```bash
+$ kubectl get druid -n demo druid-cluster -o json | jq '.spec.topology.coordinators.podTemplate.spec.containers[].resources'
+{
+ "limits": {
+ "memory": "1Gi"
+ },
+ "requests": {
+ "cpu": "500m",
+ "memory": "1Gi"
+ }
+}
+
+$ kubectl get druid -n demo druid-cluster -o json | jq '.spec.topology.historicals.podTemplate.spec.containers[].resources'
+{
+ "limits": {
+ "memory": "1Gi"
+ },
+ "requests": {
+ "cpu": "500m",
+ "memory": "1Gi"
+ }
+}
+```
+
+Let's check the coordinators and historicals Pod containers resources,
+
+```bash
+$ kubectl get pod -n demo druid-cluster-coordinators-0 -o json | jq '.spec.containers[].resources'
+{
+ "limits": {
+ "memory": "1Gi"
+ },
+ "requests": {
+ "cpu": "500m",
+ "memory": "1Gi"
+ }
+}
+
+$ kubectl get pod -n demo druid-cluster-historicals-0 -o json | jq '.spec.containers[].resources'
+{
+ "limits": {
+ "memory": "1Gi"
+ },
+ "requests": {
+ "cpu": "500m",
+ "memory": "1Gi"
+ }
+}
+```
+
+You can see from the above outputs that the resources for coordinators and historicals are same as the one we have assigned while deploying the druid.
+
+We are now ready to apply the `DruidAutoscaler` CRO to set up autoscaling for these coordinators and historicals nodes.
+
+### Compute Resource Autoscaling
+
+Here, we are going to set up compute resource autoscaling using a DruidAutoscaler Object.
+
+#### Create DruidAutoscaler Object
+
+In order to set up compute resource autoscaling for this topology cluster, we have to create a `DruidAutoscaler` CRO with our desired configuration. Below is the YAML of the `DruidAutoscaler` object that we are going to create,
+
+```yaml
+apiVersion: autoscaling.kubedb.com/v1alpha1
+kind: DruidAutoscaler
+metadata:
+ name: druid-autoscaler
+ namespace: demo
+spec:
+ databaseRef:
+ name: druid-quickstart
+ compute:
+ coordinators:
+ trigger: "On"
+ podLifeTimeThreshold: 1m
+ minAllowed:
+ cpu: 600m
+ memory: 2Gi
+ maxAllowed:
+ cpu: 1000m
+ memory: 5Gi
+ resourceDiffPercentage: 20
+ controlledResources: ["cpu", "memory"]
+ historicals:
+ trigger: "On"
+ podLifeTimeThreshold: 1m
+ minAllowed:
+ cpu: 600m
+ memory: 2Gi
+ maxAllowed:
+ cpu: 1000m
+ memory: 5Gi
+ resourceDiffPercentage: 20
+ controlledResources: [ "cpu", "memory"]
+```
+
+Here,
+
+- `spec.databaseRef.name` specifies that we are performing compute resource scaling operation on `druid-cluster` cluster.
+- `spec.compute.coordinators.trigger` specifies that compute autoscaling is enabled for this node.
+- `spec.compute.coordinators.podLifeTimeThreshold` specifies the minimum lifetime for at least one of the pod to initiate a vertical scaling.
+- `spec.compute.coordinators.resourceDiffPercentage` specifies the minimum resource difference in percentage. The default is 10%. If the difference between current & recommended resource is less than ResourceDiffPercentage, Autoscaler Operator will ignore the updating.
+- `spec.compute.coordinators.minAllowed` specifies the minimum allowed resources for the cluster.
+- `spec.compute.coordinators.maxAllowed` specifies the maximum allowed resources for the cluster.
+- `spec.compute.coordinators.controlledResources` specifies the resources that are controlled by the autoscaler.
+- `spec.compute.coordinators.containerControlledValues` specifies which resource values should be controlled. The default is "RequestsAndLimits".
+- `spec.compute.historicals` can be configured the same way shown above.
+- `spec.opsRequestOptions` contains the options to pass to the created OpsRequest. It has 2 fields.
+ - `timeout` specifies the timeout for the OpsRequest.
+ - `apply` specifies when the OpsRequest should be applied. The default is "IfReady".
+
+> **Note:** You can also configure autoscaling configurations for all other nodes as well. You can apply autoscaler for each node in separate YAML or combinedly in one a YAML as shown above.
+
+Let's create the `DruidAutoscaler` CR we have shown above,
+
+```bash
+$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/guides/druid/autoscaler/compute/yamls/druid-autoscaler.yaml
+druidautoscaler.autoscaling.kubedb.com/druid-autoscaler created
+```
+
+#### Verify Autoscaling is set up successfully
+
+Let's check that the `druidautoscaler` resource is created successfully,
+
+```bash
+$ kubectl describe druidautoscaler druid-autoscaler -n demo
+ kubectl describe druidautoscaler druid-autoscaler -n demo
+Name: druid-autoscaler
+Namespace: demo
+Labels:
+Annotations:
+API Version: autoscaling.kubedb.com/v1alpha1
+Kind: DruidAutoscaler
+Metadata:
+ Creation Timestamp: 2024-10-24T10:04:22Z
+ Generation: 1
+ Managed Fields:
+ API Version: autoscaling.kubedb.com/v1alpha1
+ Fields Type: FieldsV1
+ fieldsV1:
+ f:metadata:
+ f:annotations:
+ .:
+ f:kubectl.kubernetes.io/last-applied-configuration:
+ f:spec:
+ .:
+ f:compute:
+ .:
+ f:coordinators:
+ .:
+ f:controlledResources:
+ f:maxAllowed:
+ .:
+ f:cpu:
+ f:memory:
+ f:minAllowed:
+ .:
+ f:cpu:
+ f:memory:
+ f:podLifeTimeThreshold:
+ f:resourceDiffPercentage:
+ f:trigger:
+ f:historicals:
+ .:
+ f:controlledResources:
+ f:maxAllowed:
+ .:
+ f:cpu:
+ f:memory:
+ f:minAllowed:
+ .:
+ f:cpu:
+ f:memory:
+ f:podLifeTimeThreshold:
+ f:resourceDiffPercentage:
+ f:trigger:
+ f:databaseRef:
+ Manager: kubectl-client-side-apply
+ Operation: Update
+ Time: 2024-10-24T10:04:22Z
+ API Version: autoscaling.kubedb.com/v1alpha1
+ Fields Type: FieldsV1
+ fieldsV1:
+ f:metadata:
+ f:ownerReferences:
+ .:
+ k:{"uid":"c2a5c29d-3589-49d8-bc18-585b9c05bf8d"}:
+ Manager: kubedb-autoscaler
+ Operation: Update
+ Time: 2024-10-24T10:04:22Z
+ API Version: autoscaling.kubedb.com/v1alpha1
+ Fields Type: FieldsV1
+ fieldsV1:
+ f:status:
+ .:
+ f:checkpoints:
+ f:conditions:
+ f:vpas:
+ Manager: kubedb-autoscaler
+ Operation: Update
+ Subresource: status
+ Time: 2024-10-24T10:16:20Z
+ Owner References:
+ API Version: kubedb.com/v1alpha2
+ Block Owner Deletion: true
+ Controller: true
+ Kind: Druid
+ Name: druid-cluster
+ UID: c2a5c29d-3589-49d8-bc18-585b9c05bf8d
+ Resource Version: 274969
+ UID: 069fbdd7-87ad-4fd7-acc7-9753fa188312
+Spec:
+ Compute:
+ Coordinators:
+ Controlled Resources:
+ cpu
+ memory
+ Max Allowed:
+ Cpu: 1000m
+ Memory: 5Gi
+ Min Allowed:
+ Cpu: 600m
+ Memory: 2Gi
+ Pod Life Time Threshold: 1m
+ Resource Diff Percentage: 20
+ Trigger: On
+ Historicals:
+ Controlled Resources:
+ cpu
+ memory
+ Max Allowed:
+ Cpu: 1000m
+ Memory: 5Gi
+ Min Allowed:
+ Cpu: 600m
+ Memory: 2Gi
+ Pod Life Time Threshold: 1m
+ Resource Diff Percentage: 20
+ Trigger: On
+ Database Ref:
+ Name: druid-cluster
+Status:
+ Checkpoints:
+ Cpu Histogram:
+ Bucket Weights:
+ Index: 0
+ Weight: 10000
+ Index: 5
+ Weight: 490
+ Reference Timestamp: 2024-10-24T10:05:00Z
+ Total Weight: 2.871430450948392
+ First Sample Start: 2024-10-24T10:05:07Z
+ Last Sample Start: 2024-10-24T10:16:03Z
+ Last Update Time: 2024-10-24T10:16:20Z
+ Memory Histogram:
+ Bucket Weights:
+ Index: 25
+ Weight: 3648
+ Index: 29
+ Weight: 10000
+ Reference Timestamp: 2024-10-24T10:10:00Z
+ Total Weight: 3.3099198846728424
+ Ref:
+ Container Name: druid
+ Vpa Object Name: druid-cluster-historicals
+ Total Samples Count: 12
+ Version: v3
+ Cpu Histogram:
+ Bucket Weights:
+ Index: 0
+ Weight: 3040
+ Index: 1
+ Weight: 10000
+ Index: 2
+ Weight: 3278
+ Index: 14
+ Weight: 1299
+ Reference Timestamp: 2024-10-24T10:10:00Z
+ Total Weight: 1.0092715955023177
+ First Sample Start: 2024-10-24T10:04:53Z
+ Last Sample Start: 2024-10-24T10:14:03Z
+ Last Update Time: 2024-10-24T10:14:20Z
+ Memory Histogram:
+ Bucket Weights:
+ Index: 24
+ Weight: 10000
+ Index: 27
+ Weight: 8706
+ Reference Timestamp: 2024-10-24T10:10:00Z
+ Total Weight: 3.204567438391289
+ Ref:
+ Container Name: druid
+ Vpa Object Name: druid-cluster-coordinators
+ Total Samples Count: 10
+ Version: v3
+ Conditions:
+ Last Transition Time: 2024-10-24T10:07:19Z
+ Message: Successfully created druidOpsRequest demo/drops-druid-cluster-coordinators-g02xtu
+ Observed Generation: 1
+ Reason: CreateOpsRequest
+ Status: True
+ Type: CreateOpsRequest
+ Vpas:
+ Conditions:
+ Last Transition Time: 2024-10-24T10:05:19Z
+ Status: True
+ Type: RecommendationProvided
+ Recommendation:
+ Container Recommendations:
+ Container Name: druid
+ Lower Bound:
+ Cpu: 600m
+ Memory: 2Gi
+ Target:
+ Cpu: 600m
+ Memory: 2Gi
+ Uncapped Target:
+ Cpu: 100m
+ Memory: 764046746
+ Upper Bound:
+ Cpu: 1
+ Memory: 5Gi
+ Vpa Name: druid-cluster-historicals
+ Conditions:
+ Last Transition Time: 2024-10-24T10:06:19Z
+ Status: True
+ Type: RecommendationProvided
+ Recommendation:
+ Container Recommendations:
+ Container Name: druid
+ Lower Bound:
+ Cpu: 600m
+ Memory: 2Gi
+ Target:
+ Cpu: 600m
+ Memory: 2Gi
+ Uncapped Target:
+ Cpu: 100m
+ Memory: 671629701
+ Upper Bound:
+ Cpu: 1
+ Memory: 5Gi
+ Vpa Name: druid-cluster-coordinators
+Events:
+```
+So, the `druidautoscaler` resource is created successfully.
+
+you can see in the `Status.VPAs.Recommendation` section, that recommendation has been generated for our database. Our autoscaler operator continuously watches the recommendation generated and creates an `druidopsrequest` based on the recommendations, if the database pods resources are needed to scaled up or down.
+
+Let's watch the `druidopsrequest` in the demo namespace to see if any `druidopsrequest` object is created. After some time you'll see that a `druidopsrequest` will be created based on the recommendation.
+
+```bash
+$ watch kubectl get druidopsrequest -n demo
+Every 2.0s: kubectl get druidopsrequest -n demo
+NAME TYPE STATUS AGE
+drops-druid-cluster-coordinators-g02xtu VerticalScaling Progressing 8m
+drops-druid-cluster-historicals-g3oqje VerticalScaling Progressing 8m
+
+```
+Progressing
+Let's wait for the ops request to become successful.
+
+```bash
+$ kubectl get druidopsrequest -n demo
+NAME TYPE STATUS AGE
+drops-druid-cluster-coordinators-g02xtu VerticalScaling Successful 12m
+drops-druid-cluster-historicals-g3oqje VerticalScaling Successful 13m
+```
+
+We can see from the above output that the `DruidOpsRequest` has succeeded. If we describe the `DruidOpsRequest` we will get an overview of the steps that were followed to scale the cluster.
+
+```bash
+$ kubectl describe druidopsrequests -n demo drops-druid-cluster-coordinators-f6qbth
+Name: drops-druid-cluster-coordinators-g02xtu
+Namespace: demo
+Labels: app.kubernetes.io/component=database
+ app.kubernetes.io/instance=druid-cluster
+ app.kubernetes.io/managed-by=kubedb.com
+ app.kubernetes.io/name=druids.kubedb.com
+Annotations:
+API Version: ops.kubedb.com/v1alpha1
+Kind: DruidOpsRequest
+Metadata:
+ Creation Timestamp: 2024-10-24T10:07:19Z
+ Generation: 1
+ Managed Fields:
+ API Version: ops.kubedb.com/v1alpha1
+ Fields Type: FieldsV1
+ fieldsV1:
+ f:metadata:
+ f:labels:
+ .:
+ f:app.kubernetes.io/component:
+ f:app.kubernetes.io/instance:
+ f:app.kubernetes.io/managed-by:
+ f:app.kubernetes.io/name:
+ f:ownerReferences:
+ .:
+ k:{"uid":"069fbdd7-87ad-4fd7-acc7-9753fa188312"}:
+ f:spec:
+ .:
+ f:apply:
+ f:databaseRef:
+ f:type:
+ f:verticalScaling:
+ .:
+ f:coordinators:
+ .:
+ f:resources:
+ .:
+ f:limits:
+ .:
+ f:memory:
+ f:requests:
+ .:
+ f:cpu:
+ f:memory:
+ Manager: kubedb-autoscaler
+ Operation: Update
+ Time: 2024-10-24T10:07:19Z
+ API Version: ops.kubedb.com/v1alpha1
+ Fields Type: FieldsV1
+ fieldsV1:
+ f:status:
+ .:
+ f:conditions:
+ f:observedGeneration:
+ f:phase:
+ Manager: kubedb-ops-manager
+ Operation: Update
+ Subresource: status
+ Time: 2024-10-24T10:07:43Z
+ Owner References:
+ API Version: autoscaling.kubedb.com/v1alpha1
+ Block Owner Deletion: true
+ Controller: true
+ Kind: DruidAutoscaler
+ Name: druid-autoscaler
+ UID: 069fbdd7-87ad-4fd7-acc7-9753fa188312
+ Resource Version: 273990
+ UID: d14d964b-f4ae-4570-a296-38e91c802473
+Spec:
+ Apply: IfReady
+ Database Ref:
+ Name: druid-cluster
+ Type: VerticalScaling
+ Vertical Scaling:
+ Coordinators:
+ Resources:
+ Limits:
+ Memory: 2Gi
+ Requests:
+ Cpu: 600m
+ Memory: 2Gi
+Status:
+ Conditions:
+ Last Transition Time: 2024-10-24T10:07:19Z
+ Message: Druid ops-request has started to vertically scale the Druid nodes
+ Observed Generation: 1
+ Reason: VerticalScaling
+ Status: True
+ Type: VerticalScaling
+ Last Transition Time: 2024-10-24T10:07:28Z
+ Message: Successfully updated PetSets Resources
+ Observed Generation: 1
+ Reason: UpdatePetSets
+ Status: True
+ Type: UpdatePetSets
+ Last Transition Time: 2024-10-24T10:07:43Z
+ Message: Successfully Restarted Pods With Resources
+ Observed Generation: 1
+ Reason: RestartPods
+ Status: True
+ Type: RestartPods
+ Last Transition Time: 2024-10-24T10:07:33Z
+ Message: get pod; ConditionStatus:True; PodName:druid-cluster-coordinators-0
+ Observed Generation: 1
+ Status: True
+ Type: GetPod--druid-cluster-coordinators-0
+ Last Transition Time: 2024-10-24T10:07:33Z
+ Message: evict pod; ConditionStatus:True; PodName:druid-cluster-coordinators-0
+ Observed Generation: 1
+ Status: True
+ Type: EvictPod--druid-cluster-coordinators-0
+ Last Transition Time: 2024-10-24T10:07:38Z
+ Message: check pod running; ConditionStatus:True; PodName:druid-cluster-coordinators-0
+ Observed Generation: 1
+ Status: True
+ Type: CheckPodRunning--druid-cluster-coordinators-0
+ Last Transition Time: 2024-10-24T10:07:43Z
+ Message: Successfully completed the vertical scaling for RabbitMQ
+ Observed Generation: 1
+ Reason: Successful
+ Status: True
+ Type: Successful
+ Observed Generation: 1
+ Phase: Successful
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal Starting 12m KubeDB Ops-manager Operator Start processing for DruidOpsRequest: demo/drops-druid-cluster-coordinators-g02xtu
+ Normal Starting 12m KubeDB Ops-manager Operator Pausing Druid databse: demo/druid-cluster
+ Normal Successful 12m KubeDB Ops-manager Operator Successfully paused Druid database: demo/druid-cluster for DruidOpsRequest: drops-druid-cluster-coordinators-g02xtu
+ Normal UpdatePetSets 12m KubeDB Ops-manager Operator Successfully updated PetSets Resources
+ Warning get pod; ConditionStatus:True; PodName:druid-cluster-coordinators-0 12m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:druid-cluster-coordinators-0
+ Warning evict pod; ConditionStatus:True; PodName:druid-cluster-coordinators-0 12m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:druid-cluster-coordinators-0
+ Warning check pod running; ConditionStatus:True; PodName:druid-cluster-coordinators-0 12m KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:druid-cluster-coordinators-0
+ Normal RestartPods 12m KubeDB Ops-manager Operator Successfully Restarted Pods With Resources
+ Normal Starting 12m KubeDB Ops-manager Operator Resuming Druid database: demo/druid-cluster
+ Normal Successful 12m KubeDB Ops-manager Operator Successfully resumed Druid database: demo/druid-cluster for DruidOpsRequest: drops-druid-cluster-coordinators-g02xtu
+```
+
+Let's describe the other `DruidOpsRequest` created for scaling of historicals.
+
+```bash
+$ kubectl describe druidopsrequests -n demo drops-druid-cluster-historicals-g3oqje
+Name: drops-druid-cluster-historicals-g3oqje
+Namespace: demo
+Labels: app.kubernetes.io/component=database
+ app.kubernetes.io/instance=druid-cluster
+ app.kubernetes.io/managed-by=kubedb.com
+ app.kubernetes.io/name=druids.kubedb.com
+Annotations:
+API Version: ops.kubedb.com/v1alpha1
+Kind: DruidOpsRequest
+Metadata:
+ Creation Timestamp: 2024-10-24T10:06:19Z
+ Generation: 1
+ Managed Fields:
+ API Version: ops.kubedb.com/v1alpha1
+ Fields Type: FieldsV1
+ fieldsV1:
+ f:metadata:
+ f:labels:
+ .:
+ f:app.kubernetes.io/component:
+ f:app.kubernetes.io/instance:
+ f:app.kubernetes.io/managed-by:
+ f:app.kubernetes.io/name:
+ f:ownerReferences:
+ .:
+ k:{"uid":"069fbdd7-87ad-4fd7-acc7-9753fa188312"}:
+ f:spec:
+ .:
+ f:apply:
+ f:databaseRef:
+ f:type:
+ f:verticalScaling:
+ .:
+ f:historicals:
+ .:
+ f:resources:
+ .:
+ f:limits:
+ .:
+ f:memory:
+ f:requests:
+ .:
+ f:cpu:
+ f:memory:
+ Manager: kubedb-autoscaler
+ Operation: Update
+ Time: 2024-10-24T10:06:19Z
+ API Version: ops.kubedb.com/v1alpha1
+ Fields Type: FieldsV1
+ fieldsV1:
+ f:status:
+ .:
+ f:conditions:
+ f:observedGeneration:
+ f:phase:
+ Manager: kubedb-ops-manager
+ Operation: Update
+ Subresource: status
+ Time: 2024-10-24T10:06:37Z
+ Owner References:
+ API Version: autoscaling.kubedb.com/v1alpha1
+ Block Owner Deletion: true
+ Controller: true
+ Kind: DruidAutoscaler
+ Name: druid-autoscaler
+ UID: 069fbdd7-87ad-4fd7-acc7-9753fa188312
+ Resource Version: 273770
+ UID: fc13624c-42d4-4b03-9448-80f451b1a888
+Spec:
+ Apply: IfReady
+ Database Ref:
+ Name: druid-cluster
+ Type: VerticalScaling
+ Vertical Scaling:
+ Historicals:
+ Resources:
+ Limits:
+ Memory: 2Gi
+ Requests:
+ Cpu: 600m
+ Memory: 2Gi
+Status:
+ Conditions:
+ Last Transition Time: 2024-10-24T10:06:19Z
+ Message: Druid ops-request has started to vertically scale the Druid nodes
+ Observed Generation: 1
+ Reason: VerticalScaling
+ Status: True
+ Type: VerticalScaling
+ Last Transition Time: 2024-10-24T10:06:22Z
+ Message: Successfully updated PetSets Resources
+ Observed Generation: 1
+ Reason: UpdatePetSets
+ Status: True
+ Type: UpdatePetSets
+ Last Transition Time: 2024-10-24T10:06:37Z
+ Message: Successfully Restarted Pods With Resources
+ Observed Generation: 1
+ Reason: RestartPods
+ Status: True
+ Type: RestartPods
+ Last Transition Time: 2024-10-24T10:06:27Z
+ Message: get pod; ConditionStatus:True; PodName:druid-cluster-historicals-0
+ Observed Generation: 1
+ Status: True
+ Type: GetPod--druid-cluster-historicals-0
+ Last Transition Time: 2024-10-24T10:06:27Z
+ Message: evict pod; ConditionStatus:True; PodName:druid-cluster-historicals-0
+ Observed Generation: 1
+ Status: True
+ Type: EvictPod--druid-cluster-historicals-0
+ Last Transition Time: 2024-10-24T10:06:32Z
+ Message: check pod running; ConditionStatus:True; PodName:druid-cluster-historicals-0
+ Observed Generation: 1
+ Status: True
+ Type: CheckPodRunning--druid-cluster-historicals-0
+ Last Transition Time: 2024-10-24T10:06:37Z
+ Message: Successfully completed the vertical scaling for RabbitMQ
+ Observed Generation: 1
+ Reason: Successful
+ Status: True
+ Type: Successful
+ Observed Generation: 1
+ Phase: Successful
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal Starting 16m KubeDB Ops-manager Operator Start processing for DruidOpsRequest: demo/drops-druid-cluster-historicals-g3oqje
+ Normal Starting 16m KubeDB Ops-manager Operator Pausing Druid databse: demo/druid-cluster
+ Normal Successful 16m KubeDB Ops-manager Operator Successfully paused Druid database: demo/druid-cluster for DruidOpsRequest: drops-druid-cluster-historicals-g3oqje
+ Normal UpdatePetSets 16m KubeDB Ops-manager Operator Successfully updated PetSets Resources
+ Warning get pod; ConditionStatus:True; PodName:druid-cluster-historicals-0 16m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:druid-cluster-historicals-0
+ Warning evict pod; ConditionStatus:True; PodName:druid-cluster-historicals-0 16m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:druid-cluster-historicals-0
+ Warning check pod running; ConditionStatus:True; PodName:druid-cluster-historicals-0 16m KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:druid-cluster-historicals-0
+ Normal RestartPods 16m KubeDB Ops-manager Operator Successfully Restarted Pods With Resources
+ Normal Starting 16m KubeDB Ops-manager Operator Resuming Druid database: demo/druid-cluster
+ Normal Successful 16m KubeDB Ops-manager Operator Successfully resumed Druid database: demo/druid-cluster for DruidOpsRequest: drops-druid-cluster-historicals-g3oqje
+
+```
+
+Now, we are going to verify from the Pod, and the Druid yaml whether the resources of the coordinators and historicals node has updated to meet up the desired state, Let's check,
+
+```bash
+$ kubectl get pod -n demo druid-cluster-coordinators-0 -o json | jq '.spec.containers[].resources'
+{
+ "limits": {
+ "memory": "1536Mi"
+ },
+ "requests": {
+ "cpu": "600m",
+ "memory": "1536Mi"
+ }
+}
+
+$ kubectl get pod -n demo druid-cluster-historicals-0 -o json | jq '.spec.containers[].resources'
+{
+ "limits": {
+ "memory": "2Gi"
+ },
+ "requests": {
+ "cpu": "600m",
+ "memory": "2Gi"
+ }
+}
+
+$ kubectl get druid -n demo druid-cluster -o json | jq '.spec.topology.coordinators.podTemplate.spec.containers[].resources'
+{
+ "limits": {
+ "memory": "1536Mi"
+ },
+ "requests": {
+ "cpu": "600m",
+ "memory": "1536Mi"
+ }
+}
+
+$ kubectl get druid -n demo druid-cluster -o json | jq '.spec.topology.historicals.podTemplate.spec.containers[].resources'
+{
+ "limits": {
+ "memory": "2Gi"
+ },
+ "requests": {
+ "cpu": "600m",
+ "memory": "2Gi"
+ }
+}
+```
+
+The above output verifies that we have successfully auto scaled the resources of the Druid topology cluster for coordinators and historicals.
+
+## Cleaning Up
+
+To clean up the Kubernetes resources created by this tutorial, run:
+
+```bash
+kubectl delete druidopsrequest -n demo drops-druid-cluster-coordinators-g02xtu drops-druid-cluster-historicals-g3oqje
+kubectl delete druidautoscaler -n demo druid-autoscaler
+kubectl delete dr -n demo druid-cluster
+kubectl delete ns demo
+```
+## Next Steps
+
+- Detail concepts of [Druid object](/docs/guides/druid/concepts/druid.md).
+- Different Druid topology clustering modes [here](/docs/guides/druid/clustering/_index.md).
+- Monitor your Druid database with KubeDB using [out-of-the-box Prometheus operator](/docs/guides/druid/monitoring/using-prometheus-operator.md).
+
+[//]: # (- Monitor your Druid database with KubeDB using [out-of-the-box builtin-Prometheus](/docs/guides/druid/monitoring/using-builtin-prometheus.md).)
+- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md).
diff --git a/docs/guides/druid/autoscaler/compute/images/compute-autoscaling.png b/docs/guides/druid/autoscaler/compute/images/compute-autoscaling.png
new file mode 100644
index 0000000000000000000000000000000000000000..9406e2b2e99121bf6a2e8b13c83b248fae3ebd80
GIT binary patch
literal 65595
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