Amazon EKS Cluster setup & Spring Boot Rest API deployment
Introduction:
Kubernetes is an open-source system for automatic deployment, scaling and management of containerized (usually Docker) application. It is cloud agnostic for container orchestration. Basically it groups containers that make up an application into logical units for easy management and discovery. In this story we will focus on how we can deploy simple spring boot rest api on Amazon EKS.
Amazon Elastic Kubernetes Service
- Managed Kubernetes clusters on AWS
- EKS has two options for pod deployment one is on EC2 (worker node) and another one is Fargate (serverless)
There are two ways to create EKS Cluster. (1) Using eksctl (2) AWS Management Console.
eksctl — simplifies the step of creating cluster and saves time. But it abstracts lot of steps required to setup cluster.
In this story, we will see how we can setup cluster through AWS Management console in details.
Step-1: Create EKS Cluster
To setup the cluster, following configuration — required
- Kubernetes Version — K8s version
- Cluster Service Role — Allows K8s to manage resource
- VPC — VPC for cluster resource
- Cluster Endpoint Access — Public / private access
- Networking (Add on)
- Logging — Enable logging for K8s
Before creating Cluster, let’s create Cluster service role required for cluster.
1.1: Cluster Service Role
- Open the AWS Management Console, Choose IAM => Role => Create Role
- Choose “AWS service” for Trusted entity type and “EKS-Cluster” for the use-case
- Provide role name details and Create role.
Create Role by providing role name details
1.2: Setup Cluster
Step-2: Create Node Group
Node group is a set of EC2 instance that caters compute capacity for Amazon EKS
AMI ID, Instance Type, Auto Scaling Configuration, Disk Size
Node Group needs to be associated with EKS
IAM Role needs to be associated with NodeGroup to ensure EC2 instance can perform action like pull image from ECR.
2.1: Create IAM Role for EKS Node
Enter the role name and associate permission (as shown below) to role.
2.2: Configure Node Group
Go to java-k8s-cluster & select “Compute” tab. In the Node groups section, click on “Add node group”
- Enter Node group name and select IAM role for Node.
- Choose AMI Type, Capacity Type, Instance Type and Disk Size.
- Configure desired, minimum & maximum size for auto scaling
- Configure worker node’s subnet.
Go to “Compute” tab in eks cluster & ensure node-group/node is created.
Step-3: Setup & Configure Kubectl:
Kubectl: Kubernetes provides a command line tool for communicating with a Kubernetes cluster’s control plane, using the Kubernetes API.
Important Note: Lets ensure kubectl versions needs to be compatible with Kubernetes cluster version
3.1 Installation Link: https://docs.aws.amazon.com/eks/latest/userguide/install-kubectl.html
Once installed, ensure correct version is available using the following command.
kubectl version --output yaml
3.2 Create KubeConfig file:
Create kubeconfig file with following command to connect to kubernetes cluster
aws eks update-kubeconfig --region us-east-1 --name java-k8s-cluster
And ensure the file is created in location: <home-directory>/.kube/config
It has the following key information to connect to the Kubernetes clusters.
1. certificate-authority-data: Cluster CA
2. server: Cluster endpoint (IP/DNS of master node)
3. name: Cluster name
4. user: name of the user/service account.
5. token: Secret token of the user/service account.
We can use the following commands to test kubectl commands.
#To Print all worker node information
kubectl get nodes.
#To Print all pods available in default namespace
kubectl get pods
Step-4: Create Java/Spring Boot Project
Create Spring Boot project with Spring Intializer (https://start.spring.io) configuring spring-web dependencies.
4.1: pom.xml source file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.11-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.spingboot</groupId>
<artifactId>restapi</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>restapi</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
4.2: Simple Rest Controller — Source file
package com.spingboot.restapi;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class SimpleRestController {
@GetMapping("/")
public String hello() {
return "Hello World! from simple rest controller";
}
}
4.3: Docker Source file
FROM openjdk:11
WORKDIR /usr/src/myapp
COPY target/restapi-0.0.1-SNAPSHOT.jar /usr/src/myapp
CMD ["java", "-jar", "/usr/src/myapp/restapi-0.0.1-SNAPSHOT.jar"]
Step-5: Build the Image & Push Image to ECR
Use the following command to build and push docker image to Amazon ECR.
# Build the Docker Image
docker build . -t java-restapi
# Login to ECR
aws ecr get-login-password --region us-east-1 --profile default | docker login --username AWS --password-stdin <aws-account-no>.dkr.ecr.us-east-1.amazonaws.com
# Create ECR Repo
aws ecr create-repository --repository-name java-restapi --image-tag-mutability IMMUTABLE --image-scanning-configuration scanOnPush=true
# Create the Tag
docker tag java-restapi:latest <aws-account-no>.dkr.ecr.us-east-1.amazonaws.com/java-restapi:v1
# Push the Image
docker push <aws-account-no>.dkr.ecr.us-east-1.amazonaws.com/java-restapi:v1
Step-6: Deploy & Run the Pod in EKS Cluster
Kubernete file.
apiVersion: apps/v1kind: Deployment
metadata:
name: rest-api
spec:
selector:
matchLabels:
app: rest-api
template:
metadata:
labels:
app: rest-api
spec:
containers:
- name: rest-api
image: <aws-account-no.>.dkr.ecr.us-east-1.amazonaws.com/java-restapi:v1
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
- name: tcp
containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: rest-api
spec:
selector:
app: rest-api
ports:
- port: 80
targetPort: 8080
type: LoadBalancer
Use the following command to deploy the pod.
# Use the following command to
kubectl apply -f k8s.yaml
Conclusion:
Using Amazon EKS, users don’t have to maintain a Kubernetes control plane on their own. Only User have to focus on Worker Node (Data Plane) setup with EC2 instance. EKS also have option to run Data plane on fargate profile which is serverless.