Event Sourcing · Software Development

Set up an EventStore cluster on Kubernetes

[EDIT] The new official Event Store Helm Chart is now available

[EDIT-EDIT] Unfortunately the EventStore team was not willing to support an official Helm Chart and they discontinued it with a bit of non-sense around the need of a data operator. Having a data operator for Kubernetes it’s a good idea as an addition in order to control a fleet of EventStore instances (single or cluster) but it doesn’t add anything you can’t get with normal StatefulSet, services and deployments. A port of the old official chart is here https://github.com/riccardone/helm-eventstore. Enjoy!

This is my step by step memo on setting up an EventStore cluster with persistent volumes on Kubernetes hosted in AWS.

The open-source, functional database with Complex Event Processing

This guide assumes that you already have a Kubernetes Cluster up and running and you have set the execution context of kubectl to use that cluster. The goal of this guide is to have an EventStore Cluster formed by 3 nodes saving persisting data on durable EBS data volumes.

You can find all the yaml and config files in my EventStore-Kubernetes public repository.

To interact with our Kubernetes we will use the command line utility called “kubectl”. This utility has a context that needs to be set and it’s probably set already by kops if you have followed the previous guide to build the Kubernetes Cluster. These utilities will share the AWS credentials that have been set when you’ve configured the aws-cli with the command aws configure.

In the yaml file the apiVersion is required and I use: ‘apps/v1’. To find out what exact apps/xxx api version your Kubernetes cluster supports you can use the following command:
kubectl api-versions

To see where you Kubernetes cluster is running you can use: kubectl cluster-info

  1. (optional) Create a public Nginx endpoint to access EventStore 2113 port from the outside
    Create a file called “nginx-configmap.conf” with the content from this link and run the following commands to create a config-map to configure Nginx, a deployment and a service exposing an external endpoint
    kubectl create configmap nginx-eventstore-frontend-conf --from-file=nginx-configmap.conf="nginx-configmap.conf"
    kubectl create -f https://raw.githubusercontent.com/riccardone/EventStore-Kubernetes/master/nginx-deployment.yaml
    kubectl create -f https://raw.githubusercontent.com/riccardone/EventStore-Kubernetes/master/nginx-service.yaml
  2. Set up the necessary objects to use Aws EBS persistent volumes
    kubectl create -f https://raw.githubusercontent.com/riccardone/EventStore-Kubernetes/master/volume-deployment.yaml
    kubectl create -f https://raw.githubusercontent.com/riccardone/EventStore-Kubernetes/master/volume-claim.yaml
  3. Create a 3 nodes EventStore cluster using Statefulsets
    kubectl create -f https://raw.githubusercontent.com/riccardone/EventStore-Kubernetes/master/eventstore-statefulset.yaml
  4. Create the internal EventStore service to allow node discovery and gossips
    kubectl create -f https://raw.githubusercontent.com/riccardone/EventStore-Kubernetes/master/eventstore-service.yaml

You can browse the EventStore cluster with the link from
Kubernetes Dashboard -> services -> frontend-eventstore -> External endpoint
I wrote about how to access the Kubernetes Dashboard in the previous guide

This public endpoint is there to test your cluster and in a production environment it must be protected or removed.

To set the EventStore cluster in this guide I’ve used a Kubernetes resource called Statefulset.
A Stetefulset works better than a usual Deployment with EventStore and with databases in general as it better provides data durability:

Like a Deployment , a StatefulSet manages Pods that are based on an identical container spec. Unlike a Deployment, a StatefulSet maintains a sticky identity for each of their Pods. These pods are created from the same spec, but are not interchangeable: each has a persistent identifier that it maintains across any rescheduling.