DEV Community

Cover image for SE This Week: Using etcd as Kubernetes App Database
jguo
jguo

Posted on

SE This Week: Using etcd as Kubernetes App Database

About

This tutorial will show you how to build a web application using etcd as NoSQL database.

What is etcd?

etcd is a distributed reliable key-value store for the most critical data of a distributed system. etcd is written in Go. Since it is using grpc for user-facing API implementation, that explains why we choose protobuf in our web application.
If you are familiar with Kubernetes, you should know that etcd is a well-known implementation of Kubernetes object storage. That is actually how etcd caught my attention.

Build an etcd web app.

Ok. Let's see how to build a web application using etcd, spring boot and protobuf.

  • Use spring initializr to create a sample web project (add web dependency in).

  • Add protobuf plugin and dependency, and etcd java client.

 <plugin> <groupId>org.xolstice.maven.plugins</groupId> <artifactId>protobuf-maven-plugin</artifactId> <version>0.6.1</version> <executions> <execution> <goals> <goal>compile</goal> <goal>test-compile</goal> </goals> </execution> </executions> </plugin> 
Enter fullscreen mode Exit fullscreen mode
 <dependency> <groupId>io.etcd</groupId> <artifactId>jetcd-core</artifactId> <version>${jetcd-version}</version> </dependency> <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>3.4.0</version> </dependency> 
Enter fullscreen mode Exit fullscreen mode
  • Create a protobuf file for communication between etcd and app. It is like schema in SQL world, json in MongoDB world.
syntax = "proto2"; package com.example.proto.model; option optimize_for = SPEED; message DemoMessage { optional string name = 1; optional string body = 2; } 
Enter fullscreen mode Exit fullscreen mode
  • Let's create an etcd initialization class, which will help you create the connection between the web app and etcd.
@Component public class DbInitializer { @Value("${etcd.url}") String etcdUrl; public KV initDB() { Client client = Client.builder().endpoints(etcdUrl) .build(); KV kvClient = client.getKVClient(); return kvClient; } } 
Enter fullscreen mode Exit fullscreen mode
  • Now, let's create a dao layer.
@Repository public class MessageDaoImpl implements MessageDao{ private KV kvClient; public MessageDaoImpl(@Autowired DbInitializer initializer) { kvClient = initializer.initDB(); } @Override public Message.DemoMessage get(String key) throws ExecutionException, InterruptedException, InvalidProtocolBufferException { ByteSequence keySeq = ByteSequence.from(key.getBytes()); CompletableFuture<GetResponse> getFuture = kvClient.get(keySeq); GetResponse response = getFuture.get(); byte[] data = response.getKvs().get(0).getValue().getBytes(); return Message.DemoMessage.parseFrom(data); } @Override public void delete(String key) throws ExecutionException, InterruptedException { ByteSequence keySeq = ByteSequence.from(key.getBytes()); kvClient.delete(keySeq).get(); } @Override public void add(String key, Message.DemoMessage demoMessage) throws ExecutionException, InterruptedException { ByteSequence keySeq = ByteSequence.from(key.getBytes()); ByteSequence value = ByteSequence.from(demoMessage.toByteArray()); kvClient.put(keySeq, value).get(); } @Override public void update(String key, Message.DemoMessage demoMessage) throws ExecutionException, InterruptedException { ByteSequence keySeq = ByteSequence.from(key.getBytes()); ByteSequence value = ByteSequence.from(demoMessage.toByteArray()); kvClient.put(keySeq, value).get(); } } 
Enter fullscreen mode Exit fullscreen mode
  • Once you have the dao layer, it shouldn't make any difference like how you create a web application. Please refer to this GitHub repo for the completed source code.

How to deploy it to a Kubernetes cluster?

I will use minikube for this tutorial. It shouldn't make any difference if you choose other Kubernetes cluster, like EKS, AKS, GKS.

  • Start minikube.
    minikube start
    If you don't have minikube yet, follow this guide.

  • Deploy etcd.
    Download the etcd yaml file from here. And then, run kubectl apply -f etcd.yaml

  • Deploy our web application.
    Download the deployment yaml file from here. And then, run kubectl apply -f deployment.yaml

  • So far, you should be all good. But, let's expose the web application, so we can test it in our browser. Run this command. minikube service etcd-service

Test

Now, we are ready to test our web application. The previous step should give you a host IP address. Please replace the IP address below with what you get. You call choose postman or any other rest API client to run the CURLs.

Add record curl -X PUT \ 'http://192.168.99.102:32001/message/1?name=jguo&body=I%20am%20a%20software%20engineer' \ -H 'cache-control: no-cache' Get Record curl -X GET \ http://192.168.99.102:32001/message/1 \ -H 'cache-control: no-cache' Update Record curl -X POST \ 'http://192.168.99.102:32001/message/1?name=jiayan' \ -H 'cache-control: no-cache' Delete Record curl -X DELETE \ http://192.168.99.102:32001/message/1 \ -H 'cache-control: no-cache' 
Enter fullscreen mode Exit fullscreen mode

Wrap Up

If you are using Kubernetes to run your web applications and looking for a containerized NoSQL DB, take etcd into your account. The purpose of this post is not to persuade you to choose etcd as your solution. Since choosing a DB it usually has a lot of concerns, making a smart decision.

Reference

https://github.com/jiayanguo/etcdapp
https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/
https://github.com/etcd-io/etcd/tree/master/hack/kubernetes-deploy
https://github.com/etcd-io/jetcd

Top comments (0)