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)