Overview
ClickHouse is a high-performance, column-oriented analytical database designed for real-time querying and data warehousing at scale. This template deploys ClickHouse in either single-node or cluster mode depending on how locations are configured, backed by object storage (AWS S3, GCS, Azure Blob Storage, or Hetzner Object Storage) for the table data and a local volume for metadata and fast read caching. 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.Deployment Modes
Thelocations list is the topology, not just placement — its length selects the mode, and a location’s position in it is that shard’s number.
What Gets Created
- Stateful ClickHouse Server Workload — The analytical database itself, with configurable replicas per location.
- Stateful ClickHouse Keeper Workload (cluster modes only) — The Raft coordination service, one replica in each of the first three locations.
- Volume Sets — Persistent storage for the server (metadata,
store/and system files) and, in cluster modes, for Keeper. Table data lives in object storage; the volume is metadata and read cache. - Scratch Volumes — Local filesystem cache and temporary spill.
- Secrets — Startup script secrets for ClickHouse Server and Keeper, and a storage configuration secret for the selected provider. No credential secret — the password lives only in the prerequisite secret you create.
- Identity & Two Policies — An identity bound to the workloads, with
revealon the template’s own secrets plus exactly the secrets you created,viewon the one GVC you install into so each container can confirm at boot that the GVC really has every location you listed, and cloud access to the bucket when the provider is AWS.
This template does not create a GVC. It deploys into a GVC you already have — every resource lands in the GVC you install into, so
cpln workload exec, cpln logs and uninstalling all work against that GVC, and uninstalling can never delete it. Every location you list in locations must already be on that GVC, and a GVC location you did not list simply runs nothing.Architecture
In multi-shard mode, each of the first three locations runs one ClickHouse Keeper replica, forming a 3-node quorum for distributed coordination. ClickHouse Server replicas reach Keeper over Control Plane’s internal DNS. In single-node mode, no Keeper is deployed. Primary data is stored in the configured object storage bucket in every mode; a local scratch volume serves as a fast read cache.To minimize network egress costs, deploy all locations in the same cloud provider and keep your object storage bucket in the same region family. One server replica per location is enough for most cluster deployments.
Prerequisites
Three things must be in place before you install: a GVC with the right locations, a credentials secret, and object storage access for your chosen provider.A GVC with your locations
A GVC must already exist, and it must contain every location you list inlocations. The requirement is one-directional — the GVC may have more locations than you list, and nothing ClickHouse-related runs in those. Check what a GVC has before installing:
spec.staticPlacement.locationLinks. To add a missing one:
Database credentials
One secret must exist before you install. It holds the password every ClickHouse client connection uses, so it is not a value — a value would leave it in the Helm release.1
Create the credentials secret
A dictionary secret holding exactly two keys — Set
password and database:database.credentialsSecretName to the name you used. Secret names are org-wide, so give each release its own.2
Read the secret back later
Pass
-o yaml. A bare cpln secret reveal prints only a summary table, not the values:There is no
username key. ClickHouse authenticates as its built-in default user here, so the secret holds only the password and the database name.Object storage
Object storage is required in every deployment mode, including single-node — there is no local-only shape. Choose one provider and complete its setup below. AWS is the only keyless option: access comes from a Cloud Account through the workload identity, so there is no key to store. The other three each need their own prerequisite dictionary secret.AWS S3
-
Create an S3 bucket. Set
aws.bucketto its name andaws.regionto its region. -
If you do not have a Control Plane Cloud Account set up, follow the Create a Cloud Account guide. Set
aws.cloudAccountNameto its name. -
Create an IAM policy with the following JSON, 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 the bucket name. - In the GCP console, navigate to Settings > Interoperability and click Create a key for a service account.
- Click Create new account, name your service account, and assign the Storage Object Admin role under Permissions.
-
Store the generated HMAC key in a dictionary secret, and set
gcp.credentialsSecretNameto that secret’s name:
gcloud CLI:
Azure Blob Storage
ClickHouse uses Azure’s native Blob Storage SDK. A Cloud Account is not required — authentication uses a storage account access key.- In the Azure Portal, go to Storage accounts → Create. Use Standard performance, LRS redundancy, and leave hierarchical namespace off.
-
Inside the storage account, go to Containers → + Container and create a container (e.g.
clickhouse-data). Set access level to Private. Setazure.storageAccountandazure.container. -
Go to Security + networking → Access keys and copy either
key1orkey2. -
Store the key in a dictionary secret, and set
azure.credentialsSecretNameto that secret’s name:
Hetzner Object Storage
Hetzner Object Storage is S3-compatible. A Cloud Account is not required — authentication uses an access key pair. Available regions:-
In the Hetzner Cloud console, go to Object Storage and create a bucket. Set
hetzner.bucketandhetzner.region. - Go to Security → S3 Credentials and click Generate credentials. Save the access key and secret key immediately — the secret will not be shown again.
-
Store the pair in a dictionary secret, and set
hetzner.credentialsSecretNameto that secret’s name:
Installation
Create the prerequisite secrets first, then install by whichever method you prefer:UI
Browse, install, and manage templates visually
CLI
Manage templates from your terminal
Terraform
Declare templates in your Terraform configurations
Pulumi
Declare templates in your Pulumi programs
Migrating from 2.x
Template versions through 2.8.0 created their own GVC, so that GVC is part of the 2.x release’s manifest. Version 3.0.0 does not declare it — and Helm deletes what a chart stops declaring.1
Recover the password the existing cluster uses
Versions up to 2.5.0 took the password as a plain Helm value and wrote it into a chart-owned secret named after the release. Read it out of your current values file, or out of that secret:Pass
-o yaml. A bare cpln secret reveal prints only a summary table, not the values. Any password that came from a pre-2.6.0 default was published in the public template repository — treat it as compromised and choose a new one for the new deployment.2
Choose the GVC for the new release
Create or pick a GVC and make sure it has exactly the locations you intend to list in
locations. See Prerequisites.3
Install 3.0.0 as a NEW release into that GVC
Use a different release name — secret names are org-wide, so a same-named release collides with the 2.x one even in another GVC. Point the new release at the same bucket with a different prefix, or at a new bucket.
4
Re-ingest your data
Do not try to adopt the old release’s volume set. It holds metadata whose
<macros><shard> identity and Keeper paths belong to the old topology, and it cannot be moved between releases.5
Cut over, then uninstall the old release
Point your applications at the new endpoint, then uninstall the old release against the GVC you originally installed it into — not the GVC it created. That is where Helm tracks the release, and uninstalling from there takes the created GVC with it.
gvc.locations is now the top-level locations, and server.internal_access / keeper.internal_access are now server.internalAccess / keeper.internalAccess.
Configuration
The defaultvalues.yaml for this template:
Locations
Each entry inlocations pairs a location with a replica count, and the list length selects the deployment mode — see Deployment Modes. Every location listed must already exist in the GVC you install into; extra GVC locations run nothing. Two locations, a duplicate location, an empty list and replicas: 0 are all refused at render.
GVC locations you did not list show as red in the console, with
This workload location is deactivated because maxScale is set to 0. That is the mechanism that keeps a shared GVC safe — it is what a healthy install looks like, not a fault.Provider and Object Storage
Setprovider to aws, gcp, azure, or hetzner, then fill in the corresponding section. Only the active provider’s fields are used. See Object storage for the per-provider setup steps.
AWS S3
GCS
Azure Blob Storage
Hetzner Object Storage
Switch providers with a fresh install, not an upgrade. An identity’s cloud binding is never removed once set — the API merges rather than replaces — so a release switched from one provider to another keeps the old provider’s binding attached even though the chart no longer renders it.
Cluster and Database
clusterName— The name used for distributed DDL queries, in cluster modes only. It must be a bare identifier — letters, digits and underscores, not starting with a digit — because it becomes an XML element name and is used unquoted inON CLUSTERstatements. Anything else is refused at render.database.credentialsSecretName— Name of the dictionary secret holdingpasswordanddatabase. ClickHouse creates that database on first initialization, and the password is the one every client connection uses.
cpln://secret/... references, so the password appears in neither the Helm release nor the stored workload spec.
Credentials are applied only on first initialization, when the data directory is empty. Changing the secret afterwards does not change the running cluster — it only changes what the workload presents when it authenticates, which will then fail. To rotate on an existing cluster, run
ALTER USER default IDENTIFIED WITH sha256_password BY '...' first, then update the secret, then force a redeployment. Updating a cpln:// secret does not restart the workload by itself.Images
server.image— ClickHouse Server container image.keeper.image— ClickHouse Keeper container image. Only used in cluster modes.
Resources and Storage
server.resources/keeper.resources— CPU and memory allocated to each workload.volumeset.server.capacity— Persistent volume size in GiB for server metadata and cache (minimum 10).volumeset.keeper.capacity— Persistent volume size in GiB for Keeper state (minimum 10). Only used in cluster modes.
Internal Access
Bothserver.internalAccess and keeper.internalAccess control which workloads can reach each component. Neither workload is exposed publicly, and the template has no public access option.
List only your clients. The server and Keeper reach each other over the same internal firewall, so the chart adds this release’s own workloads to every list it renders. Without that, a
workload-list naming only your applications takes down Keeper’s Raft quorum and every cross-shard query while all status surfaces stay green.Connecting to ClickHouse
From another workload in the same GVC:
.GVC_NAME.cpln.local form. The bare workload name is not reliable on this platform — whether it resolves depends on the workload type.
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.
Important Notes
- Never upgrade a 2.x release onto 3.0.0 in place — it deletes the GVC the 2.x chart created and everything in it. Install a new release: Migrating from 2.x.
- The GVC must contain every location you list, and may contain more. A missing location is not caught at install: the container exits with
FATAL: locations declared in values are not in GVC .... An already-initialized node logs aWARNINGinstead and keeps serving. - 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.
- Keeper is the availability floor. Three members tolerate one loss; the single-shard shape has one member and tolerates none. If a majority of Keeper locations are missing from the GVC, the containers exit with a named error rather than waiting for an election that can never complete.
- A
helm upgraderestarts every replica in every location at once. Nothing serializes a rolling restart on a stateful workload, so treat an upgrade as a planned query interruption: a rolling upgrade of a 3-shard cluster was measured at about 83 seconds of total unavailability, and a Keeper settings change at roughly 60 seconds of coordination outage. On a single-node install, the first no-op upgrade after an install also restarts the one replica. - With one replica per shard, losing a shard fails every distributed query, not just the rows on that shard — measured at about 60 seconds to surface, and about 112 seconds to full recovery. Add replicas if partial results are not acceptable.
- Renaming
clusterNameorphans existingDistributedtables (Code: 701). Recreate them after a rename. - Keep locations and the bucket in the same provider and region family. Cross-region traffic to object storage is billed on every query that misses the local cache.
- Release names must be unique per org — secrets are org-wide, so two releases with the same name collide even in different GVCs.
External References
ClickHouse Documentation
Official ClickHouse documentation
ClickHouse Keeper
Raft coordination for replicated tables
Data Replication
The ReplicatedMergeTree engine family
Distributed Table Engine
Fan a query out across shards
ClickHouse with S3
Integrating ClickHouse with AWS S3 and S3-compatible providers
ClickHouse with GCS
Integrating ClickHouse with Google Cloud Storage
ClickHouse with Azure Blob Storage
Integrating ClickHouse with Azure Blob Storage
ClickHouse Template
View the source files, default values, and chart definition