Note
Find the best way to contribute my knowledge into DevOps for beginner π
DevOps is a mindset β not just a set of tools. It bridges the gap between Development (writing code) and Operations (deploying and running code). The goal is to deliver software faster, more reliably, and with fewer manual steps.
If you are new, think of it this way:
Code β Build β Test β Package β Deploy β Monitor β Repeat
This repo walks you through each phase using real Azure cloud tools so you learn by doing, not just reading.
Before starting, make sure you have these installed and configured:
| Tool | Purpose | Install Guide |
|---|---|---|
| Azure CLI | Interact with Azure cloud | curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash |
| Docker | Build and run containers | curl -fsSL https://get.docker.com | sudo sh |
| Terraform | Provision cloud infrastructure | HashiCorp APT repo |
| Packer | Build VM images | HashiCorp APT repo |
| Helm | Package manager for Kubernetes | curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash |
| kubectl | Manage Kubernetes clusters | az aks install-cli |
You also need an Azure subscription with sufficient permissions to create resource groups, AKS clusters, and ACR registries.
Follow the modules in order. Each module builds on the previous one.
Module 1: Scripting Basics β Module 2: Docker β Module 3: Packer
β
Module 6: CI/CD Pipelines β Module 5: Kubernetes β Module 4: Terraform
Where: script/
What you learn: How to write Bash and PowerShell scripts for real DevOps tasks β file operations, process management, networking, SSL certificates, and JSON parsing.
Why it matters: Automation scripts are the backbone of DevOps. Before you use any fancy tool, you need to understand how to automate tasks from the command line.
The script/resource/ folder contains 10 guided challenges in both Bash (.sh) and PowerShell (.ps1). Work through them in order:
| Script | Topic |
|---|---|
p1 |
Date validation and arithmetic |
p2 |
File listing and filtering |
p3 |
Dynamic script creation and execution |
p4 |
Process management |
p5 |
File download and ZIP extraction |
p6 |
Recursive directory cleanup |
p7 |
JSON parsing with jq |
p8 |
Port connectivity testing |
p9 |
SSH service control |
p10 |
Self-signed SSL certificate generation |
cd script/
bash run_setup.shThis script builds Docker images, manages SSL certs, and pushes to Azure Container Registry β a real-world example of automating a full workflow.
Where: docker/
What you learn: How to containerize applications, build images, configure Nginx as a load balancer, and run multi-container apps with Docker Compose.
Why it matters: Containers are the unit of deployment in modern DevOps. Everything on Kubernetes runs as a container.
Dockerfile β docker build β docker image
docker run β container
docker-compose β multiple containers working together
docker/
βββ Dockerfile.web # Node.js app image
βββ Dockerfile.nginx # Nginx reverse proxy with SSL
βββ Dockerfile.nk8s # Nginx for Kubernetes deployments
βββ docker-compose.yaml # 4-app + load balancer setup
βββ conf/ # Nginx configuration files
βββ src/ # Node.js app source code
βββ resource/ # Step-by-step building blocks
βββ Node_create/ # Learn: build Alpine + Node image from scratch
βββ Node_project_hello/ # Node 20 hello world app
βββ Node_project_hello_v12/ # Node 18 hello world (LTS)
βββ Node_project_hello_v14/ # Node 20 hello world (LTS)
Step 1 β Run a single Node app:
cd docker/resource/Node_project_hello
bash bash_rundocker.shStep 2 β Build custom Node image from scratch:
cd docker/resource/Node_create
bash bash_node.shStep 3 β Run the full multi-app setup:
cd docker/resource
bash bash_run_all.sh
# Check all apps are up
bash bash_check_web_available.shStep 4 β Clean up:
bash bash_clear_all.sh βββββββββββββββββββ
Internet ββββββΊβ nginx_alb :80 β (load balancer)
ββββββββββ¬βββββββββ
βββββββββββββββΌβββββββββββββββ
βΌ βΌ βΌ
app1:8001 app2:8002 app3:8003 ...
Where: packer/
What you learn: How to bake custom Azure VM images using Packer so every VM starts pre-configured instead of being configured at runtime.
Why it matters: "Immutable infrastructure" β instead of SSHing into a server to fix things, you bake a new image and redeploy. This makes your infrastructure predictable and faster to scale.
packer/
βββ linux-vanilla.pkr.hcl # HCL2 template: Ubuntu VM with Azure CLI
βββ linux-docker.pkr.hcl # HCL2 template: Ubuntu VM with Docker + Azure CLI
βββ linux-vanilla.json # Legacy JSON format (same as .hcl, kept for reference)
βββ linux-docker.json # Legacy JSON format (same as .hcl, kept for reference)
βββ script/
βββ setup-az.sh # Installs Azure CLI on the VM
βββ setup-docker.sh # Installs Docker Engine + Compose V2 on the VM
Note: Prefer the
.pkr.hclfiles β they use the modern HCL2 format. The.jsonfiles are kept as a reference to understand legacy Packer syntax.
All templates use Ubuntu 22.04 LTS on Azure:
- Publisher:
Canonical - Offer:
0001-com-ubuntu-server-jammy - SKU:
22_04-lts
# Login to Azure first
az login
# Validate the template
packer init packer/linux-docker.pkr.hcl
packer validate \
-var "render_image_name=my-docker-image" \
-var "resource_group_name=my-rg" \
-var "build_resource_group_name=my-rg" \
packer/linux-docker.pkr.hcl
# Build the image
packer build \
-var "render_image_name=my-docker-image" \
-var "resource_group_name=my-rg" \
-var "build_resource_group_name=my-rg" \
packer/linux-docker.pkr.hclWhere: terraform/
What you learn: How to provision Azure infrastructure declaratively β VNets, AKS clusters, databases, storage accounts, load balancers, and CI/CD agent VMs.
Why it matters: Infrastructure as Code (IaC) means your cloud setup is version-controlled, repeatable, and reviewable like any other code. No more clicking through the Azure portal.
terraform/
βββ azure/ # Main Azure infrastructure
β βββ env/dev/ # Entry point β run terraform here
β βββ modules/
β βββ aks/ # Azure Kubernetes Service cluster
β βββ networking/ # VNet, subnets
β βββ iam/ # Identity and role assignments (ACR pull, AKS access)
β βββ storageAccount/ # Azure Blob Storage
β βββ database/ # Azure Database
β βββ bastion/ # Azure Bastion for secure VM access
β βββ loadBalancer/ # Azure Load Balancer
β βββ serverless/ # Azure Functions / serverless resources
β βββ vmss/ # Virtual Machine Scale Sets
βββ azure-agent/ # Self-hosted Azure DevOps pipeline agent VM
β βββ linux-agent/ # Entry point for agent VM
β βββ modules/
β βββ iam/
β βββ network/
β βββ vm/
βββ k8s/ # Kubernetes-level deployments via Terraform + Helm
βββ env/dev/ # Entry point β run terraform here after AKS is up
βββ modules/
βββ ingress-controller/
βββ applications/
βββ monitoring/
cd terraform/azure/env/dev
# 1 β Initialize (downloads providers, sets up backend)
terraform init
# 2 β See what will be created
terraform plan -var-file="dev.tfvars"
# 3 β Create the infrastructure
terraform apply -var-file="dev.tfvars" -auto-approve
# 4 β Destroy when done (saves cost!)
terraform destroy -var-file="dev.tfvars" -auto-approvecd script/
bash run_terraform.sh| Feature | Where |
|---|---|
| Remote state (Azure Blob) | azure/env/dev/providers.tf |
| Module composition | azure/env/dev/main.tf |
| Conditional resource creation | count = var.condition_variable == "aks" ? 1 : 0 |
| Dependency management | depends_on = [module.network] |
| Output passing between modules | module.aks[0].principal_id |
Where: kubernetes/
What you learn: How to deploy applications to Kubernetes using Helm charts β deployments, services, ingress, persistent storage, and RBAC.
Why it matters: Kubernetes is the industry standard for running containers at scale. Helm makes managing Kubernetes manifests maintainable by templating repeated patterns.
kubernetes/
βββ app1/ app2/ app3/ app4/ # One Helm chart per Node.js microservice
βββ nginx/ # Nginx load balancer with ConfigMap routing
βββ nginx-persistent/ # Nginx with persistent Azure File storage
βββ common/ # Shared ingress (nginx ingress controller)
βββ rbac/ # Service account + Role + RoleBinding
# 0 β Point kubectl to your AKS cluster
az aks get-credentials --resource-group <rg> --name <cluster>
# 1 β Create namespace
kubectl create namespace devops
# 2 β Install RBAC (service account and roles)
helm install rbac kubernetes/rbac -n devops
# 3 β Install apps
helm install web-app1 kubernetes/app1 -n devops
helm install web-app2 kubernetes/app2 -n devops
helm install web-app3 kubernetes/app3 -n devops
helm install web-app4 kubernetes/app4 -n devops
# 4 β Install Nginx load balancer
helm install nginx kubernetes/nginx -n devops
# 5 β Install ingress
helm install common kubernetes/common -n devops
# Verify everything is running
kubectl get pods -n devops
kubectl get svc -n devops
kubectl get ingress -n devops ββββββββββββββββββββ
Internet ββββββββββΊβ Ingress (nginx) β
ββββββββββ¬ββββββββββ
β
ββββββββββΌββββββββββ
β Nginx ConfigMap β (upstream routing)
ββββ¬βββ¬βββ¬βββ¬ββββββ
β β β β
app1 app2 app3 app4 (ClusterIP services)
| Concept | File |
|---|---|
| Deployment | app*/templates/deployment.yaml |
| ClusterIP Service with session affinity | app*/templates/service.yaml |
Nginx Ingress with ingressClassName |
common/templates/ingress.yaml |
| ConfigMap for Nginx config | nginx/templates/config.yaml |
| PersistentVolumeClaim | nginx-persistent/templates/pv-claim.yaml |
| StorageClass (Azure File CSI) | nginx-persistent/templates/storage.yaml |
| Role + RoleBinding + ServiceAccount | rbac/templates/ |
Where: azure-pipeline/
What you learn: How to automate everything from the previous modules into a pipeline that runs on every code push β infrastructure provisioning, image building, and Kubernetes deployment.
Why it matters: CI/CD is the final piece of the DevOps loop. Humans stop clicking buttons; pipelines do the work consistently every time.
azure-pipeline/
βββ azure-pipelines.yml # Provision Azure infrastructure (Terraform)
βββ azure-pipelines-destroy.yml # Destroy infrastructure (cleanup / teardown)
βββ k8s-pipelines.yml # Deploy to Kubernetes via Terraform + Helm
βββ packer-pipeline.yml # Build custom VM images with Packer
ββββββββββββββββββββ ββββββββββββββββββββ
β terraform_plan ββββββΊβ terraform_apply β
β (PR preview) β β (after approval) β
ββββββββββββββββββββ ββββββββββββββββββββ
The pipelines run on a self-hosted Linux agent provisioned by terraform/azure-agent/. This avoids Microsoft-hosted agent limitations and keeps your Azure resources on the same private network.
To provision the agent VM:
cd terraform/azure-agent/linux-agent
terraform init
terraform apply \
-var "url_org=https://dev.azure.com/YOUR_ORG" \
-var "token=YOUR_PAT_TOKEN" \
-var "pool=linuxAgent" \
-var "agent=agent-01"| Variable | Description |
|---|---|
serviceConnection |
Azure service connection name |
environmentName |
Azure DevOps environment for approvals |
resourceGroup |
Terraform backend resource group |
storageAccount |
Terraform state storage account |
renderImageName |
Name for Packer-built VM image |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Azure DevOps β
β βββββββββββββββ ββββββββββββββββ βββββββββββββββββββββ β
β β Packer β β Terraform β β K8s Deployment β β
β β Pipeline β β Pipeline β β Pipeline β β
β ββββββββ¬βββββββ ββββββββ¬ββββββββ ββββββββββ¬βββββββββββ β
βββββββββββΌβββββββββββββββ-βΌβββββββββββββββββββ-βΌββββββββββββββ
β β β
βΌ βΌ βΌ
Azure Managed βββββββββββββββ βββββββββββββ
Image (Ubuntu β Azure IaaS β β AKS β
22.04 + Docker) β VNet / IAM β β Cluster β
β Storage β β + Helm β
βββββββββββββββ βββββββββββββ
β
ββββββββββββΌββββββββββ
β app1 app2 app3 β
β app4 nginx rbac β
ββββββββββββββββββββββ
Terraform state lock:
terraform force-unlock <lock-id>AKS credentials expired:
az aks get-credentials --resource-group <rg> --name <cluster> --overwrite-existingHelm release already exists:
helm upgrade --install <release-name> <chart-path> -n <namespace>Packer build fails on authentication:
az login
az account set --subscription <subscription-id>Docker Compose not found (V2):
docker compose version # note: no hyphen in V2
# If missing, install the plugin:
mkdir -p ~/.docker/cli-plugins
curl -SL https://github.com/docker/compose/releases/latest/download/docker-compose-linux-x86_64 \
-o ~/.docker/cli-plugins/docker-compose
chmod +x ~/.docker/cli-plugins/docker-composeFound something outdated or want to add a new module? Open a PR! Focus areas for future modules:
- Module 7: Monitoring with Prometheus + Grafana (see
terraform/k8s/modules/monitoring/) - Module 8: Azure Key Vault integration for secrets management
- Module 9: GitOps with ArgoCD or Flux
Happy learning! DevOps is a journey, not a destination.