Recently, during the Spring Office Hours, we have been discussing
Spring to Production as a topic.
There are so many ways to get Spring Boot application to production.
If your Spring Boot application is delivered as a container, all you really need is a Docker or Kubernetes dial tone.
In this post, I'm starting from nothing, and delivering a Spring Boot application to Kamatera. I've never used Kamatera before this, so I'm going document the entire process, and experience, for you.
Getting an account
Kamatera provides a
30-Day Free Trial which sounds wonderful!
After validating my email address, I was required to add a billing profile.
This makes sense.
However, before signing up for the free trial, I did verify that there was a Terraform provider for Kamatera.
While I was adding my billing profile, I saw more details of the 30-Day free trial.
30 days Free Usage: 1 Cloud Server (of up to 100 USD) 1000 GB Cloud Block Storage 1000 GB Outgoing Internet Traffic
This is plenty to work with, so I continued to proceed. The only option I had was to use a credit card. The process was pretty painless and only took a couple of minutes.
The UI is easy to understand and navigate. I just don't want to use the UI. I want to automate all the things. Now that my account is set up, I want to set up my infrastructure as code.
Kamatera Terraform Provider
A quick glance at the Terraform Provider for Kamatera usage guide and I see that I need:
I clicked the
+ Create New Key button. A
description box is presented.
Spring Boot to Production with Kamatera in the description and clicked
Create Key to move forward.
At that point, I am provided with my
Client ID and
API Secret which I then copy to a safe place.
The Terraform Provider for Kamatera usage guide also provided an example Terraform file.
I copied that and separated their
main.tf into different files, that makes things easier for me to understand later.
I started a github repository to capture my changes.
At this point, I determined that I couldn't configure Docker as an option via Terraform using one of their images. They have a tool that generates Terraform files, but the image ID never worked for me. I didn't spend much time investigating, probably user error.
That is ok, because I can use an executable JAR and deploy that as a service. Or I can just install Docker as part of the startup scripts.
I chose to use
Ubuntu and their
22.04 64bit_optimized image.
I attempted to install Docker using the
startup_script value of the
kamatera_server but I struggled with getting that to work consistently.
The problem appeared to be timing.
I'm still unsure about when the startup script gets executed.
I needed to wait for the network, then wait for DNS, and sometimes it would just fail.
I couldn't figure out a way to access the logs during the build process either.
At one point, a server appeared to have been built and completed successfully, but the startup script was stuck in a loop, waiting for something.
I couldn't access the server though, and my Terraform was stuck, for 15+ minutes.
Interesting Side Note Regarding The Stuck Server
I opened a ticket, asking for the server to be destroyed, for two reasons.
When I cancelled the stuck Terraform
apply my local state didn't show the server, so I couldn't Terraform
In the Kamatera console, the task was showing completed, but the server didn't show up in my server list, so I couldn't delete it from there either.
The response was quick, less than 30 minutes, but confusing.
Unfortunately, we do not provide support for Terraform.
The Terraform Provider that I'm using, appears to be created by
Kamatera and shows up in the Terraform Registry.
Therefore, I can only assume that the 30-day support is not going to troubleshoot Terraform related issues.
I later realized that every server creation and destroy sends out an email receipt. I did not get a receipt for the server creation, so maybe, hopefully, their system cleaned it up properly, automatically.
Docker via remote-exec
I don't recommend this approach.
Nobody recommends this approach.
The Terraform documentation states Use provisioners as a last resort.
Important and highlighted at the top of the page.
Well, it is my last resort. The purpose of this exercise was to show that getting Spring to production is doable, and Spring Boot makes it really easy. Different providers are going to have different pain points, but also, different strengths.
At this point, I use the
remote-exec provisioner to do a few things:
- Download the
Dockerinstall script via
- Execute the install script
- Pull down the image
- Run the image on
remote-exec required setting up a
connection to the host.
For this example, I chose to use a public/private key pair for access.
In order to take this for a spin yourself:
#clone the repository git clone https://github.com/dashaun/spring-to-production-kamatera cd spring-to-production-kamatera # configure Terraform with your credentials export KAMATERA_API_CLIENT=... export KAMATERA_API_SECRET=... export TF_VAR_ssh_public_key="$(cat ~/.ssh/id_rsa.pub)" export TF_VAR_ssh_private_key="$(cat ~/.ssh/id_rsa)" # Initialize Terraform to pull down the provider terraform init # Validate your credentials config by using the plan terraform plan # Apply the Terraform, ETC < 5min terraform apply -auto-approve # Access the Spring Boot application using the newly created server curl $(terraform output -raw public_ips):8080/actuator/health | jq .
When you are done, clean up behind yourself:
# Destroy the Terraform, ETC < 1min terraform destroy -auto-approve
While exploring multi-cloud architectures, I really wanted to get outside my comfort zone.
Spring Boot make getting applications up and available really simple.
I am going to continue to explore and experiment with other cloud providers.
Soon, I will deploy a reference architecture, with different Spring Boot services, each deployed to different cloud providers.
My theory is that you don't have to be a certified Azure|GCP|AWS cloud architect to be productive with Spring Boot.
I did not harden this deployment, and I wouldn't call it production ready. If you would like to see me expand and harden this example, please let me know, via the GitHub repository.