New to KubeDB? Please start here.
Update version of Druid
This guide will show you how to use KubeDB
Ops-manager operator to update the version of Druid
Combined or Topology.
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. If you do not already have a cluster, you can create one by using kind.Install
KubeDB
Provisioner and Ops-manager operator in your cluster following the steps here.You should be familiar with the following
KubeDB
concepts:
To keep everything isolated, we are going to use a separate namespace called demo
throughout this tutorial.
$ kubectl create ns demo
namespace/demo created
Note: YAML files used in this tutorial are stored in docs/examples/druid directory of kubedb/docs repository.
Prepare Druid
Now, we are going to deploy a Druid
cluster with version 28.0.1
.
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.
$ 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.
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:
$ kubectl create -f https://github.com/kubedb/docs/raw/v2024.11.18/docs/guides/druid/update-version/yamls/deep-storage-config.yaml
secret/deep-storage-config created
Deploy Druid
In this section, we are going to deploy a Druid topology cluster. Then, in the next section we will update the version using DruidOpsRequest
CRD. Below is the YAML of the Druid
CR that we are going to create,
apiVersion: kubedb.com/v1alpha2
kind: Druid
metadata:
name: druid-quickstart
namespace: demo
spec:
version: 28.0.1
deepStorage:
type: s3
configSecret:
name: deep-storage-config
topology:
routers:
replicas: 1
deletionPolicy: Delete
Let’s create the Druid
CR we have shown above,
$ kubectl create -f https://github.com/kubedb/docs/raw/v2024.11.18/docs/guides/druid/update-version/yamls/druid-cluster.yaml
druid.kubedb.com/druid-cluster created
Now, wait until druid-cluster
created has status Ready
. i.e,
$ kubectl get dr -n demo -w
NAME TYPE VERSION STATUS AGE
druid-cluster kubedb.com/v1aplha2 28.0.1 Provisioning 0s
druid-cluster kubedb.com/v1aplha2 28.0.1 Provisioning 55s
.
.
druid-cluster kubedb.com/v1aplha2 28.0.1 Ready 119s
We are now ready to apply the DruidOpsRequest
CR to update.
Check Druid Version from UI:
You can also see the version of druid cluster from the druid ui. For that, follow the following steps:
First, port-forward the port 8888
to local machine:
$ kubectl port-forward -n demo svc/druid-cluster-routers 8888
Forwarding from 127.0.0.1:8888 -> 8888
Forwarding from [::1]:8888 -> 8888
Now hit the http://localhost:8888
from any browser, and you will be prompted to provide the credential of the druid database. By following the steps discussed below, you can get the credential generated by the KubeDB operator for your Druid database.
Connection information:
Username:
$ kubectl get secret -n demo druid-cluster-admin-cred -o jsonpath='{.data.username}' | base64 -d admin
Password:
$ kubectl get secret -n demo druid-cluster-admin-cred -o jsonpath='{.data.password}' | base64 -d LzJtVRX5E8MorFaf
After providing the credentials correctly, you should be able to access the web console like shown below.
Here, we can see that the version of the druid cluster is 28.0.1
.
Update Druid Version
Here, we are going to update Druid
from 28.0.1
to 30.0.0
.
Create DruidOpsRequest:
In order to update the version, we have to create a DruidOpsRequest
CR with your desired version that is supported by KubeDB
. Below is the YAML of the DruidOpsRequest
CR that we are going to create,
apiVersion: ops.kubedb.com/v1alpha1
kind: DruidOpsRequest
metadata:
name: druid-update-version
namespace: demo
spec:
type: UpdateVersion
databaseRef:
name: druid-cluster
updateVersion:
targetVersion: 30.0.0
timeout: 5m
apply: IfReady
Here,
spec.databaseRef.name
specifies that we are performing operation ondruid-cluster
Druid.spec.type
specifies that we are going to performUpdateVersion
on our database.spec.updateVersion.targetVersion
specifies the expected version of the database30.0.0
.
Let’s create the DruidOpsRequest
CR we have shown above,
$ kubectl apply -f https://github.com/kubedb/docs/raw/v2024.11.18/docs/guides/druid/update-version/yamls/druid-hscale-up.yaml
druidopsrequest.ops.kubedb.com/druid-update-version created
Verify Druid version updated successfully
If everything goes well, KubeDB
Ops-manager operator will update the image of Druid
object and related PetSets
and Pods
.
Let’s wait for DruidOpsRequest
to be Successful
. Run the following command to watch DruidOpsRequest
CR,
$ watch kubectl get druidopsrequest -n demo
NAME TYPE STATUS AGE
druid-update-version UpdateVersion Successful 2m6s
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 update the database version.
$ kubectl describe druidopsrequest -n demo druid-update-version
Name: druid-update-version
Namespace: demo
Labels: <none>
Annotations: <none>
API Version: ops.kubedb.com/v1alpha1
Kind: DruidOpsRequest
Metadata:
Creation Timestamp: 2024-10-21T13:04:51Z
Generation: 1
Managed Fields:
API Version: ops.kubedb.com/v1alpha1
Fields Type: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
.:
f:kubectl.kubernetes.io/last-applied-configuration:
f:spec:
.:
f:apply:
f:databaseRef:
f:timeout:
f:type:
f:updateVersion:
.:
f:targetVersion:
Manager: kubectl-client-side-apply
Operation: Update
Time: 2024-10-21T13:04:51Z
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-21T13:08:46Z
Resource Version: 103855
UID: 5d470e24-37fd-4e16-b7a3-33040dcefe3d
Spec:
Apply: IfReady
Database Ref:
Name: druid-cluster
Timeout: 5m
Type: UpdateVersion
Update Version:
Target Version: 30.0.0
Status:
Conditions:
Last Transition Time: 2024-10-21T13:04:51Z
Message: Druid ops-request has started to update version
Observed Generation: 1
Reason: UpdateVersion
Status: True
Type: UpdateVersion
Last Transition Time: 2024-10-21T13:04:56Z
Message: successfully reconciled the Druid with updated version
Observed Generation: 1
Reason: UpdatePetSets
Status: True
Type: UpdatePetSets
Last Transition Time: 2024-10-21T13:08:46Z
Message: Successfully Restarted Druid nodes
Observed Generation: 1
Reason: RestartPods
Status: True
Type: RestartPods
Last Transition Time: 2024-10-21T13:05:01Z
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-21T13:05:01Z
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-21T13:08:01Z
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-21T13:08:06Z
Message: get pod; ConditionStatus:True; PodName:druid-cluster-middlemanagers-0
Observed Generation: 1
Status: True
Type: GetPod--druid-cluster-middlemanagers-0
Last Transition Time: 2024-10-21T13:08:06Z
Message: evict pod; ConditionStatus:True; PodName:druid-cluster-middlemanagers-0
Observed Generation: 1
Status: True
Type: EvictPod--druid-cluster-middlemanagers-0
Last Transition Time: 2024-10-21T13:08:11Z
Message: check pod running; ConditionStatus:True; PodName:druid-cluster-middlemanagers-0
Observed Generation: 1
Status: True
Type: CheckPodRunning--druid-cluster-middlemanagers-0
Last Transition Time: 2024-10-21T13:08:16Z
Message: get pod; ConditionStatus:True; PodName:druid-cluster-brokers-0
Observed Generation: 1
Status: True
Type: GetPod--druid-cluster-brokers-0
Last Transition Time: 2024-10-21T13:08:16Z
Message: evict pod; ConditionStatus:True; PodName:druid-cluster-brokers-0
Observed Generation: 1
Status: True
Type: EvictPod--druid-cluster-brokers-0
Last Transition Time: 2024-10-21T13:08:21Z
Message: check pod running; ConditionStatus:True; PodName:druid-cluster-brokers-0
Observed Generation: 1
Status: True
Type: CheckPodRunning--druid-cluster-brokers-0
Last Transition Time: 2024-10-21T13:08:26Z
Message: get pod; ConditionStatus:True; PodName:druid-cluster-routers-0
Observed Generation: 1
Status: True
Type: GetPod--druid-cluster-routers-0
Last Transition Time: 2024-10-21T13:08:26Z
Message: evict pod; ConditionStatus:True; PodName:druid-cluster-routers-0
Observed Generation: 1
Status: True
Type: EvictPod--druid-cluster-routers-0
Last Transition Time: 2024-10-21T13:08:31Z
Message: check pod running; ConditionStatus:True; PodName:druid-cluster-routers-0
Observed Generation: 1
Status: True
Type: CheckPodRunning--druid-cluster-routers-0
Last Transition Time: 2024-10-21T13:08:36Z
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-21T13:08:36Z
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-21T13:08:41Z
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-21T13:08:46Z
Message: Successfully completed update druid version
Observed Generation: 1
Reason: Successful
Status: True
Type: Successful
Observed Generation: 1
Phase: Successful
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Starting 21m KubeDB Ops-manager Operator Start processing for DruidOpsRequest: demo/druid-update-version
Normal UpdatePetSets 21m KubeDB Ops-manager Operator successfully reconciled the Druid with updated version
Warning get pod; ConditionStatus:True; PodName:druid-cluster-historicals-0 21m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:druid-cluster-historicals-0
Warning evict pod; ConditionStatus:True; PodName:druid-cluster-historicals-0 21m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:druid-cluster-historicals-0
Warning check pod running; ConditionStatus:False; PodName:druid-cluster-historicals-0 21m KubeDB Ops-manager Operator check pod running; ConditionStatus:False; PodName:druid-cluster-historicals-0
Warning check pod running; ConditionStatus:True; PodName:druid-cluster-historicals-0 18m KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:druid-cluster-historicals-0
Warning get pod; ConditionStatus:True; PodName:druid-cluster-middlemanagers-0 18m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:druid-cluster-middlemanagers-0
Warning evict pod; ConditionStatus:True; PodName:druid-cluster-middlemanagers-0 18m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:druid-cluster-middlemanagers-0
Warning check pod running; ConditionStatus:True; PodName:druid-cluster-middlemanagers-0 18m KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:druid-cluster-middlemanagers-0
Warning get pod; ConditionStatus:True; PodName:druid-cluster-brokers-0 17m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:druid-cluster-brokers-0
Warning evict pod; ConditionStatus:True; PodName:druid-cluster-brokers-0 17m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:druid-cluster-brokers-0
Warning check pod running; ConditionStatus:True; PodName:druid-cluster-brokers-0 17m KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:druid-cluster-brokers-0
Warning get pod; ConditionStatus:True; PodName:druid-cluster-routers-0 17m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:druid-cluster-routers-0
Warning evict pod; ConditionStatus:True; PodName:druid-cluster-routers-0 17m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:druid-cluster-routers-0
Warning check pod running; ConditionStatus:True; PodName:druid-cluster-routers-0 17m KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:druid-cluster-routers-0
Warning get pod; ConditionStatus:True; PodName:druid-cluster-coordinators-0 17m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:druid-cluster-coordinators-0
Warning evict pod; ConditionStatus:True; PodName:druid-cluster-coordinators-0 17m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:druid-cluster-coordinators-0
Warning check pod running; ConditionStatus:True; PodName:druid-cluster-coordinators-0 17m KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:druid-cluster-coordinators-0
Normal RestartPods 17m KubeDB Ops-manager Operator Successfully Restarted Druid nodes
Normal Starting 17m KubeDB Ops-manager Operator Resuming Druid database: demo/druid-cluster
Normal Successful 17m KubeDB Ops-manager Operator Successfully resumed Druid database: demo/druid-cluster for DruidOpsRequest: druid-update-version
Now, we are going to verify whether the Druid
and the related PetSets
and their Pods
have the new version image. Let’s check,
$ kubectl get dr -n demo druid-cluster -o=jsonpath='{.spec.version}{"\n"}'
30.0.0
$ kubectl get petset -n demo druid-cluster-brokers -o=jsonpath='{.spec.template.spec.containers[0].image}{"\n"}'
ghcr.io/appscode-images/druid:30.0.0@sha256:4cd60a1dc6a124e27e91ec52ca39e2b9ca6809df915ae2dd712a2dd7462626d7
$ kubectl get pods -n demo druid-cluster-brokers-0 -o=jsonpath='{.spec.containers[0].image}{"\n"}'
ghcr.io/appscode-images/druid:30.0.0
You can see from above, our Druid
has been updated with the new version. So, the updateVersion process is successfully completed.
Verify updated Druid Version from UI:
You can also see the version of druid cluster from the druid ui by following the steps described previously in this tutorial. Check Druid Version from UI
If you follow the steps properly, you should be able to see that the version is upgraded to 30.0.0
from the druid console as shown below.
Cleaning Up
To clean up the Kubernetes resources created by this tutorial, run:
kubectl delete druidopsrequest -n demo druid-update-version
kubectl delete dr -n demo druid-cluster
kubectl delete ns demo
Next Steps
- Detail concepts of Druid object.
- Different Druid topology clustering modes here.
- Monitor your Druid database with KubeDB using out-of-the-box Prometheus operator.
- Want to hack on KubeDB? Check our contribution guidelines.