By Ajnas N B
Founder, Cognifyr.CO
- What is DevOps?
- Why DevOps?
- Base Components Explained
- How DevOps Works
- Our Project Structure
- Step-by-Step Workshop Guide
- Understanding the Code
- The Future of DevOps
- Key Takeaways
DevOps is a methodology that brings together software development and IT operations teams to work collaboratively throughout the entire software lifecycle.
The Traditional Problem:
- Developers write code and want to deploy it quickly
- Operations teams manage servers and want stability
- These teams often work in silos, causing delays and conflicts
DevOps Solution: DevOps bridges this gap by:
- Encouraging collaboration between Development and Operations
- Automating the software delivery process
- Implementing continuous integration and continuous deployment (CI/CD)
- Using infrastructure as code
- Monitoring and logging everything
- Embracing a culture of shared responsibility
Result: Faster deployments, higher quality, better collaboration, and more reliable systems.
DevOps = Development + Operations
It's a way of working where:
- Developers (people who write code) and Operations (people who run servers) work together
- Code changes go from your computer β testing β production automatically
- Everything is automated, so humans make fewer mistakes
- Problems are found and fixed quickly
Code β Build β Test β Deploy β Monitor β Learn β Improve
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
This is a continuous cycle that improves with each iteration!
Traditional software deployment process:
- Developer writes code on their computer
- Developer sends code to operations team (via email, shared drive, etc.)
- Operations team manually sets up servers
- Operations team manually deploys the application
- If there's a bug, the entire process repeats from step 1
Problems:
- β Takes days or weeks
- β Lots of manual work
- β Easy to make mistakes
- β If something breaks, hard to fix
- β Developers and Operations blame each other
- You write the story
- You push a button (git push)
- Automatically:
- Story is tested
- Story is built into a website
- Story goes live
- If something breaks, it tells you immediately
Benefits:
- β Takes minutes instead of days
- β Everything is automated
- β Fewer mistakes
- β Easy to fix problems
- β Everyone works together
| Before DevOps | With DevOps |
|---|---|
| π Deployments take weeks | β‘ Deployments take minutes |
| π° Manual, error-prone | π€ Automated, reliable |
| π₯ Teams blame each other | π€ Teams work together |
| π Bugs found in production | β Bugs found before production |
| π° Expensive downtime | π΅ Less downtime, more savings |
| π Stressful releases | π Smooth, frequent releases |
Before diving into DevOps practices, it's essential to understand the fundamental components and tools that make DevOps possible. This section explains each base component in detail.
Git is a distributed version control system that tracks changes in source code during software development.
- Repository (Repo): A folder that contains your project files and the entire history of changes
- Commit: A snapshot of your code at a specific point in time
- Branch: A parallel version of your code where you can make changes without affecting the main code
- Push: Uploading your local changes to a remote repository (like GitHub)
- Pull: Downloading changes from a remote repository to your local machine
- Clone: Creating a local copy of a remote repository
- Version History: See every change ever made to your code
- Collaboration: Multiple developers can work on the same project simultaneously
- Rollback: Easily revert to previous versions if something breaks
- Branching: Work on features without affecting production code
git clone <url> # Download a repository
git add . # Stage changes for commit
git commit -m "message" # Save changes with a message
git push # Upload changes to remote
git pull # Download latest changes
git status # See what files have changedWe use Git to:
- Store our code in GitHub
- Track all changes to
server.js,Dockerfile, Kubernetes manifests, etc. - Trigger CI/CD pipelines when we push changes
A container is a lightweight, standalone, executable package that includes everything needed to run an application: code, runtime, system tools, libraries, and settings.
- Isolated: Each container runs in its own isolated environment
- Portable: Runs the same way on any machine (your laptop, cloud, server)
- Lightweight: Shares the host OS kernel, making it more efficient than virtual machines
- Consistent: Eliminates "it works on my machine" problems
| Containers | Virtual Machines |
|---|---|
| Share OS kernel | Each VM has its own OS |
| Faster startup | Slower startup |
| Less resource usage | More resource usage |
| Better for microservices | Better for full OS isolation |
Containers provide:
- Standardization: Consistent packaging format
- Completeness: Contains everything needed (app + dependencies + runtime)
- Portability: Runs identically across different environments
- Isolation: Each container operates independently
Docker is a platform that enables you to create, deploy, and run applications using containers.
- Docker Engine: The runtime that builds and runs containers
- Docker Image: A read-only template used to create containers
- Docker Container: A running instance of an image
- Dockerfile: A text file with instructions to build an image
- Docker Hub: A public registry of Docker images (like GitHub for containers)
Dockerfile β Docker Build β Docker Image β Docker Run β Container
- Write a
Dockerfile(instructions) - Build an image:
docker build -t myapp . - Run a container:
docker run myapp
- Consistency: Same environment in development, testing, and production
- Isolation: Apps don't interfere with each other
- Scalability: Easy to run multiple instances
- Portability: Works on Windows, Linux, macOS, cloud
Our Dockerfile creates a Docker image that:
- Starts with Node.js 20
- Installs dependencies
- Copies our code
- Exposes port 3000
- Runs our Express server
Azure Container Registry (ACR) is a managed Docker container registry service in Azure that stores and manages your Docker container images.
A container registry is a private repository for Docker images where you can:
- Store your Docker images securely
- Version your images (tag them with versions)
- Control who can access your images
- Integrate with Azure services
- Private Storage: Your images are private by default
- Geo-replication: Store images in multiple regions
- Security: Integration with Azure Active Directory
- Webhooks: Get notified when images are pushed
- Vulnerability Scanning: Automatically scan images for security issues
# Login to ACR
az acr login --name <registry-name>
# Build and push image
docker build -t <registry>.azurecr.io/<image>:<tag> .
docker push <registry>.azurecr.io/<image>:<tag>
# List repositories
az acr repository list --name <registry-name>
# List tags (versions)
az acr repository show-tags --name <registry-name> --repository <image>We use ACR (acedevopsdemoacr) to:
- Store our built Docker images
- Version our application images
- Provide images to AKS for deployment
Kubernetes (often abbreviated as K8s) is an open-source container orchestration platform that automates the deployment, scaling, and management of containerized applications.
Container orchestration means:
- Scheduling: Deciding which server runs which container
- Scaling: Automatically adding/removing containers based on demand
- Health Monitoring: Restarting containers if they crash
- Load Balancing: Distributing traffic across containers
- Rolling Updates: Updating apps without downtime
- Cluster: A set of nodes (machines) that run containerized applications
- Node: A worker machine (can be physical or virtual)
- Pod: The smallest deployable unit (contains one or more containers)
- Deployment: Manages a set of identical pods
- Service: Exposes pods to network traffic
- Namespace: A way to organize resources in a cluster
βββββββββββββββββββββββββββββββββββββββ
β Control Plane (Master) β
β - API Server β
β - Scheduler β
β - Controller Manager β
βββββββββββββββββββββββββββββββββββββββ
β
βββββββββββ΄ββββββββββ
β β
βββββΌββββ βββββΌββββ
β Node 1β β Node 2β
β Pods β β Pods β
βββββββββ βββββββββ
- Auto-scaling: Automatically scale up/down based on load
- Self-healing: Restarts failed containers
- Rolling Updates: Update apps without downtime
- Service Discovery: Containers can find each other automatically
- Resource Management: Efficiently uses server resources
kubectl get pods # List all pods
kubectl get deployments # List all deployments
kubectl get services # List all services
kubectl apply -f file.yaml # Apply configuration
kubectl describe pod <name> # Get pod details
kubectl logs <pod-name> # View pod logs
kubectl delete pod <name> # Delete a podWe use Kubernetes to:
- Run our containerized Express app
- Manage app lifecycle (start, stop, restart)
- Expose our app to the internet via LoadBalancer
- Scale our app if needed
Azure Kubernetes Service (AKS) is a managed Kubernetes service provided by Microsoft Azure. It simplifies deploying and managing Kubernetes clusters.
Azure handles:
- Control Plane: Azure manages the Kubernetes master nodes
- Updates: Automatic Kubernetes version updates
- Monitoring: Built-in monitoring and logging
- Scaling: Easy cluster and node scaling
- Security: Integrated security features
- Simplified Management: No need to manage Kubernetes control plane
- Azure Integration: Works seamlessly with other Azure services
- Cost Effective: Pay only for the worker nodes
- Security: Integrated with Azure Active Directory
- Developer Tools: kubectl, Helm, and other tools work out of the box
- Control Plane: Managed by Azure (you don't see it)
- Node Pools: Worker nodes where your containers run
- Networking: Virtual network integration
- Identity: Managed identity for secure access
We use AKS (devops-aks) to:
- Run our Kubernetes cluster
- Deploy our containerized application
- Manage our app's lifecycle
- Provide public access via LoadBalancer service
CI/CD stands for Continuous Integration and Continuous Deployment/Delivery.
CI is the practice of automatically testing code changes as soon as they're committed to a repository.
CI Process:
- Developer commits code
- Automated build process starts
- Automated tests run
- If tests pass β code is integrated
- If tests fail β developer is notified
Benefits:
- Catch bugs early
- Ensure code quality
- Prevent broken code from reaching production
Continuous Delivery: Code is always ready to deploy to production (but deployment is manual)
Continuous Deployment: Code is automatically deployed to production after passing tests
CD Process:
- Code passes CI tests
- Build Docker image
- Push to container registry
- Deploy to staging/production
- Run smoke tests
- Monitor deployment
Benefits:
- Faster time to market
- Reduced manual errors
- Frequent, small releases
- Easy rollback if issues occur
Code Commit β Build β Test β Build Image β Push to Registry β Deploy β Monitor
β β
ββββββββββββββββββββββββββββ Feedback Loop βββββββββββββββββββββββββββ
Our GitHub Actions workflow (azure-ci-cd.yml) implements CI/CD:
- CI: Checks out code, builds Docker image
- CD: Pushes to ACR, deploys to AKS automatically
GitHub Actions is a CI/CD platform built into GitHub that automates software workflows.
- Workflow: An automated process defined in a YAML file
- Event: Something that triggers a workflow (push, pull request, etc.)
- Job: A set of steps that run on the same runner
- Step: A single task in a job
- Action: Reusable units of code (like login, checkout, etc.)
- Runner: The machine that executes the workflow (GitHub-hosted or self-hosted)
name: Workflow Name
on: [push] # Trigger event
jobs:
job-name:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: echo "Hello World"- Integrated: Built into GitHub, no separate tool needed
- Free: Free for public repositories
- Flexible: Supports any language or platform
- Marketplace: Thousands of pre-built actions
- Easy: YAML-based configuration
We use GitHub Actions to:
- Automatically build Docker images when code is pushed
- Push images to ACR
- Deploy to AKS
- Restart deployments with new images
Azure is Microsoft's cloud computing platform that provides a wide range of cloud services.
Instead of buying and maintaining physical servers, you:
- Rent computing resources from a cloud provider
- Pay only for what you use
- Scale up or down as needed
- Access from anywhere with internet
- Azure Container Registry (ACR): Store Docker images
- Azure Kubernetes Service (AKS): Run Kubernetes clusters
- Azure Active Directory: Authentication and authorization
- Azure Resource Groups: Organize related resources
- Global: Data centers worldwide
- Secure: Enterprise-grade security
- Integrated: Services work well together
- Scalable: Scale from small to massive
- Cost-effective: Pay-as-you-go pricing
YAML (YAML Ain't Markup Language) is a human-readable data serialization format commonly used for configuration files.
# Comments start with #
key: value
number: 42
boolean: true
list:
- item1
- item2
nested:
key: value
another: value- Readable: Easy for humans to read and write
- Common: Used by Kubernetes, Docker Compose, CI/CD tools
- Structured: Supports complex data structures
- Standard: Widely adopted in DevOps tooling
We use YAML for:
- Kubernetes manifests (
deployment.yaml,service.yaml) - GitHub Actions workflows (
azure-ci-cd.yml) - Configuration files
kubectl is the command-line tool for interacting with Kubernetes clusters.
- Deploy: Apply configurations to clusters
- Inspect: View cluster resources and status
- Manage: Create, update, delete resources
- Debug: View logs, describe resources
- Scale: Scale deployments up or down
kubectl uses a kubeconfig file that contains:
- Cluster information (server address)
- Authentication credentials
- Context (which cluster to use)
# Get credentials for AKS
az aks get-credentials --resource-group <rg> --name <cluster>
# This updates your kubeconfig fileWe use kubectl to:
- Deploy our application to AKS
- Check deployment status
- View service information (get EXTERNAL-IP)
- Restart deployments
Express.js is a fast, minimalist web framework for Node.js.
- HTTP Server: Creates web servers that respond to HTTP requests
- Routing: Maps URLs to functions (routes)
- Middleware: Functions that process requests
- Templates: Can render HTML pages
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello World');
});
app.listen(3000);We use Express to:
- Create a simple web server
- Handle HTTP requests
- Provide a health check endpoint
- Serve our application
Here's how all components work together in our project:
ββββββββββββ
β Git β β Version control
ββββββ¬ββββββ
β
βΌ
ββββββββββββ
β GitHub β β Code repository
ββββββ¬ββββββ
β
βΌ
ββββββββββββββββ
βGitHub Actionsβ β CI/CD automation
ββββββ¬ββββββββββ
β
ββββΊ ββββββββββββ
β β Docker β β Containerization
β ββββββ¬ββββββ
β β
β βΌ
β ββββββββββββ
β β ACR β β Image registry
β ββββββ¬ββββββ
β β
β βΌ
ββββΊ ββββββββββββ
β AKS β β Kubernetes cluster
ββββββ¬ββββββ
β
βΌ
ββββββββββββ
β Express β β Web application
ββββββββββββ
- Developers and Operations talk to each other
- Everyone shares responsibility
- Learning from mistakes, not blaming
- CI/CD (Continuous Integration/Continuous Deployment)
- CI = Every code change is automatically tested
- CD = Every tested change can go to production automatically
- Infrastructure as Code = Servers defined in files (like recipes)
- Monitoring = Watching your app 24/7
- Git = Distributed version control system
- Docker = Containerization platform
- Kubernetes = Container orchestration platform
- GitHub Actions = CI/CD automation platform
- Azure = Cloud computing platform
βββββββββββ ββββββββββββ ββββββββββββ ββββββββ ββββββββββββ
β VS Code β --> β GitHub β --> β GitHub β --> β ACR β --> β AKS β
β (Code) β β (Store) β β Actions β β(Image)β β(Kubernetes)
βββββββββββ ββββββββββββ ββββββββββββ ββββββββ ββββββββββββ
β β
ββββββββββββββββ
Deploy!
In Simple Words:
- You write code in VS Code
- You save it to GitHub (like saving to Google Drive)
- GitHub Actions (a robot) sees your change
- The robot builds your app into a Docker image
- The robot saves the image to Azure Container Registry (ACR)
- The robot tells Kubernetes (AKS) to run your app
- Your app is now live on the internet! π
Let's explore what each file does in our project:
devops/
β
βββ π server.js # Our web application
βββ π package.json # App dependencies and scripts
βββ π Dockerfile # Instructions to build a container
βββ π .gitignore # Files Git should ignore
β
βββ π k8s/ # Kubernetes configuration
β βββ deployment.yaml # How to run our app
β βββ service.yaml # How to expose our app
β
βββ π .github/
βββ π workflows/
βββ azure-ci-cd.yml # Automation pipeline
const express = require("express");
const app = express();
const PORT = process.env.PORT || 3000;
app.get("/", (req, res) => res.send("Hello from AKS π v1"));
app.get("/health", (req, res) => res.json({ status: "ok", version: "v1" }));
app.listen(PORT, "0.0.0.0", () => console.log("Running on " + PORT));What it does:
- Creates a web server using Express (a Node.js framework)
- Listens on port 3000
- Has two routes:
/= Shows "Hello from AKS π v1"/health= Shows app status (used by Kubernetes to check if app is healthy)
Purpose:
- Main route (
/) = Displays welcome message to users - Health check (
/health) = Kubernetes uses this to verify the app is running correctly
{
"name": "y",
"version": "1.0.0",
"scripts": {
"test": "echo \"Tests passed β
\""
},
"dependencies": {
"express": "^5.2.1"
}
}What it does:
- Lists project dependencies and their versions
express= The library that helps us make a web serverscripts= Commands we can run (likenpm test)
Purpose:
- Defines project dependencies (Express library)
- Provides scripts for common tasks (testing, starting)
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]What it does (line by line):
FROM node:20-alpine= Start with a lightweight Node.js base imageWORKDIR /app= Set working directory to/appCOPY package*.json ./= Copy package files first (for better caching)RUN npm install= Install all dependenciesCOPY . .= Copy application code into the containerEXPOSE 3000= Document that the app listens on port 3000CMD ["npm", "start"]= Command to run when container starts
Docker Layer Caching:
By copying package.json first and running npm install before copying code, Docker can cache the dependency installation layer. This speeds up rebuilds when only code changes.
apiVersion: apps/v1
kind: Deployment
metadata:
name: devops-app
spec:
replicas: 1
selector:
matchLabels:
app: devops
template:
metadata:
labels:
app: devops
spec:
containers:
- name: devops
image: acedevopsdemoacr.azurecr.io/devops:latest
ports:
- containerPort: 3000What it does:
- Tells Kubernetes: "Run 1 copy of our app"
- Uses the image from ACR (Azure Container Registry)
- Opens port 3000
Purpose:
- Defines how many replicas (copies) of the app to run
- Specifies which container image to use
- Configures container ports
- Sets up labels for service discovery
apiVersion: v1
kind: Service
metadata:
name: devops-service
spec:
type: LoadBalancer
selector:
app: devops
ports:
- port: 80
targetPort: 3000What it does:
- Creates a LoadBalancer (gives us a public IP address)
- Routes traffic from port 80 (internet) to port 3000 (our app)
Purpose:
- Creates a LoadBalancer service type (provides external IP)
- Routes external traffic (port 80) to container port (3000)
- Uses label selector to find the correct pods
- Enables public internet access to the application
name: AKS Full CI/CD (Build -> Push -> Deploy)
on:
push:
branches: ["master"]
jobs:
build-push-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Azure Login
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Login to ACR
run: az acr login --name acedevopsdemoacr
- name: Build image
run: docker build -t acedevopsdemoacr.azurecr.io/devops:latest .
- name: Push image
run: docker push acedevopsdemoacr.azurecr.io/devops:latest
- name: Get AKS credentials
run: az aks get-credentials -g chainsure -n devops-aks --overwrite-existing
- name: Apply manifests
run: kubectl apply -f k8s/
- name: Rollout restart
run: |
kubectl rollout restart deployment/devops-app
kubectl rollout status deployment/devops-appWhat it does (step by step):
- Triggers: When you push to
masterbranch - Checkout: Gets your code
- Azure Login: Logs into Azure (using secrets)
- Login to ACR: Connects to container registry
- Build image: Creates Docker image
- Push image: Saves image to ACR
- Get AKS credentials: Connects to Kubernetes
- Apply manifests: Deploys your app
- Rollout restart: Restarts to use new image
Automation Benefits:
- Eliminates manual deployment steps
- Ensures consistent deployment process
- Reduces human error
- Enables rapid iteration and updates
node_modules
What it does:
- Tells Git: "Don't track
node_modulesfolder" - Why? It's huge and can be regenerated with
npm install
Purpose: Prevents unnecessary files from being tracked in version control, keeping the repository clean and focused on source code.
Where we work:
- π’ VS Code β Writing code
- π’ GitHub UI β Repository, Actions, and secrets
- π’ Azure Portal β Visual confirmation only
- π’ Azure Cloud Shell (Terminal) β ALL Azure + kubectl commands
- β NO local kubectl, NO local Azure CLI installs
Remember: Everything infrastructure-related happens in Azure Cloud Shell!
Where: Browser β github.com
Why: GitHub is where our code lives and where automation starts
- Go to github.com
- Sign up (if you don't have an account)
- Verify your email
- Open:
https://github.com/AjnasNB/devops - Click the Fork button (top right)
- Create your fork
Why fork?
"Everyone works independently. No conflicts. Same pipeline, but your own copy!"
Where: VS Code
Why: This is where developers write code
git clone https://github.com/<your-username>/devops.git
cd devops
code .What happened:
- Downloaded the project to your computer
- Opened it in VS Code
Where: VS Code
Why: We need to understand what we're deploying
Look at:
server.js- Our web apppackage.json- DependenciesDockerfile- Container instructions
npm install
npm test
npm startThen visit: http://localhost:3000
What you'll see: "Hello from AKS π v1"
Stop the server: Press Ctrl+C
Where: Azure Portal β Cloud Shell (Bash)
Why: We need to authenticate to use Azure services
- Go to portal.azure.com
- Click the Cloud Shell icon (top bar) β Choose Bash
az loginFollow the prompts to log in.
If already logged in: You can skip this step!
Where: Azure Cloud Shell
Why: We need a secure, private repository to store our Docker images
az acr show \
--name acedevopsdemoacr \
--resource-group chainsureIf it exists: β Great! Move to next step.
If it doesn't exist: Create it:
az acr create \
--resource-group chainsure \
--name acedevopsdemoacr \
--sku BasicWhat is ACR?
"ACR = Private Docker Hub for Azure. It's where we store our app images securely."
What happened:
- Created a container registry named
acedevopsdemoacr - This is where our Docker images will live
Where: Azure Cloud Shell
Why: Kubernetes runs our containers
Important: We ONLY use Azure Terminal for this (as requested)
az aks create \
--resource-group chainsure \
--name devops-aks \
--location centralindia \
--node-count 1 \
--node-vm-size Standard_B2s_v2 \
--enable-managed-identity \
--attach-acr acedevopsdemoacr \
--generate-ssh-keys1What each part does:
--resource-group chainsure= Which group to put it in--name devops-aks= Name of our cluster--node-count 1= One worker node (cheap for demo)--enable-managed-identity= No passwords needed (secure)--attach-acr acedevopsdemoacr= AKS can pull images from ACR automatically--generate-ssh-keys= Creates keys for secure access
β³ This takes 5-7 minutes! Be patient. β
Why these settings?
- Managed identity β No passwords to manage
- Attach ACR β AKS can pull private images automatically
- Node count 1 β Cheap and perfect for learning
Where: Azure Cloud Shell
Why: kubectl is how we talk to Kubernetes
Where kubectl lives: Already installed in Cloud Shell!
az aks get-credentials \
--resource-group chainsure \
--name devops-aksWhat this does:
"This command writes cluster access details into kubeconfig. From now on, kubectl knows which cluster to talk to and has the authentication credentials needed to connect."
Technical Details: The command updates your ~/.kube/config file with cluster endpoint, authentication certificates, and context information.
kubectl get nodesExpected output:
NAME STATUS ROLES AGE VERSION
aks-nodepool1-xxxxx-0 Ready agent 5m v1.xx.x
If you see nodes: β Cluster is ready!
If you see an error: Check that AKS creation completed.
Where: VS Code
Why: Kubernetes needs YAML files to know how to run our app
The files are already created! Let's understand them:
This tells Kubernetes:
- Run 1 copy (replica) of our app
- Use the image from ACR
- Open port 3000
This tells Kubernetes:
- Create a LoadBalancer (public IP)
- Route port 80 β port 3000
git add .
git commit -m "add k8s manifests"
git pushWhat happened:
- Saved changes to Git
- Pushed to GitHub
Where: Azure Cloud Shell
Why: GitHub Actions needs permission to deploy to Azure
az ad sp create-for-rbac \
--name github-actions-devops-aks \
--role contributor \
--scopes /subscriptions/476bde81-c61f-412c-a2dd-6172f1e39678 \
--sdk-auth{
"clientId": "...",
"clientSecret": "...",
"subscriptionId": "...",
"tenantId": "...",
...
}What is a Service Principal?
"A service principal is an identity used by applications, services, and automation tools (like GitHub Actions) to access Azure resources. It's similar to a user account, but designed for non-human access."
Save this JSON - you'll need it in the next step!
Where: GitHub Repo β Settings
Why: We need to store credentials securely
- Go to your GitHub repository
- Click Settings (top menu)
- Click Secrets and variables β Actions
- Click New repository secret
- Create secret:
| Name | Value |
|---|---|
AZURE_CREDENTIALS |
(Paste the full JSON from step I) |
- Click Add secret
Why secrets?
"Secrets are encrypted and only GitHub Actions can use them. Never commit secrets to code!"
Where: VS Code
Why: This is our automation pipeline
The file .github/workflows/azure-ci-cd.yml is already created!
What it does:
- Triggers on push to
master - Checks out code
- Logs into Azure
- Builds Docker image
- Pushes to ACR
- Deploys to AKS
git add .
git commit -m "add aks ci/cd"
git pushWhere: GitHub β Actions tab
Why: Watch the magic happen!
- Go to your GitHub repository
- Click Actions tab
- You'll see a workflow run starting!
Watch the stages:
- β Checkout
- β Azure login
- β Docker build
- β Push to ACR
- β kubectl apply
- β Rollout restart
β³ Takes 2-3 minutes
What's happening:
"Every step is automated! No human needed. This is DevOps in action!"
Where: Azure Cloud Shell
Why: We need the public IP to access our app
kubectl get svcWait for EXTERNAL-IP (might show <pending> first)
Expected output:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
devops-service LoadBalancer 10.x.x.x 20.x.x.x 80:xxxxx/TCP
Copy the EXTERNAL-IP and open in browser:
http://<EXTERNAL-IP>/
You should see: "Hello from AKS π v1" π
Where: VS Code β GitHub β Browser
Why: Show how easy DevOps makes updates
Edit server.js:
app.get("/", (req, res) => res.send("Hello from AKS π v2"));git add .
git commit -m "update to v2"
git push- Go to Actions tab
- Watch the pipeline run automatically!
After 2-3 minutes, refresh your browser.
You should see: "Hello from AKS π v2"
Say this:
"This is a production update with one git push. No manual steps. This is DevOps!"
All these components work together to create a complete DevOps pipeline. Refer to the Base Components Explained section above for detailed explanations of:
- Git and version control
- Docker and containers
- Kubernetes and orchestration
- ACR (Azure Container Registry)
- AKS (Azure Kubernetes Service)
- CI/CD concepts
- GitHub Actions
- Azure cloud services
- AI helps find problems before they happen
- AI writes code, tests, and fixes bugs
- Example: GitHub Copilot, ChatGPT for code
- Everything (code, infrastructure) in Git
- Git becomes the single source of truth
- Changes tracked, audited, reversible
- No servers to manage
- Pay only for what you use
- Example: Azure Functions, AWS Lambda
- Apps run on multiple clouds (Azure, AWS, GCP)
- No vendor lock-in
- Better reliability
- Security built into every step
- Automated security scanning
- "Shift left" = Find security issues early
- β Git - Version control (you're using it!)
- β Docker - Containers (you're using it!)
- β Kubernetes - Orchestration (you're using it!)
- β CI/CD - Automation (you're using it!)
- π Linux basics - Most servers run Linux
- π YAML - Configuration files (you're using it!)
- Terraform - Infrastructure as Code
- Ansible - Configuration management
- Prometheus + Grafana - Monitoring
- Helm - Kubernetes package manager
- Jenkins - Alternative CI/CD tool
- Service Mesh (Istio, Linkerd)
- Cloud-native patterns
- Chaos Engineering
- Advanced Kubernetes (operators, CRDs)
- Multi-cloud strategies
Junior DevOps Engineer
β
DevOps Engineer
β
Senior DevOps Engineer
β
DevOps Architect / SRE (Site Reliability Engineer)
β
DevOps Lead / Engineering Manager
Salary Range (2025):
- Junior: $60k - $90k
- Mid-level: $90k - $130k
- Senior: $130k - $180k
- Architect: $150k - $250k+
Skills in Demand:
- Kubernetes β
- CI/CD β
- Cloud (Azure, AWS, GCP)
- Infrastructure as Code
- Monitoring & Observability
- Security
- β What DevOps is: Development + Operations working together
- β Why DevOps matters: Faster, safer, automated deployments
- β How DevOps works: Code β Build β Test β Deploy automatically
- β Real implementation: You deployed a real app to Kubernetes!
- β
Tools you used:
- Git & GitHub
- Docker
- Kubernetes (AKS)
- GitHub Actions
- Azure Cloud
-
Automate Everything π€
- If you do it twice, automate it
-
Fail Fast, Learn Fast π
- Find problems early
- Learn from mistakes
-
Collaboration π€
- Developers + Operations = One team
-
Continuous Improvement π
- Always getting better
- Measure, learn, improve
-
Security First π
- Security built-in, not added later
DevOps = Automating the path from code to production, with collaboration and continuous improvement.
Solution:
- Check you have permissions in Azure
- Verify resource group exists
- Try a different region
Solution:
az aks get-credentials --resource-group chainsure --name devops-aks --overwrite-existingSolution:
- Wait 2-3 minutes (LoadBalancer takes time)
- Check with:
kubectl get svc -w(watch mode)
Solution:
- Verify ACR is attached:
az aks show -g chainsure -n devops-aks --query "servicePrincipalProfile" - Check image exists:
az acr repository list --name acedevopsdemoacr
Solution:
- Check
AZURE_CREDENTIALSsecret is set correctly - Verify service principal has correct permissions
- Check Actions logs for specific errors
- Katacoda - Interactive tutorials
- Play with Kubernetes - Free K8s playground
- Azure Free Account - $200 credit
Ajnas N B
Founder, Cognifyr.CO
This handbook is part of the "Demystifying DevOps" workshop series, designed to make DevOps accessible to everyone, regardless of experience level.
Contact:
- Website: Cognifyr.CO
- GitHub: @AjnasNB
This project and handbook are provided for educational purposes.
Congratulations on completing this DevOps journey! You've:
- β Learned what DevOps is
- β Understood why it matters
- β Deployed a real application
- β Set up a complete CI/CD pipeline
Keep learning, keep building, keep deploying! π
Last Updated: January 2025
Version: 1.0