Installation
The QuestDB Enterprise Operator is available to named design partners on these tested combinations:
| Platform | Kubernetes | QuestDB Enterprise |
|---|---|---|
| Amazon EKS | 1.31–1.36 | 4.0.1 |
| Azure AKS | 1.33–1.36 | 4.0.1 |
Other Kubernetes distributions and versions are untested. Only the latest
release receives fixes; obtain its <operator-version> and private registry
credentials or AWS account grant from your QuestDB design-partner contact.
Before you install
The installer needs cluster-admin-equivalent access. The chart creates CRDs,
ClusterRoles, ClusterRoleBindings, a validating webhook, and resources in
questdb-operator-system. The controller and its RBAC are cluster-scoped so one
installation can reconcile tenants in multiple namespaces. QuestDBCluster,
QuestDBObjectStore, their referenced Secrets, Pods, PVCs, and Services remain
namespaced.
Check these prerequisites:
kubectlconfigured for the target cluster, Helm 3.10 or later, and the cloud CLI used by your onboarding guide.- A CSI driver and a
ReadWriteOnceStorageClass that applies podfsGroupand hasallowVolumeExpansion: true. Do not useReadWriteOncePod. - Enough schedulable CPU, memory, and zonal disk capacity for every database instance. QuestDB memory request and limit must be equal.
- Cluster DNS and network paths for the Kubernetes API server to reach the operator webhook on TCP 9443; the operator to reach tenant pods on TCP 8812 and 9003; and nodes/pods to reach the private image registry, object store, and cloud identity endpoints over HTTPS.
- Pull access for two private images. The operator pull credential belongs
in
questdb-operator-system; each database pull credential belongs in its tenant namespace and is named byspec.imagePullSecrets. Do not reuse a short-lived ECR login token as a long-lived Secret.
Follow the complete cloud checklist before installing:
Operator permissions
The chart binds the operator's ServiceAccount to the
questdb-operator-manager-role ClusterRole with a ClusterRoleBinding, so its
permissions apply in every namespace. There is no namespace-scoped install mode:
one operator watches QuestDBCluster objects in all namespaces.
The full list of rules is in the chart's templates/rbac/role.yaml.
The chart also creates a namespaced Role in the operator's namespace for leader
election (Leases, ConfigMaps, Events), and, when metrics are enabled, a
ClusterRole to create TokenReviews and SubjectAccessReviews so it can check who
is reading /metrics.
Secrets
The operator reads Secrets you point it at: the admin password
(spec.auth.adminSecret), object-store credentials, and PGWire TLS
certificates. It creates and updates Secrets of its own: a generated admin
password if you don't supply one, its own database login, the object-store
connection strings handed to the pods, and the webhook certificate in
self-signed mode.
It watches Secrets in every namespace so that a renewed TLS certificate takes effect, but it keeps only their metadata (names and labels) in memory, never the contents. It reads contents directly from the Kubernetes API when it needs them.
The role has no delete on Secrets, on purpose. The operator never deletes a
Secret. The ones it creates for a cluster are owned by that QuestDBCluster,
and Kubernetes removes them when you delete the cluster. The webhook certificate
Secret in the operator's namespace is never removed by the operator.
Object store
The operator never touches your object store and has no cloud permissions. It does not create or delete buckets, containers, or IAM roles, and never reads or writes your data there. The QuestDB pods do all object-store I/O, with the identity or credentials you configure.
Canonical Helm install
The OCI chart on GHCR is public; its operator image is private. Replace the
placeholders first. Your QuestDB contact supplies the current operator version
and, off AWS, static credentials for registry.distribution.questdb.io.
export OPERATOR_VERSION='<operator-version>'
export REGISTRY_USER='<registry-user>'
kubectl create namespace questdb-operator-system
read -r -s -p 'Registry password: ' REGISTRY_PASSWORD; echo
kubectl create secret docker-registry questdb-operator-registry \
--namespace questdb-operator-system \
--docker-server=registry.distribution.questdb.io \
--docker-username="$REGISTRY_USER" \
--docker-password="$REGISTRY_PASSWORD"
unset REGISTRY_PASSWORD
helm install questdb-operator oci://ghcr.io/questdb/charts/questdb-operator \
--namespace questdb-operator-system \
--version "$OPERATOR_VERSION" \
--set controllerManager.container.image.repository=registry.distribution.questdb.io/questdb-enterprise-operator \
--set-json 'controllerManager.imagePullSecrets=[{"name":"questdb-operator-registry"}]'
On EKS with QuestDB's cross-account ECR repository grant, kubelets pull through
the worker-node IAM role. Omit the Secret and both --set flags; do not use
IRSA for image pulls.
Verify the deployment and APIs:
kubectl rollout status deployment/questdb-operator-controller-manager \
--namespace questdb-operator-system --timeout=5m
kubectl get crd questdbclusters.questdb.io \
questdbobjectstores.questdb.io questdbpromotions.questdb.io
Expected result: the Deployment reports successfully rolled out, and all three
CRDs are listed.
Common safe values
| Value | Default | Guidance |
|---|---|---|
controllerManager.replicas | 1 | Keep at 1 unless QuestDB advises otherwise. |
crd.enable / crd.keep | true / true | Install CRDs and retain them on Helm uninstall. |
webhook.enable | true | Keep admission validation enabled. Reconcile-time validation remains a backstop. |
webhook.certMode | self-signed | The operator creates and rotates its serving certificate; cert-manager is not required. |
webhook.failurePolicy | Ignore | Fail-open avoids blocking cluster writes during a webhook outage. Use Fail only after accepting that availability trade-off. |
metrics.enable | true | Exposes authenticated HTTPS metrics on 8443. |
prometheus.enable | false | Requires Prometheus Operator ServiceMonitor CRDs. Bind the scraper identity to questdb-operator-metrics-reader. |
certmanager.enable | false | When combined with prometheus.enable=true, the chart issues and mounts a metrics serving certificate and renders a ServiceMonitor with certificate verification. Install cert-manager first. |
networkPolicy.enable | false | Selects the manager only. It restricts metrics ingress to namespaces labeled metrics=enabled and leaves webhook 9443 open for managed API servers. It does not create database/tenant ingress policy. |
Operator scheduling and availability
The chart can place and annotate the manager independently of database
spec.scheduling. Use controllerManager.nodeSelector, tolerations,
affinity, topologySpreadConstraints, and priorityClassName for the manager
Pod. Use controllerManager.pod.annotations, controllerManager.pod.labels,
controllerManager.serviceAccount.annotations, and
controllerManager.container.env for integration metadata and environment.
The default manager has one replica and leader election enabled, so only one
reconciler is active. The manager PDB is disabled by default because
replicas=1; enable it only after running multiple replicas across failure
domains, for example:
controllerManager:
replicas: 2
podDisruptionBudget:
enabled: true
minAvailable: 1
The manager PDB accepts integer and percentage minAvailable values. The
database CRD PDB uses an integer only.
Treat upgrades, rollback, and removal as separate lifecycle procedures; use the operator operations runbook rather than inferring them from installation commands.