Enterprise Java

Deploy Spring Boot with MySQL on Amazon EKS

Amazon Elastic Kubernetes Service (Amazon EKS) is one of the most popular managed Kubernetes platforms for running containerized applications in production. Combining Spring Boot, MySQL, Docker, Kubernetes, and Amazon EKS provides an enterprise-grade deployment architecture capable of scaling thousands of requests while maintaining high availability.

1. Introduction to Amazon EKS Architecture

Amazon Elastic Kubernetes Service (Amazon EKS) is AWS’s fully managed Kubernetes service that simplifies deploying, managing, and scaling containerized applications. AWS manages the Kubernetes control plane, including API servers, etcd, upgrades, security patches, and high availability, allowing developers to focus on building and deploying applications instead of maintaining Kubernetes infrastructure. An EKS cluster consists of a managed control plane and one or more worker node groups where your application containers run. EKS integrates seamlessly with AWS services such as IAM for authentication, Elastic Load Balancing for traffic distribution, Amazon ECR for container images, Amazon EBS for persistent storage, and CloudWatch for monitoring and logging.

1.1 Key Benefits of Amazon EKS

  • Fully managed Kubernetes control plane with automatic upgrades and maintenance.
  • Highly available control plane distributed across multiple Availability Zones.
  • Native integration with AWS Identity and Access Management (IAM).
  • Automatic integration with AWS Elastic Load Balancers.
  • Built-in monitoring and logging through Amazon CloudWatch.
  • Managed Node Groups simplify worker node lifecycle management.
  • Supports EC2 and AWS Fargate for flexible compute options.
  • Horizontal Pod Autoscaler (HPA) and Cluster Autoscaler support automatic scaling.
  • Persistent storage using Amazon EBS, EFS, and FSx volumes.
  • Supports Helm charts for simplified application deployments.
  • Supports rolling updates, self-healing pods, and zero-downtime deployments.
  • Compatible with standard Kubernetes APIs and tooling.

1.2 Understanding Amazon EKS Components

  • Control Plane: Managed Kubernetes API server, scheduler, controller manager, and etcd maintained by AWS.
  • Cluster: The logical Kubernetes environment that hosts all workloads and resources.
  • Node Group: A collection of EC2 instances or AWS Fargate resources that execute application pods.
  • Pod: The smallest deployable Kubernetes unit that runs one or more containers.
  • Deployment: Manages pod creation, scaling, rolling updates, and application availability.
  • Service: Provides stable networking and load balancing for accessing application pods.
  • Ingress: Routes external HTTP/HTTPS traffic to services using host- and path-based routing rules.
  • ConfigMap: Stores non-sensitive configuration values separately from application images.
  • Secret: Securely stores sensitive information such as passwords, API keys, and authentication tokens.
  • Persistent Volume (PV): Provides durable storage for stateful applications such as MySQL.
  • Persistent Volume Claim (PVC): Requests and binds persistent storage for Kubernetes pods.
  • Amazon Elastic Container Registry (ECR): Stores Docker container images that are pulled by Amazon EKS during deployment.

2. Building a Spring Boot Application with MySQL

2.1 Configuring Maven Dependencies

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
    </dependency>
</dependencies>

The project uses three essential Spring Boot dependencies. The spring-boot-starter-web dependency provides everything required to build RESTful web applications, including the embedded Tomcat server and Spring MVC. The spring-boot-starter-data-jpa dependency simplifies database operations by providing Spring Data JPA, Hibernate, and repository support for implementing CRUD operations with minimal code. Finally, the mysql-connector-j dependency is the official MySQL JDBC driver that enables the Spring Boot application to establish a connection with the MySQL database and execute SQL queries. Together, these dependencies provide the complete foundation for developing a REST API backed by a MySQL database.

2.2 Configuring MySQL Database Connection

spring.datasource.url=jdbc:mysql://mysql-service:3306/demo
spring.datasource.username=root
spring.datasource.password=password

spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

The application.properties file contains the application’s database and JPA configuration. The spring.datasource.url property specifies the JDBC connection URL, where mysql-service is the Kubernetes Service name that allows the Spring Boot pods to communicate with the MySQL pod using Kubernetes DNS. The spring.datasource.username and spring.datasource.password properties provide the database credentials. The spring.jpa.hibernate.ddl-auto=update setting instructs Hibernate to automatically create or update database tables based on the entity classes, while spring.jpa.show-sql=true logs all generated SQL statements to the console, making it easier to debug and monitor database interactions during development.

2.3 Creating the JPA Entity Model

@Entity
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    public Employee() { }

    public Employee(String name) {
        this.name = name;
    }

    // getters and setters
}

The Employee class is a JPA entity that represents a database table in MySQL. The @Entity annotation marks this class as a persistent entity managed by Hibernate, allowing Spring Data JPA to map it to a database table automatically. The @Id annotation identifies the id field as the primary key, while @GeneratedValue(strategy = GenerationType.IDENTITY) configures the database to automatically generate unique identifier values using the auto-increment feature. The name field is mapped as a column in the employee table to store employee names. The default constructor is required by JPA so that Hibernate can create entity objects internally, while the parameterized constructor allows developers to easily create new Employee objects with a name value. The getters and setters are used by Hibernate and the application to read and update entity properties.

2.4 Creating Spring Data JPA Repository

public interface EmployeeRepository extends JpaRepository<Employee, Long> {   }

The EmployeeRepository interface provides database access functionality for the Employee entity by extending Spring Data JPA’s JpaRepository interface. The first generic parameter, Employee, specifies the entity type that this repository manages, while the second parameter, Long, defines the data type of the entity’s primary key. By extending JpaRepository, the application automatically gets built-in CRUD operations such as saving, updating, deleting, and retrieving employee records without writing SQL queries or implementation code. Spring Data JPA automatically creates the repository implementation at runtime, allowing the application to interact with the MySQL database through simple Java method calls.

2.5 Developing REST APIs with Spring Boot Controller

@RestController
@RequestMapping("/employees")
public class EmployeeController {

    @Autowired
    private EmployeeRepository repository;

    @PostMapping
    public Employee save(@RequestBody Employee employee) {
        return repository.save(employee);
    }

    @GetMapping
    public List<Employee> all() {
        return repository.findAll();
    }
}

The EmployeeController class exposes REST API endpoints for managing employee data. The @RestController annotation marks this class as a Spring MVC REST controller, allowing it to handle HTTP requests and return JSON responses directly. The @RequestMapping("/employees") annotation defines the base URL path for all APIs in this controller. The EmployeeRepository dependency is injected using @Autowired, allowing the controller to interact with the MySQL database through Spring Data JPA methods. The @PostMapping method handles HTTP POST requests and uses @RequestBody to convert incoming JSON payloads into an Employee object, which is then saved into the database using the repository.save() method. The @GetMapping method handles HTTP GET requests and retrieves all employee records from the database using the repository.findAll() method, returning the data as a JSON list in the API response.

2.6 Creating the Spring Boot Application Entry Point

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

The DemoApplication class is the main entry point of the Spring Boot application. The @SpringBootApplication annotation enables key Spring Boot features, including component scanning, auto-configuration, and Spring configuration support. It allows Spring Boot to automatically detect controllers, services, repositories, and entity classes within the application package. The main() method starts the embedded application server and initializes the Spring application context using SpringApplication.run(). During startup, Spring Boot loads the configured properties, establishes the database connection, creates required beans, and prepares the application to handle HTTP requests.

2.7 Running the Spring Boot Application and Testing APIs

The application saves the employee record and returns the generated database identifier along with the employee details. The GET /employees endpoint retrieves all employee records from the database and returns them as a JSON response.

GET http://localhost:8080/employees


// Response
[{"id":1,"name":"John"}]

The output confirms that the Spring Boot application is successfully running, connected to MySQL, storing employee data, and exposing REST APIs through HTTP endpoints.

2.8 Containerizing Spring Boot Application Using Docker

FROM eclipse-temurin:21-jdk

WORKDIR /app

COPY target/demo.jar app.jar

EXPOSE 8080

ENTRYPOINT ["java","-jar","app.jar"]

The Dockerfile defines the instructions required to package the Spring Boot application as a Docker container image. The FROM eclipse-temurin:21-jdk statement uses the Eclipse Temurin Java 21 JDK image as the base image, providing the required Java runtime environment to execute the Spring Boot application. The WORKDIR /app command sets the working directory inside the container where application files will be stored. The COPY target/demo.jar app.jar instruction copies the generated Spring Boot executable JAR file from the local build directory into the container and renames it as app.jar. The EXPOSE 8080 instruction documents that the application listens on port 8080, which is the default port used by Spring Boot’s embedded Tomcat server. Finally, the ENTRYPOINT command defines the container startup process and executes the Spring Boot application using the Java runtime when the Docker container starts.

2.9 Deploying Spring Boot Application on Amazon EKS

Before deploying the Spring Boot application on Amazon EKS, ensure that all required tools are installed and configured. The deployment process requires the AWS CLI for interacting with AWS services, kubectl for managing Kubernetes resources, eksctl for creating and managing Amazon EKS clusters, and Docker for building and packaging the application container image. An AWS account with the required permissions is also needed to create EKS clusters, manage networking resources, and access AWS services. The first step is configuring the AWS CLI by running the aws configure command, which prompts for the AWS Access Key, AWS Secret Key, default AWS Region, and output format. These credentials allow the AWS CLI to authenticate requests and execute AWS operations from the local environment.

2.9.1 Creating Amazon EKS Cluster Using eksctl

eksctl create cluster --name spring-cluster --region us-east-1 --nodes 2

The eksctl create cluster command creates a new Amazon EKS cluster along with the required AWS infrastructure. The --name spring-cluster option defines the name of the Kubernetes cluster, which is used to identify and manage the EKS environment. The --region us-east-1 option specifies the AWS region where the cluster resources will be provisioned. The --nodes 2 parameter creates a managed node group with two worker nodes that will run Kubernetes workloads such as the Spring Boot application and MySQL containers. During execution, eksctl automatically provisions the EKS control plane, creates the required VPC networking components, configures IAM roles, launches EC2 worker nodes, and updates the local Kubernetes configuration so that kubectl can communicate with the newly created cluster.

2.9.2 Verifying EKS Cluster Nodes

kubectl get nodes

The kubectl get nodes command is used to verify the status of the worker nodes connected to the Amazon EKS cluster. It communicates with the Kubernetes API server and displays information about all available nodes, including their name, readiness status, role, and Kubernetes version. A node with the status Ready indicates that the EC2 worker instance has successfully joined the cluster and is ready to run application workloads such as Spring Boot and MySQL pods. This verification step ensures that the EKS infrastructure is correctly provisioned before deploying applications.

NAME          STATUS   ROLES
ip-1          Ready
ip-2          Ready

2.9.3 Building Docker Image and Publishing to Amazon ECR

The first step is to package the Spring Boot application as a Docker image using the docker build command. This command reads the Dockerfile, creates a container image with the required Java runtime and application JAR, and tags it with the name springboot-mysql. After building the image, it needs to be stored in Amazon Elastic Container Registry (ECR), which provides a secure and scalable private container image repository for Amazon EKS deployments. The aws ecr create-repository command creates a new ECR repository where the Docker image will be stored. Before pushing the image, Docker must authenticate with ECR using the aws ecr get-login-password command, which generates a temporary authentication token. The docker tag command assigns the ECR repository URL to the local image, allowing it to be identified by AWS. Finally, the docker push command uploads the image to ECR, making it available for Amazon EKS nodes to pull and deploy as Kubernetes pods.

// Build Docker Image
docker build -t springboot-mysql .

// Create Amazon ECR Repository
aws ecr create-repository --repository-name springboot-mysql

// Authenticate Docker with Amazon ECR
aws ecr get-login-password | docker login --username AWS --password-stdin ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com

// Tag Docker Image
docker tag springboot-mysql ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/springboot-mysql

// Push Image to ECR
docker push ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/springboot-mysql

2.9.4 Deploying MySQL Database on Kubernetes

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: 'mysql:8'
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: password
            - name: MYSQL_DATABASE
              value: demo
          ports:
            - containerPort: 3306

The Kubernetes deployment configuration defines how the MySQL database container will be created and managed inside the Amazon EKS cluster. The apiVersion: apps/v1 specifies that this resource uses the Kubernetes Deployment API, while kind: Deployment indicates that Kubernetes should manage the lifecycle of the MySQL pod. The metadata.name field assigns the deployment name as mysql. The replicas: 1 setting ensures that one MySQL pod is running at any given time. The selector.matchLabels and template.metadata.labels establish the connection between the deployment and the pods it manages using the app: mysql label. Inside the pod specification, the containers section defines the MySQL container using the official mysql:8 Docker image. The environment variables MYSQL_ROOT_PASSWORD and MYSQL_DATABASE initialize the MySQL root password and create the application database named demo during startup. The containerPort: 3306 exposes the default MySQL port inside the Kubernetes pod, allowing the Spring Boot application to connect to the database through a Kubernetes Service.

// Deploy
kubectl apply -f mysql.yaml

The kubectl apply -f mysql.yaml command deploys the MySQL Kubernetes resources defined in the mysql.yaml configuration file to the Amazon EKS cluster. Kubernetes reads the YAML manifest, creates the MySQL Deployment, and starts the required pod using the specified MySQL container image and configuration values. The apply command follows a declarative approach, meaning Kubernetes compares the desired state defined in the YAML file with the current cluster state and creates or updates resources accordingly. Once executed successfully, the MySQL pod starts running inside the EKS cluster and becomes ready to accept database connections from the Spring Boot application.

2.9.5 Deploying Spring Boot Application on Kubernetes

apiVersion: apps/v1
kind: Deployment
metadata:
  name: springboot
spec:
  replicas: 2
  selector:
    matchLabels:
      app: springboot
  template:
    metadata:
      labels:
        app: springboot
    spec:
      containers:
        - name: springboot
          image: ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/springboot-mysql
          ports:
            - containerPort: 8080

The Kubernetes deployment configuration defines how the Spring Boot application will be deployed and managed inside the Amazon EKS cluster. The apiVersion: apps/v1 specifies the Kubernetes Deployment API version, while kind: Deployment indicates that Kubernetes should manage the application pod lifecycle, including creation, scaling, and recovery. The metadata.name field assigns the deployment name as springboot. The replicas: 2 configuration creates two instances of the Spring Boot application, providing high availability and allowing Kubernetes to distribute incoming traffic across multiple pods. The selector.matchLabels and template.metadata.labels use the app: springboot label to associate the deployment with the pods it manages. The container configuration uses the Spring Boot Docker image stored in Amazon ECR through the specified repository URL. When the deployment is applied, EKS pulls this image from ECR and creates running application containers on the worker nodes. The containerPort: 8080 exposes the Spring Boot application’s default HTTP port inside the Kubernetes pod, allowing it to receive requests through a Kubernetes Service.

// Deploy
kubectl apply -f springboot.yaml

The kubectl apply -f springboot.yaml command deploys the Spring Boot application to the Amazon EKS cluster using the Kubernetes configuration defined in the springboot.yaml file. Kubernetes reads the deployment manifest and creates the required Spring Boot pods based on the specified container image, replica count, and port configuration. The command ensures that the desired application state defined in the YAML file is applied to the cluster, creating new resources or updating existing ones if changes are detected. Once deployed, EKS pulls the Spring Boot Docker image from Amazon ECR, starts the application containers on available worker nodes, and maintains the configured number of replicas to provide application availability and automatic recovery.

2.9.6 Exposing Spring Boot Application Using AWS LoadBalancer Service

apiVersion: v1
kind: Service
metadata:
  name: springboot-service
spec:
  type: LoadBalancer
  selector:
    app: springboot
  ports:
    - port: 80
      targetPort: 8080

The Kubernetes Service configuration exposes the Spring Boot application outside the Amazon EKS cluster by creating an AWS Load Balancer. The apiVersion: v1 specifies the Kubernetes core API version, while kind: Service defines a networking resource that provides stable access to application pods. The metadata.name field assigns the service name as springboot-service. The type: LoadBalancer configuration instructs Kubernetes to provision an external AWS Elastic Load Balancer that routes incoming traffic to the Spring Boot application. The selector with app: springboot connects the service to the Spring Boot pods created by the deployment. The port: 80 exposes the application externally through standard HTTP traffic, while the targetPort: 8080 forwards requests to the Spring Boot container running on its internal application port. This allows users to access the Spring Boot REST APIs using the AWS Load Balancer endpoint without directly accessing individual Kubernetes pods.

// Apply
kubectl apply -f service.yaml

The kubectl apply -f service.yaml command creates the Kubernetes Service resource defined in the service.yaml file and applies it to the Amazon EKS cluster. Kubernetes reads the service configuration and creates a networking endpoint that connects external traffic to the Spring Boot application pods. Since the service type is configured as LoadBalancer, AWS automatically provisions an Elastic Load Balancer and assigns an external endpoint that can be used to access the application. The service continuously tracks pods matching the configured selector and automatically routes incoming requests to healthy Spring Boot application instances, providing load balancing and high availability.

2.9.7 Verifying Kubernetes Deployment Status

kubectl get pods

kubectl get deployments

kubectl get svc

The kubectl get pods, kubectl get deployments, and kubectl get svc commands are used to verify the status of the application components deployed in the Amazon EKS cluster. The kubectl get pods command displays the running Kubernetes pods and their current state, helping confirm that the Spring Boot and MySQL containers are running successfully. The kubectl get deployments command shows the status of Kubernetes deployments, including the desired number of replicas, available replicas, and deployment readiness. The kubectl get svc command lists the Kubernetes Services and displays networking details such as service type, internal ports, and external load balancer endpoints. Together, these commands help validate that the application deployment, database deployment, and external access configuration are working correctly.

// Deployment

NAME                 READY
springboot-abc       1/1
springboot-def       1/1
mysql                1/1

// Service
NAME                  TYPE           EXTERNAL-IP
springboot-service    LoadBalancer   a1b2c3.amazonaws.com
2.9.7.1 Accessing Spring Boot REST API Through AWS Load Balancer

The application can be accessed by opening the AWS Load Balancer URL generated for the Kubernetes Service in a web browser or API client. The LOAD_BALANCER_URL represents the external endpoint provisioned by AWS when the Spring Boot Service of type LoadBalancer was created. The /employees path maps to the REST endpoint exposed by the EmployeeController class, allowing users to retrieve employee records stored in the MySQL database. When a request is sent to this URL, the AWS Load Balancer forwards the request to the Kubernetes Service, which routes the traffic to one of the available Spring Boot pods running inside the Amazon EKS cluster.

http://LOAD_BALANCER_URL/employees
2.9.7.2 Understanding the End-to-End Deployment Flow

The Spring Boot application is first packaged as an executable JAR file, which contains all application code and dependencies required to run the service. The Dockerfile is then used to create a container image that includes the Java runtime environment and the Spring Boot application. This Docker image is pushed to Amazon Elastic Container Registry (ECR), which acts as a private repository for storing container images. When the Kubernetes deployment is applied, Amazon EKS pulls the image from ECR and creates Spring Boot application pods on the available worker nodes. The MySQL database runs as a separate Kubernetes pod and is accessed through the mysql-service Kubernetes Service, allowing Spring Boot to connect using the Kubernetes DNS name instead of relying on fixed IP addresses. The Kubernetes Service configured with type LoadBalancer automatically provisions an AWS Elastic Load Balancer that distributes external requests to available Spring Boot pods. Kubernetes continuously monitors the application state and automatically recreates failed pods to maintain availability. The deployment can be scaled horizontally by increasing the replica count or enabling Horizontal Pod Autoscaling (HPA), which automatically adjusts the number of running pods based on resource usage such as CPU or memory consumption.

3. Conclusion

Amazon EKS provides a production-ready Kubernetes environment without the operational overhead of managing the Kubernetes control plane. By containerizing a Spring Boot application, storing Docker images in Amazon ECR, and deploying workloads on EKS, developers can leverage automated scaling, self-healing capabilities, rolling updates, integrated load balancing, and seamless integration with AWS services. In this tutorial, we learned how to build a Spring Boot application with MySQL, package it as a Docker image, create an Amazon EKS cluster using the CLI, deploy MySQL and Spring Boot applications using Kubernetes manifests, expose the application using an AWS LoadBalancer, and validate the deployment. This architecture provides a strong foundation for running enterprise-grade Java microservices on AWS and can be further enhanced with services such as Amazon RDS for managed databases, Ingress controllers for advanced routing, Horizontal Pod Autoscaling for dynamic scaling, CloudWatch for monitoring and logging, IAM Roles for Service Accounts (IRSA) for secure AWS access, and CI/CD automation using tools such as GitHub Actions, AWS CodePipeline, or Jenkins.

Yatin Batra

An experience full-stack engineer well versed with Core Java, Spring/Springboot, MVC, Security, AOP, Frontend (Angular & React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Back to top button