Containers
Announcing Java support for cdk8s
Today, we are announcing Java support for cdk8s, the Cloud Development Kit for Kubernetes. This rounds out support for the top 3 most popular programming languages and probably the single most used here at Amazon. Now, you can leave YAML behind and define your Kubernetes applications in Typescript, Python, and Java.
In this tutorial, we’ll learn how to use Java cdk8s to define a simple deployment of a load balancer service that will front our containerized SpringBoot application. We’ll be using kind for local Kubernetes development, but feel free to skip that section if you already have a cluster up and running. To keep things simple, we’ll define our infrastructure and our core business logic in the same package. To complete this tutorial, you’ll need to have Java installed on your computer as well as homebrew and kind.
Java cdk8s tutorial
Let’s start by installing the cdk8s CLI:
We’ll use the quick start Java template for cdk8s
:
This will set up everything you need to get started with Java. Go ahead and open up src/main/java/com/mycompany/app/Main.java
.
You’ll see a Main
class with an empty constructor telling you to // define resources here
and we’ll do just that. We’ll be using cdk8s+, a construct library built on top of cdk8s.
For readers that are unfamiliar with constructs, constructs are the basic building blocks in CDK applications. In the AWS CDK, these refer to AWS cloud resources (i.e. S3 Bucket, DDB table, etc). In cdk8s, these refer to Kubernetes objects (i.e. Container, Deployment, etc).
Before we go too far into building our app, let’s walk through a quick example to give you a sense for how cdk8s works. We can start with creating a pod, the smallest unit in our Kubernetes application.
Inside the Main class constructor, let’s start with the Container
that will be run on our pod:
Using cdk8s
CLI, we should be able to synthesize this Java code into a valid Kubernetes manifest:
In dist/
, we’ll find our manifest that looks like this:
Now that we’ve seen how cdk8s works at a basic level, we can see some of the benefits:
- You get the type safety of Java (you couldn’t compile or synthesize your manifest with any typos or errors).
- You get hints from the IDE on what you need to put where, preventing you from making valid YAML but invalid manifests.
The higher level abstractions and familiar programming language can help you reduce the amount of repetitive and error-prone YAML that you may be used to writing.
Now let’s continue on and define our deployment. We can remove the line where we defined our Pod
because we’ll let cdk8s-plus
handle that by passing in the PodSpec
to our Deployment
.
Finally, we’ll expose our deployment through a LoadBalancer
service on port 8080:
Simply enough, we define some options for exposing our deployment behind a LoadBalancer Service
on port 8080, and then we expose the Deployment
with those options.
We’re now done with our infrastructure. You can see the full code here.
The next thing we’ll do is define our basic SpringBoot application. Since we’re doing it here in the same Maven project, let’s go ahead and open up our pom.xml
again. We’ll want to add the SpringBoot parent pom and dependency:
And now, in the same package ( com.mycompany.app
) as our infrastructure, we’ll define our service code. It’ll look like this:
This starts a SpringApplication server that returns “Hello cdk8s!” when we hit the “/” endpoint. We’re nearly finished! We just need to Dockerize our application so we can deploy it on our cluster. Let’s define our Dockerfile at the root of our project like so:
Yay! We’re done writing code now. All that’s left is packaging and deploying. Let’s first compile our code:
Next, let’s use the Dockerfile to create an image for our container:
Great! So we’ve made an image and tagged it with “helloworld,” which, if we remember earlier in the tutorial, was what we put in for the image for our Container.
Note: at this point, if you are planning to use a container registry, please upload your container there. Additionally, make sure you edit the
image
in theContainer
you defined earlier and recompile withmvn compile
. We will be using kind to run a local cluster later in this tutorial.
Let’s create a cluster with kind
and load our image into it.
The next thing we’ll want to do is synthesize our cdk8s code into a Kubernetes manifest. To synthesize here means that we’ll take the Java code we wrote and pass it through the cdk8s engine to create the YAML that Kubernetes expects. Let’s run this command:
This will create a manifest under dist/helloworld.k8s.yaml
and the contents should look something like this:
If you already have your cluster all set up, you should be able to apply this manifest to it:
Finally, to access our service, we’ll want to port-forward into our cluster. First, grab your Service name:
And copy that and port-forward like so:
And if we did everything right, you can see your service running by opening up localhost in your browser or by doing:
And just like that, we’re done! We were able to define both our business logic and our Kubernetes infrastructure in the same Java package. I hope that you learned something new in this tutorial. I’m excited to see all the amazing things developers build with Java cdk8s!
Enjoy! ?