Introduction

In this article I want to briefly discuss Cloud Native aps as well cover building a very basic one to incorporate the main technology used. In this article we will be using Spring Boot and Java. If you are not familiar with using these technologies I still urge you to read on through to the end so you can see how Spring Boot handles creating Cloud Native apps. We aren’t going to build something huge. It is just a basic hello world application to see the ins and outs of creating a Cloud Native app and the steps that go into building a service. So in other words we are just going to be creating one service that could be one of many services that make up the application.

What is Cloud Native?

I’m sure that everyone has seen the memes across the internet that the cloud is just someone else’s compute and to be fair that is true. The Cloud Native Computing Foundation (CNCF) defines Cloud Native as:

Cloud native technologies empower organizations to build and run scalable applications in modern, dynamic environments such as public, private, and hybrid clouds. Containers, service meshes, microservices, immutable infrastructure, and declarative APIs exemplify this approach.

These techniques enable loosely coupled systems that are resilient, manageable, and observable. Combined with robust automation, they allow engineers to make high-impact changes frequently and predictably with minimal toil.

Best Option?

One of the biggest mistakes one can make is thinking that you have to use a certain piece of technology because it’s the shiny new kid on the block, and it’s all the rage. There are hundreds of stories out there about companies migrating monoliths to microservices and ending in disaster. While this project could technically be considered to be a non cloud native app, I feel the experience you will go through during the development will be enough to help you determine if it’s worth looking more into for your next project.

Getting Started with Spring

Now that the reason why we are doing this has been taken care of, somewhat, let’s get started setting up our environment so that we can create our app. Below is a list of technologies we will need in order to get started. Now not all of them are pieces we will need right away but to make this easier I suggest installing it all now rather than having to come back to this section later on to install the necessary tech. Below is the list:

  1. Java: If you don’t have it installed already I recommend installing Java. Java 17 or higher should be what you use for this app. I have 19 installed and so the instructions will follow best practices for using 19.
  2. IDE or text editor: There are three that I would recommend for Java and Spring Boot development
    • VS Code: is a great free option. I highly recommend using it as it has support for the other tools that we are going to be using.
    • IntelliJ IDEA: For those of you that are only wanting to stick to the Java ecosystem I recommendIf you aren’t keen on paying for an IDE then you should be fine with the community edition, but you might lose out on some of the features that the IDE will help with such as automatic imports.
    • Fleet: Another good option for a free IDE/Text Editor is Fleet. You get support for Java and Kotlin right out of the box. So if you decide that you want to use Kotlin instead of Java then you are more than welcome to do so. Fleet also supports: Rust, Go, JavaScript, TypeScript, Python, PHP and C# as of the time of writing this article.
  3. Docker Desktop(Docker): Depending on your operating system you will need to install either Docker Desktop or docker. Those of you on Linux you don’t need Docker Desktop though you can download it if you so choose. Docker can be downloaded to your Linux distribution using your available package manager.
  4. Kubernetes: We will also need to install Kubernetes to see how we can orchestrate our containers.
  5. Gradle: If you come from something like Node or Python Gradle is a package manager. We will also use this to run our application.

That is all that we will need for this basic application. There are a few more tools we could use but because this is an introductory app I don’t want to get too crazy. With that we can now visit the Spring Initializr site to generate our application. The below bullet list will show you the values you can use to create the application.

  • Project: Gradle Project
  • Language: Java
  • Spring Boot: 2.7.5
  • Project Metadata:
    • Group: com.programmingwithjon
    • Artifact: cloud-native
    • Name: cloud-native
    • Description: Intro Cloud Native App
    • Package name: com.programmingwithjon.cloud-native
  • Packaging: Jar
  • Java: 19

Once we have that configured press the generate button to download a zip file. From there you can unzip the contents to any directory you want and begin work. I typically just use my Desktop on my Mac, but feel free to use whichever directory you normally use for your projects.

Controlling Your Routes

If this is your first Spring Boot project congratulations on getting everything installed and configured up to this point. Setting up a development environment is never an easy task, so kudos. We will now start to actually write some Java code in this section that will be our controller. It will handle returning the data, in our case a few lines of text, to the browser. Let’s get started.

  1. If your project isn’t open at this point go ahead and open it up in whatever IDE/text editor you prefer. We are going to create a new file called HomeController.java. Let’s write our code.
package com.cloudnative.spring;

import org.springframework.web.bind.application.GetMapping;
import org.springframework.web.bind.application.RestController;

@RestController
public class HomeController {
    
    @GetMapping("/")
    public String getMessage() {
        return "Hello from our awesome Cloud Native Service.";
    }
}

For anyone that hasn’t used Spring the code with the @ sign is what’s called an annotation. If you come from Python or TypeScript you might know these as decorators. They are essentially the same concept. We are setting our class to the RestController annotation and using the @GetMapping annotation we can set our root route for our application. In our case we use the default route “/” which is our root route. We can now test our application by running the gradlew command.

$ ./gradlew bootRun

It might take the application a minute to fully boot up. When I tested this on my MacBook Pro the server started and then looked like it hung at 80%, however when I opened up the browser and visited localhost:8080 I was welcomed with our greeting. That’s all our app is going to produce. I know it’s nothing special, but I did say that the app we would build wouldn’t be super great. This is just a bare-bones app to help you go through the motions of creating services that you can containerize. Speaking of containers let’s get our service wired up with Docker.

Docker Setup

Hopefully you have already installed Docker or Docker Desktop on your machine. If you are on Mac or Windows make sure you have Docker Desktop running. If you are on Linux and you aren’t using Docker Desktop then make sure to run the Docker daemon. So one thing I really like about Spring and Spring Boot is that Docker support comes baked in to every project. Due to the Cloud Native Buildpacks project by Heroku and Pivotal Spring Boot has a nice plugin both for Gradle and Maven which means that we can containerize our Spring Boot aps without configuring a Dockerfile or providing extra dependencies. All we have to do is run

$ ./gradlew bootBuildImage

This will take a bit of time as the process is downloading packages used by Buildpacks to create our container image. Any subsequent runs should only take a few seconds. Our image name, by default will be cloud-native:0.0.1-SNAPSHOT. We can run the command

$ docker images cloud-native:0.0.1-SNAPSHOT

in order to verify that the image has been created. Next up we need to run the image and test it out. We can do this by running the command:

$ docker run --rm --name cloud-native -p 8080:8080 cloud-native:0.0.1-SNAPSHOT

We can now open back up our browser and visit localhost:8080, and we should see our same message as before. Pretty awesome. Let’s now cover how to orchestrate this service and container with Kubernetes.

Kubernetes Setup

Hopefully you are feeling pretty good about your app and the progress you have made so far. We have created our app, tested it to make sure that it is working locally, containerized it and then verified we get the same results when running the app from Docker. Now we need to deploy our app to a cloud environment. We will be using Kubernetes. This is the de-facto standard for container orchestration these days. This section, much like the article itself, is just going to gloss over the subject. I just want to cover the bare minimum here in this article to showcase how to use the technologies together to create a cloud native app. I might do a more thorough deep dive on the subject in a later article. We will need to do one more installation which I saved until right now as it wasn’t needed right away. Please visit the minikube website for instructions on how to install it on your operating system. For those of you on Mac you can follow the steps below:

  1. In your terminal run brew install minikube
  2. Run minikube config set driver docker this will set the default driver for minikube to Docker
  3. Run minikube start
  4. Run brew install kubectl
  5. We can verify our minikube cluster by running kubectl get nodes

NOTE: When we are finished run minikube stop as it takes up valuable resources that you might need elsewhere if not using minikube.

Now that we have minikube installed and running let’s go ahead and run the commands we need in order to get our service container deployed to Kubernetes. In our terminal we will write:

$ minikube image load cloud-native:0.0.1-SNAPSHOT
$ kubectl create deployment cloud-native --image=cloud-native:0.0.1-SNAPSOT

We can verify that the deployment was successful by running

$ kubectl get deployment

Then we can run the next command to verify that the Pod for the application is defined in the Deployment resource

$ kubectl get pod

Next we can run the command to expose our deployment.

$ kubectl expose deployment cloud-native --name=cloud-native --port=8080

The Service object exposes the application to other components inside the cluster. We can verify this by running:

$ kubectl get service cloud-native

We can then forward the traffic to a local port on our computer by running the following command:

$ kubectl port-forward service/cloud-native 3000:8080

Now let’s visit our browser at localhost:3000 and we should see our message returned in the browser. If you don’t want to use a browser we can also open up something like Postman or Insomnia which will also allow us to test our endpoints.

Conclusion

That’s it. We have officially written a Cloud Native application. Ok, ok, so the app we built technically isn’t on the cloud nor is it really deployed, however, the steps we just went through are the exact same steps you would take to deploy it to an actual cloud native system. I hope that you enjoyed this article. I have a few more in the works so keep an eye out for them.