Skip to main content

Command Palette

Search for a command to run...

Deploy EKS cluster with jenkins

"Streamlining Java Application Deployment on Jenkins and Amazon EKS with Terraform"

Updated
15 min read
Deploy EKS cluster with jenkins
S

🚀 I build intelligent systems that learn, adapt, and scale — from LLMs to MLOps pipelines. 🌈 Currently writing about Generative AI, agentic workflows, and cloud-powered ML magic. 🔭 Passionate about connecting the dots between data and the universe — one model and one constellation at a time! 📍 Based on Earth, deploying to the cloud ☁️ 👇 Dive into my tech experiments and stardust-fueled ideas below!

in this article, we are going to create a DevOps project where we’ll use Terraform, Jenkins, GitHub, and EKS.a complete end-to-end CICD pipeline using Jenkins shared lib concept to make our code reusable.

Pre-requisites

AWS account

GitHub account & Git

Configure EC2 instance

First to install jenkins server we need ec2 instance , lets Navigate to the EC2 service and click on "Launch Instance".

Amazon Machine Image (AMI) choose ubuntu

Instance type : t2.medium

in the advanced details section : we will write the following code to install Jenkins and its dependecies , by default Jenkins is on port 8080

#!/bin/bash

sudo apt update -y

sudo apt upgrade -y 

sudo apt install openjdk-17-jre -y

curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | sudo tee \
  /usr/share/keyrings/jenkins-keyring.asc > /dev/null
echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \
  https://pkg.jenkins.io/debian-stable binary/ | sudo tee \
  /etc/apt/sources.list.d/jenkins.list > /dev/null
sudo apt-get update -y 
sudo apt-get install jenkins -y

now we are ready to launch and connect to the instance

install docker for later use, following this code

#!/bin/bash/
sudo apt update -y

sudo apt install apt-transport-https ca-certificates curl software-properties-common -y

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable" -y

sudo apt update -y

apt-cache policy docker-ce -y

sudo apt install docker-ce -y

#sudo systemctl status docker

sudo chmod 777 /var/run/docker.sock

Now , on the navigator type : <INSTANCE_PUBLIC_IP>:8080 and jenkins home page will pops out.

username is admin

to get the password , run this command on your ec2 terminal

sudo cat /var/lib/jenkins/secrets/initialAdminPassword

Setting up repositories

for this project we will be using 2 repos: for Java application and Jenkins Shared Library, but first what's jenkins shared Library?

Jenkins shared Library allows you to define reusable and shareable code across multiple Jenkins pipelines. Shared Libraries promote code reuse and standardization. The typical structure includes:

  • vars/: This directory contains Groovy scripts defining global variables or functions that can be directly invoked within pipeline scripts.

  • src/: This directory holds additional source code, classes, or resources that can be utilized by the library functions.

  • resources/: Optional directory for storing additional resource files, such as configuration files or templates.

By using Jenkins Shared Libraries, you can centralize and standardize your pipeline codebase, encourage best practices, and improve the maintainability and scalability of your Jenkins pipelines.

first Create a new repository on GitHub for the Java application

this is the repo we will be pulling from

On your local terminal: create a folder for your project cd to that directory and run this to get Java application code

git clone https://github.com/sirine707/java_Application.git
git remote set-url origin <new-remote-url>
#URL of your new remote repository.
git push origin <branch-name>

if you got any issues: "Fatal error like my pc says" , you can move to another branch

#create new branch
git branch <branch-name>
#switch to the newly created branch.
git checkout <branch-name>
git push origin <branch-name>

Now let's create an empty repo on GitHub and name it Jenkins_Shared_Lib

Configure jenkins

first on dashboard go to => manage jenkins =>plugins=>Available plugins

and download for now Repository Connector- maven- pipeline plugins- GitHub-credentials

now go to +new item or job to start working on the project

after creating the project click on it and got to configure to connect Jenkins to your Java Application repo you add a webhook to trigger builds automatically

Let's start coding ...

  • we will first Create a Jenkinsfile in our application repository

    should when it comes to configuring Jenkins jobs and defining pipelines, you have flexibility in choosing the programming language (Groovy, Shell scripting, Python, Ruby ..), we will be using Groovy.

  • go to your Jenkins shared Library directory , inside vars directory

    All the files will be inside this directory,now create a file gitCheckout.groovy : this stage is used to fetch the latest changes from git Repo and keep the pipeline updated

def call(Map stageParams){
    checkout(
        [$class: 'GitSCM',
        branches: [[name: stageParams.branch]],
        userRemoteConfigs: [[url:stageParams.url]]

        ]
    )
}

commit and push to your GitHub Repo

on the other hand, inside the Jenkinsfile we created locally in java_Application repo , we will define the stage and make it visible to jenkins:

@Library('Jenkins_Shared_Lib') _
pipeline{

    agent any
stages{


        stage('Git Checkout'){

            steps{
            gitCheckout(
                branch: "devops", 
                url: "https://github.com/sirine707/Devops_Project01.git"
            )
            }
        }
@Library('Jenkins_Shared_Lib') _

Go to Manage Jenkins =>System

scroll down to Global Pipeline Libraries, Default version is the name of your branch

for Repository HTTPS URL put your Jenkins Shared Library repo URL

this is how Jenkins knows about Jenkins Shared Library.

don't forget to replace with your branch name and repo url , commit and push changes to your GitHub repo .

now we go to jenkins dashboard: select our project and click build

in your case you wont find build with parameters for now

but you got errors , because Jenkins doesn't know yet the path of your Jenkinsfile

inside your Java application repo

in Pipeline section => Script Path,type Jenkinsfile name of your Jenkins file

and now save and rebuild again. Congrats you did well.

Now you know how we play the game and you will do it alone this time

let's go back to Jenkins Shared Lib repo and inside vars directory,create a new file :mvnTest.groovy For maven unit testing don't forget to commit and push your changes.

def call(){
    sh 'mvn test'
}

on the other hand, we will add a new stage in Jenkinsfile

@Library('Jenkins_Shared_Lib') _
pipeline{

    agent any
parameters{

        choice(name: 'action', choices: 'create\ndelete', description: 'Choose create/Destroy')
}
stages{
        stage('Git Checkout'){
         when { expression {  params.action == 'create' } }
            steps{
            gitCheckout(
                branch: "devops", 
                url: "https://github.com/sirine707/Devops_Project01.git"
            )
            }
        }
stage('Unit Test maven'){
 when { expression {  params.action == 'create' } }
            steps{
                script{

                     mvnTest()
                }
             }
         }
}
}

inside scripts block give the file name of your Jenkins shared library: mvnTest()

commit and push

Go to Jenkins, refresh and now you have build with parameters. because we added them.

for maven integration testing, Create a file: mvnIntegrationTest.groovy inside vars now you know which repo i'am talking about (Jenkins Shared Library) you guess it right

def call(){
    sh 'mvn verify -DskipUnitTests'
}

the line sh 'mvn verify -DskipUnitTests' executes the Maven build command mvn verify while skipping the execution of unit tests

inside Jenkinsfile we will add the ''Integration Test maven" stage just like we did with unit testing

stage('Integration Test maven'){
 when { expression {  params.action == 'create' } }
            steps{
              script{ 
                   mvnIntegrationTest()
                }
            }
        }

commit and push.

git add .
git commit -m "write your commit message"
git push origin <name_branch>

now time to build the code : insidevars directory create a file : mvnBuild.groovy

def call(){
    sh 'mvn clean install'
}

in Jenkinsfile add "Maven Build : maven" stage

stage('Maven Build : maven'){
         when { expression {  params.action == 'create' } }
             steps{
                script{

                   mvnBuild()
                }
             }
         }

if you faced maven error after build on Jenkins console output , try to downgrade your Java to openjdk11

Now let's move to create our docker image, for that go to your local java Application repo and create Dockerfile

FROM openjdk:8-jdk-alpine
WORKDIR /app
COPY ./target/*.jar/ app.jar
CMD ["java","-jar","app.jar"]
  1. WORKDIR /app:

    • This line sets the working directory within the Docker image to /app.

    • Any subsequent commands or operations will be performed in this directory.

  2. COPY ./target/*.jar/ app.jar:

    • This line copies the JAR file(s) from the local filesystem into the Docker image.

    • It assumes that the JAR file(s) are located in the ./target directory relative to the location of the Dockerfile.

    • The *.jar pattern indicates that all JAR files in the ./target directory should be copied.

    • The copied JAR file(s) are placed in the /app directory within the Docker image and named app.jar.

  3. CMD ["java","-jar","app.jar"]:

    • This line specifies the command to be executed when a container is created from the Docker image.

    • The command java -jar app.jar runs the Java application contained in the app.jar file.

    • This command is executed by default when the container starts, unless overridden by providing a different command at runtime.

to build the docker image go inside vars directory ( you guess it right) and create a file:dockerBuild.groovy this image will be pushed to ECR :Elastic container Registry

def call(String aws_account_id,String region,String ecr_repoName){
    sh """
     docker build -t ${ecr_repoName} .
     docker tag ${params.ECR_REPO_NAME}:latest ${params.aws_account_id}.dkr.ecr.${params.Region}.amazonaws.com/${params.ECR_REPO_NAME}:latest
    """
}

for that, you need to create an ECR repo for which you attach IAM role to make accessible from our ec2 instance and allow us to push the docker image

we will need aws_account_id, region and the name of ECR repository as parameters inside Jenkinsfile

@Library('Jenkins_Shared_Lib') _
pipeline{

    agent any

    parameters{

        choice(name: 'action', choices: 'create\ndelete', description: 'Choose create/Destroy')
        string(name: 'aws_account_id', description: " AWS Account ID", defaultValue: 'aws_account_id')
        string(name: 'Region', description: "Region of ECR", defaultValue: 'region')
        string(name: 'ECR_REPO_NAME', description: "name of the ECR", defaultValue: 'ecr-repo-name')
}

stages{
//add_the_other_stages
stage('Docker Image Build : ECR'){
            when { expression {  params.action == 'create' } }
                steps{
                    script{

                    dockerBuild("${params.aws_account_id}","${params.Region}","${params.ECR_REPO_NAME}")
                }
                }
        }
}

commit and push. Go to Jenkins and build.

now we can add a stage to scan the docker image via trivy to detect security vulnerabilities and we will skip that.

to push the image to ecr , inside vars directory for Jenkins Shared Library repo and create a file :dockerpush.groovy

def call(String aws_account_id,String region,String ecr_repoName){

    sh """aws ecr get-login-password --region ${params.Region} | docker login --username AWS --password-stdin ${params.aws_account_id}.dkr.ecr.${params.Region}.amazonaws.com"""
    sh 'docker push ${aws_account_id}.dkr.ecr.${region}.amazonaws.com/${ecr_repoName}:latest '

}

on Jenkinsfile add "Docker Image Push : ECR" stage

stage('Docker Image Push : ECR '){
                when { expression {  params.action == 'create' } }
             steps{
                script{
            dockerpush("${params.aws_account_id}","${params.Region}","${params.ECR_REPO_NAME}")
         }
                }
            }

now we clean up and remove the docker image from our local machine

inside the vars directory , create a file: dockerImageCleanUp.groovy

def call(String aws_account_id,String region,String repoName){

    sh "docker rmi -f ${repoName}:latest "

}

go to Jenkinsfile and add "Docker Image Cleanup : ECR" stage

stage('Docker Image Cleanup : ECR '){
          when { expression {  params.action == 'create' } }
             steps{
               script{
                   dockerImageCleanUp("${params.aws_account_id}","${params.Region}","${params.ECR_REPO_NAME}")
                }
            }
         }

commit and push , run builds on jenkins.

you can check that by running on ec2 terminal

docker image ls

Now , let's Configure our AWS credentials on Jenkins because we will need it later

in secret: type your ACCESS_KEYyou find in credentials folder inside .aws folder

do the same for SECRET_ACCESS_KEY

Go to Jenkinsfile and add under agent any

environment {
        ACCESS_KEY = credentials('ACCESS_KEY')
        SECRET_ACCESS_KEY = credentials('SECRET_ACCESS_KEY')
}

Great, it is time to build EKS cluster , we will be using Terraform provision infrastructure resources

for this matter, create a folder inside your java application local repo and call it Terraform, we can use modules and make our code reusable

if you don't know how this blog will help you

we need to create an AWS provider. It allows to interact with the many resources supported by AWS, such as VPC, EC2, EKS

inside terraform folder, create a file: 0-provider.tf

provider "aws" {
  region = var.region
  access_key = var.access_key
  secret_key = var.secret_key
}

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.0"
    }
  }
}
variable "access_key" {
    default = ""
}
variable "secret_key" {
    default = ""
}


variable "region" {
    default = "us-east-1"
}

The next step is to create a vpc ,10.0.0.0/16 will give you approximately 65 thousand IP addresses. for that create a file : 2-vpc.tf

resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"

  tags = {
    Name = "main"
  }
}

To provide internet access for your services, we need to have an internet gateway in our VPC .create a file: 2-igw.tf

resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "igw"
  }
}

Now, we need to create four subnets. To meet EKS requirements, we need to have two public and two private subnets in different availability zones. File name is terraform/3-subnets.tf

resource "aws_subnet" "private-us-east-1a" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.0.0/19"
  availability_zone = "us-east-1a"

  tags = {
    "Name"                            = "private-us-east-1a"
    "kubernetes.io/role/internal-elb" = "1"
    "kubernetes.io/cluster/demo"      = "owned"
  }
}

resource "aws_subnet" "private-us-east-1b" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.32.0/19"
  availability_zone = "us-east-1b"

  tags = {
    "Name"                            = "private-us-east-1b"
    "kubernetes.io/role/internal-elb" = "1"
    "kubernetes.io/cluster/demo"      = "owned"
  }
}

resource "aws_subnet" "public-us-east-1a" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.64.0/19"
  availability_zone       = "us-east-1a"
  map_public_ip_on_launch = true

  tags = {
    "Name"                       = "public-us-east-1a"
    "kubernetes.io/role/elb"     = "1"
    "kubernetes.io/cluster/demo" = "owned"
  }
}

resource "aws_subnet" "public-us-east-1b" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.96.0/19"
  availability_zone       = "us-east-1b"
  map_public_ip_on_launch = true

  tags = {
    "Name"                       = "public-us-east-1b"
    "kubernetes.io/role/elb"     = "1"
    "kubernetes.io/cluster/demo" = "owned"
  }
}

It's time to create a NAT gateway. It is used in private subnets to allow services to connect to the internet. For NAT, we need to allocate public IP address first. Then we can use it in the aws_nat_gateway resource. The important part here, you need to place it in the public subnet, Give it a name terraform/4-nat.tf

resource "aws_eip" "nat" {
  vpc = true

  tags = {
    Name = "nat"
  }
}

resource "aws_nat_gateway" "nat" {
  allocation_id = aws_eip.nat.id
  subnet_id     = aws_subnet.public-us-east-1a.id

  tags = {
    Name = "nat"
  }

  depends_on = [aws_internet_gateway.igw]
}

It's time to create routing tables and associate subnets with them. File name is terraform/5-routes.tf

resource "aws_route_table" "private" {
  vpc_id = aws_vpc.main.id

  route = [
    {
      cidr_block                 = "0.0.0.0/0"
      nat_gateway_id             = aws_nat_gateway.nat.id
      carrier_gateway_id         = ""
      destination_prefix_list_id = ""
      egress_only_gateway_id     = ""
      gateway_id                 = ""
      instance_id                = ""
      ipv6_cidr_block            = ""
      local_gateway_id           = ""
      network_interface_id       = ""
      transit_gateway_id         = ""
      vpc_endpoint_id            = ""
      vpc_peering_connection_id  = ""
    },
  ]

  tags = {
    Name = "private"
  }
}

resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id

  route = [
    {
      cidr_block                 = "0.0.0.0/0"
      gateway_id                 = aws_internet_gateway.igw.id
      nat_gateway_id             = ""
      carrier_gateway_id         = ""
      destination_prefix_list_id = ""
      egress_only_gateway_id     = ""
      instance_id                = ""
      ipv6_cidr_block            = ""
      local_gateway_id           = ""
      network_interface_id       = ""
      transit_gateway_id         = ""
      vpc_endpoint_id            = ""
      vpc_peering_connection_id  = ""
    },
  ]

  tags = {
    Name = "public"
  }
}

resource "aws_route_table_association" "private-us-east-1a" {
  subnet_id      = aws_subnet.private-us-east-1a.id
  route_table_id = aws_route_table.private.id
}

resource "aws_route_table_association" "private-us-east-1b" {
  subnet_id      = aws_subnet.private-us-east-1b.id
  route_table_id = aws_route_table.private.id
}

resource "aws_route_table_association" "public-us-east-1a" {
  subnet_id      = aws_subnet.public-us-east-1a.id
  route_table_id = aws_route_table.public.id
}

resource "aws_route_table_association" "public-us-east-1b" {
  subnet_id      = aws_subnet.public-us-east-1b.id
  route_table_id = aws_route_table.public.id
}

Finally, we got to the EKS cluster. Kubernetes clusters managed by Amazon EKS make calls to other AWS services on your behalf to manage the resources that you use with the service. For example, EKS will create an autoscaling group for each instance group if you use managed nodes. Before you can create Amazon EKS clusters, you must create an IAM role with the AmazonEKSClusterPolicy. Let's name it terraform/6-eks.tf

resource "aws_iam_role" "demo" {
  name = "eks-cluster-demo"

  assume_role_policy = <<POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "eks.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
POLICY
}

resource "aws_iam_role_policy_attachment" "demo-AmazonEKSClusterPolicy" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
  role       = aws_iam_role.demo.name
}

resource "aws_eks_cluster" "demo" {
  name     = "demo"
  role_arn = aws_iam_role.demo.arn

  vpc_config {
    subnet_ids = [
      aws_subnet.private-us-east-1a.id,
      aws_subnet.private-us-east-1b.id,
      aws_subnet.public-us-east-1a.id,
      aws_subnet.public-us-east-1b.id
    ]
  }

  depends_on = [aws_iam_role_policy_attachment.demo-AmazonEKSClusterPolicy]
}
  • Next, we are going to create a single instance group for Kubernetes. Similar to the EKS cluster, it requires an IAM role as well. Let's name it terraform/7-nodes.tf

  •   resource "aws_iam_role" "nodes" {
        name = "eks-node-group-nodes"
    
        assume_role_policy = jsonencode({
          Statement = [{
            Action = "sts:AssumeRole"
            Effect = "Allow"
            Principal = {
              Service = "ec2.amazonaws.com"
            }
          }]
          Version = "2012-10-17"
        })
      }
    
      resource "aws_iam_role_policy_attachment" "nodes-AmazonEKSWorkerNodePolicy" {
        policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy"
        role       = aws_iam_role.nodes.name
      }
    
      resource "aws_iam_role_policy_attachment" "nodes-AmazonEKS_CNI_Policy" {
        policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"
        role       = aws_iam_role.nodes.name
      }
    
      resource "aws_iam_role_policy_attachment" "nodes-AmazonEC2ContainerRegistryReadOnly" {
        policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
        role       = aws_iam_role.nodes.name
      }
    
      resource "aws_eks_node_group" "private-nodes" {
        cluster_name    = aws_eks_cluster.demo.name
        node_group_name = "private-nodes"
        node_role_arn   = aws_iam_role.nodes.arn
    
        subnet_ids = [
          aws_subnet.private-us-east-1a.id,
          aws_subnet.private-us-east-1b.id
        ]
    
        capacity_type  = "ON_DEMAND"
        instance_types = ["t3.small"]
    
        scaling_config {
          desired_size = 1
          max_size     = 5
          min_size     = 0
        }
    
        update_config {
          max_unavailable = 1
        }
    
        labels = {
          role = "general"
        }
    

    To manage permissions for applications that you deploy in Kubernetes. You can either attach policies to Kubernetes nodes directly. In that case, every pod will get the same access to AWS resources. Or you can create OpenID connect provider, which will allow granting IAM permissions based on the service account used by the pod. File name is terraform/8-iam-oidc.tf

  •   data "tls_certificate" "eks" {
        url = aws_eks_cluster.demo.identity[0].oidc[0].issuer
      }
    
      resource "aws_iam_openid_connect_provider" "eks" {
        client_id_list  = ["sts.amazonaws.com"]
        thumbprint_list = [data.tls_certificate.eks.certificates[0].sha1_fingerprint]
        url             = aws_eks_cluster.demo.identity[0].oidc[0].issuer
      }
    

    Next, let's deploy the sample application and expose it using public and private load balancers. The first is a deployment object

  • File name is k8s/deployment.yaml.

  •   apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: myjavaapp-deployment
      spec:
        replicas: 3
        selector:
          matchLabels:
            app: myjavaapp
        template:
          metadata:
            labels:
              app: myjavaapp
          spec:
            containers:
            - name: myjavaapp
              image: <AWS_account_id>.dkr.ecr.<Region>.amazonaws.com/<ecr_repoName>:latest
              ports:
              - containerPort: 8080
              affinity:
               nodeAffinity:
                requiredDuringSchedulingIgnoredDuringExecution:
                  nodeSelectorTerms:
                  - matchExpressions:
                    - key: role
                      operator: In
                      values:
                      - general
    

    To expose the application to the internet, you can create a Kubernetes service of a type load balancer and use annotations to configure load balancer properties. By default, Kubernetes will create a load balancer in public subnets, so you don't need to provide any additional configurations. Also, if you want a new network load balancer instead of the old classic load balancer, you can add aws-load-balancer-type equal to nlb. Call it k8s/public-lb.yaml

  •   apiVersion: v1
      kind: Service
      metadata:
        name: public-lb
        annotations:
          service.beta.kubernetes.io/aws-load-balancer-type: nlb
      spec:
        type: LoadBalancer
        selector:
          app: myjavaapp
        ports:
        - name: http
          port: 80
          targetPort: 8080
    

    Now let's deploy EKS cluster autoscaler, Finally, we got to the EKS autoscaller. We will be using OpenID connect provider to create an IAM role and bind it with the autoscaller. Let's create an IAM policy and role first. It's similar to the previous one, but autoscaller will be deployed in the kube-system namespace. File name is terraform/10-iam-autoscaler.tf.

  •   data "aws_iam_policy_document" "eks_cluster_autoscaler_assume_role_policy" {
        statement {
          actions = ["sts:AssumeRoleWithWebIdentity"]
          effect  = "Allow"
    
          condition {
            test     = "StringEquals"
            variable = "${replace(aws_iam_openid_connect_provider.eks.url, "https://", "")}:sub"
            values   = ["system:serviceaccount:kube-system:cluster-autoscaler"]
          }
    
          principals {
            identifiers = [aws_iam_openid_connect_provider.eks.arn]
            type        = "Federated"
          }
        }
      }
    
      resource "aws_iam_role" "eks_cluster_autoscaler" {
        assume_role_policy = data.aws_iam_policy_document.eks_cluster_autoscaler_assume_role_policy.json
        name               = "eks-cluster-autoscaler"
      }
    
      resource "aws_iam_policy" "eks_cluster_autoscaler" {
        name = "eks-cluster-autoscaler"
    
        policy = jsonencode({
          Statement = [{
            Action = [
                      "autoscaling:DescribeAutoScalingGroups",
                      "autoscaling:DescribeAutoScalingInstances",
                      "autoscaling:DescribeLaunchConfigurations",
                      "autoscaling:DescribeTags",
                      "autoscaling:SetDesiredCapacity",
                      "autoscaling:TerminateInstanceInAutoScalingGroup",
                      "ec2:DescribeLaunchTemplateVersions"
                  ]
            Effect   = "Allow"
            Resource = "*"
          }]
          Version = "2012-10-17"
        })
      }
    
      resource "aws_iam_role_policy_attachment" "eks_cluster_autoscaler_attach" {
        role       = aws_iam_role.eks_cluster_autoscaler.name
        policy_arn = aws_iam_policy.eks_cluster_autoscaler.arn
      }
    
      output "eks_cluster_autoscaler_arn" {
        value = aws_iam_role.eks_cluster_autoscaler.arn
      }
    

    Commit and Push my friend

  • Go to Jenkinsfile and add "Create EKS Cluster : Terraform" stage

    and "Deployment on EKS Cluster" stage

  • ```bash

    stage('Create EKS Cluster : Terraform'){ when { expression { params.action == 'create' } } steps{ script{ withEnv(['TF_LOG=DEBUG']) { dir('terraform'){ sh "terraform init " sh "terraform plan -var 'access_key=$ACCESS_KEY' -var 'secret_key=$SECRET_KEY' -var 'region=${params.Region}' " sh "terraform apply -var 'access_key=$ACCESS_KEY' -var 'secret_key=$SECRET_KEY' -var 'region=${params.Region}' --auto-approve " } } }

    } } stage('Deployment on EKS Cluster'){ when { expression { params.action == 'create' } } steps{ script{ dir('k8s'){ sh"aws eks --region ${params.Region} update-kubeconfig --name ${params.cluster}" sh"kubectl apply -f k8s/deployment.yaml" sh"kubectl apply -f k8s/public-lb.yaml" sh"kubectl apply -f k8s/cluster-autoscaler.yaml" }

} } } }


    on your ec2 terminal you can verify that the autoscaler pod is up and running with the following command.

* ```bash
    kubectl get pods -n kube-system

It's a good practice to check logs for any errors.

    kubectl logs -l app=cluster-autoscaler -n kube-system -f

and we are DONE ? No

  • the next blog will cover the rest of the project.

    in case you need a help, you can reach out to me on LinkedIn

    With that in mind: What other new projects would you like to see? Let us know in the comments below! 👇