DEV Community

parth patel
parth patel

Posted on

How I Built an End-to-End DevOps Environment on AWS EC2 from Scratch

A beginner-friendly walkthrough of provisioning a real Kubernetes cluster, Jenkins CI/CD pipeline, and security tooling on AWS β€” step by step.


🧭 What We're Building

By the end of this guide you'll have a fully working DevOps environment running on AWS EC2 that includes:

  • A custom VPC with security groups
  • A Kubernetes (v1.28) cluster with 1 master + 2 worker nodes
  • A Jenkins CI/CD pipeline that takes code from commit all the way to production
  • SonarQube for automated code quality analysis
  • Kubeaudit for Kubernetes security scanning
  • Nexus Repository Manager for artifact versioning
  • Docker for containerizing and pushing images

This is the exact setup I built for a real project β€” so everything here is battle-tested.


πŸ› οΈ Prerequisites

Before we start, make sure you have:

  • An AWS account (free tier works for learning)
  • Basic familiarity with the Linux command line
  • SSH client installed (Terminal on Mac/Linux, PuTTY or WSL on Windows)

That's it. You don't need to be a DevOps expert β€” that's what this guide is for.


Step 1 β€” Create Your VPC and Security Groups

The first thing we need is a Virtual Private Cloud (VPC) β€” think of it as your own private network inside AWS.

Create the VPC

  1. Go to AWS Console β†’ VPC β†’ Create VPC
  2. Set the IPv4 CIDR block to 10.0.0.0/16
  3. Give it a name like devops-vpc
  4. Click Create

Create a Subnet

  1. Go to Subnets β†’ Create Subnet
  2. Select your new VPC
  3. Set CIDR to 10.0.1.0/24
  4. Choose an availability zone (e.g. us-east-1a)

Set Up Security Groups

This is important β€” we need to open specific ports for our tools to communicate.

  1. Go to Security Groups β†’ Create Security Group
  2. Add these Inbound Rules:
Port Protocol Purpose
22 TCP SSH access
6443 TCP Kubernetes API server
8080 TCP Jenkins web UI
8081 TCP Nexus Repository Manager
9000 TCP SonarQube
30000-32767 TCP Kubernetes NodePort services

πŸ’‘ Tip: For learning purposes you can set the source to 0.0.0.0/0. For production, always restrict to your IP.


Step 2 β€” Launch Your EC2 Instances

We need 3 EC2 instances β€” one master node and two worker nodes for Kubernetes.

Launch Each Instance

  1. Go to EC2 β†’ Launch Instance
  2. Choose Ubuntu 22.04 LTS as the AMI
  3. Select t2.medium (2 vCPU, 4GB RAM) β€” minimum for Kubernetes
  4. Select your VPC and subnet from Step 1
  5. Attach your security group
  6. Create or use an existing key pair (.pem file) for SSH
  7. Launch

Repeat this 3 times β€” name them:

  • k8s-master
  • k8s-worker-1
  • k8s-worker-2

Connect via SSH

chmod 400 your-key.pem
ssh -i your-key.pem ubuntu@<YOUR_EC2_PUBLIC_IP>
Enter fullscreen mode Exit fullscreen mode

Step 3 β€” Set Up Kubernetes with Kubeadm

Run these commands on all 3 nodes first.

Install Dependencies (all nodes)

# Update packages
sudo apt-get update && sudo apt-get upgrade -y

# Install Docker
sudo apt-get install -y docker.io
sudo systemctl enable docker
sudo systemctl start docker

# Install Kubernetes tools
sudo apt-get install -y apt-transport-https ca-certificates curl
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

# Disable swap (required by Kubernetes)
sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
Enter fullscreen mode Exit fullscreen mode

Initialize the Master Node

Run this only on the master node:

sudo kubeadm init --pod-network-cidr=10.244.0.0/16

# Set up kubectl for your user
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

# Install Flannel network plugin
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
Enter fullscreen mode Exit fullscreen mode

After kubeadm init completes, you'll see a kubeadm join command. Copy it β€” you'll need it for the worker nodes.

Join the Worker Nodes

Run the join command on each worker node:

sudo kubeadm join <MASTER_IP>:6443 --token <TOKEN> --discovery-token-ca-cert-hash sha256:<HASH>
Enter fullscreen mode Exit fullscreen mode

Verify Your Cluster

Back on the master node:

kubectl get nodes
Enter fullscreen mode Exit fullscreen mode

You should see all 3 nodes with status Ready. πŸŽ‰


Step 4 β€” Install Jenkins

Run this on your master node (or a dedicated EC2 instance):

# Install Java (required by Jenkins)
sudo apt-get install -y openjdk-21-jdk

# Add Jenkins repo
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
sudo apt-get install -y jenkins
sudo systemctl enable jenkins
sudo systemctl start jenkins
Enter fullscreen mode Exit fullscreen mode

Open Jenkins in your browser at http://<YOUR_EC2_IP>:8080

Get the initial admin password:

sudo cat /var/lib/jenkins/secrets/initialAdminPassword
Enter fullscreen mode Exit fullscreen mode

Install Required Jenkins Plugins

Go to Manage Jenkins β†’ Plugins and install:

  • Docker Pipeline
  • Kubernetes CLI
  • Maven Integration
  • SonarQube Scanner

Step 5 β€” Set Up SonarQube

# Run SonarQube via Docker (easiest way)
docker run -d --name sonarqube \
  -p 9000:9000 \
  sonarqube:community
Enter fullscreen mode Exit fullscreen mode

Open http://<YOUR_EC2_IP>:9000 β€” default login is admin / admin.

Connect SonarQube to Jenkins

  1. In SonarQube go to Administration β†’ Security β†’ Generate Token
  2. Copy the token
  3. In Jenkins go to Manage Jenkins β†’ Credentials β†’ Add
  4. Add the token as a Secret Text credential named sonar-token

Step 6 β€” Set Up Nexus Repository Manager

docker run -d --name nexus \
  -p 8081:8081 \
  sonatype/nexus3
Enter fullscreen mode Exit fullscreen mode

Open http://<YOUR_EC2_IP>:8081

Get the admin password:

docker exec nexus cat /nexus-data/admin.password
Enter fullscreen mode Exit fullscreen mode

Nexus will store your built artifacts (JAR files, Docker images) so every build is versioned and traceable.


Step 7 β€” Create Your Jenkins Pipeline

Create a file called Jenkinsfile in the root of your project repo:

pipeline {
    agent any

    tools {
        jdk 'JDK21'
        maven 'Maven3'
    }

    stages {

        stage('Checkout') {
            steps {
                git branch: 'main', url: 'https://github.com/YOUR_USERNAME/YOUR_REPO.git'
            }
        }

        stage('Build') {
            steps {
                sh 'mvn clean package -DskipTests'
            }
        }

        stage('SonarQube Analysis') {
            steps {
                withSonarQubeEnv('SonarQube') {
                    sh 'mvn sonar:sonar'
                }
            }
        }

        stage('Build Docker Image') {
            steps {
                sh 'docker build -t your-app:${BUILD_NUMBER} .'
                sh 'docker tag your-app:${BUILD_NUMBER} your-registry/your-app:${BUILD_NUMBER}'
            }
        }

        stage('Push to Nexus') {
            steps {
                sh 'mvn deploy'
            }
        }

        stage('Deploy to Kubernetes') {
            steps {
                sh 'kubectl apply -f k8s/deployment.yaml'
                sh 'kubectl set image deployment/your-app your-app=your-registry/your-app:${BUILD_NUMBER}'
            }
        }
    }

    post {
        success {
            echo 'βœ… Pipeline completed successfully!'
        }
        failure {
            echo '❌ Pipeline failed β€” check the logs above.'
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 8 β€” Security Scanning with Kubeaudit

Kubeaudit scans your Kubernetes cluster for common security issues.

# Install Kubeaudit
wget https://github.com/Shopify/kubeaudit/releases/latest/download/kubeaudit_linux_amd64.tar.gz
tar -xzf kubeaudit_linux_amd64.tar.gz
sudo mv kubeaudit /usr/local/bin/

# Run a full audit
kubeaudit all
Enter fullscreen mode Exit fullscreen mode

Common issues it will flag:

  • Missing NetworkPolicies (controls traffic between pods)
  • Missing AppArmor annotations
  • Containers running as root
  • Missing resource limits

Fix them one by one β€” each fix makes your cluster significantly more secure.


πŸŽ‰ What You've Built

Congratulations! You now have a production-grade DevOps environment that:

  • Automatically builds your code on every commit
  • Scans for bugs with SonarQube before deploying
  • Stores versioned artifacts in Nexus
  • Deploys to Kubernetes with zero downtime
  • Audits security with Kubeaudit

This is the kind of infrastructure that runs real production workloads at companies around the world.


πŸ’‘ Key Lessons I Learned

  1. Security groups matter β€” always be intentional about which ports are open
  2. Swap must be disabled before Kubernetes will work β€” I learned this the hard way
  3. Kubeaudit catches things you'd never think of β€” run it early, not after you deploy
  4. Nexus + versioned artifacts means you can always roll back to any previous build

πŸ”— What's Next?

  • Add Terraform to provision all of this infrastructure as code
  • Set up Prometheus + Grafana for monitoring your cluster
  • Configure automatic SSL with cert-manager
  • Add Helm charts for cleaner Kubernetes deployments

Thanks for reading! If this helped you, drop a ❀️ and follow for more DevOps content. Feel free to ask questions in the comments β€” I'm happy to help.


Tags: devops kubernetes aws jenkins docker

Top comments (0)