Skip to Content
Cardinal Data LakeManual Install (Helm)

Manual Install (Helm)

This page covers installing Cardinal Data Lake yourself with Helm. A POC via the Helm chart is supported for a local or throwaway cluster. To have an AI agent do the install, give it the install skill.

We recommend the operator for every install — including production. The operator-managed install brings up Cardinal Data Lake and the Cardinal UI as a single unit and handles automatic upgrades, health monitoring, and clean removal for you — driven from app.cardinalhq.io . A manual Helm install means you own upgrades and monitoring yourself, so keep it to POCs.

For production or advanced installs (external S3 + Postgres at scale, air-gapped clusters, custom HA), use the operator and contact sales — we’ll help you size and harden the deployment.

Quick start (local cluster)

The fastest manual path — deploy Cardinal Data Lake on a local Kubernetes cluster with no cloud account required.

Quick Start

Up and running in minutes

Get Cardinal Data Lake deployed on a local Kubernetes cluster — no cloud account required.

Prerequisites

⎈
Kubernetes 1.33+or kind, minikube, etc.
⬡
Helm 3.14+Install guide
▸
1

Sign up for a Cardinal account

Create your free account at app.cardinalhq.io.

2

Download your Cardinal Data Lake Trial license

After signing in, download your trial license from the Cardinal dashboard.

3

Create the namespace

bash
kubectl create namespace lakerunner
4

Install using Helm

Use the configuration wizard to generate a values.yaml tailored to your environment, then install:

bash
helm install lakerunner oci://public.ecr.aws/cardinalhq.io/lakerunner \
  --values values.yaml \
  --namespace lakerunner
5

Verify the installation

Wait for all pods to become ready:

bash
kubectl get pods -n lakerunner -w
6

Access Grafana

If Grafana was included in your installation, port-forward it to your local machine:

bash
kubectl port-forward -n lakerunner svc/lakerunner-grafana 3000:3000

Open http://localhost:3000 in your browser. Cardinal Data Lake's data source is pre-configured, but you won't see any data yet — that comes in the next step.

7

Send data

Install OpenTelemetry Collectors to monitor your cluster and write telemetry to S3.

Generate data from your real applications, or use the OTel Demo Application to produce realistic logs, metrics, and traces right away.

Before you install

These apply to any install beyond the local quick start.

Kubernetes version

Use Kubernetes 1.33 or later. The chart’s README lists 1.28 as its minimum, but these docs only cover 1.33 and later.

Cluster size

At minimum replicas, the chart’s pods request about 16.3 vCPU and 29.5 GiB of memory, including Grafana and 2 pubsub-http pods. Add room for system overhead and for scale-up:

  • Each worker role can scale to 10 replicas. On a small cluster, lower process.<signal>.autoscaling.maxReplicas.
  • The query worker defaults to a 100Gi emptyDir scratch limit, which is close to the whole disk on nodes with about 120 GiB. Lower queryWorker.temporaryStorage.size to fit your nodes.

PostgreSQL connections

Set max_connections to at least 200. A minimum-replica install held 66 to 98 connections while idle, and scale-up adds more, so the common default of 100 runs out. When it does, control-plane crash-loops with:

remaining connection slots are reserved for roles with the SUPERUSER attribute (SQLSTATE 53300)

S3-compatible storage

Cardinal Data Lake only processes an object after it gets an event about it. Without events, the bucket fills, ingest stays idle, queries return nothing, and no error appears. Outside AWS, set the wizard’s S3 Endpoint, choose HTTP for notifications, and use one of these routes.

The store needs no event support, because the Cardinal collector’s awss3 exporter POSTs after each successful upload. It needs collector v1.7.0 or later. Add this to the gateway’s exporter config, using your Helm release name and namespace:

exporters: awss3: s3uploader: notifications: endpoint: http://<release>-pubsub-http.<namespace>.svc.cluster.local:8080/

This has limits:

  • The queue is in memory, and each delivery is tried 3 times by default.
  • A dropped notification leaves that object in the bucket unprocessed.
  • Anything else that writes to the bucket produces no event.

Bucket events

The store POSTs to the webhook itself, so it has to support webhook events. Set pubsub.HTTP.enabled: true and make the Service reachable from the store, because it defaults to ClusterIP (pubsub.HTTP.service.type).

The webhook:

  • Listens on port 8080 and accepts POST on any path.
  • Accepts the S3 Records JSON format.
  • Has no authentication, so restrict access by network if you expose it. On a LoadBalancer, use pubsub.HTTP.service.loadBalancerSourceRanges.

Configuration wizard

Use the interactive wizard below to generate a values.yaml for your deployment. Select your installation type and fill in the required details.

🔒 Privacy First: This wizard runs entirely in your browser. No data is sent to any server.

Installation Type

Organization Settings

Cardinal Data Lake is multi-tenant. Each tenant is an organization, and the collector and API key are used by that organization.

Click "Generate" to make a random ID, or enter one you have previously used.
Collector name is required and cannot be "default"
This will be used by Grafana and other tools to query telemetry for this organization.

Optional Components

Pre-configured Grafana with Cardinal Data Lake datasources

Cloud Provider

Only set for S3-compatible stores. These also need a way to deliver notifications: see S3-compatible storage.
Credentials will be provided by EKS via IAM Roles for Service Accounts (IRSA) or EKS Pod Identity. Ensure your cluster and service account are configured appropriately.

PostgreSQL - Cardinal Data Lake DB

lakerunner

PostgreSQL - Config DB

lakerunner

License

A valid license is required for Cardinal Data Lake to operate. Contact support@cardinalhq.io to obtain one.

Paste your license string (starts with b64: or z64:)

Scaling

Cardinal Data Lake uses internal autoscaling from 1 pod up to the max you set here.

ServiceMax Pods
Log Processing
Metric Processing
Trace Processing

Ingestion

Choose how S3 object notifications are ingested. HTTP provides a webhook endpoint. SQS polls from an AWS SQS queue. For S3-compatible stores, choose HTTP and see S3-compatible storage.

Recommend at least 2 for production

Generated values.yaml

Please complete all required fields (marked with *) above to generate your values.yaml configuration.

For the complete list of configuration options, see the full values.yaml reference on GitHub .

Post-installation

Verify the installation

After installation, verify all pods are running:

kubectl get pods -n lakerunner -l app.kubernetes.io/name=lakerunner

Access Grafana

Configure an Ingress or use port-forwarding to access Grafana:

kubectl port-forward -n lakerunner svc/lakerunner-grafana 3000:3000

Deploying on OpenShift

The chart renders cleanly under the restricted-v2 SCC with two adjustments. Add the following to the values.yaml produced by the wizard above:

1. Let the SCC assign UIDs

OpenShift’s restricted-v2 SCC rejects pods whose runAsUser/runAsGroup/fsGroup fall outside the namespace’s assigned UID range — it wants to inject them from the range itself. Null the fields so the chart emits only runAsNonRoot: true:

global: podSecurityContext: runAsNonRoot: true runAsUser: null runAsGroup: null fsGroup: null grafana: podSecurityContext: runAsNonRoot: true runAsUser: null runAsGroup: null fsGroup: null

The SCC fills in runAsUser, runAsGroup, and fsGroup. All other hardening from global.containerSecurityContext (no-privilege-escalation, drop ALL, RuntimeDefault seccomp, read-only rootfs) stays in effect.

2. Grafana needs an SCC that permits UID 472

The upstream grafana/grafana image expects UID 472 to own /var/lib/grafana. Because that UID almost never falls inside a namespace’s restricted-v2 range, Grafana needs either a custom SCC or an OpenShift-compatible image. The simplest path is:

oc adm policy add-scc-to-user nonroot-v2 -z <release>-lakerunner -n <namespace>

…and then keep Grafana’s defaults (UID 472). If you prefer to avoid the SCC grant, swap grafana.image.repository for an image that supports random UIDs.

3. Perch needs elevated RBAC

The Perch component ships with a ClusterRole that includes patch on apps/deployments cluster-wide — this is its legitimate function (cross-namespace deployment management), but it counts as a privileged grant. On clusters with strict RBAC review you may need admin approval or an oc adm policy add-role-to-user edit against the chart’s ServiceAccount.

4. Ingress / Routes

The chart uses standard networking.k8s.io/v1 Ingress resources. They work with the OpenShift HAProxy router out of the box; no nginx-specific annotations are emitted.

Upgrading

To upgrade an existing installation:

helm upgrade lakerunner oci://public.ecr.aws/cardinalhq.io/lakerunner \ --values values.yaml \ --namespace lakerunner

Uninstalling

To remove Cardinal Data Lake:

helm uninstall lakerunner --namespace lakerunner

Note: This does not delete your data in the cloud storage bucket.

Reach out to support@cardinalhq.io for support or to ask questions not answered in our documentation.

Last updated on