Prerequisites by Platform
AWS (EKS)
GCP (GKE)
Azure (AKS)
Bare Metal
Node Group Specifications
AWS (EKS)
Keeper Node Group
Server Node Group
Operator Node Group (x86)
All AWS nodes require IMDS for authentication.
For keeper and server node groups, create one node group per AZ if you wish to support cluster autoscaler across AZs.
Autoscaler tags (if using cluster-autoscaler):
k8s.io/cluster-autoscaler/enabled: truek8s.io/cluster-autoscaler/$CLUSTER_NAME: owned
GCP (GKE)
Keeper Node Pool
Server Node Pool
Default Node Pool
Azure (AKS)
Keeper Node Pool
Server Node Pool
Temp storage by instance size (
Standard_D*ds_v5, Intel Icelake):
System / Operator Node Pool
For keeper and server node pools, create one pool per availability zone if you wish to support cluster autoscaler across zones.
Bare Metal
Assign nodes to distinct roles and label and taint them so the operator schedules ClickHouse pods correctly and nothing else lands on them. At least three failure domains are recommended so the operator can spread Keeper across them (topology spread with max skew 1 and a minimum of 3 domains ontopology.kubernetes.io/zone). Map each domain to a real fault-isolation boundary such as a rack, chassis, or power feed where possible.
Keeper Nodes
Server Nodes
Operator Nodes
At least one additional node for the operator and cluster add-ons. No ClickHouse labels or taints are required.Pod QoS: Guaranteed (recommended)
ClickHouse server, keeper, and child compute group pods should run with the Kubernetes Guaranteed QoS class. In practice, this means that for every container in the pod,resources.requests equals resources.limits for both CPU and memory, and
both fields are set. Every deployment example in this documentation follows
this pattern.
Why
ClickHouse’s memory tracker relies on a stable memory ceiling. Whenrequests != limits, the effective ceiling and the OOM-kill boundary diverge
and behavior becomes hard to reason about:
- If the memory tracker uses the request value, queries are killed while the node still has headroom (over-conservative).
- If it uses the cgroup limit, the pod can exceed its request and be OOM-killed by the kernel with no ClickHouse-side warning.
Choosing a different QoS class
The operator does not enforce Guaranteed QoS — you can deliberately run ClickHouse underBurstable (or another class) if, for example, you are
trading predictability for pack density. Before you do, make sure you
understand the OOM trade-offs above and the wider Kubernetes resource model:
For the applied examples, see any of the deployment tutorials
or the compute-compute separation guide.
Networking Requirements
AWS
Example subnet layout (us-west-2):
GCP
Azure
Bare Metal
Storage Requirements
AWS
GCP
Azure
Bare Metal
IAM / Service Account Requirements
AWS
ECR Pull Role
- Role name:
ClickHouseAirgapECRPullRole - Purpose: Pull images from ClickHouse private ECR
- Permissions:
ecr:GetDownloadUrlForLayer,ecr:BatchGetImage,ecr:BatchCheckLayerAvailability,ecr:DescribeImages,ecr:ListImages,ecr:GetAuthorizationToken - Action: Provide the role ARN to the ClickHouse team
ClickHouse Server/Keeper S3 Role
- One role per provisioned ClickHouse cluster
- Naming convention:
CH-S3-$NAME-$REGION-$ORDINAL-Role$NAME: cluster name (e.g.,default-xx-01)$REGION: shortened region (e.g.,uw2forus-west-2)$ORDINAL: reserved, set to00- Example:
CH-S3-default-xx-01-uw2-00-Role
- Permissions:
s3:*,s3:ListBucketon the bucket resource - Trust policy: IRSA via
sts:AssumeRoleWithWebIdentitywith EKS cluster’s OIDC provider
EBS CSI Driver Role
- Example name:
ClickHouse_EksEbsCsiDriverRole - Managed policy:
arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy - Trust policy: IRSA with EKS cluster’s OIDC provider
GCP
Deployer Service Account
ClickHouse Workload Identity Service Account
- GCP SA:
clickhouse@$PROJECT.iam.gserviceaccount.com - K8s SA (manual):
clickhousein namespacens-$CLUSTER_NAME - K8s SA (helm-created):
ch-$CLUSTER_NAME-sain namespacens-$CLUSTER_NAME - K8s SA annotation:
iam.gke.io/gcp-service-account=<GSA_EMAIL> - IAM binding member:
serviceAccount:$PROJECT.svc.id.goog[<namespace>/<ksa>] - Bucket permissions:
roles/storage.objectAdmin,roles/storage.legacyBucketReader - Artifact Registry permissions:
roles/artifactregistry.reader
Azure
Deployer Permissions
ClickHouse Managed Identity
- Type: User-Assigned Managed Identity (UAMI)
- K8s SA (helm-created):
ch-$CLUSTER_NAME-sain namespacens-$CLUSTER_NAME - K8s SA annotation:
azure.workload.identity/client-id=<UAMI_CLIENT_ID> - Federated credential subject:
system:serviceaccount:ns-$CLUSTER_NAME:ch-$CLUSTER_NAME-sa - Role assignment:
Storage Blob Data Contributoron the Storage Account
Bare Metal
- Object storage credentials: Static access key / secret key for MinIO AIStor, held in a Kubernetes Secret (
object-storage-credentials) and injected into server and keeper pods viaadditionalEnvVars. - Registry pull secret:
registry-credentialsdocker-registry secret in theclickhouse-operator-systemand cluster namespaces, if your registry requires authentication. - Service account: No cloud identity binding required.
Cluster Naming Conventions
The naming convention for ClickHouse clusters is consistent across all platforms:
Example name:
default-xx-01
The cluster name must be unique within the target Kubernetes cluster and is used in:
- Kubernetes namespace:
ns-$CLUSTER_NAME - Kubernetes resources: prefixed with
c-$CLUSTER_NAME - IAM role names (AWS):
CH-S3-$CLUSTER_NAME-$REGION-$ORDINAL-Role - S3/GCS key prefixes:
ch-s3-<uuid>(unique per cluster)