Skip to content

Prerequisites

Before you begin the installation of DataQI, ensure that your environment meets the following requirements.

  • A supported Kubernetes distribution (e.g., AKS, OpenShift, RKE2, or vanilla Kubernetes). If you are deploying to OpenShift, refer to the OpenShift installation guide for platform-specific requirements.
  • Kubernetes version 1.28 or higher.
  • At least 4 vCPUs and 16GB of RAM available for the core DataQI components.
  • A default StorageClass configured for dynamic volume provisioning. If your cluster lacks a default storage class, you must explicitly set platform.storageClass.default: "your-class-name" in your values.yaml file so the PostgreSQL database instances can start up. Additionally, you must override the upstream NATS JetStream storage class by setting nats.config.jetstream.fileStore.pvc.storageClassName: "your-class-name".
  • A StorageClass that supports ReadWriteMany (RWX) access modes (e.g., Azure Files or CephFS) for both application file store claims. Set platform.storageClass.shared to use one class for both claims, or set platform.sharedFilesystem.storageClass and platform.persistentFilesystem.storageClass independently. The persistent class should support the backup or snapshot policy required by your organisation.

You will need the following tools installed on your local machine or host:

  • kubectl configured with administrative access to your target cluster.
  • helm

DataQI images and Helm charts are hosted in a secure, private container registry.

You must obtain the registry credentials from your DataQI account representative. These credentials will be used to create the image pull secret in your cluster and to authenticate your local Helm client. Please download and securely store these credentials once you receive them.

To successfully route traffic to your DataQI installation, your cluster must have the following networking infrastructure established:

  • Gateway API implementation: A Gateway API controller (such as NGINX Gateway Fabric, Cilium, or Azure Application Gateway for Containers) to handle incoming HTTP/HTTPS traffic. Standard Kubernetes Ingress is also supported via routing.type: ingress.
  • DNS configuration: You must own a base domain (e.g., dataqi.yourdomain.com) to configure the chart. You must be able to create DNS records (A or CNAME) pointing this domain to the public IP address or FQDN of your cluster’s load balancer.
  • TLS: DataQI supports four TLS modes — cert-manager automation, pre-provisioned secrets, external termination (Cloudflare, WAF), and plain HTTP for development. See the TLS certificate configuration guide for details.

DataQI relies on two Kubernetes Operators that must be installed on the cluster before deploying the Helm chart. These operators extend Kubernetes with Custom Resource Definitions (CRDs) that the DataQI chart uses to declare its database and identity infrastructure.

CNPG manages the PostgreSQL database clusters used by DataQI.

For all other installations, apply the operator manifest once per cluster before deploying the Helm chart:

Terminal window
# Install the CNPG operator (check for the latest stable version at https://cloudnative-pg.io)
kubectl apply --server-side -f \
https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.25/releases/cnpg-1.25.1.yaml

Verify the operator is running:

Terminal window
kubectl get deployment -n cnpg-system cnpg-controller-manager

The Keycloak Operator manages the identity server used by DataQI. It handles pod lifecycle, rolling upgrades, and high-availability clustering.

The DataQI Helm chart deploys the operator per-namespace — each environment gets its own operator instance with namespace-scoped RBAC only. No cluster-wide bindings are required.

However, Custom Resource Definitions (CRDs) and ClusterRoles are inherently cluster-scoped and must be installed once by a cluster administrator:

Terminal window
# Install the CRDs (cluster-scoped — required once per cluster)
kubectl apply -f https://raw.githubusercontent.com/keycloak/keycloak-k8s-resources/refs/tags/26.6.1/kubernetes/keycloaks.k8s.keycloak.org-v1.yml
kubectl apply -f https://raw.githubusercontent.com/keycloak/keycloak-k8s-resources/refs/tags/26.6.1/kubernetes/keycloakrealmimports.k8s.keycloak.org-v1.yml
# Install the ClusterRoles (permission definitions only — they grant nothing
# without a binding). The Helm chart creates namespace-scoped RoleBindings
# referencing these ClusterRoles.
kubectl apply -f - <<'EOF'
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: keycloakcontroller-cluster-role
labels:
app.kubernetes.io/name: keycloak-operator
rules:
- apiGroups: ["k8s.keycloak.org"]
resources: ["keycloaks", "keycloaks/status", "keycloaks/finalizers"]
verbs: ["get", "list", "watch", "patch", "update", "create", "delete"]
- apiGroups: [""]
resources: ["services"]
verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
- apiGroups: ["apps"]
resources: ["statefulsets"]
verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses", "networkpolicies"]
verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["create", "delete", "get", "list", "watch"]
- apiGroups: ["monitoring.coreos.com"]
resources: ["servicemonitors"]
verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: keycloakrealmimportcontroller-cluster-role
labels:
app.kubernetes.io/name: keycloak-operator
rules:
- apiGroups: ["k8s.keycloak.org"]
resources: ["keycloakrealmimports", "keycloakrealmimports/status", "keycloakrealmimports/finalizers"]
verbs: ["get", "list", "watch", "patch", "update", "create", "delete"]
- apiGroups: ["batch"]
resources: ["jobs"]
verbs: ["create", "delete", "get", "list", "patch", "watch"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
EOF

Verify the CRDs are installed:

Terminal window
kubectl get crd keycloaks.k8s.keycloak.org keycloakrealmimports.k8s.keycloak.org