Deploying a Java Application to Amazon Elastic Kubernetes Cluster in VS Code

This guide shows you how to create a Java application, containerize and deploy it to Amazon Elastic Kubernetes Service (EKS) from within VS Code with ease, using the Graal Development Kit for Micronaut Extension Pack. The Micronaut® Kubernetes module provides seamless integration with EKS.

EKS is a managed Kubernetes service for deploying containerized applications to the cloud.

Prerequisites #

1. Install Extensions #

To get started, install the Graal Development Kit for Micronaut Extension Pack and AWS Toolkit for Visual Studio Code.

  1. Follow Installing the Graal Development Kit for Micronaut Extension Pack to install the extension pack and its dependencies in VS Code.

  2. To install the AWS Toolkit for Visual Studio Code plugin, follow these steps:

    • In the VS Code Activity Bar, click the Extensions icon. This opens the Extensions view, which provides you with access to the VS Code Marketplace.
    • In the search box, search for AWS Toolkit.
    • Once found, choose it to see its details, then click Install.
    • Once installed, if you’re prompted to restart the editor, click Reload Required to finish the installation.

    After you install the Toolkit for VS Code, notice the AWS icon the VS Code Activity Bar.

2. Create a Java Application Using Graal Development Kit for Micronaut Launcher #

Create a Java application, using the Graal Development Kit for Micronaut Launcher, that you will later containerize and deploy to Amazon Elastic Kubernetes Service (EKS).

  1. Go to View, Command Palette, search for “Graal Dev Kit”, and invoke the Graal Dev Kit: Create New Project quick action:

    Create New Project Action

  2. Follow the command prompts to generate a new Maven or Gradle project. For example, to create a simple Java application:
    • Pick Micronaut version: Default
    • Pick application type: Application
    • Pick project Java: GraalVM or Other Java
    • Provide a project name: aws-k8s-demo
    • Provide base package: com.example
    • Pick project services: none. Click OK to confirm
    • Pick build tool: Gradle (Groovy)
    • Pick test framework: JUnit
    • Pick cloud platform: AWS. Click OK to confirm
  3. Finally, select the destination directory on your local disk and whether to open the created project in a new window or add it to the current workspace. The wizard creates a directory named aws-k8s-demo containing an application in a package named com.example.

  4. (Required only for macOS AArch64) At the beginning of the configuration file, aws/build.gradle, add the following dependency to use the appropriate version of JNA:

     buildscript {
         dependencies {
             classpath("com.github.docker-java:docker-java-transport-httpclient5:3.2.13") {
                 because("macOS AArch64 needs a specific version of JNA")
             }
         }
     }
    
  5. (Required only for macOS AArch64) At the end of the configuration file, aws/build.gradle, add the following code so that Gradle builds a container image using the openjdk:17-slim base image (it defaults to openjdk:17-alpine which is not multiplatform).

     tasks.withType(com.bmuschko.gradle.docker.tasks.image.Dockerfile) {
         baseImage = 'openjdk:17-slim'
     }
    

    2.1. Add a Controller #

To create a microservice that responds with “Hello World”, you need a controller. Create a file named lib/src/main/java/com/example/HelloController.java with the following contents:

package com.example;

import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Produces;

@Controller // <1>
public class HelloController {
    @Get
    @Produces(MediaType.TEXT_PLAIN) // <2>
    public String index() {
        return "Hello World";
    }

    @Get ("/{name}") // <3>
    @Produces(MediaType.TEXT_PLAIN)
    public String index(String name) {
        return "Hello " + name;
    }
}

1 The class is defined as a controller with the @Controller annotation mapped to the path / (the default mapping for the base URI).

2 By default, a Micronaut response uses application/json as Content-Type. To return a String, not a JSON object, set it to text/plain.

3 The @Get annotation maps the index method to an HTTP GET request on /{name}.

2.2. Build and Run the Application #

  1. Open a new Terminal window in VS Code (Terminal > New Terminal). Enter the following command to build the application JAR file and run it:

     ./gradlew :aws:run
    

    It starts the application on port 8080.

  2. Split the Terminal window (Terminal > Split Terminal) and send some curl requests to test the application in a split terminal:

     curl http://localhost:8080/
    

    It should output “Hello World”.

     curl http://localhost:8080/GDK/
    

    It should output “Hello GDK”. Press CTRL+C to stop the application.

3. Create a Shared AWS Credentials File and Connect to AWS #

Follow the instructions provided in the AWS documentation to Add your AWS access keys to your environment.

Follow the instructions provided in the AWS documentation to Connect to AWS through the Toolkit for VS Code.

4. Create a Repository in Amazon Elastic Container Registry (ECR) #

Amazon Elastic Container Registry (Amazon ECR) is an AWS-managed container image registry service. Amazon ECR supports private repositories with resource-based permissions. Amazon ECR is integrated with Amazon Elastic Container Service (Amazon ECS).


The following steps walk you through what is needed to push a container image to a private Amazon ECR repository using the AWS CLI. Before you begin, make sure that you have necessary software listed in the Prerequisites. Also, ensure that you have your AWS account id and region identifier (both of these can be obtained from your AWS console).

  1. Authenticate to Amazon ECR with docker (it requires the AWS CLI installed, see Prerequisites). The AWS CLI provides a get-login-password command to simplify the authentication process. The Docker CLI (docker) can push and pull images with Amazon ECR.

    • Open a Terminal window in VS Code (Terminal > New Terminal) and enter the following command to authenticate:
        aws ecr get-login-password --region <region> | docker login --username AWS --password-stdin <aws_account_id>.dkr.ecr.<region>.amazonaws.com
      
    • Replace <region> with your AWS region key. AWS is the default username. The password is composed of <aws_account_id>, which is your AWS account ID, and of the <region> key. For example:
        aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 1234567890.dkr.ecr.us-east-1.amazonaws.com
      

      Note: If you are a Windows user, the command is:

        (Get-ECRLoginCommand).Password | docker login --username AWS --password-stdin aws_account_id.dkr.ecr.region.amazonaws.com
      

      Read more on Using Amazon ECR with the AWS CLI.

  2. Create a repository in Amazon ECR that will hold your containerized application (a container image). Under your active AWS connection, focus on ECR and click Create Repository:

    Amazon ECR: Create Repository

    Enter a repository name, for example, gdk-demo.

  3. Get the repository URI. Open the ECR repositories list, right-click your new repository, and click Copy Repository URI:

    Amazon ECR: Copy Repository URI

  4. Specify the path to your new repository in the build configuration file, aws/build.gradle, as follows:

     dockerBuild {
         images = ["<aws_account_id>.dkr.ecr.<region>.amazonaws.com/gdk-demo:$project.version"]
     }
    

You are all set to build a container image for your application and push it to Amazon ECR.

5. Containerize the Application and Push a Container Image #

In this section, you create a container image of your Java application and then push it to Amazon ECR.

Note: The build and deployment architecture must match. You cannot build a container image on an AArch64 platform and deploy it to an Intel-based platform, such as Amazon Elastic Compute Cloud (Amazon EC2) or Amazon Elastic Kubernetes Service (Amazon EKS).

  1. Build the project in your VS Code terminal:
     ./gradlew clean build
    
  2. Build a container image of the application. Note that, because you created the application using Graal Development Kit in VS Code, you do not need to provide a Dockerfile. It is provided by the extension at build time.
     ./gradlew dockerBuild
    
  3. Query docker to list your newly built container image:
    docker images | head -n2
    
  4. Push the container image to the container repository:
     ./gradlew dockerPush
    

Now that your container image is stored in Amazon ECR, you can deploy it to an Amazon EKS cluster.

6. Create an Amazon EKS Cluster and Setup Connection to Your Cluster #

Follow the AWS documentation to Create an Amazon EKS cluster, Configure Your Computer to Communicate with Your Cluster, and Create Nodes.

Do not follow the Step 5: Delete resources chapter at this point.

7. Deploy a Java Application to EKS Cluster #

  1. Create a Kubernetes deployment manifest file. In the project root, create a file named deployment.yml with the following contents:

     apiVersion: apps/v1
     kind: Deployment
     metadata:
       name: "aws-k8s-demo"
     spec:
       selector:
         matchLabels:
           app: "aws-k8s-demo"
       template:
         metadata:
           labels:
             app: "aws-k8s-demo"
         spec:
           containers:
           - name: "aws-k8s-demo"
             image: "<aws_account_id>.dkr.ecr.<region>.amazonaws.com/gdk-demo:1.0-SNAPSHOT"
    

    (Copy the repository URI from the build configuration file, aws/build.gradle.) To learn more, see Deployments in the Kubernetes documentation.

  2. Create a deployment by applying the manifest:

     kubectl apply -f deployment.yml
    

    It should output the following:

     deployment.apps/aws-k8s-demo created
     

    This deployment pulls your container image from a public repository (Amazon ECR repository) and deploys three replicas (individual pods) of it to your cluster.

  3. Run the next command to check the status of the pods:

     kubectl get pods
    

    It should return a similar message:

     NAME                               READY   STATUS    RESTARTS   AGE
     aws-k8s-demo-6fdf89f45-5rpsp       0/1     Pending   0          3m
     

    Wait a couple of seconds for the Pending state to change to Running. Your application is now deployed to the EKS cluster.

  4. Port-forward the port to access your Kubernetes cluster directly from your local network:

     kubectl port-forward <pod-name> 8080:8080
    

    kubectl port-forward uses a resource name, such as a pod name, to select a matching pod to port forward.

  5. Send some curl requests to test your application as you did in step 2.2:

     curl http://localhost:8080/
    
     curl http://localhost:8080/GDK/
    

    The difference is that now your application is deployed to an EKS cluster and running on an Amazon EC2 Linux compute host.

8. Clean Up Resources #

To delete all the resources you created in this guide, run this command:

kubectl delete namespaces <namespace-name>

Summary #

This guide demonstrated how to deploy a Java microservice application to Amazon Elastic Kubernetes Service (EKS) from within VS Code, using the Graal Development Kit for Micronaut Extension Pack.