Deploying Angular and Java Application In EKS Cluster

Deploying Angular and Java Application In EKS Cluster

Table of contents

No heading

No headings in the article.

In this blog, we will walk you through how to create an Amazon Elastic Kubernetes Service (EKS) cluster, bind it with Elastic File System (EFS), and deploy an Angular and Java application using Elastic Container Registry (ECR) for image repository. We will also create an RDS database to store the application data.

Before we get started, make sure you have the following prerequisites in place:

  • An AWS account

  • Terraform installed on your machine

  • Basic knowledge of Kubernetes, Docker, and AWS services.

Step 1: Create an EKS cluster First, we will create an EKS cluster using Terraform. To create an EKS cluster, we need to define a few resources in Terraform, such as VPC, subnets, security group, and EKS cluster itself. Here is the Terraform code to create an EKS cluster:

provider "aws" {
  region = "us-west-2"
}

module "eks" {
  source = "terraform-aws-modules/eks/aws"
  cluster_name = "my-eks-cluster"
  subnets = ["subnet-abc123", "subnet-def456", "subnet-ghi789"]
  tags = {
    Terraform   = "true"
    Environment = "dev"
  }
}

In the above code, we are using the Terraform module "terraform-aws-modules/eks/aws" to create the EKS cluster. We are providing the cluster name, subnets, and tags as input to the module.

Step 2: Bind EFS with EKS cluster Now that we have created an EKS cluster, we will bind it with Elastic File System (EFS) to enable persistent storage for our application. Here is the Terraform code to create an EFS file system and mount it to the EKS cluster:

resource "aws_efs_file_system" "efs" {
  creation_token = "my-efs"
  encrypted      = true
  performance_mode = "generalPurpose"
}

resource "aws_efs_mount_target" "mount_target" {
  count          = length(module.eks.subnets)
  file_system_id = aws_efs_file_system.efs.id
  subnet_id      = module.eks.subnets[count.index]
  security_groups = [module.eks.cluster_security_group_id]
}

In the above code, we are creating an EFS file system and mounting it to the EKS cluster's subnets. We are also specifying the security group associated with the EKS cluster.

Step 3: Create an ECR repository Next, we will create an Elastic Container Registry (ECR) repository to store our application images. Here is the Terraform code to create an ECR repository:

resource "aws_ecr_repository" "my_ecr_repo" {
  name = "my-ecr-repo"
}

In the above code, we are creating an ECR repository with the name "my-ecr-repo".

Step 4: Deploy Angular and Java application to EKS cluster Now that we have an EKS cluster, EFS, and ECR repository, we will deploy our Angular and Java application to the EKS cluster using Kubernetes manifest files. Here is an example of Kubernetes manifest files for the Angular and Java applications:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: angular-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: angular
  template:
    metadata:
      labels:
        app: angular
    spec:
      containers:
        - name: angular
          image: <ecr-repo-uri>:<tag>
          ports:
            - containerPort: 80
          volumeMounts:
            - name: efs
              mountPath: /usr/share/nginx/html
      volumes:
        - name: efs
          persistentVolumeClaim:
            claimName: efs-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: angular-service
spec:
  selector:
    app: angular
  ports:
    - name: http
      port: 80
      targetPort: 80
  type: LoadBalancer

In the above manifest file, we are defining a deployment with two replicas of the Angular application container. We are using the ECR repository URI and tag to specify the container image. We are also mounting the EFS volume to the container at the path "/usr/share/nginx/html". Lastly, we are defining a service of type LoadBalancer to expose the deployment to the internet.

Java Application Manifest:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: java-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: java
  template:
    metadata:
      labels:
        app: java
    spec:
      containers:
        - name: java
          image: <ecr-repo-uri>:<tag>
          ports:
            - containerPort: 8080
          env:
            - name: SPRING_DATASOURCE_URL
              value: jdbc:mysql://<rds-endpoint>:3306/<database-name>
            - name: SPRING_DATASOURCE_USERNAME
              valueFrom:
                secretKeyRef:
                  name: rds-secret
                  key: username
            - name: SPRING_DATASOURCE_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: rds-secret
                  key: password
      imagePullSecrets:
        - name: ecr-creds
---
apiVersion: v1
kind: Service
metadata:
  name: java-service
spec:
  selector:
    app: java
  ports:
    - name: http
      port: 80
      targetPort: 8080
  type: LoadBalancer

Continuing from the previous blog, let's take a look at the Kubernetes manifest files for deploying the Angular and Java applications to the EKS cluster.

Angular Application Manifest:

yamlCopy codeapiVersion: apps/v1
kind: Deployment
metadata:
  name: angular-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: angular
  template:
    metadata:
      labels:
        app: angular
    spec:
      containers:
        - name: angular
          image: <ecr-repo-uri>:<tag>
          ports:
            - containerPort: 80
          volumeMounts:
            - name: efs
              mountPath: /usr/share/nginx/html
      volumes:
        - name: efs
          persistentVolumeClaim:
            claimName: efs-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: angular-service
spec:
  selector:
    app: angular
  ports:
    - name: http
      port: 80
      targetPort: 80
  type: LoadBalancer

In the above manifest file, we are defining a deployment with two replicas of the Angular application container. We are using the ECR repository URI and tag to specify the container image. We are also mounting the EFS volume to the container at the path "/usr/share/nginx/html". Lastly, we are defining a service of type LoadBalancer to expose the deployment to the internet.

Java Application Manifest:

yamlCopy codeapiVersion: apps/v1
kind: Deployment
metadata:
  name: java-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: java
  template:
    metadata:
      labels:
        app: java
    spec:
      containers:
        - name: java
          image: <ecr-repo-uri>:<tag>
          ports:
            - containerPort: 8080
          env:
            - name: SPRING_DATASOURCE_URL
              value: jdbc:mysql://<rds-endpoint>:3306/<database-name>
            - name: SPRING_DATASOURCE_USERNAME
              valueFrom:
                secretKeyRef:
                  name: rds-secret
                  key: username
            - name: SPRING_DATASOURCE_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: rds-secret
                  key: password
      imagePullSecrets:
        - name: ecr-creds
---
apiVersion: v1
kind: Service
metadata:
  name: java-service
spec:
  selector:
    app: java
  ports:
    - name: http
      port: 80
      targetPort: 8080
  type: LoadBalancer

In the above manifest file, we are defining a deployment with two replicas of the Java application container. We are using the ECR repository URI and tag to specify the container image. We are also setting the environment variables for the database connection using the RDS endpoint, database name, and username/password from the RDS secret. Lastly, we are defining a service of type LoadBalancer to expose the deployment to the internet.

Step 5: Create an RDS database Lastly, we will create an RDS database to store the application data. Here is the Terraform code to create an RDS database:

Step 1: Create a new file named rds.tf.

Step 2: Add the following code to the rds.tf file to create an RDS instance.

resource "aws_db_instance" "my_rds_instance" {
  allocated_storage    = 20
  engine               = "mysql"
  engine_version       = "5.7"
  instance_class       = "db.t2.micro"
  name                 = "my-rds-db"
  username             = "admin"
  password             = "mysecretpassword"
  parameter_group_name = "default.mysql5.7"
  skip_final_snapshot  = true

  tags = {
    Name = "My RDS Instance"
  }

  vpc_security_group_ids = [
    aws_security_group.my_rds_sg.id,
  ]

  db_subnet_group_name = aws_db_subnet_group.my_db_subnet_group.name
}

resource "aws_db_subnet_group" "my_db_subnet_group" {
  name       = "my-db-subnet-group"
  subnet_ids = [
    aws_subnet.private_subnet_1.id,
    aws_subnet.private_subnet_2.id,
  ]
}

resource "aws_security_group" "my_rds_sg" {
  name_prefix = "my-rds-sg-"
  description = "Security group for my RDS instance"

  ingress {
    from_port = 3306
    to_port   = 3306
    protocol  = "tcp"

    security_groups = [
      aws_security_group.my_ec2_sg.id,
    ]
  }

  tags = {
    Name = "My RDS Security Group"
  }

  vpc_id = aws_vpc.my_vpc.id
}