A DevOps engineer bridges the gap between development and operations — automating builds, shipping code continuously, managing infrastructure as code, and keeping systems observable and reliable. This roadmap shows you exactly what to learn, in what order, and realistic timelines to go from beginner to job-ready.
At a glance
| Phase |
Topics |
Time estimate |
| 1 |
Linux fundamentals and shell scripting |
4–6 weeks |
| 2 |
Networking and security basics |
2–3 weeks |
| 3 |
Version control with Git |
1–2 weeks |
| 4 |
Programming / scripting (Python or Go) |
6–8 weeks |
| 5 |
Containers with Docker |
3–4 weeks |
| 6 |
Container orchestration with Kubernetes |
6–8 weeks |
| 7 |
CI/CD pipelines |
3–4 weeks |
| 8 |
Infrastructure as Code (Terraform + Ansible) |
4–6 weeks |
| 9 |
Cloud platforms (AWS, Azure, or GCP) |
6–8 weeks |
| 10 |
Monitoring, logging, and observability |
3–4 weeks |
| 11 |
Security and compliance (DevSecOps) |
2–3 weeks |
| 12 |
Portfolio projects + certifications |
4–8 weeks |
| Total to first job |
|
~12–18 months |
Phase 1 — Linux fundamentals (Weeks 1–6)
Linux runs the vast majority of production servers. You must be comfortable on the command line before anything else.
Core Linux skills
| Skill |
Why it matters |
File system navigation (ls, cd, find, tree) |
Navigate and locate files on servers |
File manipulation (cp, mv, rm, chmod, chown) |
Manage configs and permissions |
Text processing (grep, awk, sed, cut, sort) |
Parse logs and config files |
Process management (ps, top, htop, kill, systemctl) |
Monitor and control running services |
Package management (apt, yum, dnf, snap) |
Install and update software |
Networking tools (curl, wget, netstat, ss, ping, traceroute) |
Debug connectivity |
Disk and memory (df, du, free, lsblk, iostat) |
Monitor resource usage |
User management (useradd, usermod, sudo, /etc/passwd) |
Secure multi-user systems |
File permissions (chmod 755, chown, ACL, umask) |
Enforce least privilege |
Cron jobs (crontab -e, systemd timers) |
Automate scheduled tasks |
Bash scripting essentials
#!/usr/bin/env bash
set -euo pipefail # fail fast, treat unset vars as errors
DEPLOY_DIR="/var/www/app"
LOG_FILE="/var/log/deploy.log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}
deploy() {
log "Starting deployment..."
cd "$DEPLOY_DIR"
git pull origin main
npm ci --production
systemctl reload nginx
log "Deployment complete."
}
deploy
| Bash concept |
Example |
| Variables |
NAME="prod" |
| Conditionals |
if [[ -f "$FILE" ]]; then … fi |
| Loops |
for server in "${SERVERS[@]}"; do … done |
| Functions |
deploy() { … } |
| Exit codes |
`command |
| Heredoc |
ssh user@host << 'EOF' … EOF |
| String manipulation |
${VAR%.*} (strip extension) |
Phase 2 — Networking and security basics (Weeks 7–9)
You will constantly debug network issues and configure firewalls, load balancers, and TLS.
| Concept |
What to know |
| TCP/IP model |
4 layers: application / transport / internet / link |
| DNS |
A, CNAME, MX, TXT records; how TTL affects propagation |
| HTTP/HTTPS |
Methods, status codes, headers, TLS handshake |
| Ports |
22 SSH, 80 HTTP, 443 HTTPS, 3306 MySQL, 5432 PG, 6379 Redis |
| Firewalls |
iptables rules, ufw commands, security groups in cloud |
| Load balancing |
Round-robin, least-connections, sticky sessions |
| VPN |
WireGuard, OpenVPN basics; split tunnelling |
| SSH hardening |
Key-based auth, disable root login, fail2ban, port change |
| TLS certificates |
Let's Encrypt, self-signed certs, cert rotation |
| CIDR notation |
10.0.0.0/24 = 256 addresses, /16 = 65,536 |
Phase 3 — Version control with Git (Weeks 10–11)
Everything in DevOps — config, code, pipelines, infra — lives in Git.
| Command |
Purpose |
git init / clone |
Create or copy a repo |
git add -p |
Stage hunks interactively |
git commit -m "feat: …" |
Commit with Conventional Commits |
git branch / checkout / switch |
Work in isolation |
git merge / rebase |
Integrate changes |
git stash |
Shelve uncommitted work |
git log --oneline --graph |
Visualise history |
git bisect |
Binary-search for regressions |
git revert |
Safe undo (creates new commit) |
git tag v1.2.3 |
Mark releases |
Git workflows for DevOps
- Trunk-based development — short-lived feature branches, merge to main daily; ideal for CI/CD
- GitFlow — main / develop / feature / release / hotfix branches; suits release-based products
- GitHub Flow — branch → PR → merge to main → auto-deploy; simple and popular
Phase 4 — Programming and scripting (Weeks 12–19)
DevOps engineers write automation scripts, tools, and sometimes services.
Python vs Go for DevOps
| Factor |
Python |
Go |
| Learning curve |
Gentle |
Moderate |
| Scripting |
Excellent |
Good |
| CLI tools |
Great (click, typer) |
Excellent (cobra) |
| Cloud SDKs |
All providers (boto3, etc.) |
All providers |
| Performance |
Slow (interpreted) |
Fast (compiled) |
| Single binary |
No |
Yes (huge DevOps advantage) |
| Terraform / K8s ecosystem |
Pulumi, Ansible |
Many cloud-native tools |
| Recommend |
First language for DevOps |
After Python mastery |
Python for DevOps — quick reference
import subprocess
import boto3
from pathlib import Path
def run(cmd: list[str]) -> str:
"""Run a shell command and return stdout."""
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
return result.stdout.strip()
def list_ec2_instances(region="us-east-1"):
ec2 = boto3.client("ec2", region_name=region)
response = ec2.describe_instances()
for reservation in response["Reservations"]:
for instance in reservation["Instances"]:
print(instance["InstanceId"], instance["State"]["Name"])
# Read config, manipulate paths
config_path = Path("/etc/myapp/config.yaml")
print(config_path.read_text())
Phase 5 — Containers with Docker (Weeks 20–23)
Docker is the foundation of modern deployment. Every DevOps role requires it.
Docker essentials
# Multi-stage build — smaller, more secure final image
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
USER node
CMD ["node", "dist/server.js"]
| Docker command |
Purpose |
docker build -t app:latest . |
Build image |
docker run -d -p 3000:3000 app |
Run container in background |
docker exec -it <id> sh |
Shell into running container |
docker logs -f <id> |
Stream logs |
docker ps / docker ps -a |
List running / all containers |
docker stop / rm / rmi |
Stop, remove container/image |
docker system prune |
Free disk space |
docker pull / push |
Registry operations |
Docker Compose for local dev
services:
app:
build: .
ports: ["3000:3000"]
environment:
DATABASE_URL: postgres://user:pass@db:5432/mydb
depends_on:
db:
condition: service_healthy
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: mydb
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 5s
timeout: 5s
retries: 5
volumes:
pgdata:
Phase 6 — Kubernetes (Weeks 24–31)
Kubernetes (K8s) is the industry-standard container orchestrator. It has a steep learning curve — budget 6–8 weeks.
K8s core objects
| Object |
Purpose |
| Pod |
One or more containers that share network/storage |
| Deployment |
Manages ReplicaSet, rolling updates, rollbacks |
| Service |
Stable DNS name + load balancer in front of pods |
| Ingress |
HTTP routing rules from external traffic to Services |
| ConfigMap |
Non-sensitive config as key-value or files |
| Secret |
Base64-encoded sensitive config (use Sealed Secrets in prod) |
| HorizontalPodAutoscaler |
Scale pods based on CPU/memory/custom metrics |
| PersistentVolumeClaim |
Request durable storage |
| Namespace |
Isolate resources within a cluster |
| ServiceAccount |
Identity for pods to call K8s API |
Minimal production Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: api
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: registry.example.com/api:1.2.3
ports:
- containerPort: 3000
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-secret
key: url
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
livenessProbe:
httpGet:
path: /healthz
port: 3000
initialDelaySeconds: 15
readinessProbe:
httpGet:
path: /ready
port: 3000
kubectl cheat sheet
| Command |
Purpose |
kubectl get pods -n production |
List pods |
kubectl describe pod <name> |
Debug a pod |
kubectl logs -f <pod> |
Stream logs |
kubectl exec -it <pod> -- sh |
Shell into pod |
kubectl apply -f manifest.yaml |
Apply manifest |
kubectl rollout status deploy/api |
Watch rolling update |
kubectl rollout undo deploy/api |
Rollback |
kubectl scale deploy/api --replicas=5 |
Scale manually |
kubectl top nodes / pods |
Resource usage |
kubectl port-forward svc/api 8080:80 |
Local tunnel |
Phase 7 — CI/CD pipelines (Weeks 32–35)
Continuous Integration + Continuous Delivery automates testing and shipping on every commit.
GitHub Actions workflow
name: CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm test
- run: npm run lint
build-and-push:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v5
with:
push: true
tags: ghcr.io/${{ github.repository }}:${{ github.sha }}
deploy:
needs: build-and-push
runs-on: ubuntu-latest
environment: production
steps:
- run: |
kubectl set image deployment/api \
api=ghcr.io/${{ github.repository }}:${{ github.sha }}
CI/CD tools comparison
| Tool |
Best for |
Hosted |
Self-hosted |
| GitHub Actions |
GitHub repos, open source |
Yes |
Via runners |
| GitLab CI/CD |
GitLab, all-in-one DevOps |
Yes |
Yes |
| Jenkins |
Complex enterprise pipelines |
No |
Yes |
| CircleCI |
Fast pipelines, Docker-first |
Yes |
Yes |
| ArgoCD |
GitOps Kubernetes deployments |
No |
Yes |
| Tekton |
Cloud-native K8s pipelines |
No |
Yes |
| Buildkite |
Large-scale, agent-based |
Yes |
Agents |
Phase 8 — Infrastructure as Code (Weeks 36–41)
IaC means your infrastructure is defined in code, version-controlled, and reproducible.
Terraform basics
# main.tf — AWS VPC + EC2 example
terraform {
required_providers {
aws = { source = "hashicorp/aws", version = "~> 5.0" }
}
backend "s3" {
bucket = "my-tfstate"
key = "prod/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "tf-lock"
}
}
provider "aws" { region = "us-east-1" }
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
tags = { Name = "main-vpc", Env = var.environment }
}
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
subnet_id = aws_subnet.public.id
tags = { Name = "web-server" }
}
| Terraform command |
Purpose |
terraform init |
Download providers |
terraform plan |
Preview changes |
terraform apply |
Apply changes |
terraform destroy |
Tear down resources |
terraform output |
Show output values |
terraform state list |
List managed resources |
terraform import |
Adopt existing resource |
Ansible for configuration management
# site.yml — configure web servers
- name: Configure web servers
hosts: webservers
become: true
vars:
app_port: 3000
app_user: deploy
tasks:
- name: Install dependencies
apt:
name: [nginx, nodejs, npm]
state: present
update_cache: true
- name: Copy nginx config
template:
src: nginx.conf.j2
dest: /etc/nginx/sites-available/app
notify: Reload nginx
- name: Ensure app service is running
systemd:
name: myapp
state: started
enabled: true
handlers:
- name: Reload nginx
systemd:
name: nginx
state: reloaded
Terraform vs Ansible
| Factor |
Terraform |
Ansible |
| Primary use |
Provisioning infrastructure |
Configuring servers |
| State |
Manages state file |
Agentless, idempotent tasks |
| Language |
HCL |
YAML playbooks |
| Cloud support |
All major providers |
All major providers |
| Idempotency |
Built-in |
Must design carefully |
| When to use |
Create VPC, EC2, RDS |
Install nginx, deploy app |
Phase 9 — Cloud platforms (Weeks 42–49)
Pick one cloud deeply; learn the others at a conceptual level.
AWS core services for DevOps
| Category |
Key services |
| Compute |
EC2, Lambda, ECS, EKS, Fargate |
| Storage |
S3, EBS, EFS, Glacier |
| Networking |
VPC, Route 53, CloudFront, ALB/NLB |
| Database |
RDS, Aurora, DynamoDB, ElastiCache |
| CI/CD |
CodePipeline, CodeBuild, CodeDeploy, ECR |
| IaC |
CloudFormation, CDK |
| Monitoring |
CloudWatch, X-Ray |
| Security |
IAM, KMS, Secrets Manager, WAF, Shield |
| Messaging |
SQS, SNS, EventBridge |
Cloud provider comparison
| Factor |
AWS |
Azure |
GCP |
| Market share 2025 |
~31% |
~25% |
~11% |
| Kubernetes service |
EKS |
AKS |
GKE (strongest) |
| Serverless |
Lambda |
Azure Functions |
Cloud Run |
| Best for |
General purpose |
Microsoft/enterprise |
Data, ML, Kubernetes |
| DevOps entry cert |
AWS SAA / DVA |
AZ-104 / AZ-204 |
ACE / PCDE |
| Managed K8s cost |
Paid ($72/cluster/mo) |
Free control plane |
Free control plane |
IAM best practices
# Never use root — create admin IAM user
# Apply least privilege with policies
# Rotate access keys every 90 days
# Use IAM roles for EC2/Lambda (not access keys)
# Enable MFA for all human users
# Use AWS Organizations SCPs for guardrails
Phase 10 — Monitoring and observability (Weeks 50–53)
You can't fix what you can't see. Observability has three pillars: metrics, logs, and traces.
| Pillar |
What it answers |
Tools |
| Metrics |
How is the system performing? |
Prometheus, Grafana, Datadog |
| Logs |
What happened and when? |
ELK Stack, Loki+Grafana, CloudWatch |
| Traces |
Where did this request spend its time? |
Jaeger, Zipkin, OpenTelemetry |
Prometheus + Grafana
# prometheus.yml — scrape config
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: "kubernetes-pods"
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: "true"
- job_name: "node-exporter"
static_configs:
- targets: ["node-exporter:9100"]
Key metrics to monitor
| Category |
Metrics |
| Infrastructure |
CPU %, memory %, disk I/O, network in/out |
| Application |
Request rate, error rate, latency (p50/p95/p99) |
| Kubernetes |
Pod restarts, pending pods, node pressure |
| Database |
Query time, connection pool usage, replication lag |
| Business |
Active users, orders/min, revenue/hour |
SLO / SLA / SLI
- SLI (Service Level Indicator) — measurable metric, e.g., 99th percentile latency
- SLO (Service Level Objective) — target, e.g., p99 latency < 200 ms
- SLA (Service Level Agreement) — contractual commitment with penalty if broken
- Error budget — how much failure you can afford; (1 − SLO) × time period
Alerting best practices
- Alert on symptoms (user-facing impact), not causes
- Use
for: duration to avoid flapping alerts
- Have runbooks linked in alert messages
- Tiered severity: page → ticket → log
- Use dead man's switch (absence of heartbeat = alert)
Phase 11 — Security and DevSecOps (Weeks 54–56)
Security must be embedded throughout the pipeline, not added at the end.
| Stage |
Security practice |
Tools |
| Code |
SAST, dependency scan |
Semgrep, Snyk, Dependabot |
| Build |
Sign images, SBOM |
Sigstore Cosign, Syft |
| Registry |
Vulnerability scanning |
Trivy, Grype, ECR scanning |
| Deploy |
Policy as code, OPA |
OPA Gatekeeper, Kyverno |
| Runtime |
Container runtime security |
Falco, AppArmor, seccomp |
| Secrets |
Dynamic secrets, rotation |
Vault, AWS Secrets Manager |
| Compliance |
Audit logging, CIS benchmarks |
kube-bench, Cloud Security Hub |
Secrets management — what NOT to do
# NEVER do this
DATABASE_URL="postgres://admin:SuperSecret@prod-db:5432/app" # hardcoded
docker run -e DB_PASS=supersecret ... # visible in ps aux
# DO this instead
export DATABASE_URL="$(aws secretsmanager get-secret-value \
--secret-id prod/db/password --query SecretString --output text)"
# Or use vault
vault kv get -field=password secret/prod/db
Full DevOps technology map
Foundation
├── Linux (Ubuntu/RHEL/Alpine)
├── Bash scripting
├── Python / Go
├── Git + GitHub/GitLab
Containers & Orchestration
├── Docker + Docker Compose
├── Kubernetes (EKS/GKE/AKS)
├── Helm (K8s package manager)
└── Service mesh (Istio/Linkerd) — advanced
CI/CD
├── GitHub Actions / GitLab CI
├── ArgoCD (GitOps)
└── Jenkins — legacy, but common
Infrastructure as Code
├── Terraform (provisioning)
├── Ansible (configuration)
├── Packer (image building)
└── Pulumi — alternative to Terraform
Cloud
├── AWS (EC2/EKS/S3/RDS/Lambda/IAM)
├── Azure (AKS/ACI/Blob/CosmosDB)
└── GCP (GKE/Cloud Run/BigQuery)
Observability
├── Prometheus + Grafana
├── ELK Stack (Elasticsearch/Logstash/Kibana)
├── Loki (Grafana logging)
├── OpenTelemetry (traces)
└── Datadog / New Relic (commercial)
Security
├── Vault (secrets)
├── Trivy / Snyk (scanning)
├── OPA / Kyverno (policy)
└── Falco (runtime)
Realistic 18-month timeline
| Month |
Focus |
Milestone |
| 1–2 |
Linux, Bash, Git |
Comfortable on command line; own a VPS |
| 3–4 |
Python scripting, networking |
Write deploy scripts; understand DNS/TLS |
| 5–6 |
Docker, Docker Compose |
Containerise a full-stack app; push to Docker Hub |
| 7–9 |
Kubernetes |
Deploy app to K8s cluster; write Helm chart |
| 10–11 |
CI/CD with GitHub Actions |
Full pipeline: lint → test → build → deploy |
| 12–14 |
Terraform + cloud (AWS) |
Provision VPC/EC2/RDS with Terraform; pass AWS SAA |
| 15–16 |
Monitoring with Prometheus/Grafana |
Working dashboards and alerts; on-call runbook |
| 17–18 |
Security, portfolio, job search |
Two public projects; first DevOps job |
DevOps vs related roles
| Role |
Core focus |
Unique skills |
Avg salary 2025 |
| DevOps Engineer |
Automation, CI/CD, IaC |
Bridges dev and ops |
$110–140k |
| SRE (Site Reliability Engineer) |
Reliability, SLOs, toil reduction |
Error budgets, capacity planning |
$130–170k |
| Platform Engineer |
Internal developer platform |
Backstage, golden paths, self-service |
$120–155k |
| Cloud Engineer |
Cloud architecture and migration |
Deep cloud provider expertise |
$115–145k |
| Infrastructure Engineer |
Servers, networking, storage |
Physical/virtual infra |
$100–130k |
| Security Engineer (DevSecOps) |
Security in CI/CD and infra |
SAST/DAST, policy as code |
$120–160k |
Common mistakes
| Mistake |
Better approach |
| Skipping Linux fundamentals |
Spend 4–6 weeks on Linux before Docker or K8s |
| Learning Kubernetes before Docker |
Docker first — K8s orchestrates Docker containers |
| Hardcoding secrets in pipelines |
Use Vault, cloud secret managers, or GitHub Secrets |
| No state locking in Terraform |
Always use remote backend with DynamoDB lock |
| Deploying without rollback plan |
Use rolling updates with maxUnavailable: 0; keep previous image |
| Alert fatigue (too many alerts) |
Alert on symptoms, set for: duration, tier severity |
| Manual server configuration |
Ansible/Terraform for all changes — immutable infra |
| Ignoring cost monitoring |
Set billing alerts; use Infracost in CI before applying |
Frequently asked questions
Do I need to know programming to become a DevOps engineer?
Yes — Bash is mandatory, Python is strongly recommended. You don't need to build full applications, but you must write automation scripts, CLI tools, and sometimes glue services together.
Should I learn AWS, Azure, or GCP first?
Start with AWS — it has the most jobs, the richest free-tier for learning, and the most learning resources. Once you understand cloud fundamentals in one provider, learning the others takes weeks, not months.
What certifications help most for DevOps?
In order of value: AWS Solutions Architect Associate (SAA-C03) → Certified Kubernetes Administrator (CKA) → HashiCorp Terraform Associate → AWS DevOps Engineer Professional. The CKA is widely respected and demonstrates hands-on Kubernetes skill.
Is DevOps a good career in 2025?
Yes — demand remains strong. Cloud-native adoption is expanding, Kubernetes is now standard, and platform engineering is a growing adjacent field. Salaries are above the software engineering median.
Docker or Podman?
Docker for learning — it has more resources, tutorials, and tooling. Podman is rootless and daemonless (better security) and is becoming standard on RHEL/Fedora. Many teams use both. Learn Docker first, understand Podman as an alternative.
Can I become a DevOps engineer without prior experience?
Yes, but it's hard to start here with zero experience. Many successful DevOps engineers came from sysadmin, backend dev, or QA backgrounds. If you're a complete beginner, spend 3–4 months on Linux + Python + Docker before applying to DevOps roles.