DataScience / AzureDevops /index.html
AashishAIHub's picture
Expand Azure DevOps module: 10 modules with in-depth theory, YAML examples, and interview Q&A (1768β†’2949 lines)
8876fbf
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Azure DevOps & MLOps Masterclass</title>
<!-- Shared Design System -->
<link rel="stylesheet" href="../shared/css/design-system.css">
<link rel="stylesheet" href="../shared/css/components.css">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--bg: #0f1419;
--surface: #1a1f2e;
--text: #e4e6eb;
--text-dim: #b0b7c3;
--cyan: #0078D4;
--orange: #ff6b35;
--green: #00ff88;
--yellow: #ffa500;
--azure: #0078D4;
--teal: #00b7c3;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: var(--bg);
color: var(--text);
line-height: 1.6;
overflow-x: hidden;
}
.container {
max-width: 1400px;
margin: 0 auto;
padding: 20px;
}
header {
text-align: center;
margin-bottom: 40px;
padding: 30px 0;
border-bottom: 2px solid var(--azure);
}
h1 {
font-size: 2.5em;
background: linear-gradient(135deg, var(--azure), var(--teal));
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin-bottom: 10px;
}
.subtitle {
color: var(--text-dim);
font-size: 1.1em;
}
.dashboard {
display: none;
}
.dashboard.active {
display: block;
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 25px;
margin: 40px 0;
}
.card {
background: linear-gradient(135deg, rgba(0, 120, 212, 0.1), rgba(0, 183, 195, 0.1));
border: 2px solid var(--azure);
border-radius: 12px;
padding: 30px;
cursor: pointer;
transition: all 0.3s ease;
text-align: center;
}
.card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 30px rgba(0, 120, 212, 0.3);
border-color: var(--teal);
}
.card-icon {
font-size: 3em;
margin-bottom: 15px;
}
.card h3 {
color: var(--azure);
font-size: 1.5em;
margin-bottom: 10px;
}
.card p {
color: var(--text-dim);
font-size: 0.95em;
}
.category-label {
display: inline-block;
margin-top: 10px;
padding: 5px 12px;
background: rgba(0, 120, 212, 0.2);
border-radius: 20px;
font-size: 0.85em;
color: var(--green);
}
.module {
display: none;
}
.module.active {
display: block;
animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.btn-back {
padding: 10px 20px;
background: var(--azure);
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-weight: 600;
margin-bottom: 25px;
transition: all 0.3s ease;
}
.btn-back:hover {
background: var(--teal);
}
.tabs {
display: flex;
gap: 10px;
margin-bottom: 30px;
flex-wrap: wrap;
justify-content: center;
border-bottom: 1px solid rgba(0, 120, 212, 0.2);
padding-bottom: 15px;
overflow-x: auto;
}
.tab-btn {
padding: 10px 20px;
background: var(--surface);
color: var(--text);
border: 2px solid transparent;
border-radius: 6px;
cursor: pointer;
font-size: 0.95em;
transition: all 0.3s ease;
font-weight: 500;
white-space: nowrap;
}
.tab-btn:hover {
background: rgba(0, 120, 212, 0.1);
border-color: var(--azure);
}
.tab-btn.active {
background: var(--azure);
color: white;
border-color: var(--azure);
}
.tab {
display: none;
}
.tab.active {
display: block;
animation: fadeIn 0.3s ease;
}
.section {
background: var(--surface);
border: 1px solid rgba(0, 120, 212, 0.2);
border-radius: 10px;
padding: 30px;
margin-bottom: 25px;
transition: all 0.3s ease;
}
.section:hover {
border-color: var(--azure);
box-shadow: 0 0 20px rgba(0, 120, 212, 0.1);
}
h2 {
color: var(--azure);
font-size: 1.8em;
margin-bottom: 15px;
}
h3 {
color: var(--orange);
font-size: 1.3em;
margin-top: 20px;
margin-bottom: 12px;
}
h4 {
color: var(--green);
font-size: 1.1em;
margin-top: 15px;
margin-bottom: 10px;
}
p {
margin-bottom: 15px;
line-height: 1.8;
}
ul {
margin-left: 20px;
margin-bottom: 15px;
}
ul li {
margin-bottom: 8px;
}
.info-box {
background: rgba(0, 120, 212, 0.08);
border: 1px solid rgba(0, 120, 212, 0.2);
border-radius: 8px;
padding: 20px;
margin: 15px 0;
}
.box-title {
font-weight: bold;
color: var(--azure);
margin-bottom: 10px;
font-size: 1.1em;
}
.box-content {
color: var(--text-dim);
line-height: 1.8;
}
.warning-box {
background: rgba(255, 165, 0, 0.08);
border: 1px solid rgba(255, 165, 0, 0.3);
border-radius: 8px;
padding: 20px;
margin: 15px 0;
}
.warning-box .box-title {
color: var(--yellow);
}
table {
width: 100%;
border-collapse: collapse;
margin: 20px 0;
border-radius: 8px;
overflow: hidden;
}
th,
td {
padding: 12px 16px;
text-align: left;
border-bottom: 1px solid rgba(0, 120, 212, 0.15);
}
th {
background: rgba(0, 120, 212, 0.15);
color: var(--azure);
font-weight: 600;
}
td {
color: var(--text-dim);
}
tr:hover td {
background: rgba(0, 120, 212, 0.05);
}
.code-block {
background: #1e1e2e;
border: 1px solid rgba(0, 120, 212, 0.2);
border-radius: 8px;
padding: 20px;
margin: 15px 0;
font-family: 'Fira Code', 'Consolas', monospace;
font-size: 0.9em;
overflow-x: auto;
color: #cdd6f4;
line-height: 1.6;
}
.code-block .comment {
color: #6c7086;
}
.code-block .keyword {
color: #cba6f7;
}
.code-block .string {
color: #a6e3a1;
}
.code-block .key {
color: #89b4fa;
}
.formula {
background: rgba(0, 120, 212, 0.08);
padding: 20px;
border-radius: 8px;
margin: 15px 0;
border-left: 4px solid var(--azure);
font-family: 'Georgia', serif;
}
.callout {
padding: 20px;
border-radius: 8px;
margin: 15px 0;
border-left: 4px solid;
}
.callout.insight {
background: rgba(0, 255, 136, 0.05);
border-color: var(--green);
}
.callout.insight .callout-title {
color: var(--green);
font-weight: bold;
margin-bottom: 8px;
}
.callout.warning {
background: rgba(255, 165, 0, 0.05);
border-color: var(--yellow);
}
.callout.warning .callout-title {
color: var(--yellow);
font-weight: bold;
margin-bottom: 8px;
}
.pipeline-flow {
display: flex;
align-items: center;
gap: 0;
flex-wrap: wrap;
justify-content: center;
margin: 20px 0;
padding: 20px;
background: rgba(0, 120, 212, 0.05);
border-radius: 12px;
}
.pipeline-stage {
padding: 12px 20px;
border-radius: 8px;
font-weight: 600;
font-size: 0.85em;
text-align: center;
min-width: 100px;
}
.pipeline-arrow {
font-size: 1.5em;
color: var(--azure);
padding: 0 4px;
}
.interview-box {
background: rgba(163, 113, 247, 0.08);
border: 1px solid rgba(163, 113, 247, 0.25);
border-radius: 8px;
padding: 20px;
margin: 15px 0;
}
.interview-box .box-title {
color: #a371f7;
}
@media (max-width: 768px) {
.grid {
grid-template-columns: 1fr;
}
.pipeline-flow {
flex-direction: column;
}
.pipeline-arrow {
transform: rotate(90deg);
}
h1 {
font-size: 1.8em;
}
}
</style>
</head>
<body>
<div class="container">
<!-- Dashboard -->
<div class="dashboard active" id="dashboard">
<header>
<h1>☁️ Azure DevOps & MLOps Masterclass</h1>
<p class="subtitle">CI/CD Pipelines Β· Containers Β· Kubernetes Β· MLOps β€” From Zero to Production</p>
</header>
<div class="grid" id="modulesGrid"></div>
</div>
<!-- Module Container -->
<div id="modulesContainer"></div>
</div>
<script>
const modules = [
{id: "devops-fundamentals", title: "DevOps Fundamentals", icon: "πŸ”„", category: "Foundations", color: "#0078D4", description: "CI/CD concepts, DevOps culture, and the shift to MLOps" },
{id: "azure-setup", title: "Azure DevOps Setup", icon: "βš™οΈ", category: "Foundations", color: "#0078D4", description: "Organizations, Projects, Repos, and Git workflows" },
{id: "infrastructure", title: "Infrastructure & Networking", icon: "🌐", category: "Infrastructure", color: "#00b7c3", description: "VPCs, Security Groups, VMs, and Azure networking" },
{id: "cicd-yaml", title: "CI/CD Pipeline (YAML)", icon: "πŸ“œ", category: "Pipeline", color: "#ff6b35", description: "YAML syntax, Triggers, Variables, Stages, Multi-stage pipelines" },
{id: "build-test", title: "Build & Test", icon: "πŸ§ͺ", category: "Pipeline", color: "#ff6b35", description: "Maven, Unit Tests, SonarQube quality gates, Trivy scanning" },
{id: "docker", title: "Docker & Containers", icon: "🐳", category: "Containers", color: "#2496ED", description: "Dockerfile, Build, Push to ACR, Image scanning" },
{id: "kubernetes", title: "Kubernetes & AKS", icon: "☸️", category: "Orchestration", color: "#326CE5", description: "AKS setup, Deployments, Services, Manifests, Helm" },
{id: "security", title: "Service Connections & Security", icon: "πŸ”", category: "Security", color: "#e74c3c", description: "Service Principals, RBAC, Key Vault, PAT tokens" },
{id: "mlops", title: "MLOps Pipeline", icon: "πŸ€–", category: "MLOps", color: "#a371f7", description: "ML lifecycle, Model versioning, Data drift, CT/CI/CD for ML" },
{id: "monitoring", title: "Monitoring & Automation", icon: "πŸ“Š", category: "Operations", color: "#2ecc71", description: "Deployment verification, Pipeline automation, Notifications" }
];
const MODULE_CONTENT = {
"devops-fundamentals": {
concepts: `
<h3>What is DevOps?</h3>
<p>DevOps is a <strong>cultural and technical movement</strong> that unifies software development (Dev) and IT operations (Ops). It aims to shorten the software development lifecycle, deliver high-quality software continuously, and create a feedback loop between development and production.</p>
<div class="pipeline-flow">
<div class="pipeline-stage" style="background: rgba(0,120,212,0.2); color: #0078D4;">Plan</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(0,183,195,0.2); color: #00b7c3;">Code</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(255,107,53,0.2); color: #ff6b35;">Build</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(0,255,136,0.2); color: #00ff88;">Test</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(163,113,247,0.2); color: #a371f7;">Release</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(46,204,113,0.2); color: #2ecc71;">Deploy</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(255,165,0,0.2); color: #ffa500;">Operate</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(231,76,60,0.2); color: #e74c3c;">Monitor</div>
</div>
<h3>CI/CD β€” The Heart of DevOps</h3>
<table>
<tr><th>Concept</th><th>What It Does</th><th>Tools</th><th>Key Metric</th></tr>
<tr><td><strong>Continuous Integration (CI)</strong></td><td>Automatically build & test code on every commit</td><td>Azure Pipelines, Jenkins, GitHub Actions</td><td>Build success rate</td></tr>
<tr><td><strong>Continuous Delivery (CD)</strong></td><td>Automatically deploy to staging after tests pass</td><td>Azure Pipelines, ArgoCD, Spinnaker</td><td>Lead time for changes</td></tr>
<tr><td><strong>Continuous Deployment</strong></td><td>Auto-deploy to production (no manual gate)</td><td>Azure DevOps + approvals removed</td><td>Deployment frequency</td></tr>
<tr><td><strong>Continuous Testing (CT)</strong></td><td>Automated tests at every stage of the pipeline</td><td>Selenium, pytest, JUnit</td><td>Test pass rate</td></tr>
</table>
<h3>DevOps vs MLOps vs DataOps vs GitOps</h3>
<table>
<tr><th>Aspect</th><th>DevOps</th><th>MLOps</th><th>DataOps</th><th>GitOps</th></tr>
<tr><td>What ships?</td><td>Code β†’ App</td><td>Code + Data + Model</td><td>Data pipelines</td><td>Declarative configs</td></tr>
<tr><td>Testing</td><td>Unit / Integration / E2E</td><td>+ Data & Model validation</td><td>Data quality checks</td><td>Policy checks</td></tr>
<tr><td>Versioning</td><td>Code (Git)</td><td>Code + Data + Model</td><td>Schema + Pipeline</td><td>Git as single source</td></tr>
<tr><td>Monitoring</td><td>Latency, Errors, CPU</td><td>+ Data/Model drift</td><td>Data freshness, quality</td><td>Drift detection</td></tr>
<tr><td>Trigger</td><td>Code push</td><td>Code push + Data change</td><td>Schedule + events</td><td>Git commit</td></tr>
</table>
<h3>DevOps Principles β€” CALMS Framework</h3>
<div class="info-box">
<div class="box-title">🎯 CALMS Framework</div>
<div class="box-content">
<strong>C</strong> β€” Culture: Break silos between Dev and Ops. Shared responsibility for production.<br>
<strong>A</strong> β€” Automation: Automate everything β€” builds, tests, deployments, infrastructure provisioning.<br>
<strong>L</strong> β€” Lean: Eliminate waste, small batch sizes. Inspired by Toyota Production System.<br>
<strong>M</strong> β€” Measurement: Measure everything using DORA metrics. Data-driven decisions.<br>
<strong>S</strong> β€” Sharing: Share knowledge, feedback loops, blameless postmortems.
</div>
</div>
<h3>The 12-Factor App Methodology</h3>
<p>A methodology for building modern, cloud-native, scalable applications β€” the foundation of DevOps-friendly software:</p>
<table>
<tr><th>#</th><th>Factor</th><th>Principle</th><th>DevOps Impact</th></tr>
<tr><td>1</td><td>Codebase</td><td>One codebase in version control</td><td>Single Git repo per service</td></tr>
<tr><td>2</td><td>Dependencies</td><td>Explicitly declare dependencies</td><td>pom.xml, requirements.txt, package.json</td></tr>
<tr><td>3</td><td>Config</td><td>Store config in environment variables</td><td>Azure Key Vault, ConfigMaps</td></tr>
<tr><td>4</td><td>Backing Services</td><td>Treat databases as attached resources</td><td>Connection strings via env vars</td></tr>
<tr><td>5</td><td>Build, Release, Run</td><td>Strict separation of stages</td><td>CI/CD pipeline stages</td></tr>
<tr><td>6</td><td>Processes</td><td>Stateless processes</td><td>Enables horizontal scaling</td></tr>
<tr><td>7</td><td>Port Binding</td><td>Export services via port binding</td><td>Containerized services</td></tr>
<tr><td>8</td><td>Concurrency</td><td>Scale via process model</td><td>K8s replica sets</td></tr>
<tr><td>9</td><td>Disposability</td><td>Fast startup, graceful shutdown</td><td>Health checks, readiness probes</td></tr>
<tr><td>10</td><td>Dev/Prod Parity</td><td>Keep environments similar</td><td>Docker + IaC ensures parity</td></tr>
<tr><td>11</td><td>Logs</td><td>Treat logs as event streams</td><td>Azure Monitor, Log Analytics</td></tr>
<tr><td>12</td><td>Admin Processes</td><td>Run admin tasks as one-off processes</td><td>K8s Jobs, Azure Functions</td></tr>
</table>
<h3>SRE vs DevOps β€” Key Differences</h3>
<table>
<tr><th>Aspect</th><th>DevOps</th><th>SRE (Site Reliability Engineering)</th></tr>
<tr><td>Origin</td><td>Industry movement</td><td>Google (2003)</td></tr>
<tr><td>Focus</td><td>Culture + Automation</td><td>Reliability + Engineering</td></tr>
<tr><td>Error Budget</td><td>Not formalized</td><td>Core concept: 100% - SLO = error budget</td></tr>
<tr><td>Toil</td><td>Reduce manual work</td><td>Max 50% toil, rest = engineering</td></tr>
<tr><td>On-Call</td><td>Varies</td><td>Structured rotation with blameless postmortems</td></tr>
<tr><td>Relationship</td><td colspan="2">SRE implements DevOps principles with concrete practices</td></tr>
</table>
<h3>DevSecOps β€” Shift-Left Security</h3>
<div class="callout warning">
<div class="callout-title">⚠️ Why DevSecOps Matters</div>
<strong>Cost of fixing vulnerabilities:</strong><br>
β€’ Design phase: $1x<br>
β€’ Development: $6.5x<br>
β€’ Testing: $15x<br>
β€’ Production: $100x<br><br>
DevSecOps integrates security at every stage, not as a final gate.
</div>
<div class="pipeline-flow">
<div class="pipeline-stage" style="background: rgba(231,76,60,0.2); color: #e74c3c;">Threat Model</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(0,120,212,0.2); color: #0078D4;">SAST</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(0,183,195,0.2); color: #00b7c3;">SCA</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(255,107,53,0.2); color: #ff6b35;">Container Scan</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(163,113,247,0.2); color: #a371f7;">DAST</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(46,204,113,0.2); color: #2ecc71;">Runtime Protection</div>
</div>
<h3>Deployment Strategies Deep Dive</h3>
<table>
<tr><th>Strategy</th><th>How It Works</th><th>Downtime</th><th>Rollback</th><th>Risk</th><th>Best For</th></tr>
<tr><td><strong>Rolling Update</strong></td><td>Gradually replace old pods</td><td>Zero</td><td>Slow</td><td>Low</td><td>Standard deployments</td></tr>
<tr><td><strong>Blue-Green</strong></td><td>Two identical environments, switch traffic</td><td>Zero</td><td>Instant</td><td>Very Low</td><td>Mission-critical apps</td></tr>
<tr><td><strong>Canary</strong></td><td>Route small % to new version</td><td>Zero</td><td>Fast</td><td>Low</td><td>Feature validation</td></tr>
<tr><td><strong>A/B Testing</strong></td><td>Route by user segments</td><td>Zero</td><td>Fast</td><td>Low</td><td>UX experiments</td></tr>
<tr><td><strong>Shadow/Dark</strong></td><td>Mirror prod traffic to new version</td><td>Zero</td><td>N/A</td><td>Very Low</td><td>Performance testing</td></tr>
<tr><td><strong>Recreate</strong></td><td>Kill all old, create new</td><td>Yes</td><td>Slow</td><td>High</td><td>Dev/test only</td></tr>
</table>
`,
handson: `
<h3>DORA Metrics β€” Measuring DevOps Performance</h3>
<table>
<tr><th>Metric</th><th>Elite</th><th>High</th><th>Medium</th><th>Low</th></tr>
<tr><td>Deployment Frequency</td><td>Multiple/day</td><td>Weekly</td><td>Monthly</td><td>Months</td></tr>
<tr><td>Lead Time for Changes</td><td>< 1 hour</td><td>< 1 week</td><td>< 1 month</td><td>> 6 months</td></tr>
<tr><td>Change Failure Rate</td><td>0-15%</td><td>16-30%</td><td>16-30%</td><td>46-60%</td></tr>
<tr><td>Time to Restore</td><td>< 1 hour</td><td>< 1 day</td><td>< 1 week</td><td>> 6 months</td></tr>
</table>
<div class="callout insight">
<div class="callout-title">πŸ’‘ DORA + SPACE Framework</div>
Google's DORA metrics measure team delivery. GitHub's SPACE framework adds developer experience:<br>
<strong>S</strong>atisfaction, <strong>P</strong>erformance, <strong>A</strong>ctivity, <strong>C</strong>ommunication, <strong>E</strong>fficiency.<br>
Together, they provide a complete view of engineering productivity.
</div>
<h3>Shift-Left Testing</h3>
<p>Move testing earlier in the development lifecycle:</p>
<div class="code-block">
<span class="comment"># Traditional: Test late (expensive to fix)</span>
Code β†’ Code β†’ Code β†’ <span class="keyword">TEST</span> β†’ Fix β†’ Fix β†’ Deploy
<span class="comment"># Shift-Left: Test early (cheap to fix)</span>
Code β†’ <span class="keyword">TEST</span> β†’ Code β†’ <span class="keyword">TEST</span> β†’ Code β†’ <span class="keyword">TEST</span> β†’ Deploy
<span class="comment"># Test Pyramid (bottom = more, faster, cheaper)</span>
/ E2E \\ ← Few, slow, expensive
/ Integration \\ ← Moderate
/ Unit Tests \\ ← Many, fast, cheap
/ Static Analysis \\ ← Instant (linters, SAST)
</div>
<h3>Infrastructure as Code (IaC) β€” Terraform vs Bicep</h3>
<table>
<tr><th>Feature</th><th>Terraform</th><th>Bicep (Azure-native)</th><th>ARM Templates</th></tr>
<tr><td>Multi-cloud</td><td>βœ… Yes</td><td>❌ Azure only</td><td>❌ Azure only</td></tr>
<tr><td>State Management</td><td>Required (tfstate)</td><td>Not needed</td><td>Not needed</td></tr>
<tr><td>Readability</td><td>Good (HCL)</td><td>Excellent</td><td>Very verbose (JSON)</td></tr>
<tr><td>Learning Curve</td><td>Moderate</td><td>Low</td><td>High</td></tr>
<tr><td>Community</td><td>Very large</td><td>Growing</td><td>Legacy</td></tr>
</table>
<div class="code-block">
<span class="comment"># Terraform example β€” Azure Resource Group</span>
<span class="keyword">resource</span> <span class="string">"azurerm_resource_group"</span> <span class="string">"example"</span> {
<span class="key">name</span> = <span class="string">"rg-devops-prod"</span>
<span class="key">location</span> = <span class="string">"East US"</span>
<span class="key">tags</span> = {
<span class="key">environment</span> = <span class="string">"production"</span>
<span class="key">managed_by</span> = <span class="string">"terraform"</span>
}
}
<span class="comment"># Bicep equivalent β€” much cleaner!</span>
<span class="keyword">resource</span> rg <span class="string">'Microsoft.Resources/resourceGroups@2021-04-01'</span> = {
<span class="key">name</span>: <span class="string">'rg-devops-prod'</span>
<span class="key">location</span>: <span class="string">'eastus'</span>
<span class="key">tags</span>: {
<span class="key">environment</span>: <span class="string">'production'</span>
<span class="key">managed_by</span>: <span class="string">'bicep'</span>
}
}
</div>
<div class="callout insight">
<div class="callout-title">πŸ’‘ IaC Benefits</div>
<strong>Repeatability</strong> β€” Same infra every time<br>
<strong>Version Control</strong> β€” Track changes in Git<br>
<strong>Audit Trail</strong> β€” Who changed what and when<br>
<strong>Self-Documentation</strong> β€” Infra IS the documentation<br>
<strong>Blast Radius</strong> β€” Preview changes with <code>terraform plan</code> before applying
</div>
<h3>GitOps Workflow</h3>
<div class="code-block">
<span class="comment"># GitOps: Git is the single source of truth for infrastructure</span>
<span class="comment"># 1. Developer pushes change to Git</span>
<span class="keyword">git</span> commit -m <span class="string">"Update replicas to 5"</span>
<span class="keyword">git</span> push origin main
<span class="comment"># 2. GitOps operator (ArgoCD/Flux) detects change</span>
<span class="comment"># 3. Operator applies change to Kubernetes cluster</span>
<span class="comment"># 4. If cluster state drifts, operator auto-corrects</span>
<span class="comment"># ArgoCD Application Manifest</span>
<span class="key">apiVersion</span>: argoproj.io/v1alpha1
<span class="key">kind</span>: Application
<span class="key">metadata</span>:
<span class="key">name</span>: bankapp
<span class="key">spec</span>:
<span class="key">source</span>:
<span class="key">repoURL</span>: <span class="string">'https://dev.azure.com/org/project/_git/manifests'</span>
<span class="key">path</span>: <span class="string">'k8s/'</span>
<span class="key">destination</span>:
<span class="key">server</span>: <span class="string">'https://kubernetes.default.svc'</span>
<span class="key">namespace</span>: <span class="string">'production'</span>
<span class="key">syncPolicy</span>:
<span class="key">automated</span>:
<span class="key">prune</span>: true
<span class="key">selfHeal</span>: true
</div>
`,
applications: `
<h3>Real-World Applications</h3>
<div class="info-box">
<div class="box-title">🏒 Industry Use Cases</div>
<div class="box-content">
<strong>Netflix:</strong> 1000+ deployments/day using CI/CD, canary releases, and Chaos Engineering<br>
<strong>Amazon:</strong> Deploys every 11.7 seconds on average. Microservices architecture since 2002.<br>
<strong>Google:</strong> Pioneered SRE. Manages billions of containers weekly with Borg/Kubernetes.<br>
<strong>Spotify:</strong> "Squad" model for autonomous DevOps teams. Each squad owns their full stack.<br>
<strong>Microsoft:</strong> Azure DevOps used internally for all products. 80,000+ engineers on one monorepo.<br>
<strong>Etsy:</strong> Pioneered continuous deployment in 2010. Deploys 50+ times/day.
</div>
</div>
<h3>Value Stream Mapping</h3>
<div class="info-box">
<div class="box-title">πŸ—ΊοΈ Identify Bottlenecks in Your Delivery Pipeline</div>
<div class="box-content">
Value Stream Mapping (VSM) visualizes the flow of work from idea to production:<br><br>
<strong>Step 1:</strong> Map every step from idea β†’ code β†’ build β†’ test β†’ deploy β†’ monitor<br>
<strong>Step 2:</strong> Measure lead time (total time) and process time (active work) for each step<br>
<strong>Step 3:</strong> Calculate % value-add vs wait time<br>
<strong>Step 4:</strong> Eliminate or automate non-value-add steps<br><br>
<strong>Typical finding:</strong> 80% of lead time is waiting (approvals, handoffs, queues). Only 20% is active work.
</div>
</div>
<div class="interview-box">
<div class="box-title">πŸ“‹ Interview Questions & Answers</div>
<div class="box-content">
<strong>1. What is DevOps and why is it important?</strong><br>
DevOps unifies Dev and Ops to shorten delivery cycles, increase deployment frequency, and improve reliability. It's a cultural shift + automation practices. Key benefits: faster TTM, fewer failures, faster recovery.<br><br>
<strong>2. Explain CI vs CD (Delivery) vs CD (Deployment).</strong><br>
CI = auto build+test on every commit. Continuous Delivery = auto deploy to staging (manual prod gate). Continuous Deployment = auto deploy to production (no manual gate). Each builds on the previous.<br><br>
<strong>3. What are DORA metrics and why do they matter?</strong><br>
Four metrics from Google's research: Deployment Frequency, Lead Time for Changes, Change Failure Rate, Time to Restore. They correlate with organizational performance. Elite = multiple deploys/day, <1hr lead time.<br><br>
<strong>4. How does DevOps differ from MLOps?</strong><br>
MLOps adds data versioning, model versioning, experiment tracking, data drift detection, and continuous training. ML has more axes of change β€” code, data, model, hyperparameters β€” making it more complex.<br><br>
<strong>5. What is Shift-Left testing?</strong><br>
Move testing earlier in the lifecycle. Includes static analysis in IDE, pre-commit hooks, CI-level unit tests, and security scanning before deployment. Catches bugs when they're cheapest to fix.<br><br>
<strong>6. Explain Infrastructure as Code (IaC) and its benefits.</strong><br>
Define infrastructure in code files (Terraform, Bicep, ARM). Benefits: repeatability, version control, peer review, audit trail, self-documentation. Enables GitOps where Git is the source of truth.<br><br>
<strong>7. What is the CALMS framework?</strong><br>
Culture (break silos), Automation (CI/CD, IaC), Lean (small batches), Measurement (DORA metrics), Sharing (knowledge, postmortems). It's a maturity model for assessing DevOps adoption.<br><br>
<strong>8. Explain Blue-Green vs Canary deployments.</strong><br>
Blue-Green: two identical environments, switch 100% traffic at once. Instant rollback by switching back. Canary: gradually increase traffic (1% β†’ 5% β†’ 25% β†’ 100%). Lower risk but slower rollout.<br><br>
<strong>9. What is GitOps?</strong><br>
Git as the single source of truth for infrastructure. An operator (ArgoCD/Flux) watches Git repos and auto-applies changes to clusters. If cluster drifts, operator auto-corrects. Declarative, auditable, reversible.<br><br>
<strong>10. What is the 12-Factor App methodology?</strong><br>
12 principles for building cloud-native apps: single codebase, explicit dependencies, config in env vars, backing services as resources, strict build/release/run stages, stateless processes, port binding, concurrency, disposability, dev/prod parity, logs as streams, admin tasks as one-off processes.<br><br>
<strong>11. What is SRE and how does it relate to DevOps?</strong><br>
SRE (Site Reliability Engineering) is Google's implementation of DevOps principles. Key concepts: SLOs (reliability targets), error budgets (100% - SLO = room for innovation), toil reduction (max 50%), blameless postmortems.<br><br>
<strong>12. What is DevSecOps?</strong><br>
Integrating security at every stage of the DevOps pipeline: threat modeling in design, SAST in CI, SCA for dependencies, container scanning, DAST in staging, runtime protection in production. "Security is everyone's responsibility."<br><br>
<strong>13. How do you measure DevOps maturity?</strong><br>
Use DORA metrics as baseline. Assess: automation level (manual β†’ partial β†’ full), deployment frequency, test coverage, IaC adoption, monitoring coverage, incident response time, cultural adoption (blameless postmortems, shared ownership).<br><br>
<strong>14. What is Value Stream Mapping?</strong><br>
VSM visualizes the flow from idea to production, measuring lead time vs process time at each step. Typically reveals 80% of lead time is waiting (approvals, handoffs). Used to identify and eliminate bottlenecks.<br><br>
<strong>15. Explain the concept of "Toil" in SRE.</strong><br>
Toil is manual, repetitive, automatable operational work that scales linearly with service size. Google mandates no more than 50% toil β€” the rest should be engineering work to eliminate toil. Examples: manual deployments, alert handling, capacity planning.
</div>
</div>
`
},
"azure-setup": {
concepts: `
<h3>Azure DevOps β€” The Complete Platform</h3>
<p>Azure DevOps is Microsoft's end-to-end DevOps platform. It provides 5 integrated services that cover the entire software development lifecycle.</p>
<table>
<tr><th>Service</th><th>Purpose</th><th>Equivalent</th><th>Key Features</th></tr>
<tr><td><strong>Azure Boards</strong></td><td>Work tracking, Kanban, Sprints</td><td>Jira, Trello</td><td>Epics, Features, Stories, Bugs, Sprints, Burndown charts</td></tr>
<tr><td><strong>Azure Repos</strong></td><td>Git repositories</td><td>GitHub, GitLab</td><td>Branch policies, PR reviews, TFVC support</td></tr>
<tr><td><strong>Azure Pipelines</strong></td><td>CI/CD automation</td><td>Jenkins, GitHub Actions</td><td>YAML + Classic, multi-stage, 1800+ tasks</td></tr>
<tr><td><strong>Azure Test Plans</strong></td><td>Manual & automated testing</td><td>TestRail</td><td>Test suites, exploratory testing, traceability</td></tr>
<tr><td><strong>Azure Artifacts</strong></td><td>Package management</td><td>Nexus, JFrog</td><td>npm, Maven, NuGet, Python, Universal packages</td></tr>
</table>
<h3>Project Hierarchy & Governance</h3>
<div class="info-box">
<div class="box-title">πŸ“ Azure DevOps Hierarchy</div>
<div class="box-content">
<strong>Organization</strong> (top level β€” company or business unit)<br>
&nbsp;&nbsp;β”œβ”€β”€ <strong>Project 1</strong> (team/product β€” e.g., "Multi-Tier Application")<br>
&nbsp;&nbsp;β”‚&nbsp;&nbsp;&nbsp;β”œβ”€β”€ <strong>Repos</strong> (multiple repos per project)<br>
&nbsp;&nbsp;β”‚&nbsp;&nbsp;&nbsp;β”œβ”€β”€ <strong>Pipelines</strong> (CI/CD definitions)<br>
&nbsp;&nbsp;β”‚&nbsp;&nbsp;&nbsp;β”œβ”€β”€ <strong>Boards</strong> (work items, sprints, Kanban)<br>
&nbsp;&nbsp;β”‚&nbsp;&nbsp;&nbsp;β”œβ”€β”€ <strong>Test Plans</strong> (test suites)<br>
&nbsp;&nbsp;β”‚&nbsp;&nbsp;&nbsp;└── <strong>Artifacts</strong> (packages)<br>
&nbsp;&nbsp;└── <strong>Project 2</strong> (another team/product)
</div>
</div>
<h3>Setting Up Azure DevOps</h3>
<div class="info-box">
<div class="box-title">πŸš€ Setup Flow</div>
<div class="box-content">
<strong>Step 1:</strong> Go to portal.azure.com β†’ Search "Azure DevOps Organization"<br>
<strong>Step 2:</strong> Click "Create new Organization" β†’ Name it (e.g., "myorgforyaml")<br>
<strong>Step 3:</strong> Create a Project (e.g., "Multi-Tier Application")<br>
<strong>Step 4:</strong> Set visibility (Private recommended for enterprise)<br>
<strong>Step 5:</strong> Azure Repos is automatically created with the project<br>
<strong>Step 6:</strong> Configure process template (Agile, Scrum, or CMMI)
</div>
</div>
<h3>Process Templates β€” Agile vs Scrum vs CMMI</h3>
<table>
<tr><th>Template</th><th>Work Item Types</th><th>Best For</th><th>Key Difference</th></tr>
<tr><td><strong>Agile</strong></td><td>Epic β†’ Feature β†’ User Story β†’ Task</td><td>Most teams</td><td>Flexible, user story focused</td></tr>
<tr><td><strong>Scrum</strong></td><td>Epic β†’ Feature β†’ PBI β†’ Task</td><td>Scrum teams</td><td>Sprint-focused with burndown</td></tr>
<tr><td><strong>CMMI</strong></td><td>Epic β†’ Feature β†’ Requirement β†’ Task</td><td>Regulated industries</td><td>Formal change management</td></tr>
<tr><td><strong>Basic</strong></td><td>Epic β†’ Issue β†’ Task</td><td>Simple projects</td><td>Minimal overhead</td></tr>
</table>
<h3>Branching Strategies</h3>
<table>
<tr><th>Strategy</th><th>Best For</th><th>Branches</th><th>Release Cadence</th></tr>
<tr><td><strong>Trunk-Based</strong></td><td>Small teams, fast releases</td><td>main + short-lived feature branches</td><td>Multiple/day</td></tr>
<tr><td><strong>GitFlow</strong></td><td>Scheduled releases</td><td>main, develop, feature/*, release/*, hotfix/*</td><td>Weekly/Monthly</td></tr>
<tr><td><strong>GitHub Flow</strong></td><td>Continuous deployment</td><td>main + feature branches + PRs</td><td>Multiple/day</td></tr>
<tr><td><strong>Release Flow</strong></td><td>Large teams (Microsoft uses this)</td><td>main + topic branches + release/*</td><td>Scheduled sprints</td></tr>
</table>
<div class="callout insight">
<div class="callout-title">πŸ’‘ Microsoft's Recommendation</div>
For most teams, <strong>Trunk-Based Development</strong> with short-lived feature branches is the best strategy. It reduces merge conflicts, enables CI, and aligns with DORA's findings that trunk-based development correlates with elite performance.
</div>
<h3>Azure DevOps CLI & REST API</h3>
<div class="info-box">
<div class="box-title">πŸ”§ Automation Beyond the UI</div>
<div class="box-content">
<strong>Azure DevOps CLI:</strong> <code>az devops</code> extension for managing projects, repos, pipelines from terminal<br>
<strong>REST API:</strong> Full programmatic access to all Azure DevOps services<br>
<strong>Service Hooks:</strong> Webhooks to integrate with Slack, Teams, Jenkins, etc.<br>
<strong>Azure DevOps Extensions:</strong> 1000+ marketplace extensions for custom functionality
</div>
</div>
`,
handson: `
<h3>Uploading Code to Azure Repos</h3>
<div class="code-block">
<span class="comment"># Step 1: Initialize local repo</span>
<span class="keyword">git</span> init
<span class="comment"># Step 2: Stage all files</span>
<span class="keyword">git</span> add .
<span class="comment"># Step 3: Commit</span>
<span class="keyword">git</span> commit -m <span class="string">"Initial commit"</span>
<span class="comment"># Step 4: Switch to main branch</span>
<span class="keyword">git</span> branch -M main
<span class="comment"># Step 5: Add Azure remote and push</span>
<span class="keyword">git</span> remote add origin https://myorg@dev.azure.com/myorg/Project/_git/Project
<span class="keyword">git</span> push -u origin --all
</div>
<h3>Branch Policies (Best Practice)</h3>
<div class="code-block">
<span class="comment"># Recommended branch policies for 'main':</span>
βœ… Require pull request reviews (min 1 reviewer)
βœ… Check for linked work items
βœ… Build validation (CI must pass)
βœ… Comment resolution required
βœ… Limit merge types (squash merge preferred)
βœ… Automatic reviewers for critical paths
βœ… Status checks (SonarQube quality gate)
</div>
<h3>Azure DevOps CLI</h3>
<div class="code-block">
<span class="comment"># Install Azure DevOps CLI extension</span>
<span class="keyword">az</span> extension add --name azure-devops
<span class="comment"># Configure default organization and project</span>
<span class="keyword">az</span> devops configure --defaults organization=https://dev.azure.com/myorg project=MyProject
<span class="comment"># Create a new project</span>
<span class="keyword">az</span> devops project create --name <span class="string">"NewProject"</span> --visibility private
<span class="comment"># List all repos in a project</span>
<span class="keyword">az</span> repos list --output table
<span class="comment"># Create a pull request</span>
<span class="keyword">az</span> repos pr create \\
--repository MyRepo \\
--source-branch feature/new-feature \\
--target-branch main \\
--title <span class="string">"Add new feature"</span> \\
--description <span class="string">"Implements user authentication"</span>
<span class="comment"># List pipelines</span>
<span class="keyword">az</span> pipelines list --output table
<span class="comment"># Run a pipeline</span>
<span class="keyword">az</span> pipelines run --name <span class="string">"CI-Pipeline"</span> --branch main
</div>
<h3>REST API Examples</h3>
<div class="code-block">
<span class="comment"># List all projects in an organization</span>
<span class="keyword">curl</span> -u :$(PAT) \\
<span class="string">"https://dev.azure.com/{org}/_apis/projects?api-version=7.0"</span>
<span class="comment"># Queue a pipeline run via REST API</span>
<span class="keyword">curl</span> -X POST \\
-u :$(PAT) \\
-H <span class="string">"Content-Type: application/json"</span> \\
-d <span class="string">'{"definition":{"id":1},"sourceBranch":"refs/heads/main"}'</span> \\
<span class="string">"https://dev.azure.com/{org}/{project}/_apis/build/builds?api-version=7.0"</span>
<span class="comment"># Create a work item</span>
<span class="keyword">curl</span> -X POST \\
-u :$(PAT) \\
-H <span class="string">"Content-Type: application/json-patch+json"</span> \\
-d <span class="string">'[{"op":"add","path":"/fields/System.Title","value":"New Bug"}]'</span> \\
<span class="string">"https://dev.azure.com/{org}/{project}/_apis/wit/workitems/$Bug?api-version=7.0"</span>
</div>
<h3>Azure Boards β€” Agile Configuration</h3>
<div class="info-box">
<div class="box-title">πŸ“‹ Sprint Setup Checklist</div>
<div class="box-content">
<strong>1.</strong> Define iteration paths (Sprint 1, Sprint 2, etc.)<br>
<strong>2.</strong> Set sprint dates and capacity for each team member<br>
<strong>3.</strong> Create backlog items (User Stories / PBIs)<br>
<strong>4.</strong> Break stories into tasks with estimates<br>
<strong>5.</strong> Use Kanban board for daily standups<br>
<strong>6.</strong> Track burndown chart for sprint health<br>
<strong>7.</strong> Link work items to commits and PRs for traceability
</div>
</div>
`,
applications: `
<h3>Azure DevOps vs GitHub β€” Decision Matrix</h3>
<table>
<tr><th>Feature</th><th>Azure DevOps</th><th>GitHub</th><th>Winner</th></tr>
<tr><td>CI/CD</td><td>Azure Pipelines (YAML + Classic)</td><td>GitHub Actions</td><td>Azure (more mature)</td></tr>
<tr><td>Work Tracking</td><td>Azure Boards (enterprise-grade)</td><td>GitHub Issues + Projects</td><td>Azure (enterprise)</td></tr>
<tr><td>Packages</td><td>Azure Artifacts (npm, Maven, NuGet, Python)</td><td>GitHub Packages</td><td>Tie</td></tr>
<tr><td>Security</td><td>Advanced Security, RBAC</td><td>Dependabot, Code Scanning</td><td>GitHub (Copilot)</td></tr>
<tr><td>Community</td><td>Enterprise-focused</td><td>Largest open-source community</td><td>GitHub</td></tr>
<tr><td>Best For</td><td>Enterprise, Azure-heavy orgs</td><td>Open source, startups</td><td>Depends on context</td></tr>
</table>
<h3>Enterprise Governance Patterns</h3>
<div class="info-box">
<div class="box-title">🏒 Multi-Team Organization</div>
<div class="box-content">
<strong>Pattern 1: One Project per Team</strong> β€” Full isolation, separate backlogs. Best for independent teams.<br>
<strong>Pattern 2: One Project, Multiple Repos</strong> β€” Shared boards, separate code. Best for related services.<br>
<strong>Pattern 3: Monorepo</strong> β€” All code in one repo with path-based pipelines. Best for tight coupling.<br><br>
<strong>Microsoft's recommendation:</strong> Start with fewer projects. Use area paths and teams within a project for organization. Only split projects when teams need true independence.
</div>
</div>
<div class="interview-box">
<div class="box-title">πŸ“‹ Interview Questions & Answers</div>
<div class="box-content">
<strong>1. What are the 5 main services in Azure DevOps?</strong><br>
Azure Boards (work tracking), Azure Repos (Git), Azure Pipelines (CI/CD), Azure Test Plans (testing), Azure Artifacts (packages). Each can be used independently or together.<br><br>
<strong>2. How do you set up an Azure DevOps Organization?</strong><br>
Go to dev.azure.com β†’ Create organization β†’ Create project β†’ Choose process template (Agile/Scrum/CMMI) β†’ Set visibility. Each org gets 1 free parallel job + 1800 CI/CD minutes/month.<br><br>
<strong>3. Azure Repos vs GitHub β€” when to use which?</strong><br>
Azure Repos for enterprise teams heavily invested in Azure, needing Azure Boards integration. GitHub for open-source, community, GitHub Copilot, and when using GitHub Actions. Many large orgs use both.<br><br>
<strong>4. Explain Trunk-Based vs GitFlow.</strong><br>
Trunk-Based: short-lived branches merged to main frequently. Fast CI, less merge conflicts. GitFlow: long-lived develop branch, release branches. Better for scheduled releases. DORA research shows trunk-based correlates with higher performance.<br><br>
<strong>5. What are Branch Policies?</strong><br>
Rules enforced on branches: required reviewers, build validation, linked work items, comment resolution, merge type restrictions. They prevent direct pushes and ensure code quality on protected branches.<br><br>
<strong>6. How do you push code to Azure Repos using Git CLI?</strong><br>
git init β†’ git add . β†’ git commit β†’ git branch -M main β†’ git remote add origin [Azure URL] β†’ git push -u origin --all. Authenticate with PAT or SSH key.<br><br>
<strong>7. What is a PAT and when is it needed?</strong><br>
Personal Access Token β€” an alternative to passwords for Azure DevOps authentication. Used for Git operations, REST API calls, and CI/CD. Should have minimum scopes and short expiration. Prefer Managed Identity when possible.<br><br>
<strong>8. What Azure DevOps process templates are available?</strong><br>
Agile (User Stories), Scrum (PBIs), CMMI (Requirements β€” for regulated industries), Basic (simple Issues). Each defines different work item types, workflows, and board layouts.<br><br>
<strong>9. How do you automate Azure DevOps with CLI?</strong><br>
Install az devops extension. Configure defaults with az devops configure. Then use az repos, az pipelines, az boards commands for creating PRs, running pipelines, managing work items programmatically.<br><br>
<strong>10. Explain Azure DevOps REST API use cases.</strong><br>
Programmatic access to all services: queue builds, create work items, manage repos, query analytics. Useful for custom dashboards, cross-tool integration, automated governance, and audit reporting.<br><br>
<strong>11. How do you manage access control in Azure DevOps?</strong><br>
Three levels: Organization (security groups), Project (teams + groups), Repository (branch policies). Built-in groups: Project Admins, Contributors, Readers. Support Azure AD integration for SSO and conditional access.<br><br>
<strong>12. What is Azure Artifacts and when would you use it?</strong><br>
Private package registry supporting npm, Maven, NuGet, Python, Universal packages. Use when: sharing libraries across teams, caching upstream packages (proxy), ensuring reproducible builds, managing internal dependencies.
</div>
</div>
`
},
"infrastructure": {
concepts: `
<h3>Azure Networking for DevOps</h3>
<p>Before deploying applications, you need a <strong>secure network environment</strong>. The project sets up isolated networking so no outside entity can access resources directly.</p>
<table>
<tr><th>Component</th><th>Purpose</th><th>Azure Equivalent</th><th>AWS Equivalent</th></tr>
<tr><td><strong>VPC / VNet</strong></td><td>Isolated virtual network</td><td>Azure Virtual Network</td><td>AWS VPC</td></tr>
<tr><td><strong>Subnet</strong></td><td>Segment within a VNet</td><td>Subnet</td><td>Subnet</td></tr>
<tr><td><strong>Security Group</strong></td><td>Firewall rules for VMs</td><td>Network Security Group (NSG)</td><td>Security Group</td></tr>
<tr><td><strong>NAT Gateway</strong></td><td>Outbound internet for private subnets</td><td>Azure NAT Gateway</td><td>NAT Gateway</td></tr>
<tr><td><strong>Load Balancer</strong></td><td>Distribute traffic across VMs</td><td>Azure Load Balancer / App Gateway</td><td>ALB / NLB</td></tr>
<tr><td><strong>Private Link</strong></td><td>Private access to PaaS services</td><td>Azure Private Endpoint</td><td>AWS PrivateLink</td></tr>
<tr><td><strong>DNS</strong></td><td>Name resolution</td><td>Azure DNS / Private DNS Zone</td><td>Route 53</td></tr>
</table>
<h3>Azure Landing Zones</h3>
<div class="info-box">
<div class="box-title">πŸ—οΈ Enterprise-Scale Architecture</div>
<div class="box-content">
Azure Landing Zones are a set of reference architectures for setting up multi-subscription Azure environments:<br><br>
<strong>Management Group:</strong> Top-level governance container<br>
&nbsp;&nbsp;β”œβ”€β”€ <strong>Platform</strong> (shared services: identity, management, connectivity)<br>
&nbsp;&nbsp;β”‚&nbsp;&nbsp;&nbsp;β”œβ”€β”€ Identity (Azure AD, DNS)<br>
&nbsp;&nbsp;β”‚&nbsp;&nbsp;&nbsp;β”œβ”€β”€ Management (monitoring, automation)<br>
&nbsp;&nbsp;β”‚&nbsp;&nbsp;&nbsp;└── Connectivity (hub VNet, firewall, VPN)<br>
&nbsp;&nbsp;└── <strong>Landing Zones</strong> (workload subscriptions)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;β”œβ”€β”€ Corp (internal apps β€” private connectivity)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└── Online (public-facing apps β€” internet connectivity)
</div>
</div>
<h3>Hub-and-Spoke Network Topology</h3>
<div class="info-box">
<div class="box-title">🌐 Recommended Enterprise Pattern</div>
<div class="box-content">
<strong>Hub VNet:</strong> Shared services β€” Azure Firewall, VPN Gateway, Bastion, DNS<br>
<strong>Spoke VNet (Dev):</strong> Development workloads β€” VNet peered to Hub<br>
<strong>Spoke VNet (Staging):</strong> Pre-production β€” VNet peered to Hub<br>
<strong>Spoke VNet (Prod):</strong> Production workloads β€” VNet peered to Hub<br><br>
All traffic flows through the Hub's firewall for centralized security and logging.
</div>
</div>
<h3>NSG vs Azure Firewall vs WAF</h3>
<table>
<tr><th>Feature</th><th>NSG</th><th>Azure Firewall</th><th>WAF (Web Application Firewall)</th></tr>
<tr><td>Layer</td><td>L3/L4 (Network)</td><td>L3-L7 (Network + App)</td><td>L7 (Application only)</td></tr>
<tr><td>Scope</td><td>Subnet / NIC level</td><td>VNet level</td><td>Per App Gateway / Front Door</td></tr>
<tr><td>Use Case</td><td>Basic port filtering</td><td>Centralized egress control, FQDN filtering</td><td>OWASP protection, SQL injection, XSS</td></tr>
<tr><td>Cost</td><td>Free</td><td>~$900/month</td><td>~$200/month per gateway</td></tr>
<tr><td>Logging</td><td>NSG Flow Logs</td><td>Full IDPS, threat intelligence</td><td>WAF logs with rule matches</td></tr>
</table>
<h3>VM Roles in the Pipeline</h3>
<div class="info-box">
<div class="box-title">πŸ–₯️ VM Roles</div>
<div class="box-content">
<strong>Agent VM:</strong> Runs the Azure Pipelines self-hosted agent. Has Maven, Java, Docker, Trivy, kubectl installed.<br>
<strong>SonarQube VM:</strong> Hosts Docker + SonarQube container for code quality analysis.<br>
Both VMs are placed in security groups with controlled inbound rules.
</div>
</div>
<h3>Security Group Rules</h3>
<table>
<tr><th>Port</th><th>Protocol</th><th>Purpose</th><th>Best Practice</th></tr>
<tr><td>22</td><td>SSH</td><td>Remote access to VMs</td><td>Restrict to your IP or use Bastion</td></tr>
<tr><td>80/443</td><td>HTTP/HTTPS</td><td>Web traffic</td><td>Use only HTTPS in production</td></tr>
<tr><td>9000</td><td>TCP</td><td>SonarQube dashboard</td><td>Internal only or VPN</td></tr>
<tr><td>30000-32767</td><td>TCP</td><td>Kubernetes NodePort range</td><td>Use LoadBalancer/Ingress instead</td></tr>
<tr><td>465</td><td>SMTPS</td><td>Email notifications</td><td>Use managed email service</td></tr>
</table>
<div class="callout warning">
<div class="callout-title">⚠️ Security Best Practices</div>
Never use "0.0.0.0/0" (open to all) in production. Restrict SSH access to your IP range. Use Azure Bastion for secure VM access instead of public IPs. Enable NSG flow logs for auditing. Use Private Endpoints for PaaS services.
</div>
`,
handson: `
<h3>Creating Azure VNet with CLI</h3>
<div class="code-block">
<span class="comment"># Create a resource group</span>
<span class="keyword">az</span> group create --name rg-devops --location eastus
<span class="comment"># Create a VNet with subnet</span>
<span class="keyword">az</span> network vnet create \\
--resource-group rg-devops \\
--name vnet-devops \\
--address-prefix <span class="string">10.0.0.0/16</span> \\
--subnet-name subnet-agents \\
--subnet-prefix <span class="string">10.0.1.0/24</span>
<span class="comment"># Create NSG with rules</span>
<span class="keyword">az</span> network nsg create --resource-group rg-devops --name nsg-agents
<span class="keyword">az</span> network nsg rule create \\
--resource-group rg-devops \\
--nsg-name nsg-agents \\
--name AllowSSH \\
--priority 100 \\
--destination-port-ranges 22 \\
--access Allow \\
--protocol Tcp \\
--source-address-prefixes <span class="string">"YOUR_IP/32"</span>
</div>
<h3>Terraform for Azure Infrastructure</h3>
<div class="code-block">
<span class="comment"># main.tf β€” Azure VNet + Subnet + NSG</span>
<span class="keyword">terraform</span> {
<span class="key">required_providers</span> {
<span class="key">azurerm</span> = {
<span class="key">source</span> = <span class="string">"hashicorp/azurerm"</span>
<span class="key">version</span> = <span class="string">"~> 3.0"</span>
}
}
<span class="key">backend</span> <span class="string">"azurerm"</span> {
<span class="key">resource_group_name</span> = <span class="string">"rg-terraform-state"</span>
<span class="key">storage_account_name</span> = <span class="string">"tfstatedevops"</span>
<span class="key">container_name</span> = <span class="string">"tfstate"</span>
<span class="key">key</span> = <span class="string">"terraform.tfstate"</span>
}
}
<span class="keyword">resource</span> <span class="string">"azurerm_virtual_network"</span> <span class="string">"devops"</span> {
<span class="key">name</span> = <span class="string">"vnet-devops"</span>
<span class="key">address_space</span> = [<span class="string">"10.0.0.0/16"</span>]
<span class="key">location</span> = azurerm_resource_group.devops.location
<span class="key">resource_group_name</span> = azurerm_resource_group.devops.name
}
<span class="keyword">resource</span> <span class="string">"azurerm_subnet"</span> <span class="string">"agents"</span> {
<span class="key">name</span> = <span class="string">"subnet-agents"</span>
<span class="key">virtual_network_name</span> = azurerm_virtual_network.devops.name
<span class="key">address_prefixes</span> = [<span class="string">"10.0.1.0/24"</span>]
}
</div>
<h3>Bicep Template β€” Complete Network Setup</h3>
<div class="code-block">
<span class="comment">// network.bicep β€” Hub Network with Firewall</span>
<span class="keyword">param</span> location <span class="keyword">string</span> = resourceGroup().location
<span class="keyword">resource</span> hubVnet <span class="string">'Microsoft.Network/virtualNetworks@2023-04-01'</span> = {
<span class="key">name</span>: <span class="string">'vnet-hub'</span>
<span class="key">location</span>: location
<span class="key">properties</span>: {
<span class="key">addressSpace</span>: { <span class="key">addressPrefixes</span>: [<span class="string">'10.0.0.0/16'</span>] }
<span class="key">subnets</span>: [
{
<span class="key">name</span>: <span class="string">'AzureFirewallSubnet'</span>
<span class="key">properties</span>: { <span class="key">addressPrefix</span>: <span class="string">'10.0.1.0/24'</span> }
}
{
<span class="key">name</span>: <span class="string">'AzureBastionSubnet'</span>
<span class="key">properties</span>: { <span class="key">addressPrefix</span>: <span class="string">'10.0.2.0/24'</span> }
}
]
}
}
<span class="keyword">resource</span> spokeVnet <span class="string">'Microsoft.Network/virtualNetworks@2023-04-01'</span> = {
<span class="key">name</span>: <span class="string">'vnet-spoke-prod'</span>
<span class="key">location</span>: location
<span class="key">properties</span>: {
<span class="key">addressSpace</span>: { <span class="key">addressPrefixes</span>: [<span class="string">'10.1.0.0/16'</span>] }
}
}
</div>
<h3>Self-Hosted Agent Setup</h3>
<div class="code-block">
<span class="comment"># Install self-hosted agent on Ubuntu VM</span>
<span class="comment"># 1. Download agent</span>
<span class="keyword">mkdir</span> myagent && <span class="keyword">cd</span> myagent
<span class="keyword">wget</span> https://vstsagentpackage.azureedge.net/.../vsts-agent-linux-x64.tar.gz
<span class="keyword">tar</span> zxvf vsts-agent-linux-x64.tar.gz
<span class="comment"># 2. Configure agent</span>
./config.sh \\
--url https://dev.azure.com/myorg \\
--auth pat \\
--token <span class="string">YOUR_PAT</span> \\
--pool <span class="string">"myagentpool"</span> \\
--agent <span class="string">"agent-vm-01"</span>
<span class="comment"># 3. Install as service and start</span>
<span class="keyword">sudo</span> ./svc.sh install
<span class="keyword">sudo</span> ./svc.sh start
<span class="comment"># 4. Install required tools</span>
<span class="keyword">sudo</span> apt-get install -y maven openjdk-17-jdk docker.io
<span class="keyword">curl</span> -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh
</div>
`,
applications: `
<h3>Network Architecture Patterns</h3>
<div class="info-box">
<div class="box-title">πŸ—οΈ Production Network Checklist</div>
<div class="box-content">
βœ… <strong>Hub-Spoke topology</strong> with centralized firewall<br>
βœ… <strong>Azure Bastion</strong> for secure VM access (no public IPs)<br>
βœ… <strong>Private Endpoints</strong> for all PaaS services (ACR, Key Vault, SQL)<br>
βœ… <strong>NSG Flow Logs</strong> enabled for audit and troubleshooting<br>
βœ… <strong>Azure DDoS Protection</strong> on public-facing VNets<br>
βœ… <strong>Network Watcher</strong> for diagnostics and topology visualization<br>
βœ… <strong>Service Endpoints</strong> or Private Links for Azure-to-Azure traffic<br>
βœ… <strong>DNS Zones</strong> for internal name resolution
</div>
</div>
<h3>Cost Optimization</h3>
<table>
<tr><th>Resource</th><th>Cost Tip</th><th>Savings</th></tr>
<tr><td>VMs</td><td>Use B-series (burstable) for dev/test agents</td><td>~60%</td></tr>
<tr><td>Bastion</td><td>Use Basic SKU or stop when not needed</td><td>~50%</td></tr>
<tr><td>Firewall</td><td>Use Firewall Basic SKU for small workloads</td><td>~50%</td></tr>
<tr><td>NAT Gateway</td><td>Share across subnets in same VNet</td><td>~30%</td></tr>
<tr><td>VPN Gateway</td><td>Use P2S instead of S2S for dev teams</td><td>~40%</td></tr>
</table>
<div class="interview-box">
<div class="box-title">πŸ“‹ Interview Questions & Answers</div>
<div class="box-content">
<strong>1. What is an Azure VNet and why is it needed?</strong><br>
A VNet is an isolated virtual network in Azure. It provides: network segmentation, security boundaries (NSGs), connectivity to on-premises (VPN/ExpressRoute), and private access to Azure services. Every Azure resource needs a network context.<br><br>
<strong>2. NSG vs Azure Firewall β€” when to use which?</strong><br>
NSG: basic L3/L4 filtering at subnet/NIC level, free. Azure Firewall: centralized L3-L7 filtering, FQDN filtering, threat intelligence, IDPS. Use NSG for simple rules, Firewall for centralized egress control and compliance.<br><br>
<strong>3. What ports does a Kubernetes cluster need?</strong><br>
API Server: 443 (HTTPS). kubelet: 10250. NodePort range: 30000-32767. etcd: 2379-2380. Required for pod-to-pod communication, service discovery, and external access.<br><br>
<strong>4. How do you secure SSH access to Azure VMs?</strong><br>
Best: Use Azure Bastion (no public IP needed). Good: Restrict NSG to your IP range. Also: use SSH keys instead of passwords, enable Just-In-Time VM access, use Azure AD SSH login.<br><br>
<strong>5. What is Hub-and-Spoke architecture?</strong><br>
Hub VNet has shared services (firewall, VPN, Bastion). Spoke VNets have workloads (dev, staging, prod). Connected via VNet Peering. All traffic routes through hub firewall. Recommended by Microsoft for enterprise.<br><br>
<strong>6. What are Azure Private Endpoints?</strong><br>
Private Endpoints give PaaS services (ACR, Key Vault, SQL) a private IP in your VNet. Traffic stays on Microsoft backbone, never goes to public internet. Essential for security compliance.<br><br>
<strong>7. How do you set up a self-hosted pipeline agent?</strong><br>
Create a VM in your VNet. Download the Azure Pipelines agent package. Configure with your org URL and PAT. Install as a Linux service. Add to an agent pool. Install required tools (Docker, Maven, etc.).<br><br>
<strong>8. What are Azure Landing Zones?</strong><br>
Reference architecture for multi-subscription environments. Includes: management groups for governance, platform subscriptions (identity, management, connectivity), and landing zone subscriptions for workloads. Follows Azure Cloud Adoption Framework.<br><br>
<strong>9. Terraform vs Bicep β€” which to choose?</strong><br>
Terraform: multi-cloud, large ecosystem, requires state management. Bicep: Azure-native, no state needed, cleaner syntax than ARM. Use Terraform for multi-cloud. Use Bicep for Azure-only with simpler toolchain.<br><br>
<strong>10. How would you design a network for a multi-tier application?</strong><br>
Hub-Spoke with separate subnets per tier: Web tier (public subnet with WAF/App Gateway), App tier (private subnet), Data tier (private with Private Endpoints). NSGs between tiers. All egress through Azure Firewall in hub. Azure Bastion for management access.
</div>
</div>
`
},
"cicd-yaml": {
concepts: `
<h3>YAML Pipeline β€” Core Components</h3>
<p>Azure DevOps YAML pipelines are <strong>pipeline-as-code</strong> β€” giving you version control, code review, and full traceability. The YAML file lives in your repo alongside your source code.</p>
<table>
<tr><th>Component</th><th>Purpose</th><th>Scope</th><th>Example</th></tr>
<tr><td><strong>Trigger</strong></td><td>What starts the pipeline</td><td>Branch, PR, Schedule, None</td><td><code>trigger: [main]</code></td></tr>
<tr><td><strong>Pool</strong></td><td>Where it runs</td><td>MS-hosted or Self-hosted</td><td><code>pool: {name: 'mypool'}</code></td></tr>
<tr><td><strong>Variables</strong></td><td>Reusable values</td><td>Pipeline, Stage, Job</td><td><code>variables: {tag: 'v1'}</code></td></tr>
<tr><td><strong>Stages</strong></td><td>Logical groups (Build, Test, Deploy)</td><td>Sequential or parallel</td><td><code>stages: [{stage: Build}]</code></td></tr>
<tr><td><strong>Jobs</strong></td><td>Units of work within a stage</td><td>Run on an agent</td><td><code>jobs: [{job: compile}]</code></td></tr>
<tr><td><strong>Steps</strong></td><td>Individual tasks</td><td>Script, Task, Checkout</td><td><code>steps: [{script: 'echo hi'}]</code></td></tr>
</table>
<h3>Pipeline Hierarchy</h3>
<div class="info-box">
<div class="box-title">πŸ“ Structure (Top β†’ Bottom)</div>
<div class="box-content">
<strong>Pipeline</strong><br>
&nbsp;&nbsp;β”œβ”€β”€ trigger / pr / schedules<br>
&nbsp;&nbsp;β”œβ”€β”€ variables / parameters<br>
&nbsp;&nbsp;β”œβ”€β”€ resources (repos, pipelines, containers)<br>
&nbsp;&nbsp;└── <strong>stages[]</strong><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;β”œβ”€β”€ condition / dependsOn<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└── <strong>jobs[]</strong> (or deployment jobs)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;β”œβ”€β”€ pool / environment<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;β”œβ”€β”€ strategy (runOnce, rolling, canary)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└── <strong>steps[]</strong><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;β”œβ”€β”€ checkout / script / task / template
</div>
</div>
<h3>Trigger Types</h3>
<table>
<tr><th>Type</th><th>When It Fires</th><th>YAML</th><th>Use Case</th></tr>
<tr><td>CI Trigger</td><td>Push to branch</td><td><code>trigger: [main]</code></td><td>Main pipeline</td></tr>
<tr><td>PR Trigger</td><td>PR created</td><td><code>pr: [main]</code></td><td>Validation builds</td></tr>
<tr><td>Scheduled</td><td>Cron schedule</td><td><code>schedules: [{cron: ...}]</code></td><td>Nightly builds, drift checks</td></tr>
<tr><td>Manual</td><td>User clicks Run</td><td><code>trigger: none</code></td><td>Production deploys</td></tr>
<tr><td>Pipeline Resource</td><td>Another pipeline completes</td><td><code>resources: {pipelines: [...]}</code></td><td>Chain pipelines</td></tr>
</table>
<h3>Variables β€” Scope & Precedence</h3>
<table>
<tr><th>Source</th><th>Scope</th><th>Precedence</th><th>Secret Support</th></tr>
<tr><td>YAML inline</td><td>Pipeline/Stage/Job</td><td>Lowest</td><td>No</td></tr>
<tr><td>Variable Group</td><td>Linked to pipeline</td><td>Medium</td><td>Yes (Key Vault)</td></tr>
<tr><td>Pipeline UI</td><td>Pipeline settings</td><td>Medium</td><td>Yes</td></tr>
<tr><td>Runtime parameter</td><td>User input at runtime</td><td>Highest</td><td>No</td></tr>
<tr><td>Predefined</td><td>System-provided</td><td>N/A</td><td>N/A</td></tr>
</table>
<h3>Template Types</h3>
<div class="info-box">
<div class="box-title">πŸ“„ Reusable Pipeline Templates</div>
<div class="box-content">
<strong>Include templates:</strong> Insert steps/jobs/stages from another file (<code>template: steps.yml</code>)<br>
<strong>Extends templates:</strong> Define pipeline structure that teams must follow (<code>extends: template: pipeline.yml</code>)<br>
<strong>Variable templates:</strong> Share variable definitions across pipelines<br>
<strong>Expression templates:</strong> Conditional logic using <code>\${{ if }}</code> expressions<br><br>
<strong>Best Practice:</strong> Use extends templates to enforce security stages (scanning, approvals) that teams cannot skip.
</div>
</div>
<h3>Environments & Approvals</h3>
<div class="callout insight">
<div class="callout-title">πŸ’‘ Deployment Jobs vs Regular Jobs</div>
Use <strong>deployment jobs</strong> (not regular jobs) for deployments. They support:<br>
β€’ <strong>Environments</strong> β€” logical targets (dev, staging, prod)<br>
β€’ <strong>Approval gates</strong> β€” manual or automated checks before deploy<br>
β€’ <strong>Deployment strategies</strong> β€” runOnce, rolling, canary<br>
β€’ <strong>Deployment history</strong> β€” audit trail of what deployed where
</div>
`,
handson: `
<h3>Complete Multi-Stage YAML Pipeline</h3>
<div class="code-block">
<span class="comment"># azure-pipelines.yml β€” Full CI/CD Pipeline</span>
<span class="key">trigger</span>:
<span class="key">branches</span>:
<span class="key">include</span>: [main]
<span class="key">paths</span>:
<span class="key">exclude</span>: [docs/*, README.md]
<span class="key">variables</span>:
<span class="key">dockerRegistry</span>: <span class="string">"myacr.azurecr.io"</span>
<span class="key">imageName</span>: <span class="string">"bankapp"</span>
<span class="key">imageTag</span>: <span class="string">"$(Build.BuildId)"</span>
<span class="key">k8sNamespace</span>: <span class="string">"default"</span>
<span class="key">stages</span>:
- <span class="key">stage</span>: Compile
<span class="key">displayName</span>: <span class="string">"Compile Stage"</span>
<span class="key">jobs</span>:
- <span class="key">job</span>: compile
<span class="key">pool</span>:
<span class="key">name</span>: <span class="string">"myagentpool"</span>
<span class="key">steps</span>:
- <span class="key">task</span>: Maven@4
<span class="key">inputs</span>:
<span class="key">mavenPomFile</span>: <span class="string">"pom.xml"</span>
<span class="key">goals</span>: <span class="string">"compile"</span>
- <span class="key">stage</span>: Test
<span class="key">dependsOn</span>: Compile
<span class="key">jobs</span>:
- <span class="key">job</span>: test
<span class="key">steps</span>:
- <span class="key">task</span>: Maven@4
<span class="key">inputs</span>:
<span class="key">goals</span>: <span class="string">"test"</span>
- <span class="key">task</span>: PublishTestResults@2
<span class="key">inputs</span>:
<span class="key">testResultsFormat</span>: <span class="string">"JUnit"</span>
<span class="key">testResultsFiles</span>: <span class="string">"**/TEST-*.xml"</span>
- <span class="key">stage</span>: SecurityScan
<span class="key">dependsOn</span>: Test
<span class="key">jobs</span>:
- <span class="key">job</span>: trivy_scan
<span class="key">steps</span>:
- <span class="key">script</span>: |
trivy fs --format table -o report.html .
<span class="key">displayName</span>: <span class="string">"Trivy FS Scan"</span>
- <span class="key">stage</span>: CodeQuality
<span class="key">dependsOn</span>: SecurityScan
<span class="key">displayName</span>: <span class="string">"SonarQube Analysis"</span>
- <span class="key">stage</span>: BuildImage
<span class="key">dependsOn</span>: CodeQuality
<span class="key">displayName</span>: <span class="string">"Docker Build & Push"</span>
- <span class="key">stage</span>: Deploy
<span class="key">dependsOn</span>: BuildImage
<span class="key">displayName</span>: <span class="string">"Deploy to AKS"</span>
</div>
<h3>Runtime Parameters</h3>
<div class="code-block">
<span class="comment"># Allow users to choose environment at runtime</span>
<span class="key">parameters</span>:
- <span class="key">name</span>: environment
<span class="key">displayName</span>: <span class="string">"Target Environment"</span>
<span class="key">type</span>: string
<span class="key">default</span>: <span class="string">"dev"</span>
<span class="key">values</span>: [<span class="string">"dev"</span>, <span class="string">"staging"</span>, <span class="string">"production"</span>]
- <span class="key">name</span>: skipTests
<span class="key">displayName</span>: <span class="string">"Skip Tests?"</span>
<span class="key">type</span>: boolean
<span class="key">default</span>: false
<span class="key">stages</span>:
- <span class="key">stage</span>: Test
<span class="key">condition</span>: eq(<span class="string">'\${{ parameters.skipTests }}'</span>, false)
<span class="key">jobs</span>:
- <span class="key">job</span>: test
<span class="key">steps</span>:
- <span class="key">script</span>: echo <span class="string">"Running tests..."</span>
- <span class="key">stage</span>: Deploy
<span class="key">jobs</span>:
- <span class="key">deployment</span>: deploy_app
<span class="key">environment</span>: <span class="string">"\${{ parameters.environment }}"</span>
<span class="key">strategy</span>:
<span class="key">runOnce</span>:
<span class="key">deploy</span>:
<span class="key">steps</span>:
- <span class="key">script</span>: echo <span class="string">"Deploying to \${{ parameters.environment }}"</span>
</div>
<h3>Pipeline Templates (Reuse)</h3>
<div class="code-block">
<span class="comment"># templates/build-stage.yml β€” Reusable build template</span>
<span class="key">parameters</span>:
- <span class="key">name</span>: projectPath
<span class="key">type</span>: string
- <span class="key">name</span>: buildConfiguration
<span class="key">type</span>: string
<span class="key">default</span>: <span class="string">"Release"</span>
<span class="key">stages</span>:
- <span class="key">stage</span>: Build
<span class="key">jobs</span>:
- <span class="key">job</span>: build
<span class="key">steps</span>:
- <span class="key">task</span>: Maven@4
<span class="key">inputs</span>:
<span class="key">mavenPomFile</span>: <span class="string">"\${{ parameters.projectPath }}/pom.xml"</span>
<span class="key">goals</span>: <span class="string">"package"</span>
<span class="comment"># Main pipeline β€” uses the template</span>
<span class="key">trigger</span>: [main]
<span class="key">stages</span>:
- <span class="key">template</span>: templates/build-stage.yml
<span class="key">parameters</span>:
<span class="key">projectPath</span>: <span class="string">"src/backend"</span>
</div>
<h3>Matrix Strategy (Parallel Builds)</h3>
<div class="code-block">
<span class="comment"># Build across multiple configurations simultaneously</span>
<span class="key">jobs</span>:
- <span class="key">job</span>: Build
<span class="key">strategy</span>:
<span class="key">matrix</span>:
<span class="key">java11</span>:
<span class="key">jdkVersion</span>: <span class="string">"1.11"</span>
<span class="key">java17</span>:
<span class="key">jdkVersion</span>: <span class="string">"1.17"</span>
<span class="key">java21</span>:
<span class="key">jdkVersion</span>: <span class="string">"1.21"</span>
<span class="key">maxParallel</span>: 3
<span class="key">steps</span>:
- <span class="key">task</span>: JavaToolInstaller@0
<span class="key">inputs</span>:
<span class="key">versionSpec</span>: <span class="string">"$(jdkVersion)"</span>
- <span class="key">script</span>: mvn test
</div>
`,
applications: `
<h3>Pipeline Architecture Patterns</h3>
<div class="pipeline-flow">
<div class="pipeline-stage" style="background: rgba(0,120,212,0.2); color: #0078D4;">Compile</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(0,183,195,0.2); color: #00b7c3;">Test</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(231,76,60,0.2); color: #e74c3c;">Trivy Scan</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(163,113,247,0.2); color: #a371f7;">SonarQube</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(36,150,237,0.2); color: #2496ED;">Docker Build</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(255,107,53,0.2); color: #ff6b35;">Image Scan</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(0,255,136,0.2); color: #00ff88;">Push ACR</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(46,204,113,0.2); color: #2ecc71;">Deploy AKS</div>
</div>
<h3>Pipeline Optimization Tips</h3>
<div class="info-box">
<div class="box-title">⚑ Speed Up Your Pipelines</div>
<div class="box-content">
<strong>Caching:</strong> Cache Maven/npm dependencies between runs (<code>Cache@2</code> task)<br>
<strong>Parallel jobs:</strong> Run independent stages simultaneously (remove dependsOn)<br>
<strong>Path triggers:</strong> Only trigger on changed paths (<code>paths: {include: [src/]}</code>)<br>
<strong>Incremental builds:</strong> Only rebuild changed modules<br>
<strong>Self-hosted agents:</strong> Pre-install tools, avoid download time<br>
<strong>Docker layer caching:</strong> Cache Docker build layers in ACR
</div>
</div>
<div class="interview-box">
<div class="box-title">πŸ“‹ Interview Questions & Answers</div>
<div class="box-content">
<strong>1. What are the main YAML pipeline components?</strong><br>
Trigger (when), Pool (where), Variables (config), Stages β†’ Jobs β†’ Steps (what). Stages are logical groups, jobs run on agents, steps are individual tasks.<br><br>
<strong>2. Stages vs Jobs vs Steps β€” what's the difference?</strong><br>
Stages: logical phases (Build, Test, Deploy) with dependencies. Jobs: units of work that run on an agent. Steps: individual commands/tasks within a job. Stages contain jobs, jobs contain steps.<br><br>
<strong>3. What are pipeline trigger types?</strong><br>
CI (branch push), PR (pull request), Scheduled (cron), Manual (trigger: none), Pipeline Resource (triggered by another pipeline completing). Path filters limit triggers to specific file changes.<br><br>
<strong>4. How do you use variables and variable groups?</strong><br>
Inline variables in YAML, variable groups (shared across pipelines), Key Vault-linked groups for secrets, runtime parameters for user input. Precedence: runtime > UI > variable group > YAML.<br><br>
<strong>5. Microsoft-hosted vs self-hosted agents?</strong><br>
MS-hosted: zero maintenance, clean VM each run, limited to 6hrs. Self-hosted: you manage, persistent, no time limit, pre-installed tools, can access internal resources. Use self-hosted for private networks and custom tooling.<br><br>
<strong>6. How do you create multi-stage pipelines with dependencies?</strong><br>
Use dependsOn to define stage order. Stages run sequentially by default. For parallel: remove dependsOn or set parallel stages. For conditional: use condition expressions.<br><br>
<strong>7. What are pipeline templates?</strong><br>
Reusable YAML files for steps, jobs, or stages. Include templates insert content. Extends templates enforce structure. Used for: DRY code, enforcing security stages, standardizing pipelines across teams.<br><br>
<strong>8. How do you implement approval gates?</strong><br>
Create Environments in Azure DevOps (dev, staging, prod). Add approval checks (manual approvers, branch control, business hours). Use deployment jobs that reference environments. Approvers get notified before deploy.<br><br>
<strong>9. YAML vs Classic editor β€” when to use which?</strong><br>
YAML: version controlled, code review, templatable, recommended for all new pipelines. Classic: visual editor, good for learning, limited reusability. Microsoft recommends YAML for all scenarios.<br><br>
<strong>10. How do you pass variables between stages?</strong><br>
Use output variables: set in a step with <code>##vso[task.setvariable variable=NAME;isOutput=true]</code>, consume in later stages with <code>dependencies.StageName.outputs['jobName.stepName.NAME']</code>.<br><br>
<strong>11. What is pipeline caching and how does it help?</strong><br>
Cache@2 task stores/restores files between runs (Maven .m2, npm node_modules). Keyed by lock file hash. Can reduce build times by 50-80% for dependency-heavy projects.<br><br>
<strong>12. How does matrix strategy work?</strong><br>
Runs the same job with different variable values simultaneously. Example: test across Java 11, 17, 21. maxParallel controls concurrency. Great for cross-platform/cross-version testing.
</div>
</div>
`
},
"build-test": {
concepts: `
<h3>Build Stage β€” Maven Lifecycle</h3>
<p>The first stage in the CI pipeline compiles source code, runs tests, and packages the application.</p>
<div class="info-box">
<div class="box-title">πŸ”¨ Maven Build Lifecycle (Complete)</div>
<div class="box-content">
<strong>validate</strong> β†’ Check project is correct and all dependencies available<br>
<strong>compile</strong> β†’ Compile source code (.java β†’ .class)<br>
<strong>test</strong> β†’ Run unit tests with JUnit/TestNG<br>
<strong>package</strong> β†’ Create JAR/WAR file<br>
<strong>verify</strong> β†’ Run integration tests and quality checks<br>
<strong>install</strong> β†’ Install package to local Maven repository<br>
<strong>deploy</strong> β†’ Push to remote repository (Nexus/Artifactory)
</div>
</div>
<h3>Test Pyramid</h3>
<table>
<tr><th>Level</th><th>Type</th><th>Speed</th><th>Cost</th><th>Coverage Target</th><th>Tools</th></tr>
<tr><td><strong>Top</strong></td><td>E2E Tests</td><td>Slowest</td><td>Highest</td><td>~10%</td><td>Selenium, Cypress, Playwright</td></tr>
<tr><td><strong>Middle</strong></td><td>Integration Tests</td><td>Medium</td><td>Medium</td><td>~20%</td><td>Spring Test, Testcontainers</td></tr>
<tr><td><strong>Bottom</strong></td><td>Unit Tests</td><td>Fastest</td><td>Lowest</td><td>~70%</td><td>JUnit, Mockito, pytest</td></tr>
<tr><td><strong>Foundation</strong></td><td>Static Analysis</td><td>Instant</td><td>Free</td><td>100%</td><td>SonarQube, ESLint, Pylint</td></tr>
</table>
<h3>Code Quality β€” SonarQube Deep Dive</h3>
<table>
<tr><th>Metric</th><th>What It Measures</th><th>Quality Gate</th><th>Impact</th></tr>
<tr><td><strong>Bugs</strong></td><td>Code errors causing failures</td><td>0 new bugs</td><td>Reliability</td></tr>
<tr><td><strong>Vulnerabilities</strong></td><td>Security weaknesses</td><td>0 new vulnerabilities</td><td>Security</td></tr>
<tr><td><strong>Code Smells</strong></td><td>Maintainability issues</td><td>A rating</td><td>Technical Debt</td></tr>
<tr><td><strong>Coverage</strong></td><td>% of code tested</td><td>β‰₯ 80%</td><td>Confidence</td></tr>
<tr><td><strong>Duplications</strong></td><td>Copy-pasted code</td><td>< 3%</td><td>Maintenance</td></tr>
<tr><td><strong>Hotspots</strong></td><td>Security-sensitive code</td><td>Reviewed</td><td>Risk</td></tr>
</table>
<h3>Security Scanning β€” SAST vs DAST vs SCA</h3>
<table>
<tr><th>Type</th><th>What</th><th>When</th><th>Tools</th><th>Finds</th></tr>
<tr><td><strong>SAST</strong></td><td>Static Application Security Testing</td><td>During CI (code analysis)</td><td>SonarQube, Checkmarx, Semgrep</td><td>SQL injection, XSS, buffer overflow</td></tr>
<tr><td><strong>DAST</strong></td><td>Dynamic Application Security Testing</td><td>Against running app</td><td>OWASP ZAP, Burp Suite</td><td>Runtime vulnerabilities, auth issues</td></tr>
<tr><td><strong>SCA</strong></td><td>Software Composition Analysis</td><td>During CI (dependency check)</td><td>Trivy, Snyk, OWASP Dependency-Check</td><td>Known CVEs in libraries</td></tr>
<tr><td><strong>IaC Scan</strong></td><td>Infrastructure as Code scanning</td><td>During CI</td><td>Trivy config, Checkov, tfsec</td><td>Misconfigurations in Terraform/K8s</td></tr>
</table>
<h3>Trivy β€” Multi-Scanner</h3>
<table>
<tr><th>Scan Type</th><th>Command</th><th>What It Scans</th><th>Pipeline Stage</th></tr>
<tr><td>File System</td><td><code>trivy fs .</code></td><td>Dependencies, configs</td><td>Before Docker build</td></tr>
<tr><td>Image</td><td><code>trivy image myimage:tag</code></td><td>Docker image layers + OS packages</td><td>After Docker build</td></tr>
<tr><td>Config</td><td><code>trivy config .</code></td><td>Terraform, K8s manifests</td><td>Before deploy</td></tr>
<tr><td>Repository</td><td><code>trivy repo .</code></td><td>Git repository</td><td>PR validation</td></tr>
</table>
<div class="callout insight">
<div class="callout-title">πŸ’‘ Defense in Depth</div>
The pipeline runs TWO Trivy scans: first on the file system (before Docker build), then on the built Docker image (before push to ACR). This catches vulnerabilities at both the dependency layer and the container OS layer.
</div>
`,
handson: `
<h3>SonarQube Setup</h3>
<div class="code-block">
<span class="comment"># Install Docker on SonarQube VM</span>
<span class="keyword">sudo</span> apt-get update
<span class="keyword">sudo</span> apt-get install docker.io -y
<span class="keyword">sudo</span> usermod -aG docker ubuntu
<span class="comment"># Run SonarQube container</span>
<span class="keyword">docker</span> run -d --name sonarqube \\
-p 9000:9000 \\
-v sonarqube_data:/opt/sonarqube/data \\
-v sonarqube_logs:/opt/sonarqube/logs \\
sonarqube:lts-community
<span class="comment"># Access at http://&lt;VM-IP&gt;:9000</span>
<span class="comment"># Default login: admin / admin (change immediately!)</span>
<span class="comment"># Generate token: My Account β†’ Security β†’ Generate Token</span>
</div>
<h3>SonarQube Pipeline Stage</h3>
<div class="code-block">
<span class="comment"># SonarQube Analysis Stage</span>
- <span class="key">stage</span>: SonarQube
<span class="key">displayName</span>: <span class="string">"SonarQube Analysis"</span>
<span class="key">jobs</span>:
- <span class="key">job</span>: sonarqube
<span class="key">steps</span>:
- <span class="key">task</span>: SonarQubePrepare@6
<span class="key">inputs</span>:
<span class="key">SonarQube</span>: <span class="string">"sonar-conn"</span>
<span class="key">scannerMode</span>: <span class="string">"Other"</span>
<span class="key">extraProperties</span>: |
sonar.projectKey=bankapp
sonar.java.coveragePlugin=jacoco
sonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml
- <span class="key">task</span>: Maven@4
<span class="key">inputs</span>:
<span class="key">goals</span>: <span class="string">"verify"</span>
<span class="key">sonarQubeRunAnalysis</span>: true
- <span class="key">task</span>: SonarQubePublish@6
<span class="key">inputs</span>:
<span class="key">pollingTimeoutSec</span>: <span class="string">"300"</span>
</div>
<h3>Trivy Scan Stages</h3>
<div class="code-block">
<span class="comment"># Trivy File System Scan β€” catches dependency CVEs</span>
- <span class="key">stage</span>: trivy_fs_scan
<span class="key">jobs</span>:
- <span class="key">job</span>: trivy_scan
<span class="key">steps</span>:
- <span class="key">script</span>: |
trivy fs --format table -o fs-report.html .
trivy fs --severity HIGH,CRITICAL --exit-code 1 .
<span class="key">displayName</span>: <span class="string">"Trivy File System Scan"</span>
<span class="comment"># Trivy Image Scan β€” catches container OS CVEs</span>
- <span class="key">stage</span>: trivy_image_scan
<span class="key">jobs</span>:
- <span class="key">job</span>: trivy_image
<span class="key">steps</span>:
- <span class="key">script</span>: |
trivy image --severity HIGH,CRITICAL \\
--exit-code 1 \\
--ignore-unfixed \\
myacr.azurecr.io/dev:latest
<span class="key">displayName</span>: <span class="string">"Trivy Image Scan"</span>
</div>
<h3>Code Coverage Enforcement</h3>
<div class="code-block">
<span class="comment"># pom.xml β€” JaCoCo plugin for code coverage</span>
&lt;<span class="keyword">plugin</span>&gt;
&lt;<span class="key">groupId</span>&gt;org.jacoco&lt;/<span class="key">groupId</span>&gt;
&lt;<span class="key">artifactId</span>&gt;jacoco-maven-plugin&lt;/<span class="key">artifactId</span>&gt;
&lt;<span class="key">executions</span>&gt;
&lt;<span class="keyword">execution</span>&gt;
&lt;<span class="key">goals</span>&gt;&lt;<span class="keyword">goal</span>&gt;prepare-agent&lt;/<span class="keyword">goal</span>&gt;&lt;/<span class="key">goals</span>&gt;
&lt;/<span class="keyword">execution</span>&gt;
&lt;<span class="keyword">execution</span> <span class="key">id</span>=<span class="string">"check"</span>&gt;
&lt;<span class="key">goals</span>&gt;&lt;<span class="keyword">goal</span>&gt;check&lt;/<span class="keyword">goal</span>&gt;&lt;/<span class="key">goals</span>&gt;
&lt;<span class="key">configuration</span>&gt;
&lt;<span class="key">rules</span>&gt;
&lt;<span class="keyword">rule</span>&gt;
&lt;<span class="key">limits</span>&gt;
&lt;<span class="keyword">limit</span>&gt;
&lt;<span class="key">minimum</span>&gt;<span class="string">0.80</span>&lt;/<span class="key">minimum</span>&gt;
&lt;/<span class="keyword">limit</span>&gt;
&lt;/<span class="key">limits</span>&gt;
&lt;/<span class="keyword">rule</span>&gt;
&lt;/<span class="key">rules</span>&gt;
&lt;/<span class="key">configuration</span>&gt;
&lt;/<span class="keyword">execution</span>&gt;
&lt;/<span class="key">executions</span>&gt;
&lt;/<span class="keyword">plugin</span>&gt;
</div>
`,
applications: `
<h3>Quality Gate Strategy</h3>
<div class="info-box">
<div class="box-title">πŸ›‘οΈ Defense in Depth β€” 5 Layers</div>
<div class="box-content">
<strong>Layer 1:</strong> Pre-commit hooks β€” Lint, format, basic checks (instant feedback)<br>
<strong>Layer 2:</strong> SAST β€” SonarQube static analysis β†’ Catch code smells and bugs<br>
<strong>Layer 3:</strong> Unit Tests β€” Maven test with JaCoCo coverage β†’ Catch logic errors<br>
<strong>Layer 4:</strong> SCA β€” Trivy fs scan β†’ Catch dependency CVEs<br>
<strong>Layer 5:</strong> Container Scan β€” Trivy image scan β†’ Catch container OS CVEs<br>
<strong>Bonus:</strong> DAST β€” OWASP ZAP against staging β†’ Catch runtime vulnerabilities
</div>
</div>
<h3>OWASP Top 10 (2021) β€” What Scanners Detect</h3>
<table>
<tr><th>#</th><th>Vulnerability</th><th>Detected By</th></tr>
<tr><td>A01</td><td>Broken Access Control</td><td>DAST, Code Review</td></tr>
<tr><td>A02</td><td>Cryptographic Failures</td><td>SAST, SCA</td></tr>
<tr><td>A03</td><td>Injection (SQL, XSS)</td><td>SAST, DAST</td></tr>
<tr><td>A04</td><td>Insecure Design</td><td>Threat Modeling</td></tr>
<tr><td>A05</td><td>Security Misconfiguration</td><td>IaC Scan, DAST</td></tr>
<tr><td>A06</td><td>Vulnerable Components</td><td>SCA (Trivy, Snyk)</td></tr>
<tr><td>A07</td><td>Authentication Failures</td><td>DAST, Pen Testing</td></tr>
<tr><td>A08</td><td>Software Integrity Failures</td><td>SCA, Supply Chain</td></tr>
<tr><td>A09</td><td>Logging & Monitoring Failures</td><td>Manual Review</td></tr>
<tr><td>A10</td><td>Server-Side Request Forgery</td><td>SAST, DAST</td></tr>
</table>
<div class="interview-box">
<div class="box-title">πŸ“‹ Interview Questions & Answers</div>
<div class="box-content">
<strong>1. What is the Maven build lifecycle?</strong><br>
7 phases: validate β†’ compile β†’ test β†’ package β†’ verify β†’ install β†’ deploy. Each phase runs all previous phases. <code>mvn package</code> runs validate, compile, test, then package.<br><br>
<strong>2. What is SonarQube and what does it measure?</strong><br>
Static code analysis platform. Measures: bugs (reliability), vulnerabilities (security), code smells (maintainability), coverage (test %), duplications (DRY), security hotspots. Uses quality gates to pass/fail builds.<br><br>
<strong>3. Explain Quality Gates.</strong><br>
Configurable thresholds in SonarQube that determine if code passes: 0 new bugs, 0 new vulnerabilities, β‰₯80% coverage on new code, <3% duplication. Pipeline fails if gate fails.<br><br>
<strong>4. What is Trivy and how does it differ from OWASP Dependency-Check?</strong><br>
Both are SCA tools. Trivy: multi-purpose (fs, image, config, repo), fast, zero-config. OWASP DC: dependency-only, uses NVD database, more detailed reports. Trivy is preferred for container scanning.<br><br>
<strong>5. Why run both file system and image scans?</strong><br>
FS scan catches vulnerable dependencies in your code (pom.xml, package.json). Image scan catches vulnerabilities in the container OS and system packages. Different layers, different CVEs.<br><br>
<strong>6. What is SAST vs DAST vs SCA?</strong><br>
SAST: analyzes source code without running it (finds code-level bugs). DAST: tests running application (finds runtime issues). SCA: checks third-party dependencies for known CVEs. All three should be in your pipeline.<br><br>
<strong>7. What is a "code smell" vs a "bug" vs a "vulnerability"?</strong><br>
Bug: code that will cause incorrect behavior. Vulnerability: code exploitable by attackers. Code smell: maintainability issue (long methods, dead code). Smells don't break things but increase technical debt.<br><br>
<strong>8. How do you publish test results in Azure Pipelines?</strong><br>
Use PublishTestResults@2 task with format (JUnit/NUnit), path to XML results. Results appear in pipeline run's "Tests" tab with pass/fail breakdown and trend charts.<br><br>
<strong>9. How would you fail a pipeline if coverage drops below 80%?</strong><br>
Two options: JaCoCo check goal in pom.xml (fails Maven build), or SonarQube quality gate with coverage threshold. JaCoCo is faster (no SonarQube call), quality gate is more comprehensive.<br><br>
<strong>10. Explain the test pyramid.</strong><br>
Bottom: many fast unit tests (70%). Middle: moderate integration tests (20%). Top: few slow E2E tests (10%). Foundation: static analysis (100%). Inverted pyramid (too many E2E) leads to slow, flaky pipelines.
</div>
</div>
`
},
"docker": {
concepts: `
<h3>What is Docker?</h3>
<p>Docker is a platform for building, shipping, and running applications in <strong>containers</strong> β€” lightweight, portable, self-sufficient units that package code with all its dependencies.</p>
<h3>Docker Internals β€” How Containers Work</h3>
<div class="info-box">
<div class="box-title">πŸ”§ Linux Kernel Features Behind Docker</div>
<div class="box-content">
<strong>Namespaces:</strong> Process isolation β€” each container has its own PID, network, mount, user, IPC namespace<br>
<strong>cgroups:</strong> Resource limits β€” control CPU, memory, disk I/O per container<br>
<strong>Union File System:</strong> Layered storage β€” OverlayFS stacks read-only image layers + read-write container layer<br>
<strong>Container Runtime:</strong> containerd (Docker default) or CRI-O (Kubernetes native)
</div>
</div>
<h3>Docker Architecture</h3>
<table>
<tr><th>Component</th><th>Description</th><th>Example</th></tr>
<tr><td><strong>Image</strong></td><td>Read-only template (layers of instructions)</td><td>openjdk:17-alpine</td></tr>
<tr><td><strong>Container</strong></td><td>Running instance of an image (writable layer)</td><td>bankapp-container</td></tr>
<tr><td><strong>Dockerfile</strong></td><td>Instructions to build an image</td><td>FROM, RUN, COPY, CMD</td></tr>
<tr><td><strong>Registry</strong></td><td>Image storage (Docker Hub, ACR, ECR)</td><td>myacr.azurecr.io/app:v1</td></tr>
<tr><td><strong>Volume</strong></td><td>Persistent storage outside container lifecycle</td><td>Database data, logs</td></tr>
<tr><td><strong>Network</strong></td><td>Communication between containers</td><td>bridge, host, overlay</td></tr>
</table>
<h3>Docker vs Virtual Machines</h3>
<table>
<tr><th>Feature</th><th>Docker Container</th><th>Virtual Machine</th></tr>
<tr><td>Boot Time</td><td>Milliseconds to seconds</td><td>Minutes</td></tr>
<tr><td>Size</td><td>MBs (Alpine: 5MB)</td><td>GBs</td></tr>
<tr><td>Isolation</td><td>Process-level (shared kernel)</td><td>Full OS-level (own kernel)</td></tr>
<tr><td>Performance</td><td>Near-native</td><td>Hypervisor overhead (~10%)</td></tr>
<tr><td>Density</td><td>100s per host</td><td>10s per host</td></tr>
<tr><td>Security</td><td>Shared kernel = smaller boundary</td><td>Stronger isolation</td></tr>
<tr><td>Use Case</td><td>Microservices, CI/CD</td><td>Legacy apps, different OS</td></tr>
</table>
<h3>Docker Networking Modes</h3>
<table>
<tr><th>Mode</th><th>Description</th><th>Use Case</th></tr>
<tr><td><strong>bridge</strong></td><td>Default. Containers get private IP, NAT for external</td><td>Most applications</td></tr>
<tr><td><strong>host</strong></td><td>Container uses host's network directly</td><td>High performance (no NAT overhead)</td></tr>
<tr><td><strong>none</strong></td><td>No networking</td><td>Security-sensitive batch jobs</td></tr>
<tr><td><strong>overlay</strong></td><td>Multi-host networking (Swarm/K8s)</td><td>Container orchestration</td></tr>
</table>
<h3>Azure Container Registry (ACR)</h3>
<div class="info-box">
<div class="box-title">πŸ“¦ ACR Features</div>
<div class="box-content">
<strong>SKUs:</strong> Basic ($0.17/day), Standard ($0.67/day), Premium ($1.67/day β€” geo-replication, private link)<br>
<strong>Features:</strong> Geo-replication, image scanning, webhook triggers, content trust, retention policies<br>
<strong>Integration:</strong> Native integration with AKS (no credentials needed with managed identity)<br>
<strong>ACR Tasks:</strong> Build images in the cloud (no local Docker needed)
</div>
</div>
`,
handson: `
<h3>Dockerfile Best Practices</h3>
<div class="code-block">
<span class="comment"># Multi-stage build for a Java application</span>
<span class="comment"># Stage 1: Build (large image with build tools)</span>
<span class="keyword">FROM</span> maven:3.9-eclipse-temurin-17 <span class="keyword">AS</span> build
<span class="key">WORKDIR</span> /app
<span class="key">COPY</span> pom.xml .
<span class="keyword">RUN</span> mvn dependency:go-offline <span class="comment"># Cache dependencies</span>
<span class="key">COPY</span> src/ ./src/
<span class="keyword">RUN</span> mvn package -DskipTests
<span class="comment"># Stage 2: Runtime (minimal image)</span>
<span class="keyword">FROM</span> eclipse-temurin:17-jre-alpine
<span class="keyword">RUN</span> addgroup -S appgroup && adduser -S appuser -G appgroup
<span class="key">WORKDIR</span> /app
<span class="key">COPY</span> --from=build /app/target/*.jar app.jar
<span class="keyword">USER</span> appuser
<span class="key">EXPOSE</span> 8080
<span class="key">HEALTHCHECK</span> --interval=30s --timeout=3s \\
CMD wget --no-verbose --tries=1 http://localhost:8080/actuator/health || exit 1
<span class="key">ENTRYPOINT</span> [<span class="string">"java"</span>, <span class="string">"-jar"</span>, <span class="string">"app.jar"</span>]
</div>
<h3>Docker Pipeline Stages</h3>
<div class="code-block">
<span class="comment"># Build, Scan, and Push Docker Image</span>
- <span class="key">stage</span>: DockerBuild
<span class="key">displayName</span>: <span class="string">"Build Docker Image"</span>
<span class="key">jobs</span>:
- <span class="key">job</span>: docker_build
<span class="key">steps</span>:
- <span class="key">task</span>: Docker@2
<span class="key">inputs</span>:
<span class="key">containerRegistry</span>: <span class="string">"acr-service-conn"</span>
<span class="key">repository</span>: <span class="string">"bankapp"</span>
<span class="key">command</span>: <span class="string">"build"</span>
<span class="key">tags</span>: |
$(Build.BuildId)
latest
- <span class="key">stage</span>: ImageScan
<span class="key">displayName</span>: <span class="string">"Scan Docker Image"</span>
<span class="key">jobs</span>:
- <span class="key">job</span>: scan
<span class="key">steps</span>:
- <span class="key">script</span>: |
trivy image --severity HIGH,CRITICAL \\
--exit-code 1 \\
myacr.azurecr.io/bankapp:$(Build.BuildId)
- <span class="key">stage</span>: DockerPush
<span class="key">displayName</span>: <span class="string">"Push to ACR"</span>
<span class="key">jobs</span>:
- <span class="key">job</span>: docker_push
<span class="key">steps</span>:
- <span class="key">task</span>: Docker@2
<span class="key">inputs</span>:
<span class="key">containerRegistry</span>: <span class="string">"acr-service-conn"</span>
<span class="key">repository</span>: <span class="string">"bankapp"</span>
<span class="key">command</span>: <span class="string">"push"</span>
<span class="key">tags</span>: |
$(Build.BuildId)
latest
</div>
<h3>Docker Compose for Local Development</h3>
<div class="code-block">
<span class="comment"># docker-compose.yml β€” Local dev environment</span>
<span class="key">version</span>: <span class="string">"3.8"</span>
<span class="key">services</span>:
<span class="key">app</span>:
<span class="key">build</span>: .
<span class="key">ports</span>: [<span class="string">"8080:8080"</span>]
<span class="key">environment</span>:
- <span class="string">SPRING_DATASOURCE_URL=jdbc:mysql://db:3306/bankdb</span>
<span class="key">depends_on</span>: [db]
<span class="key">db</span>:
<span class="key">image</span>: <span class="string">mysql:8.0</span>
<span class="key">environment</span>:
<span class="key">MYSQL_ROOT_PASSWORD</span>: <span class="string">rootpass</span>
<span class="key">MYSQL_DATABASE</span>: <span class="string">bankdb</span>
<span class="key">volumes</span>:
- <span class="string">db_data:/var/lib/mysql</span>
<span class="key">ports</span>: [<span class="string">"3306:3306"</span>]
<span class="key">sonarqube</span>:
<span class="key">image</span>: <span class="string">sonarqube:lts-community</span>
<span class="key">ports</span>: [<span class="string">"9000:9000"</span>]
<span class="key">volumes</span>:
<span class="key">db_data</span>:
</div>
<h3>Essential Docker Commands</h3>
<div class="code-block">
<span class="comment"># Build, run, manage</span>
<span class="keyword">docker</span> build -t myapp:v1 .
<span class="keyword">docker</span> run -d -p 8080:8080 --name myapp myapp:v1
<span class="keyword">docker</span> ps <span class="comment"># List running containers</span>
<span class="keyword">docker</span> logs myapp <span class="comment"># View logs</span>
<span class="keyword">docker</span> exec -it myapp sh <span class="comment"># Shell into container</span>
<span class="keyword">docker</span> stop myapp && docker rm myapp
<span class="comment"># Image management</span>
<span class="keyword">docker</span> images <span class="comment"># List images</span>
<span class="keyword">docker</span> image prune -a <span class="comment"># Remove unused images</span>
<span class="keyword">docker</span> history myapp:v1 <span class="comment"># Show layer history</span>
<span class="comment"># Push to ACR</span>
<span class="keyword">az</span> acr login --name myacr
<span class="keyword">docker</span> tag myapp:v1 myacr.azurecr.io/myapp:v1
<span class="keyword">docker</span> push myacr.azurecr.io/myapp:v1
<span class="comment"># ACR Tasks β€” Build in the cloud (no local Docker!)</span>
<span class="keyword">az</span> acr build --registry myacr --image myapp:v1 .
</div>
`,
applications: `
<h3>Container Best Practices β€” Production Checklist</h3>
<div class="info-box">
<div class="box-title">βœ… Production Dockerfile Checklist</div>
<div class="box-content">
<strong>Security:</strong> Don't run as root (USER directive), use minimal base images (Alpine/Distroless)<br>
<strong>Size:</strong> Multi-stage builds, minimize layers, use .dockerignore<br>
<strong>Scanning:</strong> Scan with Trivy before pushing, enable ACR image scanning<br>
<strong>Tagging:</strong> Never use :latest in production β€” use semantic versioning or build ID<br>
<strong>Health Checks:</strong> Add HEALTHCHECK in Dockerfile for orchestrator integration<br>
<strong>Reproducibility:</strong> Pin base image versions, use lock files for dependencies<br>
<strong>Secrets:</strong> Never bake secrets into images β€” use env vars or mounted secrets
</div>
</div>
<h3>Image Size Optimization</h3>
<table>
<tr><th>Base Image</th><th>Size</th><th>Use Case</th></tr>
<tr><td>ubuntu:22.04</td><td>~77 MB</td><td>Development, debugging</td></tr>
<tr><td>alpine:3.18</td><td>~5 MB</td><td>Production (most apps)</td></tr>
<tr><td>distroless/java17</td><td>~190 MB</td><td>Production (no shell!)</td></tr>
<tr><td>scratch</td><td>0 MB</td><td>Statically compiled Go/Rust</td></tr>
</table>
<div class="interview-box">
<div class="box-title">πŸ“‹ Interview Questions & Answers</div>
<div class="box-content">
<strong>1. Docker image vs container β€” what's the difference?</strong><br>
Image: read-only template with layered instructions (like a class). Container: running instance of an image with a writable layer (like an object). Multiple containers can share one image.<br><br>
<strong>2. Explain multi-stage builds.</strong><br>
Use multiple FROM statements. Stage 1: build environment with all tools (Maven, npm). Stage 2: minimal runtime (Alpine/JRE). Only final stage is in the output image. Reduces image size by 60-90%.<br><br>
<strong>3. How does Docker differ from a VM?</strong><br>
Docker: shares host kernel, process-level isolation (namespaces + cgroups), MBs, seconds to start. VM: own kernel, full OS isolation (hypervisor), GBs, minutes to start. Docker is lighter but weaker isolation.<br><br>
<strong>4. What is ACR and how do you push images?</strong><br>
Azure Container Registry β€” managed Docker registry. Push: az acr login, docker tag with ACR URL, docker push. Or use ACR Tasks for cloud builds. Integrates natively with AKS via managed identity.<br><br>
<strong>5. Docker networking modes?</strong><br>
Bridge (default, NAT), Host (no isolation, best performance), None (no network), Overlay (multi-host for orchestration). Bridge is standard, host for performance-critical apps, overlay for K8s.<br><br>
<strong>6. How do you optimize Docker image size?</strong><br>
Multi-stage builds, Alpine/Distroless base, .dockerignore, combine RUN commands (fewer layers), order instructions for cache efficiency (COPY package.json before source), remove build artifacts.<br><br>
<strong>7. What are Docker volumes?</strong><br>
Persistent storage that outlives containers. Types: named volumes (Docker managed), bind mounts (host directory), tmpfs (in-memory). Use for databases, logs, config files that need persistence.<br><br>
<strong>8. Docker Compose vs Kubernetes β€” when to use which?</strong><br>
Compose: local development, single-host, simple orchestration, docker-compose.yml. K8s: production, multi-host, auto-scaling, self-healing, rolling updates. Compose for dev, K8s for prod.<br><br>
<strong>9. What is a Distroless image?</strong><br>
Google's minimal images containing only the application runtime (no shell, no package manager). More secure (smaller attack surface) but harder to debug. Ideal for production Java, Python, Node.js apps.<br><br>
<strong>10. How does Docker layer caching work?</strong><br>
Each Dockerfile instruction creates a layer. Docker caches layers and reuses them if the instruction + context haven't changed. Order matters: put rarely-changing instructions first (FROM, RUN apt-get) and frequently-changing last (COPY src/).
</div>
</div>
`
},
"kubernetes": {
concepts: `
<h3>What is Kubernetes?</h3>
<p>Kubernetes (K8s) is an open-source <strong>container orchestration platform</strong> that automates deployment, scaling, and management of containerized applications. Originally designed by Google (based on Borg), now maintained by CNCF.</p>
<h3>Kubernetes Architecture</h3>
<div class="info-box">
<div class="box-title">πŸ—οΈ Control Plane vs Worker Nodes</div>
<div class="box-content">
<strong>Control Plane (Master):</strong><br>
&nbsp;&nbsp;β€’ <strong>API Server</strong> β€” Entry point for all kubectl commands and REST calls<br>
&nbsp;&nbsp;β€’ <strong>etcd</strong> β€” Distributed key-value store (cluster state & config)<br>
&nbsp;&nbsp;β€’ <strong>Scheduler</strong> β€” Assigns Pods to nodes based on resources, affinity, taints<br>
&nbsp;&nbsp;β€’ <strong>Controller Manager</strong> β€” Runs controllers (Replication, Node, Endpoint, SA)<br>
&nbsp;&nbsp;β€’ <strong>Cloud Controller Manager</strong> β€” Integrates with cloud provider APIs<br><br>
<strong>Worker Nodes:</strong><br>
&nbsp;&nbsp;β€’ <strong>kubelet</strong> β€” Agent that manages Pods on each node<br>
&nbsp;&nbsp;β€’ <strong>kube-proxy</strong> β€” Network rules (iptables/IPVS) for Service routing<br>
&nbsp;&nbsp;β€’ <strong>Container Runtime</strong> β€” containerd (default) or CRI-O
</div>
</div>
<h3>Core Kubernetes Objects</h3>
<table>
<tr><th>Object</th><th>Purpose</th><th>Key Fields</th></tr>
<tr><td><strong>Pod</strong></td><td>Smallest unit β€” one or more containers</td><td>containers, volumes, restartPolicy</td></tr>
<tr><td><strong>Deployment</strong></td><td>Manages replica sets and rolling updates</td><td>replicas, strategy, selector</td></tr>
<tr><td><strong>Service</strong></td><td>Stable network endpoint for Pods</td><td>type, selector, ports</td></tr>
<tr><td><strong>ConfigMap</strong></td><td>External configuration data</td><td>key-value pairs, mounted as env/files</td></tr>
<tr><td><strong>Secret</strong></td><td>Sensitive data (base64 encoded)</td><td>Opaque, TLS, docker-registry types</td></tr>
<tr><td><strong>Namespace</strong></td><td>Virtual cluster for isolation</td><td>Resource quotas, network policies</td></tr>
<tr><td><strong>Ingress</strong></td><td>HTTP/HTTPS routing and TLS termination</td><td>rules, hosts, paths, TLS</td></tr>
<tr><td><strong>PersistentVolumeClaim</strong></td><td>Request persistent storage</td><td>storageClassName, accessModes, size</td></tr>
<tr><td><strong>HPA</strong></td><td>Horizontal Pod Autoscaler</td><td>minReplicas, maxReplicas, metrics</td></tr>
<tr><td><strong>NetworkPolicy</strong></td><td>Pod-to-pod firewall rules</td><td>ingress, egress, podSelector</td></tr>
</table>
<h3>Service Types</h3>
<table>
<tr><th>Type</th><th>Access</th><th>Use Case</th><th>External IP</th></tr>
<tr><td><strong>ClusterIP</strong></td><td>Internal only</td><td>Inter-service communication</td><td>No</td></tr>
<tr><td><strong>NodePort</strong></td><td>External via node IP:port</td><td>Development, testing</td><td>Node IP:30000-32767</td></tr>
<tr><td><strong>LoadBalancer</strong></td><td>External via cloud LB</td><td>Production (single service)</td><td>Yes (cloud-provisioned)</td></tr>
<tr><td><strong>ExternalName</strong></td><td>DNS CNAME</td><td>External service alias</td><td>No</td></tr>
</table>
<h3>Azure Kubernetes Service (AKS)</h3>
<div class="info-box">
<div class="box-title">☸️ AKS β€” Managed Kubernetes</div>
<div class="box-content">
<strong>Free control plane:</strong> Microsoft manages API Server, etcd, scheduler (you pay only for worker nodes)<br>
<strong>Auto-scaling:</strong> Cluster autoscaler (nodes) + HPA (pods) + VPA (vertical)<br>
<strong>Networking:</strong> Azure CNI (VNet integration) or kubenet (basic)<br>
<strong>Identity:</strong> Azure AD integration, Managed Identity, Workload Identity<br>
<strong>Monitoring:</strong> Container Insights, Prometheus, Grafana<br>
<strong>Add-ons:</strong> Azure Policy, Key Vault CSI, Dapr, KEDA, GitOps (Flux)
</div>
</div>
<h3>Deployment Strategies in Kubernetes</h3>
<table>
<tr><th>Strategy</th><th>How It Works</th><th>YAML Config</th><th>Rollback</th></tr>
<tr><td><strong>Rolling Update</strong></td><td>Gradually replace old pods</td><td>strategy: {type: RollingUpdate, maxSurge: 1, maxUnavailable: 0}</td><td>kubectl rollout undo</td></tr>
<tr><td><strong>Recreate</strong></td><td>Kill all, then create new</td><td>strategy: {type: Recreate}</td><td>Manual redeploy</td></tr>
<tr><td><strong>Blue-Green</strong></td><td>Two deployments, switch service selector</td><td>Two Deployments + Service label switch</td><td>Switch selector back</td></tr>
<tr><td><strong>Canary</strong></td><td>Multiple deployments with weighted traffic</td><td>Istio/Nginx ingress weighted routing</td><td>Scale down canary</td></tr>
</table>
`,
handson: `
<h3>Kubernetes Manifests</h3>
<div class="code-block">
<span class="comment"># ds.yml β€” Deployment + Service + ConfigMap</span>
<span class="key">apiVersion</span>: v1
<span class="key">kind</span>: ConfigMap
<span class="key">metadata</span>:
<span class="key">name</span>: bankapp-config
<span class="key">data</span>:
<span class="key">SPRING_PROFILES_ACTIVE</span>: <span class="string">"production"</span>
<span class="key">DB_HOST</span>: <span class="string">"mysql-service"</span>
---
<span class="key">apiVersion</span>: apps/v1
<span class="key">kind</span>: Deployment
<span class="key">metadata</span>:
<span class="key">name</span>: bankapp
<span class="key">spec</span>:
<span class="key">replicas</span>: 3
<span class="key">selector</span>:
<span class="key">matchLabels</span>:
<span class="key">app</span>: bankapp
<span class="key">strategy</span>:
<span class="key">type</span>: RollingUpdate
<span class="key">rollingUpdate</span>:
<span class="key">maxSurge</span>: 1
<span class="key">maxUnavailable</span>: 0
<span class="key">template</span>:
<span class="key">metadata</span>:
<span class="key">labels</span>:
<span class="key">app</span>: bankapp
<span class="key">spec</span>:
<span class="key">containers</span>:
- <span class="key">name</span>: bankapp
<span class="key">image</span>: <span class="string">myacr.azurecr.io/bankapp:latest</span>
<span class="key">ports</span>:
- <span class="key">containerPort</span>: 8080
<span class="key">envFrom</span>:
- <span class="key">configMapRef</span>:
<span class="key">name</span>: bankapp-config
<span class="key">resources</span>:
<span class="key">requests</span>:
<span class="key">cpu</span>: <span class="string">"250m"</span>
<span class="key">memory</span>: <span class="string">"256Mi"</span>
<span class="key">limits</span>:
<span class="key">cpu</span>: <span class="string">"500m"</span>
<span class="key">memory</span>: <span class="string">"512Mi"</span>
<span class="key">readinessProbe</span>:
<span class="key">httpGet</span>:
<span class="key">path</span>: /actuator/health
<span class="key">port</span>: 8080
<span class="key">initialDelaySeconds</span>: 15
<span class="key">livenessProbe</span>:
<span class="key">httpGet</span>:
<span class="key">path</span>: /actuator/health
<span class="key">port</span>: 8080
<span class="key">initialDelaySeconds</span>: 30
---
<span class="key">apiVersion</span>: v1
<span class="key">kind</span>: Service
<span class="key">metadata</span>:
<span class="key">name</span>: bankapp-service
<span class="key">spec</span>:
<span class="key">type</span>: LoadBalancer
<span class="key">selector</span>:
<span class="key">app</span>: bankapp
<span class="key">ports</span>:
- <span class="key">port</span>: 80
<span class="key">targetPort</span>: 8080
</div>
<h3>AKS Deploy Pipeline Stage</h3>
<div class="code-block">
<span class="comment"># Deploy to AKS Stage</span>
- <span class="key">stage</span>: deploy_to_aks
<span class="key">displayName</span>: <span class="string">"Deploy to AKS"</span>
<span class="key">jobs</span>:
- <span class="key">deployment</span>: deploy_to_aks
<span class="key">environment</span>: <span class="string">"production.default"</span>
<span class="key">strategy</span>:
<span class="key">runOnce</span>:
<span class="key">deploy</span>:
<span class="key">steps</span>:
- <span class="key">task</span>: KubernetesManifest@1
<span class="key">inputs</span>:
<span class="key">action</span>: <span class="string">"deploy"</span>
<span class="key">kubernetesServiceConnection</span>: <span class="string">"k8s-conn"</span>
<span class="key">namespace</span>: <span class="string">"default"</span>
<span class="key">manifests</span>: <span class="string">"ds.yml"</span>
<span class="key">containers</span>: <span class="string">"myacr.azurecr.io/bankapp:$(Build.BuildId)"</span>
</div>
<h3>HPA β€” Horizontal Pod Autoscaler</h3>
<div class="code-block">
<span class="comment"># Auto-scale based on CPU utilization</span>
<span class="key">apiVersion</span>: autoscaling/v2
<span class="key">kind</span>: HorizontalPodAutoscaler
<span class="key">metadata</span>:
<span class="key">name</span>: bankapp-hpa
<span class="key">spec</span>:
<span class="key">scaleTargetRef</span>:
<span class="key">apiVersion</span>: apps/v1
<span class="key">kind</span>: Deployment
<span class="key">name</span>: bankapp
<span class="key">minReplicas</span>: 2
<span class="key">maxReplicas</span>: 10
<span class="key">metrics</span>:
- <span class="key">type</span>: Resource
<span class="key">resource</span>:
<span class="key">name</span>: cpu
<span class="key">target</span>:
<span class="key">type</span>: Utilization
<span class="key">averageUtilization</span>: 70
</div>
<h3>Essential kubectl Commands</h3>
<div class="code-block">
<span class="comment"># Cluster & Node info</span>
<span class="keyword">kubectl</span> cluster-info
<span class="keyword">kubectl</span> get nodes -o wide
<span class="keyword">kubectl</span> top nodes
<span class="comment"># Deploy and manage</span>
<span class="keyword">kubectl</span> apply -f ds.yml
<span class="keyword">kubectl</span> get pods -o wide
<span class="keyword">kubectl</span> get services
<span class="keyword">kubectl</span> get deployments
<span class="comment"># Debugging</span>
<span class="keyword">kubectl</span> describe pod bankapp-xyz
<span class="keyword">kubectl</span> logs bankapp-xyz --follow
<span class="keyword">kubectl</span> exec -it bankapp-xyz -- /bin/sh
<span class="keyword">kubectl</span> get events --sort-by=.metadata.creationTimestamp
<span class="comment"># Scaling & Updates</span>
<span class="keyword">kubectl</span> scale deployment bankapp --replicas=5
<span class="keyword">kubectl</span> rollout status deployment/bankapp
<span class="keyword">kubectl</span> rollout undo deployment/bankapp
<span class="keyword">kubectl</span> rollout history deployment/bankapp
</div>
`,
applications: `
<h3>Production Kubernetes Checklist</h3>
<div class="info-box">
<div class="box-title">βœ… Production-Ready AKS</div>
<div class="box-content">
βœ… <strong>Resource Limits:</strong> Set CPU/memory requests and limits on all containers<br>
βœ… <strong>Health Probes:</strong> Readiness + liveness probes for auto-restart and traffic control<br>
βœ… <strong>HPA:</strong> Horizontal Pod Autoscaler based on CPU/memory/custom metrics<br>
βœ… <strong>PDB:</strong> Pod Disruption Budget to ensure availability during updates<br>
βœ… <strong>Network Policies:</strong> Restrict pod-to-pod communication<br>
βœ… <strong>RBAC:</strong> Kubernetes RBAC + Azure AD integration<br>
βœ… <strong>Secrets:</strong> Use Azure Key Vault CSI driver instead of K8s Secrets<br>
βœ… <strong>Monitoring:</strong> Container Insights + Prometheus + Grafana<br>
βœ… <strong>Ingress:</strong> Use Ingress controller (NGINX/App Gateway) instead of LoadBalancer per service
</div>
</div>
<h3>Troubleshooting Common Issues</h3>
<table>
<tr><th>Status</th><th>Cause</th><th>Debug Command</th></tr>
<tr><td><strong>CrashLoopBackOff</strong></td><td>App crashes repeatedly</td><td>kubectl logs [pod] --previous</td></tr>
<tr><td><strong>ImagePullBackOff</strong></td><td>Can't pull image</td><td>kubectl describe pod [pod] β†’ check image name/registry auth</td></tr>
<tr><td><strong>Pending</strong></td><td>No schedulable node</td><td>kubectl describe pod β†’ check Events section</td></tr>
<tr><td><strong>OOMKilled</strong></td><td>Out of memory</td><td>Increase memory limits, check for memory leaks</td></tr>
<tr><td><strong>Evicted</strong></td><td>Node under pressure</td><td>kubectl get events, check node resources</td></tr>
</table>
<div class="interview-box">
<div class="box-title">πŸ“‹ Interview Questions & Answers</div>
<div class="box-content">
<strong>1. What is Kubernetes and why is it needed?</strong><br>
K8s automates container deployment, scaling, and management. Needed because: containers alone don't handle scheduling, scaling, self-healing, service discovery, or rolling updates. K8s provides all these.<br><br>
<strong>2. Pod vs Deployment vs Service β€” explain each.</strong><br>
Pod: smallest unit with one or more containers. Deployment: manages Pod replicas, rolling updates, rollbacks. Service: stable network endpoint (DNS name + IP) that routes to Pods via label selector.<br><br>
<strong>3. AKS vs self-managed K8s?</strong><br>
AKS: free managed control plane, automatic upgrades, Azure AD integration, no etcd management. Self-managed: full control, more operational burden, needed for air-gapped or highly customized environments.<br><br>
<strong>4. K8s Service types β€” explain each.</strong><br>
ClusterIP: internal only (default). NodePort: external via node IP:30000-32767. LoadBalancer: cloud LB with external IP. ExternalName: DNS CNAME alias. Use Ingress for HTTP routing instead of multiple LoadBalancers.<br><br>
<strong>5. Rolling Update vs Blue-Green vs Canary?</strong><br>
Rolling: gradual replacement (built-in). Blue-Green: two deployments, switch service selector (instant switch). Canary: route small % to new version (needs Istio/Nginx). Rolling is default, Blue-Green for zero-downtime, Canary for risk reduction.<br><br>
<strong>6. How do you troubleshoot CrashLoopBackOff?</strong><br>
1) kubectl logs [pod] --previous (check crash reason). 2) kubectl describe pod (check events). 3) Check resource limits (OOMKilled?). 4) Check health probes (failing?). 5) Exec into pod and test manually.<br><br>
<strong>7. What is Helm?</strong><br>
Package manager for Kubernetes. Helm Charts bundle K8s manifests into reusable, versioned packages. Supports templating (values.yaml), dependencies, rollback. Like npm/Maven but for K8s deployments.<br><br>
<strong>8. Readiness vs Liveness probes?</strong><br>
Readiness: "Am I ready to receive traffic?" β€” fails β†’ pod removed from Service endpoints. Liveness: "Am I still alive?" β€” fails β†’ pod restarted. Both are essential for production. Common mistake: same endpoint for both.<br><br>
<strong>9. What are Namespaces?</strong><br>
Virtual clusters within a K8s cluster. Use cases: environment separation (dev/staging/prod), team isolation, resource quotas. Default namespaces: default, kube-system, kube-public, kube-node-lease.<br><br>
<strong>10. How do you integrate AKS with Azure DevOps?</strong><br>
Create Kubernetes service connection in Azure DevOps (using kubeconfig or service account). Use KubernetesManifest@1 task in pipeline to deploy manifests. Use deployment jobs with environments for approval gates.
</div>
</div>
`
},
"security": {
concepts: `
<h3>Azure Security Model β€” Defense in Depth</h3>
<p>Security in Azure DevOps spans identity management, access control, secrets management, and service-to-service authentication across multiple layers.</p>
<h3>Identity & Authentication</h3>
<table>
<tr><th>Identity Type</th><th>What It Is</th><th>Use Case</th><th>Security Level</th></tr>
<tr><td><strong>Service Principal</strong></td><td>App identity in Azure AD</td><td>CI/CD pipeline authentication</td><td>Good (secret-based)</td></tr>
<tr><td><strong>Managed Identity</strong></td><td>Auto-managed identity for Azure resources</td><td>VM/AKS to Azure services</td><td>Best (no secrets)</td></tr>
<tr><td><strong>Workload Identity</strong></td><td>OIDC federation for K8s pods</td><td>K8s pod to Azure services</td><td>Best (no secrets)</td></tr>
<tr><td><strong>PAT (Personal Access Token)</strong></td><td>Alternative to password</td><td>Git auth, REST API</td><td>Moderate (user-scoped)</td></tr>
</table>
<div class="callout insight">
<div class="callout-title">πŸ’‘ Security Hierarchy (Best β†’ Worst)</div>
<strong>1. Managed Identity</strong> (no secrets, auto-rotated) β†’ <strong>2. Workload Identity</strong> (OIDC, no secrets) β†’ <strong>3. Service Principal</strong> (secret/cert, manual rotation) β†’ <strong>4. PAT</strong> (user-scoped, expires)
</div>
<h3>Service Connections</h3>
<table>
<tr><th>Connection Type</th><th>Connects To</th><th>Authentication</th><th>Used For</th></tr>
<tr><td><strong>Azure Resource Manager</strong></td><td>Azure subscription</td><td>Service Principal / Managed Identity</td><td>Deploy to Azure services</td></tr>
<tr><td><strong>SonarQube</strong></td><td>SonarQube server</td><td>Token</td><td>Code quality analysis</td></tr>
<tr><td><strong>Kubernetes</strong></td><td>AKS cluster</td><td>Kubeconfig / Service Account</td><td>Deploy manifests</td></tr>
<tr><td><strong>Docker Registry</strong></td><td>ACR / Docker Hub</td><td>Service Principal / Admin user</td><td>Push/pull images</td></tr>
</table>
<h3>Azure Key Vault</h3>
<div class="info-box">
<div class="box-title">πŸ” Key Vault β€” Secrets Management</div>
<div class="box-content">
<strong>What it stores:</strong> Secrets (passwords, connection strings), Keys (encryption keys), Certificates (TLS certs)<br>
<strong>Access control:</strong> RBAC (recommended) or Vault access policies<br>
<strong>Integration:</strong> Variable groups in Azure Pipelines, CSI driver in AKS, App Configuration<br>
<strong>Audit:</strong> Full logging of all secret access in Azure Monitor<br>
<strong>Rotation:</strong> Auto-rotation for storage account keys, manual for others
</div>
</div>
<h3>RBAC in Azure DevOps</h3>
<table>
<tr><th>Level</th><th>Role</th><th>Permissions</th></tr>
<tr><td>Organization</td><td>Collection Admin</td><td>Full control over all projects</td></tr>
<tr><td>Project</td><td>Project Admin</td><td>Full control within project</td></tr>
<tr><td>Project</td><td>Build Admin</td><td>Manage pipeline definitions</td></tr>
<tr><td>Project</td><td>Contributors</td><td>Edit code, run pipelines</td></tr>
<tr><td>Project</td><td>Readers</td><td>View only</td></tr>
<tr><td>Repository</td><td>Per-branch policies</td><td>Enforce reviews, build validation</td></tr>
</table>
<h3>Zero Trust for DevOps</h3>
<div class="callout warning">
<div class="callout-title">⚠️ Zero Trust Principles</div>
<strong>Verify explicitly:</strong> Authenticate and authorize every request<br>
<strong>Least privilege:</strong> Minimum permissions needed for the task<br>
<strong>Assume breach:</strong> Encrypt, segment, monitor as if already compromised<br><br>
Applied to DevOps: branch policies, required reviewers, environment approvals, secret scanning, audit logging, immutable artifacts.
</div>
`,
handson: `
<h3>Creating a Service Principal</h3>
<div class="code-block">
<span class="comment"># Step 1: Create service principal with contributor role</span>
<span class="keyword">az</span> ad sp create-for-rbac \\
--name <span class="string">"devops-pipeline-sp"</span> \\
--role Contributor \\
--scopes /subscriptions/<SUB_ID> \\
--sdk-auth
<span class="comment"># Output: appId, password, tenant (save securely!)</span>
<span class="comment"># Step 2: Use in Azure DevOps Service Connection</span>
<span class="comment"># Project Settings β†’ Service Connections β†’ New β†’ Azure Resource Manager</span>
<span class="comment"># Choose "Service Principal (manual)" β†’ Enter appId, password, tenant</span>
</div>
<h3>Managed Identity Setup</h3>
<div class="code-block">
<span class="comment"># System-assigned identity (auto-created with resource)</span>
<span class="keyword">az</span> vm identity assign \\
--resource-group rg-devops \\
--name agent-vm
<span class="comment"># User-assigned identity (reusable across resources)</span>
<span class="keyword">az</span> identity create \\
--resource-group rg-devops \\
--name pipeline-identity
<span class="comment"># Assign Key Vault access</span>
<span class="keyword">az</span> keyvault set-policy \\
--name my-keyvault \\
--object-id <IDENTITY_PRINCIPAL_ID> \\
--secret-permissions get list
</div>
<h3>Key Vault Integration with Pipelines</h3>
<div class="code-block">
<span class="comment"># Method 1: Variable Group linked to Key Vault</span>
<span class="key">variables</span>:
- <span class="key">group</span>: <span class="string">"kv-secrets"</span> <span class="comment"># Linked to Azure Key Vault in UI</span>
<span class="key">steps</span>:
- <span class="key">script</span>: |
echo "DB Password: $(db-password)"
<span class="key">displayName</span>: <span class="string">"Use secret from Key Vault"</span>
<span class="comment"># Method 2: AzureKeyVault task (more control)</span>
<span class="key">steps</span>:
- <span class="key">task</span>: AzureKeyVault@2
<span class="key">inputs</span>:
<span class="key">azureSubscription</span>: <span class="string">"azure-conn"</span>
<span class="key">keyVaultName</span>: <span class="string">"my-keyvault"</span>
<span class="key">secretsFilter</span>: <span class="string">"db-password,api-key"</span>
- <span class="key">script</span>: |
echo "DB Password: $(db-password)"
echo "API Key: $(api-key)"
</div>
<h3>K8s RBAC + Azure AD</h3>
<div class="code-block">
<span class="comment"># Kubernetes RBAC β€” Limit namespace access</span>
<span class="key">apiVersion</span>: rbac.authorization.k8s.io/v1
<span class="key">kind</span>: Role
<span class="key">metadata</span>:
<span class="key">namespace</span>: production
<span class="key">name</span>: deployment-manager
<span class="key">rules</span>:
- <span class="key">apiGroups</span>: [<span class="string">"apps"</span>]
<span class="key">resources</span>: [<span class="string">"deployments"</span>]
<span class="key">verbs</span>: [<span class="string">"get"</span>, <span class="string">"list"</span>, <span class="string">"update"</span>, <span class="string">"patch"</span>]
---
<span class="key">apiVersion</span>: rbac.authorization.k8s.io/v1
<span class="key">kind</span>: RoleBinding
<span class="key">metadata</span>:
<span class="key">namespace</span>: production
<span class="key">name</span>: deployer-binding
<span class="key">subjects</span>:
- <span class="key">kind</span>: Group
<span class="key">name</span>: <span class="string">"AAD-GROUP-OBJECT-ID"</span>
<span class="key">roleRef</span>:
<span class="key">kind</span>: Role
<span class="key">name</span>: deployment-manager
</div>
<h3>Secret Scanning Prevention</h3>
<div class="code-block">
<span class="comment"># .gitignore β€” Never commit secrets</span>
*.env
.env.local
secrets/
*.pem
*.key
<span class="comment"># Pre-commit hook for secret detection</span>
<span class="comment"># Install: pip install detect-secrets</span>
<span class="keyword">detect-secrets</span> scan > .secrets.baseline
<span class="keyword">detect-secrets</span> audit .secrets.baseline
<span class="comment"># Azure DevOps: Enable credential scanning</span>
<span class="comment"># Pipeline β†’ CredScan@3 task scans for leaked passwords, tokens, keys</span>
</div>
`,
applications: `
<h3>Security Checklist for CI/CD</h3>
<div class="info-box">
<div class="box-title">πŸ›‘οΈ Production Security Checklist</div>
<div class="box-content">
βœ… Use Managed Identity or Workload Identity (not Service Principals with secrets)<br>
βœ… Store all secrets in Azure Key Vault, never in code or pipeline variables<br>
βœ… Enable branch policies and required reviewers on main<br>
βœ… SAST (SonarQube) + SCA (Trivy) + container scanning in every pipeline<br>
βœ… Implement least-privilege RBAC in Azure DevOps and Kubernetes<br>
βœ… Enable audit logging in Azure DevOps and Azure Monitor<br>
βœ… Secret rotation with auto-rotation policies where possible<br>
βœ… Sign container images (Docker Content Trust / Notary)<br>
βœ… Network segmentation with NSGs and Network Policies<br>
βœ… Enable Azure Defender for Containers (runtime protection)
</div>
</div>
<div class="interview-box">
<div class="box-title">πŸ“‹ Interview Questions & Answers</div>
<div class="box-content">
<strong>1. Service Principal vs Managed Identity?</strong><br>
SP: app identity with client ID + secret/cert (you manage rotation). MI: Azure-managed identity (no secrets, auto-rotated). Always prefer MI. Use SP only when MI isn't available (e.g., cross-tenant).<br><br>
<strong>2. How do you manage Service Connections?</strong><br>
Project Settings β†’ Service Connections. Types: Azure RM, K8s, Docker, SonarQube. Best practice: use Workload Identity federation, limit to specific pipelines, audit usage regularly.<br><br>
<strong>3. What is Azure Key Vault and pipeline integration?</strong><br>
Centralized secrets management. Integrate via: Variable Groups linked to Key Vault (auto-sync secrets), AzureKeyVault@2 task (fetch at runtime), or K8s CSI driver (mount as volumes in pods).<br><br>
<strong>4. PAT security risks and alternatives?</strong><br>
Risks: can be leaked in logs, shared between users, broad permissions. Alternatives: Managed Identity (Azure resources), SSH keys (Git), OAuth (interactive), Service Principal (automation).<br><br>
<strong>5. Explain RBAC in Azure DevOps.</strong><br>
Role-Based Access Control at org, project, and resource levels. Built-in groups (Admin, Contributor, Reader). Can create custom groups. Best practice: least privilege, use Azure AD groups, regular access reviews.<br><br>
<strong>6. How do you prevent secrets from leaking in pipeline logs?</strong><br>
Mark variables as secret (masked in logs), use Key Vault (variables auto-masked), don't echo secrets in scripts, use ##vso[task.setvariable variable=x;issecret=true], enable credential scanning.<br><br>
<strong>7. What is Workload Identity Federation?</strong><br>
OIDC-based authentication that eliminates secrets entirely. K8s pod gets an OIDC token β†’ exchanges for Azure AD token β†’ accesses Azure resources. No client secret needed. Newest and most secure approach.<br><br>
<strong>8. What is Zero Trust for DevOps?</strong><br>
Apply Zero Trust principles: verify explicitly (authenticate everything), least privilege (minimum permissions), assume breach (encrypt, segment, log). Specific: branch policies, environment approvals, signed artifacts, audit trails.
</div>
</div>
`
},
"mlops": {
concepts: `
<h3>What is MLOps?</h3>
<p>MLOps (Machine Learning Operations) applies DevOps principles to the ML lifecycle: data preparation, model training, evaluation, deployment, and monitoring. It bridges the gap between <strong>data scientists</strong> (experimentation) and <strong>ML engineers</strong> (production).</p>
<div class="pipeline-flow">
<div class="pipeline-stage" style="background: rgba(0,120,212,0.2); color: #0078D4;">Data</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(0,183,195,0.2); color: #00b7c3;">Feature Eng</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(163,113,247,0.2); color: #a371f7;">Train</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(255,107,53,0.2); color: #ff6b35;">Evaluate</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(0,255,136,0.2); color: #00ff88;">Register</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(46,204,113,0.2); color: #2ecc71;">Deploy</div>
<span class="pipeline-arrow">β†’</span>
<div class="pipeline-stage" style="background: rgba(231,76,60,0.2); color: #e74c3c;">Monitor</div>
</div>
<h3>MLOps Maturity Levels</h3>
<table>
<tr><th>Level</th><th>Name</th><th>Description</th><th>Automation</th></tr>
<tr><td>0</td><td>No MLOps</td><td>Manual notebooks, no versioning, manual deployment</td><td>None</td></tr>
<tr><td>1</td><td>DevOps but no MLOps</td><td>CI/CD for code but not for data or models</td><td>Code only</td></tr>
<tr><td>2</td><td>Automated Training</td><td>Automated training pipeline, model registry, experiment tracking</td><td>Code + Training</td></tr>
<tr><td>3</td><td>Automated Deployment</td><td>CI/CD for models, A/B testing, automated validation</td><td>Code + Training + Deploy</td></tr>
<tr><td>4</td><td>Full MLOps</td><td>Auto-retraining on drift, canary rollouts, full observability</td><td>Everything</td></tr>
</table>
<h3>The Three Pillars of MLOps</h3>
<div class="info-box">
<div class="box-title">🧠 Data + Model + Deploy</div>
<div class="box-content">
<strong>1. Data Management:</strong> Data versioning (DVC), data validation (Great Expectations), feature stores (Feast), lineage tracking<br>
<strong>2. Model Management:</strong> Experiment tracking (MLflow), model registry (versioning + staging), reproducibility (environment + hyperparams)<br>
<strong>3. Deployment & Monitoring:</strong> Model serving (batch/real-time), A/B testing, shadow deployments, drift detection, retraining triggers
</div>
</div>
<h3>Data Drift vs Concept Drift vs Model Decay</h3>
<table>
<tr><th>Type</th><th>What Changes</th><th>Detection Method</th><th>Example</th><th>Solution</th></tr>
<tr><td><strong>Data Drift</strong></td><td>Input distribution shifts</td><td>KS test, PSI, JS divergence</td><td>Avg income increases over time</td><td>Retrain on new data</td></tr>
<tr><td><strong>Concept Drift</strong></td><td>Input→Output relationship changes</td><td>Performance monitoring</td><td>COVID changes purchasing patterns</td><td>Retrain with new labels</td></tr>
<tr><td><strong>Model Decay</strong></td><td>Accuracy degrades gradually</td><td>Accuracy/F1 dashboards</td><td>Model slowly becomes stale</td><td>Scheduled retraining</td></tr>
</table>
<h3>MLOps vs LLMOps</h3>
<table>
<tr><th>Aspect</th><th>Traditional MLOps</th><th>LLMOps</th></tr>
<tr><td>Training</td><td>Custom models from scratch</td><td>Fine-tuning pre-trained models</td></tr>
<tr><td>Evaluation</td><td>Accuracy, F1, AUC</td><td>Human eval, benchmarks, safety tests</td></tr>
<tr><td>Data</td><td>Structured datasets</td><td>Text corpora, RLHF data</td></tr>
<tr><td>Deployment</td><td>Model serving</td><td>Prompt management + model serving</td></tr>
<tr><td>Monitoring</td><td>Data drift, accuracy</td><td>Hallucination, toxicity, latency</td></tr>
<tr><td>Cost</td><td>Compute for training</td><td>Inference cost (token-based billing)</td></tr>
</table>
`,
handson: `
<h3>Azure ML + Azure DevOps Integration</h3>
<div class="code-block">
<span class="comment"># azure-pipelines.yml β€” MLOps Pipeline</span>
<span class="key">trigger</span>:
<span class="key">branches</span>: { <span class="key">include</span>: [main] }
<span class="key">paths</span>: { <span class="key">include</span>: [src/ml/*, data/*] }
<span class="key">stages</span>:
- <span class="key">stage</span>: DataValidation
<span class="key">jobs</span>:
- <span class="key">job</span>: validate_data
<span class="key">steps</span>:
- <span class="key">script</span>: |
python validate_data.py \\
--input data/train.csv \\
--schema schema.json
python check_data_drift.py \\
--reference data/baseline.csv \\
--current data/train.csv \\
--threshold 0.05
- <span class="key">stage</span>: TrainModel
<span class="key">dependsOn</span>: DataValidation
<span class="key">jobs</span>:
- <span class="key">job</span>: train
<span class="key">steps</span>:
- <span class="key">task</span>: AzureCLI@2
<span class="key">inputs</span>:
<span class="key">azureSubscription</span>: <span class="string">"azure-ml-conn"</span>
<span class="key">scriptType</span>: <span class="string">"bash"</span>
<span class="key">inlineScript</span>: |
az ml job create -f train_job.yml \\
--set inputs.train_data=azureml:train_data:latest
- <span class="key">stage</span>: EvaluateModel
<span class="key">dependsOn</span>: TrainModel
<span class="key">jobs</span>:
- <span class="key">job</span>: evaluate
<span class="key">steps</span>:
- <span class="key">script</span>: |
python evaluate_model.py \\
--model-path outputs/model.pkl \\
--test-data data/test.csv \\
--min-accuracy 0.85
- <span class="key">stage</span>: RegisterModel
<span class="key">dependsOn</span>: EvaluateModel
<span class="key">jobs</span>:
- <span class="key">job</span>: register
<span class="key">steps</span>:
- <span class="key">script</span>: |
az ml model create \\
--name fraud-detector \\
--version $(Build.BuildId) \\
--path outputs/model.pkl \\
--type mlflow_model
- <span class="key">stage</span>: DeployModel
<span class="key">dependsOn</span>: RegisterModel
<span class="key">jobs</span>:
- <span class="key">deployment</span>: deploy
<span class="key">environment</span>: <span class="string">"ml-production"</span>
<span class="key">strategy</span>:
<span class="key">runOnce</span>:
<span class="key">deploy</span>:
<span class="key">steps</span>:
- <span class="key">script</span>: |
az ml online-deployment create \\
-f deployment.yml \\
--set traffic=10 <span class="comment"># Canary: 10% traffic</span>
</div>
<h3>MLflow Experiment Tracking</h3>
<div class="code-block">
<span class="comment"># Python β€” Track experiments with MLflow</span>
<span class="keyword">import</span> mlflow
<span class="keyword">from</span> sklearn.ensemble <span class="keyword">import</span> RandomForestClassifier
<span class="keyword">from</span> sklearn.metrics <span class="keyword">import</span> accuracy_score, f1_score
mlflow.set_tracking_uri(<span class="string">"azureml://..."</span>)
mlflow.set_experiment(<span class="string">"fraud-detection"</span>)
<span class="keyword">with</span> mlflow.start_run():
<span class="comment"># Log parameters</span>
mlflow.log_param(<span class="string">"learning_rate"</span>, 0.01)
mlflow.log_param(<span class="string">"n_estimators"</span>, 100)
mlflow.log_param(<span class="string">"max_depth"</span>, 10)
<span class="comment"># Train</span>
model = RandomForestClassifier(n_estimators=100)
model.fit(X_train, y_train)
<span class="comment"># Evaluate and log metrics</span>
y_pred = model.predict(X_test)
mlflow.log_metric(<span class="string">"accuracy"</span>, accuracy_score(y_test, y_pred))
mlflow.log_metric(<span class="string">"f1_score"</span>, f1_score(y_test, y_pred))
<span class="comment"># Log model + artifacts</span>
mlflow.sklearn.log_model(model, <span class="string">"model"</span>)
mlflow.log_artifact(<span class="string">"confusion_matrix.png"</span>)
</div>
<h3>Data Drift Detection Script</h3>
<div class="code-block">
<span class="comment"># drift_detector.py β€” Detect data drift using PSI</span>
<span class="keyword">import</span> numpy <span class="keyword">as</span> np
<span class="keyword">def</span> <span class="key">calculate_psi</span>(baseline, current, bins=10):
<span class="string">"""Population Stability Index"""</span>
baseline_pct = np.histogram(baseline, bins=bins)[0] / len(baseline)
current_pct = np.histogram(current, bins=bins)[0] / len(current)
<span class="comment"># Avoid division by zero</span>
baseline_pct = np.clip(baseline_pct, 0.001, None)
current_pct = np.clip(current_pct, 0.001, None)
psi = np.sum((current_pct - baseline_pct) * np.log(current_pct / baseline_pct))
<span class="keyword">return</span> psi
<span class="comment"># PSI thresholds:</span>
<span class="comment"># < 0.1 β†’ No drift (stable)</span>
<span class="comment"># 0.1-0.2 β†’ Moderate drift (investigate)</span>
<span class="comment"># > 0.2 β†’ Significant drift (retrain!)</span>
</div>
`,
applications: `
<h3>MLOps Tools Ecosystem</h3>
<table>
<tr><th>Category</th><th>Azure</th><th>Open Source</th><th>When to Use</th></tr>
<tr><td>Experiment Tracking</td><td>Azure ML Studio</td><td>MLflow, W&B</td><td>Every ML project</td></tr>
<tr><td>Data Versioning</td><td>Azure ML Datasets</td><td>DVC, LakeFS</td><td>Reproducibility needed</td></tr>
<tr><td>Model Registry</td><td>Azure ML Registry</td><td>MLflow Registry</td><td>Model management</td></tr>
<tr><td>Feature Store</td><td>Azure ML Feature Store</td><td>Feast, Tecton</td><td>Feature reuse across teams</td></tr>
<tr><td>Model Serving</td><td>Azure ML Endpoints</td><td>Seldon, BentoML, TorchServe</td><td>Real-time inference</td></tr>
<tr><td>Monitoring</td><td>Azure ML Monitoring</td><td>Evidently, WhyLabs</td><td>Production drift detection</td></tr>
<tr><td>Pipeline Orchestration</td><td>Azure ML Pipelines</td><td>Kubeflow, Airflow</td><td>Complex training workflows</td></tr>
</table>
<h3>Responsible AI</h3>
<div class="info-box">
<div class="box-title">πŸ€– Microsoft's Responsible AI Principles</div>
<div class="box-content">
<strong>Fairness:</strong> Models should not discriminate (check across demographics)<br>
<strong>Reliability:</strong> Models should work consistently in production<br>
<strong>Privacy:</strong> Data handling must respect privacy regulations (GDPR, CCPA)<br>
<strong>Inclusiveness:</strong> Accessible to all users<br>
<strong>Transparency:</strong> Explainable predictions (SHAP, LIME)<br>
<strong>Accountability:</strong> Clear ownership of model decisions<br><br>
<strong>Azure Tool:</strong> Responsible AI Dashboard (fairness, interpretability, error analysis, causal analysis)
</div>
</div>
<div class="interview-box">
<div class="box-title">πŸ“‹ Interview Questions & Answers</div>
<div class="box-content">
<strong>1. What is MLOps and how does it differ from DevOps?</strong><br>
MLOps adds data versioning, model versioning, experiment tracking, drift detection, and continuous training to DevOps. ML systems have more axes of change (code + data + model + hyperparams) making them more complex.<br><br>
<strong>2. Explain MLOps maturity levels.</strong><br>
Level 0: Manual everything. Level 1: CI/CD for code only. Level 2: Automated training pipelines. Level 3: Automated model deployment with validation. Level 4: Full automation including drift-triggered retraining.<br><br>
<strong>3. How do you detect data drift?</strong><br>
Statistical tests: KS test (distribution comparison), PSI (Population Stability Index), JS divergence. Monitor feature distributions over time. PSI > 0.2 = significant drift requiring retraining.<br><br>
<strong>4. What is a model registry?</strong><br>
Central repository for versioned ML models. Tracks: model versions, metrics, lineage (what data/code produced it), stage (staging/production/archived). Enables reproducibility and governance.<br><br>
<strong>5. How do you implement CI/CD for ML in Azure DevOps?</strong><br>
Pipeline stages: data validation β†’ training (az ml job create) β†’ model evaluation (compare to baseline) β†’ register model β†’ deploy to endpoint. Trigger on data changes or code changes.<br><br>
<strong>6. What is a feature store?</strong><br>
Centralized repository for feature definitions and computed feature values. Benefits: feature reuse across teams, consistent features in training vs serving, point-in-time correctness, feature discovery.<br><br>
<strong>7. How do you implement A/B testing for ML models?</strong><br>
Deploy multiple model versions behind same endpoint. Route traffic by percentage (canary: 10/90) or user segments. Compare metrics (accuracy, latency, business KPIs). Gradually shift traffic to winner.<br><br>
<strong>8. What is MLflow and Azure ML integration?</strong><br>
MLflow: open-source platform for experiment tracking, model packaging, deployment. Azure ML natively supports MLflow tracking URI β€” log experiments from local code to Azure ML. Models logged as MLflow format are auto-deployable.<br><br>
<strong>9. How would you design an auto-retraining pipeline?</strong><br>
Monitor data drift (PSI) and model performance (accuracy). When drift exceeds threshold OR accuracy drops below baseline: trigger training pipeline β†’ evaluate new model β†’ if better, auto-deploy with canary strategy β†’ notify team.<br><br>
<strong>10. What is Responsible AI and why does it matter?</strong><br>
Ethical AI development: fairness (no discrimination), reliability (consistent performance), privacy (data protection), transparency (explainable predictions), accountability (ownership). Azure provides Responsible AI Dashboard for automated checks.
</div>
</div>
`
},
"monitoring": {
concepts: `
<h3>The Three Pillars of Observability</h3>
<div class="info-box">
<div class="box-title">πŸ“Š Logs + Metrics + Traces</div>
<div class="box-content">
<strong>Logs:</strong> Timestamped records of events. Structured logging (JSON) with correlation IDs for tracing across services. Tool: Azure Log Analytics (KQL queries).<br><br>
<strong>Metrics:</strong> Numeric measurements over time (time-series). CPU, memory, request rate, error rate, latency percentiles. Tool: Azure Monitor Metrics, Prometheus.<br><br>
<strong>Traces:</strong> End-to-end request journey across microservices. Shows latency breakdown per service hop. Tool: Application Insights (distributed tracing), Jaeger.
</div>
</div>
<h3>Monitoring Stack in Azure</h3>
<table>
<tr><th>Layer</th><th>What to Monitor</th><th>Azure Tool</th><th>Key Metrics</th></tr>
<tr><td><strong>Infrastructure</strong></td><td>CPU, Memory, Disk, Network</td><td>Azure Monitor</td><td>CPU %, Memory %, Disk IOPS</td></tr>
<tr><td><strong>Application</strong></td><td>Response time, Errors, Throughput</td><td>Application Insights</td><td>P50/P95/P99 latency, error rate</td></tr>
<tr><td><strong>Kubernetes</strong></td><td>Pod health, Node status</td><td>Container Insights</td><td>Pod restarts, OOMKills, node CPU</td></tr>
<tr><td><strong>Pipeline</strong></td><td>Build time, Failure rate</td><td>Azure DevOps Analytics</td><td>DORA metrics</td></tr>
<tr><td><strong>ML Models</strong></td><td>Accuracy, Data drift</td><td>Azure ML Monitoring</td><td>PSI, prediction accuracy</td></tr>
</table>
<h3>SLOs, SLIs, and SLAs</h3>
<table>
<tr><th>Term</th><th>Definition</th><th>Example</th><th>Owner</th></tr>
<tr><td><strong>SLI</strong></td><td>Service Level Indicator (metric)</td><td>Request latency P99</td><td>Engineering</td></tr>
<tr><td><strong>SLO</strong></td><td>Service Level Objective (target)</td><td>P99 latency < 200ms</td><td>Engineering + Product</td></tr>
<tr><td><strong>SLA</strong></td><td>Service Level Agreement (contract)</td><td>99.9% uptime or credits</td><td>Business + Legal</td></tr>
<tr><td><strong>Error Budget</strong></td><td>100% - SLO = room for risk</td><td>99.9% SLO = 43min/month downtime OK</td><td>SRE Team</td></tr>
</table>
<h3>Deployment Verification</h3>
<div class="info-box">
<div class="box-title">βœ… Post-Deployment Checklist</div>
<div class="box-content">
<strong>1.</strong> AKS β†’ Workloads β†’ Verify pods are Running (not CrashLoopBackOff)<br>
<strong>2.</strong> Services and Ingresses β†’ Get External IP<br>
<strong>3.</strong> Access the app via browser and verify functionality<br>
<strong>4.</strong> Check Application Insights for error spikes<br>
<strong>5.</strong> Verify health check endpoints responding (200 OK)<br>
<strong>6.</strong> Check Container Insights for resource utilization
</div>
</div>
<h3>Incident Management</h3>
<div class="callout warning">
<div class="callout-title">⚠️ Incident Response Framework</div>
<strong>Detect:</strong> Automated alerts (Azure Monitor, PagerDuty)<br>
<strong>Triage:</strong> Classify severity (SEV1 = customer-facing, SEV4 = cosmetic)<br>
<strong>Respond:</strong> Incident commander coordinates. Communicate to stakeholders.<br>
<strong>Mitigate:</strong> Rollback, feature flag, scale up β€” restore service ASAP<br>
<strong>Review:</strong> Blameless postmortem within 48 hours. Document root cause, timeline, action items.
</div>
<h3>Pipeline Automation</h3>
<div class="callout insight">
<div class="callout-title">πŸ’‘ From Manual to Automated</div>
Change <code>trigger: none</code> to <code>trigger: [main]</code> in the YAML pipeline. Then test by creating a new file in Azure Repos β€” the pipeline should start automatically. Use path filters to trigger only on relevant changes.
</div>
`,
handson: `
<h3>Azure Monitor + Container Insights</h3>
<div class="code-block">
<span class="comment"># Enable Container Insights on AKS</span>
<span class="keyword">az</span> aks enable-addons \\
--resource-group rg-devops \\
--name my-aks-cluster \\
--addons monitoring \\
--workspace-resource-id /subscriptions/.../log-analytics-workspace
<span class="comment"># Create Application Insights</span>
<span class="keyword">az</span> monitor app-insights component create \\
--app bankapp-insights \\
--location eastus \\
--resource-group rg-devops \\
--kind web
</div>
<h3>KQL Queries for Log Analytics</h3>
<div class="code-block">
<span class="comment">// Find all container restarts in last 24 hours</span>
<span class="keyword">KubePodInventory</span>
| <span class="keyword">where</span> TimeGenerated > ago(24h)
| <span class="keyword">where</span> ContainerRestartCount > 0
| <span class="keyword">project</span> TimeGenerated, Namespace, Name, ContainerRestartCount
| <span class="keyword">order by</span> ContainerRestartCount desc
<span class="comment">// Request latency percentiles (Application Insights)</span>
<span class="keyword">requests</span>
| <span class="keyword">where</span> timestamp > ago(1h)
| <span class="keyword">summarize</span>
p50 = percentile(duration, 50),
p95 = percentile(duration, 95),
p99 = percentile(duration, 99),
total = count(),
errors = countif(success == false)
<span class="keyword">by</span> bin(timestamp, 5m)
| <span class="keyword">render</span> timechart
<span class="comment">// Find pods with high CPU usage</span>
<span class="keyword">Perf</span>
| <span class="keyword">where</span> ObjectName == <span class="string">"K8SContainer"</span>
| <span class="keyword">where</span> CounterName == <span class="string">"cpuUsageNanoCores"</span>
| <span class="keyword">summarize</span> avg(CounterValue) by InstanceName
| <span class="keyword">where</span> avg_CounterValue > 500000000 <span class="comment">// > 500m CPU</span>
</div>
<h3>Alerting Rules</h3>
<div class="code-block">
<span class="comment"># Create Azure Monitor Alert for high CPU</span>
<span class="keyword">az</span> monitor metrics alert create \\
--name <span class="string">"high-cpu-alert"</span> \\
--resource-group rg-devops \\
--scopes /subscriptions/.../aks-cluster \\
--condition <span class="string">"avg Percentage CPU > 80"</span> \\
--action /subscriptions/.../action-group \\
--window-size 5m \\
--evaluation-frequency 1m \\
--severity 2
<span class="comment"># Create alert for error rate spike</span>
<span class="keyword">az</span> monitor metrics alert create \\
--name <span class="string">"high-error-rate"</span> \\
--resource-group rg-devops \\
--scopes /subscriptions/.../app-insights \\
--condition <span class="string">"count requests/failed > 10"</span> \\
--window-size 5m \\
--severity 1
</div>
<h3>Pipeline Notifications</h3>
<div class="code-block">
<span class="comment"># Notification stage β€” runs always (even on failure)</span>
<span class="key">stages</span>:
- <span class="key">stage</span>: Notify
<span class="key">condition</span>: always()
<span class="key">jobs</span>:
- <span class="key">job</span>: send_notification
<span class="key">steps</span>:
- <span class="key">script</span>: |
<span class="keyword">if</span> [ "$(Agent.JobStatus)" == "Succeeded" ]; then
MSG="βœ… Pipeline PASSED β€” Build $(Build.BuildId)"
<span class="keyword">else</span>
MSG="❌ Pipeline FAILED β€” Build $(Build.BuildId)"
<span class="keyword">fi</span>
<span class="comment"># Send to Microsoft Teams via webhook</span>
curl -H "Content-Type: application/json" \\
-d "{\"text\":\"$MSG\"}" \\
$(TEAMS_WEBHOOK_URL)
</div>
<h3>Grafana Dashboard Setup on AKS</h3>
<div class="code-block">
<span class="comment"># Install Prometheus + Grafana via Helm</span>
<span class="keyword">helm</span> repo add prometheus-community \\
https://prometheus-community.github.io/helm-charts
<span class="keyword">helm</span> install monitoring prometheus-community/kube-prometheus-stack \\
--namespace monitoring \\
--create-namespace \\
--set grafana.adminPassword=<span class="string">"SecurePass123"</span>
<span class="comment"># Access Grafana</span>
<span class="keyword">kubectl</span> port-forward svc/monitoring-grafana 3000:80 -n monitoring
<span class="comment"># Open http://localhost:3000 (admin / SecurePass123)</span>
<span class="comment"># Pre-built dashboards: K8s Cluster, Pod Resources, Node Exporter</span>
</div>
`,
applications: `
<h3>Observability Best Practices</h3>
<div class="info-box">
<div class="box-title">πŸ“Š Production Monitoring Checklist</div>
<div class="box-content">
βœ… <strong>Application:</strong> Application Insights (latency, errors, throughput)<br>
βœ… <strong>Infrastructure:</strong> Container Insights (CPU, memory, disk per pod/node)<br>
βœ… <strong>Alerting:</strong> Severity-based alerts (SEV1 β†’ PagerDuty, SEV3 β†’ Teams)<br>
βœ… <strong>Dashboards:</strong> Grafana or Azure Workbooks for team-specific views<br>
βœ… <strong>Logging:</strong> Structured JSON logs with correlation IDs<br>
βœ… <strong>Tracing:</strong> Distributed tracing across microservices<br>
βœ… <strong>SLOs:</strong> Defined for critical services with error budgets<br>
βœ… <strong>Runbooks:</strong> Automated remediation for common issues<br>
βœ… <strong>Postmortems:</strong> Blameless review within 48 hours of incidents
</div>
</div>
<h3>Golden Signals of Monitoring</h3>
<table>
<tr><th>Signal</th><th>What to Measure</th><th>Alert Threshold</th></tr>
<tr><td><strong>Latency</strong></td><td>P50, P95, P99 response times</td><td>P99 > 500ms</td></tr>
<tr><td><strong>Traffic</strong></td><td>Requests per second</td><td>Sudden drop > 50%</td></tr>
<tr><td><strong>Errors</strong></td><td>HTTP 5xx rate, exception rate</td><td>Error rate > 1%</td></tr>
<tr><td><strong>Saturation</strong></td><td>CPU, memory, queue depth</td><td>CPU > 80%, Memory > 85%</td></tr>
</table>
<div class="interview-box">
<div class="box-title">πŸ“‹ Interview Questions & Answers</div>
<div class="box-content">
<strong>1. How do you verify a deployment in AKS?</strong><br>
Check pod status (kubectl get pods), verify service endpoints, test health check URLs, check Application Insights for error spikes, verify Container Insights for resource usage. Use deployment jobs with health checks.<br><br>
<strong>2. What are the three pillars of observability?</strong><br>
Logs (what happened β€” event records), Metrics (how much β€” time-series numbers), Traces (where β€” request journey across services). All three together provide complete system understanding.<br><br>
<strong>3. What are SLOs, SLIs, SLAs?</strong><br>
SLI: the metric you measure (P99 latency). SLO: the target you set (P99 < 200ms). SLA: the contract with customers (99.9% uptime or credits). Error budget = 100% - SLO = acceptable downtime.<br><br>
<strong>4. What are the Golden Signals?</strong><br>
Google SRE's four key metrics: Latency (how fast), Traffic (how much), Errors (how often it fails), Saturation (how full). Every service should be monitored on these four signals.<br><br>
<strong>5. What is KQL and how is it used?</strong><br>
Kusto Query Language β€” used in Azure Log Analytics and Application Insights. SQL-like syntax for querying logs and metrics. Key operators: where, summarize, project, render. Essential for building dashboards and alerts.<br><br>
<strong>6. How do you set up alerting?</strong><br>
Azure Monitor β†’ Alerts β†’ Metric/log-based rules with severity levels. Action groups define notification targets (email, SMS, Teams, PagerDuty, Azure Functions). Use severity 1-4 for priority routing.<br><br>
<strong>7. Prometheus + Grafana vs Azure Monitor?</strong><br>
Prometheus+Grafana: open-source, portable, highly customizable, runs in-cluster. Azure Monitor: managed service, integrated with Azure, less ops burden, supports multi-cloud via Azure Arc. Many teams use both.<br><br>
<strong>8. What is a blameless postmortem?</strong><br>
After-incident review focused on systems and processes, not individuals. Documents: timeline, root cause, impact, what went well, what didn't, action items. Goal: organizational learning and system improvement.<br><br>
<strong>9. How do you track DORA metrics?</strong><br>
Deployment Frequency: pipeline run count. Lead Time: commit timestamp to deploy timestamp. Change Failure Rate: failed deploys / total deploys. MTTR: time between incident detection and resolution. Azure DevOps Analytics provides these.<br><br>
<strong>10. How would you set up monitoring for an ML model?</strong><br>
Monitor: prediction latency, request volume, prediction distribution, data drift (PSI), model accuracy on labeled samples. Alert on: drift > threshold, accuracy drop, latency spike. Auto-trigger retraining pipeline on significant drift.
</div>
</div>
`
}
};
function createModuleHTML(module) {
const content = MODULE_CONTENT[module.id] || {};
return `
<div class="module" id="${module.id}-module">
<button class="btn-back" onclick="switchTo('dashboard')">← Back to Dashboard</button>
<header>
<h1>${module.icon} ${module.title}</h1>
<p class="subtitle">${module.description}</p>
</header>
<div class="tabs">
<button class="tab-btn active" onclick="switchTab(event, '${module.id}-concepts')">πŸ“– Key Concepts</button>
<button class="tab-btn" onclick="switchTab(event, '${module.id}-handson')">πŸ”§ Hands-On / YAML</button>
<button class="tab-btn" onclick="switchTab(event, '${module.id}-applications')">🎯 Applications & Interview</button>
</div>
<div id="${module.id}-concepts" class="tab active">
<div class="section">
<h2>πŸ“– Key Concepts</h2>
${content.concepts || '<p>Content loading...</p>'}
</div>
</div>
<div id="${module.id}-handson" class="tab">
<div class="section">
<h2>πŸ”§ Hands-On / YAML</h2>
${content.handson || '<p>Content loading...</p>'}
</div>
</div>
<div id="${module.id}-applications" class="tab">
<div class="section">
<h2>🎯 Applications & Interview Questions</h2>
${content.applications || '<p>Content loading...</p>'}
</div>
</div>
</div>
`;
}
function initDashboard() {
const grid = document.getElementById("modulesGrid");
const container = document.getElementById("modulesContainer");
modules.forEach((module) => {
const card = document.createElement("div");
card.className = "card";
card.style.borderColor = module.color;
card.onclick = () => switchTo(module.id + "-module");
card.innerHTML = `
<div class="card-icon">${module.icon}</div>
<h3>${module.title}</h3>
<p>${module.description}</p>
<span class="category-label">${module.category}</span>
`;
grid.appendChild(card);
container.innerHTML += createModuleHTML(module);
});
}
function switchTo(target) {
document.querySelectorAll('.dashboard, .module').forEach(el => el.classList.remove('active'));
const elem = document.getElementById(target);
if (elem) { elem.classList.add('active'); window.scrollTo(0, 0); }
}
function switchTab(e, tabId) {
const module = e.target.closest('.module');
if (!module) return;
module.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
module.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
const tab = document.getElementById(tabId);
if (tab) tab.classList.add('active');
e.target.classList.add('active');
}
initDashboard();
</script>
</body>
</html>