Kubernetes
You can run Replicator in a Kubernetes cluster in the same cloud as your managed Kurrent Cloud cluster. The Kubernetes cluster workloads must be able to reach the managed KurrentDB cluster. Usually, with a proper VPC (or VN) peering between your VPC and Kurrent Cloud network, it works without issues.
We provide guidelines about connecting managed Kubernetes clusters.
The easiest way to deploy Replicator to Kubernetes is by using a provided Helm chart. On this page, you find detailed instructions for using the Replicator Helm chart.
Add Helm repository
Section titled “Add Helm repository”Ensure you have Helm 3 installed on your machine:
$ helm versionversion.BuildInfo{Version:"v3.5.2", GitCommit:"167aac70832d3a384f65f9745335e9fb40169dc2", GitTreeState:"dirty", GoVersion:"go1.15.7"}If you don’t have Helm, following their installation guide.
Add the Replicator repository:
helm repo add kurrent-replicator https://kurrent-io.github.io/replicatorhelm repo updateProvide configuration
Section titled “Provide configuration”Configure the Replicator options using a new values.yml file:
replicator: reader: connectionString: "GossipSeeds=node1.esdb.local:2113,node2.esdb.local:2113,node3.esdb.local:2113; HeartBeatTimeout=500; UseSslConnection=False; DefaultUserCredentials=admin:changeit;" sink: connectionString: "esdb://admin:changeit@[cloudclusterid].mesdb.eventstore.cloud:2113" partitionCount: 6 filters: - type: eventType include: "." exclude: "((Bad|Wrong)\w+Event)" transform: type: http config: "http://transform.somenamespace.svc:5000"prometheus: metrics: true operator: trueAvailable options are:
| Option | Description | Default |
|---|---|---|
replicator.reader.connectionString | Connection string for the source cluster or instance | nil |
replicator.reader.protocol | Reader protocol | tcp |
replicator.reader.pageSize | Reader page size (only applicable for TCP protocol | 4096 |
replicator.sink.connectionString | Connection string for the target cluster or instance | nil |
replicator.sink.protocol | Writer protocol | grpc |
replicator.sink.partitionCount | Number of partitioned concurrent writers | 1 |
replicator.sink.partitioner | Custom JavaScript partitioner | null |
replicator.sink.bufferSize | Size of the sink buffer, in events | 1000 |
replicator.scavenge | Enable real-time scavenge | true |
replicator.runContinuously | Set to false if you want Replicator to stop when it reaches the end of $all stream. | true |
replicator.filters | Add one or more of provided filters | [] |
replicator.transform | Configure the event transformation | |
replicator.transform.bufferSize | Size of the prepare buffer (filtering and transformations), in events | 1000 |
replicator.reader.auth.* | Reader authentication (gRPC only), e.g. type: oauthClientCredentials | nil |
replicator.sink.auth.* | Sink authentication (gRPC only), configured independently of the reader | nil |
serviceAccountName | Service account for the pod (e.g. federated for Azure Workload Identity) | "" |
podLabels | Extra pod labels, e.g. azure.workload.identity/use: "true" | {} |
extraEnv | Extra container environment variables (use for secrets such as REPLICATOR_SINK_AUTH_CLIENTSECRET) | [] |
extraEnvFrom | Extra envFrom sources (Secrets, ConfigMaps) | [] |
extraVolumes | Extra pod volumes (e.g. a Secret with a client secret or token file) | [] |
extraVolumeMounts | Extra container volume mounts | [] |
prometheus.metrics | Enable annotations for Prometheus | false |
prometheus.operator | Create PodMonitor custom resource for Prometheus Operator | false |
resources.requests.cpu | CPU request | 250m |
resources.requests.memory | Memory request | 512Mi |
resources.limits.cpu | CPU limit | 1 |
resources.limits.memory | Memory limit | 1Gi |
pvc.storageClass | Persistent volume storage class name | null |
terminationGracePeriodSeconds | Timeout for the workload graceful shutdown, it must be long enough for the sink buffer to flush | 300 |
jsConfigMaps | List of existing config maps to be used as JS code files (for JS transform, for example) | {} |
You should at least provide both connection strings and ensure that workloads in your Kubernetes cluster can reach both the source and the target EventStoreDB clusters or instances.
OAuth authentication
Section titled “OAuth authentication”OAuth requires a Replicator release that includes OAuth support, which is newer than the chart’s default image tag (0.4.7). Set image.tag to such a release.
When a cluster uses OAuth (for example with Microsoft Entra ID), configure that side’s auth section and inject the secret from a Kubernetes Secret. Never put clientSecret in values.yml: the replicator block is rendered into a ConfigMap.
kubectl create secret generic replicator-oauth --from-literal=client-secret='<secret>'replicator: reader: protocol: grpc connectionString: "esdb://admin:changeit@source.example.com:2113?tls=true" sink: protocol: grpc connectionString: "esdb://[cloudclusterid].mesdb.eventstore.cloud:2113?tls=true" auth: type: oauthClientCredentials tokenEndpoint: "https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token" clientId: "<replicator-app-client-id>" clientSecretFile: /var/run/secrets/replicator/client-secret scope: "api://kurrentdb/.default"extraVolumes: - name: replicator-oauth secret: secretName: replicator-oauthextraVolumeMounts: - name: replicator-oauth mountPath: /var/run/secrets/replicator readOnly: trueAlternatively, pass the secret as an environment variable instead of a file. In that case remove clientSecretFile (and the secret volume) from the values above, because exactly one of clientSecret, clientSecretFile and clientAssertionFile may be set:
extraEnv: - name: REPLICATOR_SINK_AUTH_CLIENTSECRET valueFrom: secretKeyRef: name: replicator-oauth key: client-secretWith Azure Workload Identity there is no secret at all. Set serviceAccountName to the federated service account, add the azure.workload.identity/use: "true" pod label, and use clientAssertionFile: /var/run/secrets/azure/tokens/azure-identity-token instead of clientSecretFile. See Authentication for every option.
Configuring a JavaScript transform
Section titled “Configuring a JavaScript transform”Follow the documentation to configure a JavaScript transform in your values.yml file.
Then append the following option to your helm install command:
--set-file transformJs=./transform.jsConfiguring a custom partitioner
Section titled “Configuring a custom partitioner”Follow the documentation to configure a custom partitioner in your values.yml file.
Then append the following option to your helm install command:
--set-file partitionerJs=./partitioner.jsComplete the deployment
Section titled “Complete the deployment”When you have the values.yml file complete, deploy the release using Helm. Remember to set the current kubectl context to the cluster where you are deploying to.
helm install kurrent-replicator \ kurrent-replicator/replicator \ --values values.yml \ --namespace kurrent-replicatorYou can choose another namespace, the namespace must exist before doing a deployment.
The replication starts immediately after the deployment, assuming that all the connection strings are correct, and the Replicator workload has network access to both source and sink EventStoreDB instances.