This is a test assignment for a DevOps role that demonstrates proficiency with:
- Terraform/OpenTofu - Infrastructure as Code
- Kubernetes - Container orchestration
- Helm - Kubernetes package manager
- AWS - Cloud infrastructure
This project creates a complete AWS EKS (Elastic Kubernetes Service) cluster deployment with:
- Custom VPC with public and private subnets across multiple AZs
- NAT Gateways for private subnet internet access
- EKS Cluster with managed node groups
- Security Groups and IAM Roles properly configured
- Load Balancers for ingress traffic
- httpbin application deployed via custom Helm chart
- Two Nginx Ingress Controllers:
- External ingress for public traffic (
/getendpoint) - Internal ingress for private traffic (
/post,/anythingendpoints)
- External ingress for public traffic (
- Curl pod for testing the application
Internet → NLB (internet-facing) → External Nginx Ingress → httpbin (/get)
Internal Network → NLB (Internal) → Internal Nginx Ingress → httpbin (/post, /anything)
To properly review this assignment, you need the following tools installed:
# macOS
brew install opentofu
# Linux
wget https://github.com/opentofu/opentofu/releases/download/v1.8.0/tofu_1.8.0_linux_amd64.zip
unzip tofu_1.8.0_linux_amd64.zip
sudo mv tofu /usr/local/bin/
# Verify installation
tofu version# macOS
brew install awscli
# Linux
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
# Configure AWS credentials
aws configure# macOS
brew install kubectl
# Linux
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/
# Verify installation
kubectl version --client# macOS
brew install helm
# Linux
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
# Verify installation
helm versiongit clone <repository-url>
cd devops-testEnsure you have AWS credentials configured with permissions for:
- VPC creation and management
- EKS cluster creation
- IAM role and policy management
- EC2 instance management
aws configure
# Enter your AWS Access Key ID, Secret Access Key, and regionExamine the key configuration files:
terraform.tfvars- Main configuration valuesvariables.tf- Variable definitionseks.tf- EKS cluster configurationvpc.tf- VPC and networkinghelmcharts.tf- Application deploymenthttpbin/- Custom Helm chart for the application
# Initialize OpenTofu
tofu init
# Plan the deployment
tofu plan
# Apply the configuration
tofu apply# Get the cluster name from outputs
tofu output cluster_name
# Configure kubectl to access the cluster
aws eks update-kubeconfig --region eu-central-1 --name devops-test# Check cluster status
kubectl get nodes
kubectl get pods --all-namespaces
# Check ingress controllers
kubectl get pods -n ingress-nginx-ext
kubectl get pods -n ingress-nginx-int
# Check httpbin application
kubectl get pods -n httpbin
kubectl get ingress -n httpbinWhen we create two ingress resources for httpbin we create two http endpoints:
- http://httbin.local/ for external ingress
- http://httpbin-int.local/ for internal ingress To test it properly you need to get both external and internal NLBs DNS endpoints. To get them, run following commands:
kubectl get svc ingress-nginx-ext-controller -n ingress-nginx-ext
kubectl get svc ingress-nginx-ext-controller-internal -n ingress-nginx-intIn EXTERNAL-IP field you will get the NLBs DNS endpoints.
Then we need to add those endpoints to CoreDNS configmap:
kubectl edit configmaps -n kube-system corednsand add these two lines of config:
...
data:
Corefile: |
.:53 {
...
rewrite name httpbin.local <EXTERNAL_LB_DNS>
rewrite name httpbin-int.local <INTERNAL_LB_DNS>
...
}
...Then we enter the shell of our curl deployment and test.
First let's make sure that out endpoints returns proper IP adresses when we call them:
nslookup httpbin.local
## Exptected result should look like:
# Server: 172.20.0.10
# Address: 172.20.0.10:53
# Non-authoritative answer:
# Non-authoritative answer:
# Name: httpbin.local
# Address: 3.65.121.188 # Public IP
# Name: httpbin.local
# Address: 3.74.210.208
nslookup httpbin-int.local
## Exptected result should look like:
# Server: 172.20.0.10
# Address: 172.20.0.10:53
# Non-authoritative answer:
# Non-authoritative answer:
# Name: httpbin-int.local
# Address: 10.12.1.204 # Private IP from our subnet
# Name: httpbin-int.local
# Address: 10.12.2.111Now let's test it with curl:
curl http://httpbin.local/get
## Expected result should look like:
# {
# "args": {},
# "headers": {
# "Accept": "*/*",
# "Host": "httpbin.local",
# "User-Agent": "curl/8.15.0",
# "X-Forwarded-Host": "httpbin.local",
# "X-Forwarded-Scheme": "http",
# "X-Scheme": "http"
# },
# "origin": "10.12.1.159",
# "url": "http://httpbin.local/get"
# }
curl http://httpbin.local/post
## Expected result should look like:
# <html>
# <head><title>404 Not Found</title></head>
# <body>
# <center><h1>404 Not Found</h1></center>
# <hr><center>nginx</center>
# </body>
# </html>
## Because /post is not configured to be available via public endpoint
curl -X POST http://httpbin-int.local/post
## Expected result should look like:
# {
# "args": {},
# "data": "",
# "files": {},
# "form": {},
# "headers": {
# "Accept": "*/*",
# "Host": "httpbin-int.local",
# "User-Agent": "curl/8.15.0",
# "X-Forwarded-Host": "httpbin-int.local",
# "X-Forwarded-Scheme": "http",
# "X-Scheme": "http"
# },
# "json": null,
# "origin": "10.12.1.159",
# "url": "http://httpbin-int.local/post"
# }
curl http://httpbin-int.local/anything
## Expected result should look like:
# {
# "args": {},
# "data": "",
# "files": {},
# "form": {},
# "headers": {
# "Accept": "*/*",
# "Host": "httpbin-int.local",
# "User-Agent": "curl/8.15.0",
# "X-Forwarded-Host": "httpbin-int.local",
# "X-Forwarded-Scheme": "http",
# "X-Scheme": "http"
# },
# "json": null,
# "method": "GET",
# "origin": "10.12.1.159",
# "url": "http://httpbin-int.local/anything"
# }After successful deployment, you should see:
- EKS cluster with 2 worker nodes (t3.medium instances)
- VPC with public and private subnets in eu-central-1
- NAT Gateway for private subnet internet access
- Security groups properly configured
- External Nginx Ingress: 2 replicas with external load balancer
- Internal Nginx Ingress: 2 replicas with internal load balancer
- httpbin Application: 1 replica accessible via both ingresses
- Curl Pod: For testing the application
- External traffic → External NLB → External Nginx → httpbin (/get)
- Internal traffic → Internal NLB → Internal Nginx → httpbin (/post, /anything)
- Complete infrastructure defined in Terraform/OpenTofu
- Modular design with separate VPC and EKS modules
- Proper variable management and configuration
- Custom Helm chart development
- Ingress configuration with multiple controllers
- Resource management and scaling configurations
- Service mesh concepts with internal/external traffic separation
- EKS cluster management
- VPC design with public/private subnets
- Load balancer configuration
- Security group and IAM role management
- Infrastructure versioning
- Modular and reusable code
- Proper documentation
- Security best practices (private subnets, IAM roles, etc.)
To destroy all resources and avoid AWS charges:
tofu destroyWarning: This will delete the entire EKS cluster and all associated resources.
This assignment demonstrates:
- ✅ Terraform/OpenTofu proficiency - Complete infrastructure as code
- ✅ Kubernetes expertise - Custom Helm charts and ingress configuration
- ✅ AWS knowledge - EKS, VPC, and networking components
- ✅ DevOps practices - Modular design, security, and documentation
- ✅ Problem-solving - Complex multi-tier application deployment
MIT License - see LICENSE file for details.