You are looking at the documentation of a prior release. To read the documentation of the latest release, please
visit here.
New to KubeDB? Please start here.
Version Update Recommendation
Database versions often need to be updated. Older versions can carry CVEs that attackers exploit, newer versions include query/indexing/storage optimisations, and vendors keep shipping bug fixes and features. Staying on top of these upgrades is one of the most impactful and most easily forgotten maintenance tasks.
KubeDB watches the versions you actually have running and generates a Recommendation when it notices any of these:
- The current version’s container image has been updated.
- A newer major or minor version is available.
- A patch release is available for your current minor.
Note:
Recommendationworks for most KubeDB-managed databases. The walkthrough below uses Elasticsearch as a concrete example.
Before you begin
- A Kubernetes cluster with KubeDB and the Supervisor installed. The easiest way is
--set supervisor.enabled=truewhen installing KubeDB via Helm. kubectlconfigured to talk to the cluster.- Familiarity with the Recommendation Spec & Status page is helpful but not required.
How a version-update recommendation flows
Recommendation is a Kubernetes Custom Resource Definition (CRD) that declares a maintenance action for a KubeDB-managed database like Elasticsearch or OpenSearch. The Ops-manager creates it; the Supervisor schedules and executes it.
Let’s walk through a complete demo. First, list the Elasticsearch versions provided by KubeDB:
$ kubectl get elasticsearchversions | grep xpack
xpack-6.8.23 6.8.23 ElasticStack ghcr.io/appscode-images/elastic:6.8.23 12d
xpack-7.17.15 7.17.15 ElasticStack ghcr.io/appscode-images/elastic:7.17.15 12d
xpack-7.17.28 7.17.28 ElasticStack ghcr.io/appscode-images/elastic:7.17.28 12d
xpack-8.17.10 8.17.10 ElasticStack ghcr.io/appscode-images/elastic:8.17.10 12d
xpack-8.17.6 8.17.6 ElasticStack ghcr.io/appscode-images/elastic:8.17.6 12d
xpack-8.18.2 8.18.2 ElasticStack ghcr.io/appscode-images/elastic:8.18.2 12d
xpack-8.18.8 8.18.8 ElasticStack ghcr.io/appscode-images/elastic:8.18.8 12d
xpack-8.19.9 8.19.9 ElasticStack ghcr.io/appscode-images/elastic:8.19.9 12d
xpack-8.2.3 8.2.3 ElasticStack ghcr.io/appscode-images/elastic:8.2.3 12d
xpack-8.5.3 8.5.3 ElasticStack ghcr.io/appscode-images/elastic:8.5.3 12d
xpack-9.0.2 9.0.2 ElasticStack ghcr.io/appscode-images/elastic:9.0.2 12d
xpack-9.0.8 9.0.8 ElasticStack ghcr.io/appscode-images/elastic:9.0.8 12d
xpack-9.1.4 9.1.4 ElasticStack ghcr.io/appscode-images/elastic:9.1.4 12d
xpack-9.1.9 9.1.9 ElasticStack ghcr.io/appscode-images/elastic:9.1.9 12d
xpack-9.2.3 9.2.3 ElasticStack ghcr.io/appscode-images/elastic:9.2.3 12d
We will deliberately deploy an older version, xpack-9.1.9, so KubeDB will recommend the upgrade to xpack-9.2.3:
apiVersion: kubedb.com/v1
kind: Elasticsearch
metadata:
name: es-vurecommendation
namespace: demo
spec:
version: xpack-9.1.9
replicas: 3
storageType: Durable
storage:
storageClassName: local-path
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
deletionPolicy: WipeOut
Wait until the Elasticsearch cluster reports Ready. The required time depends on image pull speed and node specs.
$ kubectl get elasticsearch,pods -n demo
NAME VERSION STATUS AGE
elasticsearch.kubedb.com/es-vurecommendation xpack-9.1.9 Ready 3m43s
NAME READY STATUS RESTARTS AGE
pod/es-vurecommendation-0 1/1 Running 0 3m37s
pod/es-vurecommendation-1 1/1 Running 0 3m30s
pod/es-vurecommendation-2 1/1 Running 0 3m25s
Once the Elasticsearch instance is Ready, the KubeDB Ops-manager creates a Recommendation automatically. It can take a couple of minutes for the create-event to be reconciled.
$ kubectl get recommendation -n demo
NAME STATUS OUTDATED AGE
es-vurecommendation-x-elasticsearch-x-update-version-t7dy9o Pending false 2m49s
The Recommendation name follows the pattern <DB-name>-x-<DB-type>-x-<recommendation-type>-<random-suffix>. Initially the Supervisor sets status.phase: Pending. Let’s look at the full manifest:
$ kubectl get recommendation -n demo es-vurecommendation-x-elasticsearch-x-update-version-t7dy9o -oyaml
apiVersion: supervisor.appscode.com/v1alpha1
kind: Recommendation
metadata:
annotations:
kubedb.com/recommendation-for-version: xpack-9.1.9
creationTimestamp: "2026-06-08T16:44:12Z"
generation: 1
labels:
app.kubernetes.io/instance: es-vurecommendation
app.kubernetes.io/managed-by: kubedb.com
app.kubernetes.io/type: version-update
kubedb.com/version-update-recommendation-type: major-minor
name: es-vurecommendation-x-elasticsearch-x-update-version-t7dy9o
namespace: demo
spec:
backoffLimit: 10
description: Latest Major/Minor version is available. Recommending version Update
from xpack-9.1.9 to xpack-9.2.3.
operation:
apiVersion: ops.kubedb.com/v1alpha1
kind: ElasticsearchOpsRequest
metadata:
name: update-version
namespace: demo
spec:
databaseRef:
name: es-vurecommendation
type: UpdateVersion
updateVersion:
targetVersion: xpack-9.2.3
status: {}
recommender:
name: kubedb-ops-manager
requireExplicitApproval: true
rules:
failed: has(self.status) && has(self.status.phase) && self.status.phase == 'Failed'
inProgress: has(self.status) && has(self.status.phase) && self.status.phase == 'Progressing'
success: has(self.status) && has(self.status.phase) && self.status.phase == 'Successful'
target:
apiGroup: kubedb.com
kind: Elasticsearch
name: es-vurecommendation
status:
approvalStatus: Pending
failedAttempt: 0
outdated: false
parallelism: Namespace
phase: Pending
reason: WaitingForApproval
What this manifest tells you:
spec.description— a new Major/Minor version (xpack-9.2.3) is available; KubeDB recommends upgrading fromxpack-9.1.9.spec.operation— the recommended action is anElasticsearchOpsRequestof typeUpdateVersionwithupdateVersion.targetVersion: xpack-9.2.3.spec.requireExplicitApproval: true— version updates always require explicit human approval, because an upgrade can involve breaking changes or compatibility concerns. Auto-approval via anApprovalPolicyis intentionally bypassed.status.approvalStatus: Pending/status.reason: WaitingForApproval— nothing will run until you approve it.
Approving the recommendation
Approve via the AppsCode UI, or with kubectl:
$ kubectl patch Recommendation es-vurecommendation-x-elasticsearch-x-update-version-t7dy9o \
-n demo \
--type merge \
--subresource='status' \
-p '{"status":{"approvalStatus":"Approved","approvedWindow":{"window":"Immediate"}}}'
recommendation.supervisor.appscode.com/es-vurecommendation-x-elasticsearch-x-update-version-t7dy9o patched
A new condition appears almost immediately confirming the OpsRequest was created:
$ kubectl get recommendation -n demo es-vurecommendation-x-elasticsearch-x-update-version-t7dy9o -o jsonpath='{.status}'
{"approvalStatus":"Approved","approvedWindow":{"window":"Immediate"},"conditions":[{"lastTransitionTime":"2026-06-08T16:47:29Z","message":"OpsRequest is successfully created","reason":"SuccessfullyCreatedOperation","status":"True","type":"SuccessfullyCreatedOperation"}],"createdOperationRef":{"name":"es-vurecommendation-1780937248-update-version-auto"},"failedAttempt":0,"outdated":false,"parallelism":"Namespace","phase":"InProgress","reason":"StartedExecutingOperation"}
The Supervisor has now created an ElasticsearchOpsRequest and is upgrading the cluster to xpack-9.2.3 with negligible downtime. The Supervisor will keep retrying on transient failures up to spec.backoffLimit attempts.
$ kubectl get elasticsearchopsrequest -n demo
NAME TYPE STATUS AGE
es-vurecommendation-1780937248-update-version-auto UpdateVersion Successful 2m39s
Once the OpsRequest succeeds, the Recommendation rolls into Succeeded:
$ kubectl get recommendation -n demo es-vurecommendation-x-elasticsearch-x-update-version-t7dy9o
NAME STATUS OUTDATED AGE
es-vurecommendation-x-elasticsearch-x-update-version-t7dy9o Succeeded false 5m55s
The Elasticsearch cluster is now on the target version:
$ kubectl get es es-vurecommendation -n demo
NAME VERSION STATUS AGE
es-vurecommendation xpack-9.2.3 Ready 6m50s
Rejecting a recommendation
If you do not want a recommendation to run, set its approvalStatus to Rejected:
$ kubectl patch Recommendation es-vurecommendation-x-elasticsearch-x-update-version-t7dy9o \
-n demo \
--type merge \
--subresource='status' \
-p '{"status":{"approvalStatus":"Rejected"}}'
recommendation.supervisor.appscode.com/es-vurecommendation-x-elasticsearch-x-update-version-t7dy9o patched
Automating execution
Approving every recommendation by hand defeats the point. For routine maintenance you can have the Supervisor approve and run recommendations automatically — but only inside a window of your choosing (off-peak hours, weekends, etc.).
Note: Because version updates set
requireExplicitApproval: true, ApprovalPolicies do not auto-approve them. The pattern below applies to recommendation types where a human approval is not mandatory (e.g. TLS or auth secret rotation). It is shown here for reference because the sameMaintenanceWindowresource is used for those flows.
1. Define a MaintenanceWindow
A MaintenanceWindow says when ops are allowed to run. See Maintenance Window for the full reference.
apiVersion: supervisor.appscode.com/v1alpha1
kind: MaintenanceWindow
metadata:
name: elastic-maintenance
namespace: demo
spec:
isDefault: true
timezone: UTC
days:
Sunday:
- start: "00:00"
end: "04:00"
Saturday:
- start: "00:00"
end: "04:00"
2. Auto-approve with an ApprovalPolicy
An ApprovalPolicy says what gets auto-approved and links to the window above. See Approval Policy for the full reference.
apiVersion: supervisor.appscode.com/v1alpha1
kind: ApprovalPolicy
metadata:
name: elasticsearch-policy
namespace: demo
maintenanceWindowRef:
kind: MaintenanceWindow
name: elastic-maintenance
namespace: demo
targets:
- group: kubedb.com
kind: Elasticsearch
operations:
- group: ops.kubedb.com
kind: ElasticsearchOpsRequest
3. Or use a cluster-wide default
If you want one default schedule for the whole cluster, swap the namespace-scoped MaintenanceWindow for a ClusterMaintenanceWindow and point maintenanceWindowRef.kind at it. See Cluster Maintenance Window.
For the complete field reference for Recommendation, see Recommendation Spec & Status.































