Azure Cloud โ
The Mental Model
Every concept explained like you're 15. No jargon without explanation. Built for your developer background with practical examples.
3 Service Models:
MyApp-Production (Resource Group) โโโ myapp-webapp (App Service) โโโ myapp-db (SQL Database) โโโ myapp-storage (Storage Account) โโโ myapp-cache (Redis) โโโ myapp-vault (Key Vault) // All resources share lifecycle, region, billing tags // Delete the resource group โ deletes EVERYTHING in it
Compute Services
"Compute" = things that run your code. Azure has 4 main ways to run code, each with different tradeoffs.
When to use: Legacy apps that need specific OS, full control over environment, lift-and-shift of on-premise servers.
- VM Size โ Standard_B2s (2 vCPU, 4GB RAM) to massive GPU machines
- VM Scale Sets โ Auto-scale VM count based on CPU/traffic demand
- Availability Set โ Spread VMs across physical racks (prevent single point of failure)
- Managed Disks โ OS and data disks, backed by Azure (SSD or HDD)
- Azure Bastion โ Secure SSH/RDP access WITHOUT exposing public IP
# Create a Linux VM az vm create \ --resource-group MyRG \ --name MyVM \ --image UbuntuLTS \ --admin-username azureuser \ --generate-ssh-keys \ --size Standard_B2s # Open port 80 for web traffic az vm open-port --resource-group MyRG --name MyVM --port 80
When to use: Web apps, REST APIs, Angular frontends, .NET/Node/Python backends. This is what you'd deploy your Angular app or a Python ML API to.
- Deployment slots โ staging slot, then swap to production with ZERO downtime
- Auto-scale โ scale out (more instances) automatically based on CPU/requests
- Custom domains + free SSL certificates (Let's Encrypt)
- App Service Plan โ the underlying compute you pay for (F1=Free, B1=Basic, P1=Premium)
- CI/CD built-in โ connect GitHub, push code โ auto-deploys
# Create App Service Plan az appservice plan create \ --name MyPlan --resource-group MyRG \ --sku B1 --is-linux # Create web app az webapp create \ --name myapi-prod \ --resource-group MyRG \ --plan MyPlan \ --runtime "NODE|18-lts" # Deploy from local git az webapp deployment source config-local-git \ --name myapi-prod --resource-group MyRG
Perfect for: Event-driven code, scheduled tasks (cron jobs), webhooks, data processing pipelines, background jobs.
- HTTP Trigger โ runs when someone calls a URL (like a REST endpoint)
- Timer Trigger โ cron schedule (every day at 9am, every 5 minutes)
- Blob Trigger โ runs when file uploaded to Azure Storage
- Queue Trigger โ runs when message added to Azure Queue/Service Bus
- Event Grid Trigger โ runs in response to Azure events
import azure.functions as func import logging # HTTP Trigger โ becomes a REST endpoint @app.route(route="predict", methods=["POST"]) def predict(req: func.HttpRequest) -> func.HttpResponse: data = req.get_json() result = ml_model.predict(data['features']) return func.HttpResponse(json.dumps({'prediction': result})) # Timer Trigger โ runs every day at 9am UTC @app.timer_trigger(schedule="0 0 9 * * *") def daily_report(timer: func.TimerRequest): logging.info('Running daily report...') generate_report_and_email()
When to use: Microservices, complex multi-container apps, when you need fine-grained control over scaling and deployment strategies.
- Pod โ smallest unit, one or more containers running together
- Deployment โ manages pods, rolling updates, rollbacks
- Service โ stable IP/DNS name for a group of pods
- Ingress โ HTTP routing rules, like an nginx config for all your services
- ConfigMap / Secret โ inject config/secrets into pods without hardcoding
# Run your Python ML API as a container, instantly
az container create \
--resource-group MyRG \
--name ml-api \
--image myregistry.azurecr.io/ml-model:latest \
--cpu 2 --memory 4 \
--ports 8000 \
--environment-variables MODEL_PATH=/models/v2
Storage Services
Azure has multiple storage types because different data needs different storage. Files โ Tables โ Blobs โ Queues.
- Hot โ frequently accessed data, highest storage cost, lowest access cost
- Cool โ infrequently accessed, lower cost, slightly slower
- Archive โ rarely accessed, cheapest storage, hours to retrieve
from azure.storage.blob import BlobServiceClient client = BlobServiceClient.from_connection_string(conn_str) container = client.get_container_client("ml-datasets") # Upload a file (e.g., CSV dataset) with open("dataset.csv", "rb") as f: container.upload_blob("data/dataset.csv", f, overwrite=True) # Download it blob = container.get_blob_client("data/dataset.csv") data = blob.download_blob().readall() # Generate a temporary shareable URL (SAS Token) from azure.storage.blob import generate_blob_sas, BlobSasPermissions from datetime import datetime, timedelta sas = generate_blob_sas(account_name, container_name, blob_name, account_key=key, permission=BlobSasPermissions(read=True), expiry=datetime.utcnow() + timedelta(hours=1)) url = f"https://{account_name}.blob.core.windows.net/{container_name}/{blob_name}?{sas}"
az storage account create \ --name mystorageaccount \ --resource-group MyRG \ --location eastus \ --sku Standard_LRS \ # Locally Redundant = 3 copies in 1 datacenter --kind StorageV2 # Latest version, supports all 4 types # Redundancy options: # LRS โ 3 copies, same datacenter (cheapest) # ZRS โ 3 copies across 3 Availability Zones (same region) # GRS โ LRS + copies in paired region (disaster recovery)
For Angular apps: Build with ng build โ upload to Blob Storage โ enable Static Website โ add Azure CDN in front โ users get your app in milliseconds globally.
# 1. Build Angular app ng build --configuration production # 2. Upload to blob storage (with web hosting enabled) az storage blob upload-batch \ --source dist/my-app \ --destination '$web' \ --account-name mystaticsite # 3. Get the URL az storage account show \ --name mystaticsite \ --query "primaryEndpoints.web" # โ https://mystaticsite.z13.web.core.windows.net
Networking in Azure
How Azure resources talk to each other and to the internet โ securely.
MyApp-VNet (10.0.0.0/16) โโโ Frontend-Subnet (10.0.1.0/24) โ App Service, Load Balancer โโโ Backend-Subnet (10.0.2.0/24) โ APIs, Functions โโโ DB-Subnet (10.0.3.0/24) โ SQL, Redis โ NO internet access # Resources in same VNet talk freely # NSG (Network Security Group) = firewall rules per subnet # DB-Subnet NSG: only allow traffic FROM Backend-Subnet on port 1433
Identity & Access Management
Who is allowed to do what in Azure. The most important security topic.
- Tenant โ your organization's Azure AD instance (one per company)
- User โ a person with email + password in Azure AD
- Service Principal โ an identity for an APP (not a person) to authenticate
- Managed Identity โ an automatic identity for Azure services (no password needed!)
- App Registration โ register your app to use Azure AD for login (OAuth2/OIDC)
from azure.identity import DefaultAzureCredential from azure.keyvault.secrets import SecretClient # No password, connection string, or API key anywhere in code! # The VM/Function/App Service has an identity, Azure validates it credential = DefaultAzureCredential() # Access Key Vault using managed identity kv_client = SecretClient( vault_url="https://myvault.vault.azure.net", credential=credential ) secret = kv_client.get_secret("db-connection-string") print(secret.value) # Got it without any hardcoded credentials!
- Owner โ full access including managing who else has access
- Contributor โ create/modify resources, but can't manage access
- Reader โ view resources only, no changes
- Storage Blob Data Contributor โ read/write blobs only
- Key Vault Secrets User โ read secrets only (not keys or certificates)
# Give a user "Reader" access to a resource group az role assignment create \ --assignee [email protected] \ --role Reader \ --resource-group MyRG # Give a Function App's managed identity access to Key Vault az role assignment create \ --assignee {managed-identity-object-id} \ --role "Key Vault Secrets User" \ --scope /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.KeyVault/vaults/{vault}
Azure Key Vault
The secure place to store all your passwords, API keys, certificates, and connection strings. Never hardcode secrets in code again.
# 1. Store a secret via CLI az keyvault secret set \ --vault-name myapp-vault \ --name "openai-api-key" \ --value "sk-xxxxxxxxxxxxxxxx" # 2. Give your app's managed identity access az keyvault set-policy \ --name myapp-vault \ --object-id {app-managed-identity-id} \ --secret-permissions get list # 3. App reads secret at runtime โ Python from azure.identity import DefaultAzureCredential from azure.keyvault.secrets import SecretClient credential = DefaultAzureCredential() client = SecretClient("https://myapp-vault.vault.azure.net", credential) openai_key = client.get_secret("openai-api-key").value # Use it โ never stored in code or environment variables! # App Service: reference Key Vault in app settings # @Microsoft.KeyVault(SecretUri=https://vault.azure.net/secrets/name/version)
Azure Database Services
Azure has managed versions of every popular database. "Managed" means Azure handles backups, patches, HA, scaling.
- DTU model โ simpler, fixed bundles (Basic/Standard/Premium)
- vCore model โ choose exact CPUs and RAM, more flexible
- Serverless โ auto-scales compute, pauses when idle (save cost!)
- Hyperscale โ up to 100TB, read replicas
APIs supported: NoSQL (documents), MongoDB, Cassandra, Gremlin (graph), Table. You pick your preferred API and it works.
- Global apps needing <10ms reads anywhere in the world
- Variable/schema-less data (JSON documents)
- Massive scale (millions of requests/second)
- IoT telemetry, social media feeds, gaming leaderboards
import redis r = redis.from_url(os.getenv("REDIS_URL")) def get_user(user_id: str): # 1. Check cache first cached = r.get(f"user:{user_id}") if cached: return json.loads(cached) # 2. Cache miss โ fetch from DB user = db.query("SELECT * FROM users WHERE id=?", user_id) # 3. Store in cache for 5 minutes r.setex(f"user:{user_id}", 300, json.dumps(user)) return user
Messaging & Event Services
Decouple your services. Instead of calling each other directly (tight coupling), services communicate via messages or events.
- Queue โ one sender, one receiver (point-to-point, competitive consumers)
- Topic + Subscriptions โ one sender, many receivers (pub/sub, fan-out)
- Dead Letter Queue โ failed messages go here for inspection/retry
- Sessions โ guarantee ordering for a specific customer's messages
Azure AI & Cognitive Services
Pre-built AI models as APIs โ no ML knowledge required to USE them. This connects directly to your ML learning.
from openai import AzureOpenAI client = AzureOpenAI( azure_endpoint="https://myapp.openai.azure.com", api_key=os.getenv("AZURE_OPENAI_KEY"), # or Managed Identity! api_version="2024-02-01" ) response = client.chat.completions.create( model="gpt-4", # your deployment name messages=[ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "Explain machine learning simply."} ] ) print(response.choices[0].message.content)
- Workspace โ the container for everything ML in your project
- Compute Clusters โ auto-scale GPU/CPU VMs for training
- Experiments โ track model training runs (hyperparams, metrics, artifacts)
- Model Registry โ versioned models with metadata
- Endpoints โ deploy a model as a REST API (managed online endpoint)
- Pipelines โ chain data prep โ training โ evaluation โ deployment
from azure.ai.ml import MLClient from azure.identity import DefaultAzureCredential ml_client = MLClient(DefaultAzureCredential(), subscription, rg, workspace) # Register trained model model = ml_client.models.create_or_update(Model( path="./model", name="fraud-detector", version="2" )) # Deploy as online endpoint deployment = ManagedOnlineDeployment( name="v2", endpoint_name="fraud-api", model=model, instance_type="Standard_DS3_v2", instance_count=1 ) ml_client.online_deployments.begin_create_or_update(deployment)
Azure DevOps & CI/CD
Automate everything from code commit to production deployment.
trigger:
branches:
include: [main]
stages:
- stage: Build
jobs:
- job: BuildAngular
steps:
- task: NodeTool@0
inputs: { versionSpec: '18.x' }
- script: |
npm ci
npm run build -- --configuration production
- publish: dist/my-app
artifact: angular-build
- job: BuildPythonAPI
steps:
- script: pip install -r requirements.txt
- script: pytest tests/ -v
- script: docker build -t myapi:$(Build.BuildId) .
- stage: Deploy
dependsOn: Build
condition: succeeded()
jobs:
- deployment: DeployToProduction
environment: production
strategy:
runOnce:
deploy:
steps:
- task: AzureWebApp@1
inputs:
azureSubscription: 'MyAzureConnection'
appName: 'myapp-api'
package: '$(Pipeline.Workspace)/drop/*.zip'
Monitoring & Observability
"If you can't measure it, you can't improve it." Azure Monitor is the central hub for all observability.
- Live Metrics โ see requests/sec and failures in real time
- Transaction Search โ trace every individual request end-to-end
- Failures โ which endpoints fail, what exceptions are thrown
- Performance โ slowest requests, external dependencies (SQL, HTTP calls)
- Users โ page views, sessions, geographic breakdown
- Alerts โ notify on Slack/email when error rate > 5%
from applicationinsights import TelemetryClient tc = TelemetryClient(os.getenv("APPINSIGHTS_KEY")) # Track custom events tc.track_event("ModelPrediction", {"model_version": "v2"}, {"confidence": 0.95}) # Track exceptions try: result = model.predict(data) except Exception as e: tc.track_exception() tc.flush() raise # For FastAPI โ use opencensus-ext-azure (auto-instruments everything) from opencensus.ext.azure.trace_exporter import AzureExporter from opencensus.trace.samplers import ProbabilitySampler
// Top 10 most common errors in last 24h exceptions | where timestamp > ago(24h) | summarize count() by outerMessage | order by count_ desc | take 10 // Average API response time by endpoint requests | where timestamp > ago(1h) | summarize avg(duration) by name | order by avg_duration desc // Find slow SQL queries dependencies | where type == "SQL" and duration > 1000 | project timestamp, name, duration, data
Pricing & Cost Management
Cloud costs can surprise you. Understand pricing models and how to keep bills low.
- Auto-shutdown dev/test VMs outside business hours
- Use Azure Functions (serverless) instead of always-on VMs for intermittent work
- Set budgets and alerts in Cost Management before you overspend
- Delete unused resources (orphaned disks, old snapshots, unused IPs)
- Use Cool/Archive blob tiers for infrequently accessed data
- Azure Advisor โ free recommendations on cost, security, performance
- AZ-900: Azure Fundamentals โ concepts, no technical depth (start here if new)
- AZ-104: Azure Administrator โ VMs, networking, storage, identity (3yr devs)
- AZ-204: Azure Developer โ Functions, App Service, Cosmos DB, APIs โ MOST RELEVANT
- AZ-305: Azure Architect โ design solutions end-to-end
- AI-102: Azure AI Engineer โ Cognitive Services, Azure ML
For your background (3yr dev, learning ML): Start with AZ-204 (Developer) โ it covers exactly what you'll use: App Service, Functions, Cosmos DB, Key Vault, Storage, identity. Then AI-102 to combine cloud + ML knowledge.