Enabling Replication
There are two ways to add replication support to your ClickHouse cluster: ClickHouse Keeper and Zookeeper. Here are the installation instructions for both:
When you install the operator, it creates four custom resource definitions (CRDs). We’ve already worked with the ClickHouseInstallation
, but we also have a ClickHouseKeeperInstallation
(abbreviation chk
) that makes it easy to install ClickHouse Keeper.
Copy and paste the following into keeper.yaml
:
apiVersion: "clickhouse-keeper.altinity.com/v1"
kind: "ClickHouseKeeperInstallation"
metadata:
name: clickhouse-keeper
spec:
configuration:
clusters:
- name: "chk01"
layout:
replicasCount: 3
defaults:
templates:
# Templates are specified as default for all clusters
podTemplate: default
dataVolumeClaimTemplate: default
templates:
podTemplates:
- name: default
metadata:
labels:
app: clickhouse-keeper
containers:
- name: clickhouse-keeper
imagePullPolicy: IfNotPresent
image: "clickhouse/clickhouse-keeper:latest"
resources:
requests:
memory: "256M"
cpu: "1"
limits:
memory: "4Gi"
cpu: "2"
securityContext:
fsGroup: 101
volumeClaimTemplates:
- name: default
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
Now use kubectl apply
to create the ClickHouseKeeperInstallation
:
kubectl apply -f keeper.yaml -n operator
This creates the chk
:
clickhousekeeperinstallation.clickhouse-keeper.altinity.com/clickhouse-keeper created
You’ll need to wait until state of the chk
is Completed
:
kubectl get chk -o wide -n operator
It will take a minute, but you’ll see this at some point:
NAME VERSION CLUSTERS SHARDS HOSTS TASKID STATUS HOSTS-UNCHANGED HOSTS-UPDATED HOSTS-ADDED HOSTS-COMPLETED HOSTS-DELETED HOSTS-DELETE ENDPOINT AGE SUSPEND
clickhouse-keeper 0.25.1 1 1 3 Completed keeper-clickhouse-keeper.operator.svc.cluster.local 3m47s
We’ll reference the chk
resource in a YAML file to enable replication in our ClickHouse cluster.
Adding a replica to our cluster
The spec for a ClickHouse Installation includes a zookeeper
parameter. (Yes, we’re using ClickHouse Keeper, but the zookeeper
parameter works for both.) Copy this text and save it in the file manifest03.yaml
:
apiVersion: "clickhouse.altinity.com/v1"
kind: "ClickHouseInstallation"
metadata:
name: cluster01
spec:
templates:
podTemplates:
- name: clickhouse-pod-template
spec:
containers:
- name: clickhouse
image: altinity/clickhouse-server:24.8.14.10501.altinitystable
volumeMounts:
- name: clickhouse-storage
mountPath: /var/lib/clickhouse
volumeClaimTemplates:
- name: clickhouse-storage
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: standard
configuration:
zookeeper:
nodes:
- host: keeper-clickhouse-keeper.operator.svc.cluster.local
port: 2181
clusters:
- name: cluster01
layout:
shardsCount: 1
replicasCount: 2
templates:
podTemplate: clickhouse-pod-template
Notice that we’re increasing the number of replicas (replicasCount
) from the manifest02.yaml
file on the Adding persistent storage to your cluster page.
We’re updating the definition of our chi
object to point to a chk
object. To get the object’s endpoint, use this command:
kubectl get chk -n operator -o custom-columns="NAME:.metadata.name,ENDPOINT:.status.endpoint"
You’ll see something like this:
NAME ENDPOINT
clickhouse-keeper keeper-clickhouse-keeper.operator.svc.cluster.local
Take a look at manifest03.yaml
. Make sure the endpoint of the chk
object is the value of the configuration\zookeeper\nodes\host
field. Also be sure the storageClass
is set correctly for your cloud provider, then apply the new configuration file:
kubectl apply -f manifest03.yaml -n operator
You’ll get immediate feedback:
clickhouseinstallation.clickhouse.altinity.com/cluster01 configured
Check the status of your updated chi
:
kubectl get chi -o wide -n operator
Wait until the status of the chi
is Completed
. Here we can see that we have one cluster, one shard, and two hosts.
NAME VERSION CLUSTERS SHARDS HOSTS TASKID STATUS HOSTS-COMPLETED HOSTS-UPDATED HOSTS-ADDED HOSTS-DELETED ENDPOINT AGE SUSPEND
cluster01 0.25.1 1 1 2 94041e87-8689-4c68-8e87-f8cd9165c6a9 Completed clickhouse-cluster01.operator.svc.cluster.local 33m
If we log into any of the two hosts in our cluster and look at the system.clusters
table, we can show the updated results and that we have a total of two hosts for cluster01 - one each of the two replicas.
kubectl exec -it chi-cluster01-cluster01-0-1-0 -n operator -- clickhouse-client
We’ll select a few parameters that we care about:
SELECT
cluster,
shard_num,
replica_num,
host_name,
host_address
FROM system.clusters
WHERE cluster = 'cluster01'
┌─cluster───┬─shard_num─┬─replica_num─┬─host_name───────────────────┬─host_address─┐
1. │ cluster01 │ 1 │ 1 │ chi-cluster01-cluster01-0-0 │ 10.244.2.4 │
2. │ cluster01 │ 1 │ 2 │ chi-cluster01-cluster01-0-1 │ 127.0.0.1 │
└───────────┴───────────┴─────────────┴─────────────────────────────┴──────────────┘
2 rows in set. Elapsed: 0.001 sec.
👉 Type exit
to end the clickhouse-client
session.
Now that we’ve got ClickHouse Keeper in place, we’re ready to create a table that uses the ReplicatedMergeTree
engine, and that engine will keep all our replicas synchronized. So let’s move on….
Zookeeper is easy to install and enable. (Although we should say that if you’re using the operator on minikube, it may be difficult to get Zookeeper’s PersistentVolumeClaim
s configured correctly. Proceed with caution. Or use ClickHouse Keeper instead.)
We’ll use kubectl
apply to create a three-node Zookeeper deployment:
kubectl apply -f https://raw.githubusercontent.com/Altinity/clickhouse-operator/release-0.25.1/deploy/zookeeper/zookeeper-manually/quick-start-persistent-volume/zookeeper-3-nodes.yaml -n operator
This creates some new resources:
service/zookeeper created
service/zookeepers created
poddisruptionbudget.policy/zookeeper-pod-disruption-budget created
statefulset.apps/zookeeper created
Now make sure things are running. Run this command:
kubectl get all -n operator
Wait until you see READY 1/1
and Running
for the three Zookeeper pods and READY 3/3
for its statefulset
:
NAME READY STATUS RESTARTS AGE
pod/chi-cluster01-cluster01-0-0-0 1/1 Running 0 3m59s
pod/clickhouse-operator-6f655c97bd-crvhl 2/2 Running 0 9m55s
pod/zookeeper-0 1/1 Running 0 2m15s
pod/zookeeper-1 1/1 Running 0 92s
pod/zookeeper-2 1/1 Running 0 49s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/chi-cluster01-cluster01-0-0 ClusterIP None <none> 9000/TCP,8123/TCP,9009/TCP 8m41s
service/clickhouse-cluster01 ClusterIP None <none> 8123/TCP,9000/TCP 8m29s
service/clickhouse-operator-metrics ClusterIP 10.0.176.159 <none> 8888/TCP,9999/TCP 9m55s
service/zookeeper ClusterIP 10.0.47.117 <none> 2181/TCP,7000/TCP 2m15s
service/zookeepers ClusterIP None <none> 2888/TCP,3888/TCP 2m15s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/clickhouse-operator 1/1 1 1 9m55s
NAME DESIRED CURRENT READY AGE
replicaset.apps/clickhouse-operator-6f655c97bd 1 1 1 9m55s
NAME READY AGE
statefulset.apps/chi-cluster01-cluster01-0-0 1/1 5m30s
statefulset.apps/zookeeper 3/3 2m15s
Now we’ve got a running Zookeeper, so we can tell our ClickHouse cluster how to connect to it…and add a second replica.
Adding a replica to our cluster
The spec for a ClickHouseInstallation
includes a zookeeper
parameter. Copy the following text and save it as manifest03.yaml
:
apiVersion: "clickhouse.altinity.com/v1"
kind: "ClickHouseInstallation"
metadata:
name: cluster01
spec:
templates:
podTemplates:
- name: clickhouse-pod-template
spec:
containers:
- name: clickhouse
image: altinity/clickhouse-server:24.8.14.10501.altinitystable
volumeMounts:
- name: clickhouse-storage
mountPath: /var/lib/clickhouse
volumeClaimTemplates:
- name: clickhouse-storage
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: standard
configuration:
zookeeper:
nodes:
- host: zookeeper.operator.svc.cluster.local
port: 2181
clusters:
- name: cluster01
layout:
shardsCount: 1
replicasCount: 2
templates:
podTemplate: clickhouse-pod-template
Notice that we’re increasing the number of replicas from the manifest02.yaml
file on the Adding persistent storage to your cluster page. The hostname for Zookeeper is the name of the service (zookeeper
), its namespace (operator
), followed by .svc.cluster.local
.
Be sure you’re using the correct storageClassName
for your Kubernetes provider. With that done, apply the new configuration file:
kubectl apply -f manifest03.yaml -n operator
You’ll get immediate feedback:
clickhouseinstallation.clickhouse.altinity.com/cluster01 configured
It will likely take a minute or two, but you should see your updated chi:
kubectl get chi -o wide -n operator
Wait until the status of the chi
is Completed
. Here we can see that we have one cluster, one shard, and two hosts.
NAME VERSION CLUSTERS SHARDS HOSTS TASKID STATUS HOSTS-COMPLETED HOSTS-UPDATED HOSTS-ADDED HOSTS-DELETED ENDPOINT AGE SUSPEND
cluster01 0.25.1 1 1 2 21dfe453-2967-446e-933b-63880c3d0014 Completed clickhouse-cluster01.operator.svc.cluster.local 17m
(Adding the -o wide
option shows more data.) Taking a look at our new layout, we now have three services in our namespace:
kubectl get service -n operator
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
chi-cluster01-cluster01-0-0 ClusterIP None <none> 9000/TCP,8123/TCP,9009/TCP 20m
chi-cluster01-cluster01-0-1 ClusterIP None <none> 9000/TCP,8123/TCP,9009/TCP 6m45s
clickhouse-cluster01 ClusterIP None <none> 8123/TCP,9000/TCP 19m
clickhouse-operator-metrics ClusterIP 10.0.176.159 <none> 8888/TCP,9999/TCP 21m
zookeeper ClusterIP 10.0.47.117 <none> 2181/TCP,7000/TCP 13m
zookeepers ClusterIP None <none> 2888/TCP,3888/TCP 13m
If we log into either of the hosts in our cluster (chi-cluster01-cluster01-0-0
or chi-cluster01-cluster01-0-1
) and look at the system.clusters
table, we can show the updated results and that we have a total of two hosts for cluster01
- one for each of the two replicas.
kubectl exec -it chi-cluster01-cluster01-0-1-0 -n operator -- clickhouse-client
We’ll select a few parameters that we care about:
SELECT
cluster,
shard_num,
replica_num,
host_name,
host_address
FROM system.clusters
WHERE cluster = 'cluster01'
┌─cluster───┬─shard_num─┬─replica_num─┬─host_name───────────────────┬─host_address─┐
1. │ cluster01 │ 1 │ 1 │ chi-cluster01-cluster01-0-0 │ 10.244.2.4 │
2. │ cluster01 │ 1 │ 2 │ chi-cluster01-cluster01-0-1 │ 127.0.0.1 │
└───────────┴───────────┴─────────────┴─────────────────────────────┴──────────────┘
2 rows in set. Elapsed: 0.003 sec.
👉 Type exit
to end the clickhouse-client
session.
Now that we’ve got Zookeeper in place, we’re ready to work with our replicas. We’ll set up tables with the ReplicatedMergeTree
engine, and that engine will keep all our replicas synchronized. So let’s move on….