← Back to Home
☸️

Project 2: Provision with Terraform & Deploy to Kubernetes

Infrastructure as code creates the cluster; Kubernetes runs your app at scale.

⏱12 min readπŸ“šDevOps Fundamentals

Your image is published β€” but where does it run? In Project 2 you provision infrastructure as code with Terraform (reproducible, version-controlled), then deploy your app to Kubernetes with the resilience features that make it production-worthy: health checks, resource limits, and autoscaling.


🎯 Learning Objectives


Step 1 β€” Provision Infrastructure with Terraform

Rather than clicking around a cloud console, you declare the cluster in code. A minimal example provisioning a managed cluster:

hcl
# main.tf
terraform {
backend "s3" {                 # remote state (see below)
  bucket = "my-tf-state"
  key    = "prod/cluster.tfstate"
  region = "us-east-1"
}
}

module "cluster" {
source          = "terraform-aws-modules/eks/aws"
cluster_name    = "portfolio-cluster"
cluster_version = "1.30"
# ... vpc, node groups, etc.
}

output "cluster_endpoint" {
value = module.cluster.cluster_endpoint
}

The workflow is always the same three commands:

bash
terraform init      # download providers, connect backend
terraform plan      # preview what will change (review this!)
terraform apply     # create the infrastructure

⚠ Always read the plan

terraform plan shows exactly what will be created, changed, or destroyed. Never apply in production without reading it β€” a careless change can destroy and recreate a database. The plan is your safety review.


Step 2 β€” Use Remote State

Notice the backend "s3" block. Terraform tracks reality in a state file. Keeping it on your laptop is a disaster waiting to happen β€” lost laptop, no teamwork, conflicting changes. Remote state (S3, GCS, Terraform Cloud) fixes this:

πŸ’‘ State is sensitive

The state file can contain secrets (passwords, keys) in plaintext. Store it in an encrypted, access-controlled backend β€” never commit it to Git.


Step 3 β€” Deploy to Kubernetes

With the cluster up, deploy your Project 1 image. A production-worthy Deployment includes probes and resource limits β€” not just the bare minimum:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
selector:
  matchLabels: { app: myapp }
template:
  metadata:
    labels: { app: myapp }
  spec:
    containers:
      - name: myapp
        image: ghcr.io/you/myapp:a1b2c3d      # deploy by SHA, not latest
        ports:
          - containerPort: 3000
        livenessProbe:                          # restart if hung
          httpGet: { path: /health, port: 3000 }
          initialDelaySeconds: 5
        readinessProbe:                         # don't send traffic until ready
          httpGet: { path: /health, port: 3000 }
        resources:
          requests: { cpu: "100m", memory: "128Mi" }
          limits:   { cpu: "500m", memory: "256Mi" }

Expose it with a Service so traffic can reach the pods:

yaml
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
type: LoadBalancer
selector: { app: myapp }
ports:
  - port: 80
    targetPort: 3000
bash β€” 80Γ—24
student@devops:~$kubectl apply -f k8s/ && kubectl get pods

Step 4 β€” Autoscale

Let Kubernetes add and remove pods based on load with a HorizontalPodAutoscaler:

yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: myapp
spec:
scaleTargetRef:
  apiVersion: apps/v1
  kind: Deployment
  name: myapp
minReplicas: 3
maxReplicas: 10
metrics:
  - type: Resource
    resource:
      name: cpu
      target: { type: Utilization, averageUtilization: 70 }

Now the app scales out past 3 pods when CPU crosses 70%, and back in when load drops β€” capacity that follows demand, defined declaratively.


πŸ§ͺ Hands-on Lab

πŸ“

Explain the Probes

Your app occasionally hangs (still β€œrunning” but not responding), and during startup it briefly returns errors before it’s ready. Which probe addresses each problem, and what would happen without them?


🧠 Knowledge Check

Knowledge Check

Why should Terraform state be stored in a remote backend rather than locally?

Knowledge Check

What is the difference between a liveness and a readiness probe?


πŸ’Ό Interview Preparation

Interview Q&A

Walk through how you'd deploy a containerised app to production on Kubernetes.


Summary

Project 2 is complete: Terraform provisions your cluster reproducibly with remote state, and your app runs on Kubernetes with probes, resource limits, a Service, and autoscaling. The final project adds the operational layer β€” observability and GitOps β€” to make the whole system truly production-grade.

Up Next

Project 3: Add Monitoring, Tracing & GitOps

You've mastered this lesson. Continue your journey to becoming a DevOps Engineer.

Start Next Lesson→