Overview
ClickHouse is a column-oriented analytical database for real-time querying and data warehousing at scale. This template deploys ClickHouse in single-node or cluster mode — the mode is derived from thelocations list — with object storage (AWS S3, GCS, Azure Blob Storage, or Hetzner Object Storage) as the primary store for table data and a persistent volume for metadata and a local read cache.
The database password is not a template value. ClickHouse reads it from a dictionary secret you create before installing, so it never passes through Helm or lands in the release.
--gvc GVC_NAME at install time. Every location you list in locations must already be on that GVC, and a GVC location you did not list simply starts nothing.Deployment Modes
Thelocations list is the topology, not just placement: its length selects the mode, and a location’s position in the list is that shard’s number.
What Gets Created
/var/lib/clickhouse_cache and temporary spill space at /var/lib/clickhouse-tmp. Table data lives in your bucket in every mode; the volume set holds metadata and cache only. The template creates no credential secret: the password exists only in the secret you create.
Prerequisites
Three things must be in place before you install: a GVC with the right locations, a credentials secret, and object storage for the provider you choose. Secrets are org-level, so no--gvc flag is involved when creating them.
Have a GVC that contains every location you will list
locations. It may have more locations than you list — nothing ClickHouse-related runs in those. Check what a GVC has before installing; the locations are under spec.staticPlacement.locationLinks:cpln gvc add-location. Add locations to a shared GVC deliberately — other workloads in that GVC run in every location it has.Create the credentials secret
password and database. ClickHouse authenticates as its built-in default user, so there is no username key:database.credentialsSecretName to the name you used. Secret names are org-wide, so give each release its own.Set up object storage for one provider
provider to aws, gcp, azure or hetzner. AWS is the only keyless option; the other three each need their own prerequisite dictionary secret.Read a secret back later
-o yaml; a bare cpln secret reveal prints only a summary table, not the values:Object Storage
Complete the steps for exactly one provider. Only the active provider’s values are used.AWS S3
Access comes from a Control Plane cloud account through the workload identity, so there is no key to store.-
Create an S3 bucket. Set
aws.bucketto its name andaws.regionto its region. -
If you do not have one yet, create a Control Plane cloud account for the AWS account holding the bucket. Set
aws.cloudAccountNameto its name. -
Create an IAM policy scoped to exactly that bucket, replacing
YOUR_BUCKET_NAME, and setaws.policyNameto its name:
GCS
ClickHouse reaches GCS over its S3-compatible interface, which requires an interoperability HMAC key. A cloud account is not required.-
Create a GCS bucket. Set
gcp.bucketto its name. -
In the Google Cloud console, open Cloud Storage → Settings → Interoperability and choose Create a key for a service account. Create a new service account (or pick one) and grant it the Storage Object Admin (
roles/storage.objectAdmin) role. -
Store the HMAC pair in a dictionary secret holding exactly the keys
accessKeyIdandsecretAccessKey, and setgcp.credentialsSecretNameto its name:
gcloud CLI:
Azure Blob Storage
ClickHouse uses Azure’s native Blob Storage SDK, authenticating with a storage account access key. A cloud account is not required.-
In the Azure Portal, go to Storage accounts → Create. Use Standard performance, LRS redundancy, and leave hierarchical namespace off. Set
azure.storageAccountto the account name. -
Inside the storage account, go to Containers → + Container and create a container with the access level Private. Set
azure.containerto its name. -
Go to Security + networking → Access keys and copy either
key1orkey2. -
Store the key in a dictionary secret holding exactly the key
accountKey, and setazure.credentialsSecretNameto its name:
Hetzner Object Storage
Hetzner Object Storage is S3-compatible and authenticates with an access key pair. A cloud account is not required. Available regions arenbg1 (Nuremberg), hel1 (Helsinki) and fsn1 (Falkenstein).
-
In the Hetzner Cloud console, go to Object Storage and create a bucket. Set
hetzner.bucketto its name andhetzner.regionto its region. - Go to Security → S3 Credentials and choose Generate credentials. Save the access key and secret key immediately — the secret is not shown again.
-
Store the pair in a dictionary secret holding exactly the keys
accessKeyIdandsecretAccessKey, and sethetzner.credentialsSecretNameto its name:
Installation
With the prerequisites in place, install into your existing GVC. The default provider is AWS, so a default install needs the credentials secret and the fouraws values:
locations entry is aws-us-east-1 with one replica. If your GVC does not have that location, or you want a cluster, set locations (and any other provider’s values) in a values file passed with -f, as shown in the CLI guide. Or follow the instructions for your preferred method:
UI
CLI
Terraform
Pulumi
Configuration
Locations
replicas: 0 are all refused at render.
This workload location is deactivated because maxScale is set to 0. That is what a healthy install looks like in a shared GVC, not a fault.Provider and Object Storage
provider and fill in the matching section; the setup steps for each are under Object Storage. Only the active provider’s section is read, its storage configuration secret is the only one created, and its credentials secret (for gcp, azure and hetzner) is the only one the policy grants reveal on.
Cluster and Database
clusterName is the name used in ON CLUSTER DDL and Distributed tables in cluster modes; anything other than a bare identifier is refused at render. The database key of your credentials secret names the database created at first start (with ON CLUSTER in cluster modes), and the password key is the password every client connection uses.
Volumes
Server and Keeper
keeper is only read in cluster modes. Neither workload is exposed publicly, and the template has no public access option; internalAccess controls which workloads can reach each component:
workload-list, list only your clients. The server and Keeper reach each other over the same internal firewall, so the chart adds this release’s own server and Keeper workloads to every list it renders. Access changes can take a few minutes to take effect.Connecting
.GVC_NAME.cpln.local form; the bare workload name is not reliable. From another workload in the same GVC:
clickhouse-client inside the server container:
Tables in Cluster Modes
UseReplicatedMergeTree plus a Distributed table. A plain MergeTree in a multi-shard cluster is single-copy and is not covered by the cluster’s availability story.
{shard} and {replica} come from each node’s <macros>, which the chart derives from the location’s position in locations and the replica’s index.
Operations
Backing Up
The template ships no backup job. Table data lives in your bucket and the volume set holds only metadata and the object-storage disk metadata that points at those objects, so a volume set snapshot on its own is not a backup of your data — merges continually replace the objects the snapshot’s metadata refers to. The volume sets do take a final snapshot when deleted, kept for 7 days, which protects against an accidental uninstall but not against data loss inside ClickHouse. For a restorable copy, use ClickHouse’s ownBACKUP statement to write to a separate bucket or path, as documented in the upstream backup and restore guide:
BACKUP ... TO S3(...) has not been exercised on this template. The statement is upstream’s documented form; run it against your own install and confirm the objects land before relying on it. In cluster modes, run it on each shard’s replica (the statement backs up the replica it runs on), or back up the Distributed table’s underlying local table per shard.Restoring a Backup
Upstream’s documented form restores into the same or a different table name:Rotating the Password
The server startup script writes thepassword key of your credentials secret into ClickHouse’s user configuration every time a replica starts, so a rotation takes effect when the replicas restart with the new value. Workloads resolve a secret only at replica start, so updating the secret alone changes nothing on a running replica.
Update the secret
database key unchanged — it names the database created at first start, and a different value makes the next start create an additional database rather than renaming the existing one:Force a redeployment of the server
Update your clients
Upgrading from 2.x
Template versions through 2.8.0 created their own GVC, so that GVC is part of a 2.x release’s manifest. Version 3.0.0 does not declare a GVC, and Helm deletes what a chart stops declaring. What changed between 2.x and 3.0.0:Recover the password the existing cluster uses
Choose the GVC for the new release
locations. See Prerequisites.Install 3.0.0 as a new release into that GVC
Reload your data
Cut over, then uninstall the old release
Scaling and Availability
locations[].replicasadds replicas to a shard; adding locations adds shards. A location’s position inlocationsis its shard number and the first three host Keeper, so settle the topology before loading data — existing replicated table paths and macros are derived from that position.- Keeper is the availability floor. The three-member group in a multi-shard cluster tolerates the loss of one member; the single-shard cluster has one member and tolerates none. If a majority of the Keeper locations are missing from the GVC, the containers exit with a named error rather than waiting for an election that can never complete.
- With one replica per shard, losing a shard fails every distributed query, not just the rows on that shard. Add replicas per location if partial results are not acceptable.
- A
cpln helm upgraderestarts every replica in every location at once, including the first upgrade after an install even when nothing changed. Plan each one as a query interruption. - A node failure reschedules a replica and reattaches the same volume set; table data in the bucket is unaffected.
- Keep every location and the bucket in the same cloud provider and region family. Cross-region traffic to object storage is billed on every query that misses the local cache.
Troubleshooting
Workload never becomes ready and cpln logs returns nothing
Workload never becomes ready and cpln logs returns nothing
RELEASE_NAME-clickhouse-server never becomes ready, and cpln logs '{gvc="GVC_NAME", workload="RELEASE_NAME-clickhouse-server"}' --limit 50 --since 10m returns zero lines.Cause: a credentialsSecretName names a secret that does not exist, so the container is never started. The message is only visible in status.versions[].message:cpln workload force-redeployment RELEASE_NAME-clickhouse-server --gvc GVC_NAME.Container exits with FATAL: locations declared in values are not in GVC
Container exits with FATAL: locations declared in values are not in GVC
locations names a location the GVC does not have. The platform does not validate this at install time, so each container checks its GVC at start. A node that is already initialized logs a WARNING instead and keeps serving, so this check never takes down a running cluster.Fix: add the missing location to the GVC (see Prerequisites) or remove it from locations, then upgrade.Container exits with FATAL: Keeper quorum is unreachable
Container exits with FATAL: Keeper quorum is unreachable
0 of the first three entries in locations, and fewer than a majority of those locations exist in the GVC.Fix: add the missing locations to the GVC, or remove them from locations so the first three entries are all locations the GVC has.A location shows zero replicas and 'deactivated because maxScale is set to 0'
A location shows zero replicas and 'deactivated because maxScale is set to 0'
cpln workload get-deployments RELEASE_NAME-clickhouse-server --gvc GVC_NAME -o yaml shows a location with no replicas and the message This workload location is deactivated because maxScale is set to 0.Cause: that GVC location is not in locations. This is expected — the template runs nothing in GVC locations you did not declare. If every location shows it, none of your locations entries matches a location on the GVC, so nothing starts and there is no container to log an error.Fix: nothing, when the location is one you did not intend to use. Otherwise compare locations against spec.staticPlacement.locationLinks from cpln gvc get GVC_NAME -o yaml and correct whichever side is wrong.Install or upgrade is refused at render with a clickhouse validation message
Install or upgrade is refused at render with a clickhouse validation message
cpln helm install or cpln helm upgrade stops before creating anything with one of:locations, clusterName, provider and every credentialsSecretName at render time, and refuses shapes that cannot work.Fix: follow the message — use one or three-plus locations, a bare-identifier clusterName, a supported provider, and a non-empty secret name for the active provider. Your running release is unaffected until the upgrade succeeds.helm upgrade is refused with 'the gvc values key was REMOVED'
helm upgrade is refused with 'the gvc values key was REMOVED'
gvc key. The refusal is deliberate — the upgrade it blocks would delete the GVC the 2.x chart created.Fix: do not retry the upgrade with the key removed. Install 3.0.0 as a new release against an existing GVC, reload the data, and remove the old release as described in Upgrading from 2.x.Bootstrap fails with FATAL: Keeper quorum was not reachable within 300s
Bootstrap fails with FATAL: Keeper quorum was not reachable within 300s
ON CLUSTER, which needs Keeper. It waits a bounded time for Keeper quorum rather than looping forever.Fix: check that RELEASE_NAME-clickhouse-keeper is ready in each of the first three locations with cpln workload get-deployments RELEASE_NAME-clickhouse-keeper --gvc GVC_NAME -o yaml, and read its logs with cpln logs '{gvc="GVC_NAME", workload="RELEASE_NAME-clickhouse-keeper"}' --limit 50 --since 10m. Once Keeper is up the server replica is restarted automatically and bootstraps the database.Distributed queries fail with Code: 701 CLUSTER_DOESNT_EXIST
Distributed queries fail with Code: 701 CLUSTER_DOESNT_EXIST
Distributed table fail with Code: 701 ... Requested cluster 'my_cluster' not found (CLUSTER_DOESNT_EXIST).Cause: clusterName was changed on an existing install. Distributed tables keep the cluster name they were created with.Fix: drop and recreate the Distributed tables with the new cluster name, or restore the previous clusterName.Changing internalAccess appears to have no effect
Changing internalAccess appears to have no effect
helm upgrade that changed server.internalAccess or keeper.internalAccess, clients still get the old answer.Cause: firewall changes take a few minutes to propagate.Fix: wait and re-test before concluding the setting is broken.Important Notes
- Never run
cpln helm upgradeon a 2.x release against 3.0.0 — it deletes the GVC the 2.x chart created and everything in it. Install a new release: Upgrading from 2.x. - Create the credentials secret before installing. A missing one wedges the deployment with no log output;
cpln workload get-deploymentsis the one command that names it. - The GVC must contain every location you list, and may contain more. Undeclared GVC locations run nothing.
- Two locations is not supported. Use one (single-node or single-shard) or three or more.
- Object storage is required in every mode, including single-node. There is no local-only shape.
- The credentials secret has no
usernamekey — ClickHouse authenticates as its built-indefaultuser. - Rotating the password requires a forced redeployment of the server workload to take effect.
- Switch object-storage providers with a fresh install, not an upgrade.
- Renaming
clusterNameorphans existingDistributedtables (Code: 701). Recreate them after a rename. - A
helm upgraderestarts every replica in every location at once. Plan it as a query interruption. - Uninstalling deletes the volume sets (a final snapshot is kept for 7 days) but leaves your bucket and your secrets in place.