SE This Week: Using etcd as Kubernetes App Database

jiayanguo

jguo

Posted on May 3, 2020

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

💖 💪 🙅 🚩
jiayanguo
jguo

Posted on May 3, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related