Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Developing Multi-Pod Apps With Kubernetes and Che

DZone's Guide to

Developing Multi-Pod Apps With Kubernetes and Che

In this tutorial, you'll learn how to develop multi-pod microservice apps on Minikube with Che and deploy them using Kubernetes.

· Microservices Zone ·
Free Resource

Learn how modern cloud architectures use of microservices has many advantages and enables developers to deliver business software in a CI/CD way.

Che and Microservices

Microservices and containers are disrupting many traditional aspects of development and operations. Packaging, updating, deploying, monitoring, scaling and migrating such apps require new approaches and technologies. Despite the necessary changes in tooling and process, microservices are taking over the world (although monolithic apps aren’t history yet).

Since 2013, Eclipse Che has depended on containers for its workspaces and has always been well suited to microservices development. With Che 6 the Che server and workspaces can be run as workloads on Kubernetes, OpenShift, and Docker. What’s very exciting about this is that you can finally run your production pods/containers in “dev mode” so you’re working with the identical images as used in production. That may sound weird/impossible — but it is actually true. In fact, it’s in this scenario that the true power of Eclipse Che in unleashed — no other cloud or desktop IDE do this.

In this tutorial, I will use Kubernetes deployment YAMLs for a microservices application that I run on Minikube. This creates a Che workspace with multiple pods where I can build, run and debug each microservice with auto update and all the perks of a developer mode (restarting services, hot deploying changes etc…).

The video is below:


The App

I googled microservices app example and came across this project that I forked: a few server-side components (APIs) written in Go, Java, and Node.js, a database and some frontend - a good mix to play with. Each microservice comes with two YAMLs: deployment and service. Building container images and deploying to Minikube did not take long and in a few minutes, the app was up and running.

Dev Mode With Che

Here comes the fun part. Somehow, I need to run all microservices in a Che workspace, define language tooling and inject source code. Luckily Che makes this task quite easy.

Che Workspace Recipe

The first thing Che asks for is a workspace recipe. Currently, the server can process Kind:List with Kind:Pod and Kind:Service objects only. Converting existing YAMLs into one master YAML was the most time-consuming thing. Automating it will be part of improvements we're making in the coming months to workspace instantiation and structuring (we call it the "workspace.next" project). Once my recipe was complete, I had a replica of a production environment in my Che workspace.

Tooling

Having a replica of a production microservices application in a Che workspace is great, but Che's greatness is all about providing developer tools. There are three languages used in this sample app: Spring, Golang and Node.js. The Eclipse Orion editor that we use provides JavaScript autocompletion and error marking out of the box, while Go and Java need to be added.

Image title

The seven services that make up the Che-enabled sample app.

So, I added two additional machines: Java and Go. The Java machine is the "developer machine" with a workspace agent that comes with built-in Java tooling (this will soon be replaced with the Eclipse JDT.ls as a sidecar container). This pod is used as a build pod for Spring boot microservice.

The Go pod has a Go language server that listens on TCP through socat. Below is the CMD instruction from a Dockerfile used to build the Go language server image:

CMD socat -d -d TCP4-LISTEN:5555,reuseaddr,fork EXEC:"go-language-server"

Source Code Sharing

Next, I need to get my project source code in all the workspace pods (except for Redis) to be able to either recompile and restart servers or just edit project sources (the node server picks up those changes on the go).

I added volumes for all machines with an identical name - projects. This way all pods will share the same volume and I can be sure that my project source code is in sync in the /projects directory in all pods. With source code in all pods, I can edit code, move files and folders across machines and generally perform any file operations that I need to.

Image title

Adding volumes in the Che user dashboard.

Servers

My app components need to communicate with each other. Since my recipe had a bunch of service YAML files, all communications will take place internally using services. Kubernetes takes care of that for me! However, I do need to expose my frontend service on port 8080. Adding a server is easy in the Che User Dashboard.

Image title

Using the Servers > Add Server dialog in the user dashboard to expose port 8080.

There's another server that needs to be declared in order to let the IDE know there's a Go language server running on port 5555 in one of the machines. This server has a special type and a set of attributes that the LS client will use to connect:

"servers": {
 "golang-ls": {
  "attributes": {
   "internal": "true",
   "type": "ls",
   "config": "{\"id\":\"golang\", \"languageIds\":[go]}"
  },
  "port": "5555",
  "protocol": "tcp"
 }
}


Installers

I will need a shell to some of the pods, and exec agent in most of them. An exec agent is a REST service that executes commands, and interested clients can subscribe to output. I am going to execute a lot of commands, so I have added exec agents to all pods except Redis.

Image title

Adding shell capabilities with the Exec agent is done with a toggle on each machine.

Commands

Now that I have defined my workspace recipe, tooling, source code sharing and servers, I need a command that will compile my binaries and start / stop/restart my services.

Eclipse Che has a command widget to execute commands against chosen pods. It's as if you typed a command in your local terminal or execute an ssh command against a remote server. All you need to do is to choose the right command and the right target pod.

Here's an example of two commands, each executed in its own pod. The first one compiles users-api JAR in a build pod, the second one stops existing spring boot process and executes an updated jar in a debug mode:

"[INFO]: Compiling binary..."
cd ${current.project.path}
mvn clean install

Now that an updated JAR is mounted into a users-api pod, I can execute it in a debug mode:

echo "[INFO]: Stopping users server..."
pid=$(netstat -tulpn | grep 8083 | awk '{print $7}' | rev | cut -d"/" -f2- | rev)
cd ${current.project.path}/target
java -jar -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000 -Dserver.port=8083 *.jar

Each pod gets at least one command (a bash script) so you have complete freedom in what you can do in your command.

Image title

Commands in the Che command palette.

Image title

Selecting a command from the Run button.

Debug Configuration

One of the services is a Spring Boot app, which I can debug using Che built-in debugger (part of a workspace agent deployed with Java tooling pod). Like in any remote debugger configuration, I need host and port, which will be users-api:8080, where users-api is resolved to an internal users-api pod IP.

Image title

Setting up a Java debug configuration.

Having Fun

There you go - I can play with each microservice, restart servers and introduce code changes in the runtime, which is an actual production runtime. The video shows it from 3:16.

What's Next?

I committed and pushed my changes to a GitHub repo, but I could have created a PR or pushed to a branch too.

Is this the end of a developer story? Probably yes, as far as a developer is concerned. However, a devops guy or even a developer needs to make sure the branch or a PR gets deployed to a staging to be tested there. In this demo I have executed a simple script that pulls changes from GitHub, re-builds and tags images, pushes them to DockerHub and updates existing MiniKube deployments. It is just an easy simple way to demonstrate how Che can be integrated into a development process. Of course, your Jenkins may use a webhook when a GitHub repo gets a new branch, PR or a merge into master. Depending on pipeline setting, updated images can be rolled out to staging and if approved for production, too.

Keep Learning!

Using Apache OpenWhisk for Function-as-a-Service in Che: https://che.eclipse.org/apache-openwhisk-eclipse-che-and-openshift-minishift-13627bf2452

Che 6 Release Blog: https://che.eclipse.org/release-notes-eclipse-che-6-0-43feff5797e5

Discover how to deploy pre-built sample microservices OR create simple microservices from scratch.

Topics:
microservices ,tutorial ,che ,kubernetes ,deployment

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}