3 — Container Services (AZ-305)
A. Decision tree containers AZ-305 ⭐⭐
Quel besoin container ?
├─ 1 container batch one-shot simple
│ └─ Azure Container Instances (ACI)
│
├─ Microservices simples, scale-to-zero, sans gérer K8s
│ └─ Azure Container Apps (ACA) ⭐
│
├─ Web app containerisée mono-stack, écosystème App Service
│ └─ Web App for Containers
│
├─ Containers + besoin K8s full control (CRDs, operators, Helm)
│ └─ Azure Kubernetes Service (AKS)
│
├─ K8s lift-and-shift on-prem existant
│ └─ AKS
│
└─ Batch event-driven container event-driven
└─ Container Apps Jobs ou AKS Jobs/Argo
Tableau de décision rapide ⭐⭐
| Critère | ACI | ACA | AKS | Web App Containers |
|---|---|---|---|---|
| K8s knowledge requis | ❌ | ❌ (caché) | ✅ | ❌ |
| Scale-to-zero | ❌ | ✅ | ❌ (KEDA OK) | ❌ |
| Long-running web | ⚠️ | ✅ | ✅ | ✅ |
| Batch jobs | ✅ one-shot | ✅ Jobs | ✅ Jobs/Argo | ❌ |
| Custom K8s (CRDs, operators) | ❌ | ❌ | ✅ | ❌ |
| Dapr natif | ❌ | ✅ | ❌ (à installer) | ❌ |
| Coût gestion | $ | $$ | $$$ | $$ |
🎯 Mémo 305 :
- "1 container ponctuel batch" → ACI
- "Microservices scale-to-zero sans K8s" → ACA ⭐
- "K8s full control, CRDs, operators, Helm" → AKS
- "Web app container écosystème App Service" → Web App for Containers
B. Kubernetes — vocab essentiel (awareness 305)
⚠️ Le détail K8s = AZ-204 / CKAD. Ici juste reconnaître les termes.
| Objet K8s | Quoi |
|---|---|
| Pod | Unité minimale (1+ containers) |
| Deployment | Manage N pods identiques + rolling updates |
| Service | IP/DNS stable qui expose N pods (les pods changent, le Service reste) |
| Ingress | Routing HTTP/HTTPS public → Services |
| Node Pool | Groupe de nodes (VMSS sous le capot) |
| Namespace | Cloisonnement logique |
Cluster
├─ Control Plane (managé Azure pour AKS)
└─ Node Pool (VMSS sous le capot)
└─ Node = 1 VM Azure
└─ Pod = 1+ containers
└─ Container
C. Azure Container Registry (ACR)
C.1 C'est quoi
Registry Docker/OCI managé Azure : stocke et distribue images containers vers AKS / ACA / ACI / Web App for Containers.
C.2 Tiers
| SKU | Storage | Géo-rep | Private Endpoint | Use case |
|---|---|---|---|---|
| Basic | 10 GB | ❌ | ❌ | Dev/test |
| Standard | 100 GB | ❌ | ❌ | Prod single-region |
| Premium ⭐ | 100 TiB | ✅ | ✅ | Multi-region, compliance |
🎯 Choix 305 : "AKS multi-région pull local" → Premium (geo-replication). "VNet only, zero public" → Premium (Private Endpoint).
C.3 Pièges ACR 305
- 🚨 Admin user : à désactiver en prod (préférer MI / SP / tokens).
- 🚨 Auth recommandée : MI + AcrPull via
az aks update --attach-acr(zéro secret). - 🚨 Sans Premium = pas de geo-replication → multi-region AKS pull cross-region = latence + egress.
- 🚨 Sans Premium = pas de Private Endpoint → registry exposé public (whitelist IP seulement).
D. Azure Container Instances (ACI)
D.1 C'est quoi
Container as a Service le plus simple : 1 container (ou container group) sans orchestration, facturation à la seconde.
D.2 Use cases AZ-305
- 1 container batch ponctuel (one-shot job).
- Build agents éphémères CI/CD.
- Burst depuis AKS via Virtual Nodes (Linux seulement).
- Cas simple sans orchestration / scale-to-zero / multi-revision.
D.3 Contraintes 305
- Container group = même OS (jamais Linux+Windows mélangés).
- Windows = mono-container (sidecars/multi = Linux only).
- Restart policy :
Always(défaut) /OnFailure/Never→ pour un one-shot job, mettreOnFailureouNever.
D.4 Pièges ACI 305
- ❌ Pas de scale-to-zero auto ni autoscale natif → préférer ACA pour event-driven.
- ❌ Pas idéal pour web long-running → préférer ACA ou Web App for Containers.
- ❌ Pas de Helm / CRDs / orchestration K8s → besoin = AKS.
E. Azure Container Apps (ACA) ⭐
E.1 C'est quoi
Serverless microservices sur AKS managé MS, pas d'accès K8s direct. KEDA + Dapr intégrés, scale-to-zero natif, revisions immutables.
E.2 Architecture rapide
Environment (cluster équivalent + LAW + VNet optionnel)
└─ Container App
└─ Revisions (versions immutables)
└─ Replicas (instances en cours)
E.3 Features clés 305
| Feature | Quoi |
|---|---|
| Scale-to-zero ⭐ | Natif (vs AKS HPA qui ne descend pas à 0) |
| KEDA scaling | Event-driven (Service Bus, Event Hub, Queue, Kafka, Cron, HTTP) |
| Revisions ⭐ | Versions immutables. Blue-green / canary natif (traffic split %) |
| Dapr (awareness) | Sidecar microservices : pub/sub, state, secrets, service invocation — sans coupler à un backend précis. Intégré ACA (toggle), à installer manuellement sur AKS |
| Container Apps Jobs | Batch event-driven (Manual / Schedule / Event) |
E.4 Tiers
- Consumption (default) : pay-per-use, scale-to-zero, idéal event-driven.
- Dedicated (Workload Profiles) : profils dédiés (D/E-series, GPU) — workloads costauds ou prédictibles.
E.5 Quand l'utiliser
- Microservices simples, scale-to-zero, no K8s mgmt → ACA ⭐
- Dapr natif → ACA
- Containers event-driven (queues, events) → ACA + KEDA
- Blue-green / canary natif → ACA revisions
- Plein contrôle K8s (CRDs, operators, Helm) → ❌ ACA, ✅ AKS
F. Azure Kubernetes Service (AKS)
F.1 C'est quoi
Kubernetes managé Azure : control plane géré gratuit, tu paies uniquement les node pools. Plein contrôle K8s (CRDs, operators, Helm).
F.2 Tiers
| Tier | SLA | Use case |
|---|---|---|
| Free | SLO 99.5% (pas garanti $) | Dev/test |
| Standard ⭐ | SLA 99.95% | Prod |
| Premium | + LTS (K8s 2 ans support long-terme) | Compliance / lifecycle long |
🎯 Piège SLO vs SLA : Free = SLO (objectif, aucune garantie financière). Standard = vrai SLA avec crédits. "Prod avec SLA garanti" → Standard.
F.3 Networking — choix du plugin (irréversible à la création)
| Plugin | IP des pods | Scale | Quand |
|---|---|---|---|
| Kubenet | Hors VNet | ~400 nodes max, Linux only | Legacy |
| Azure CNI (flat) | IP du VNet (1 IP/pod) | Consomme bcp d'IP | Pod doit être joignable directement (rare) |
| Azure CNI Overlay ⭐ | Hors VNet (encapsulation) | Milliers de nodes | Default moderne |
| Cilium (data plane) | Avec CNI/Overlay | eBPF + Network Policy L3-L7 | Perf / sécurité fine |
🚨 Virtual Nodes (burst vers ACI) = Azure CNI obligatoire (incompatible Kubenet).
Services K8s : ClusterIP (interne) ou LoadBalancer (Azure LB Standard + IP publique auto).
Ingress : NGINX (dans le cluster), AGIC (Azure App Gateway + WAF) ⭐ pour prod, App Routing add-on (NGINX managé AKS).
Outbound : Load Balancer (default), NAT Gateway ⭐ (évite SNAT exhaustion), UDR → Azure Firewall (filtrage compliance).
F.4 API server modes
| Mode | Quoi |
|---|---|
| Public (default) | API public + Authorized IP ranges optionnel |
| Private cluster ⭐ | API server en Private Endpoint → VNet only, zero public |
| API server VNet integration | API server dans subnet délégué (pas de DNS privé à gérer) |
F.5 Storage — awareness
| Access mode | Backend Azure | Use case |
|---|---|---|
| RWO | Azure Disk (Premium SSD) | Pod stateful (DB) — 1 node à la fois |
| RWX ⭐ | Azure Files | Shared multi-pods (config, uploads) |
| ROX | Azure Files / Blob | Lecture seule multi-nodes |
🚨 Azure Disk = LRS par défaut → épinglé à 1 zone. Pour cross-AZ → disques ZRS.
F.6 Autoscale — awareness
| Outil | Scale | Use case |
|---|---|---|
| HPA | Pods (replicas) | CPU/RAM/custom metrics |
| Cluster Autoscaler (CA) | Nodes (VMSS) | Pods Pending |
| VPA | Right-sizing CPU/RAM requests | Optimisation |
| KEDA ⭐ | Pods + scale-to-zero | Event-driven (queues, events) |
🎯 HPA ne descend jamais à 0 (min 1). KEDA permet le scale-to-zero.
F.7 Node pools
- System pool obligatoire : composants K8s internes (CoreDNS…), Linux only, jamais Spot.
- User pools : tes apps (Linux/Windows).
- Spot pools : VMs Spot (-90%, éviction possible) — batch/dev tolérant aux interruptions.
F.8 Identity — Workload Identity ⭐⭐
2 questions de sécu différentes :
- Pod accède à Azure (KV, SQL, Storage) → Workload Identity ⭐ (le pod reçoit une identité Entra, zéro secret).
- Humain accède au cluster (
kubectl) → Entra ID + Azure RBAC ⭐ (recommandé vs local accounts legacy).
🚨 OIDC issuer + Workload Identity doivent être activés à la création (sinon recréation cluster).
F.9 HA / DR
Intra-region : --zones 1 2 3 à la création (zone-redundant control plane + nodes cross-AZ + disques ZRS pour PVCs).
Cross-region DR :
- 2 clusters dans 2 régions (CI/CD parallèle)
- Front Door / Traffic Manager devant → failover (fiche 6)
- Données geo-replicated : ACR Premium geo-rep, Cosmos multi-region, SQL Auto-FG
- PVs : Velero ou Azure Backup for AKS
F.10 Pièges AKS 305
- 🚨 Network plugin irréversible à la création.
- 🚨 OIDC issuer + Workload Identity activés à la création (sinon recréation).
- 🚨 Zone redundancy control plane = à la création (irréversible).
G. Scénarios 305 → solution ⭐⭐
| Scénario business | Réponse |
|---|---|
| "1 container batch one-shot ponctuel" | ACI |
| "Burst depuis AKS sans provisionner nodes" | ACI via Virtual Nodes (AKS + CNI obligatoire) |
| "Microservices scale-to-zero, sans gérer K8s" | Azure Container Apps (ACA) |
| "Microservices event-driven Service Bus + Dapr" | ACA + KEDA + Dapr |
| "Blue-green deployment / canary 10/90 natif" | ACA revisions (Multiple revision mode) |
| "Containers + plein contrôle K8s (CRDs, operators, Helm)" | AKS Standard |
| "K8s lift-and-shift on-prem" | AKS |
| "K8s prod avec SLA financier 99.95%" | AKS Standard (pas Free) |
| "K8s avec support long-terme 2 ans" | AKS Premium (LTS) |
| "AKS multi-région avec pull image local" | ACR Premium + geo-replication |
| "AKS VNet-only zero public" | Private cluster + Private Endpoint ACR |
| "Web app container écosystème App Service + slots" | Web App for Containers |
| "Container job event-driven simple" | Container Apps Jobs (Event trigger KEDA) |
| "Workflow DAG complexe containers" | AKS + Argo Workflows |
| "Cluster autoscaling pods + nodes" | HPA + Cluster Autoscaler |
| "Scale-to-zero containers event-driven" | KEDA (ACA natif ou AKS) |
| "Pod accède KV/SQL/Storage sans secret" | Workload Identity |
| "Admin accède cluster avec MFA + RBAC central" | Entra ID + Azure RBAC |
| "AKS cross-region DR" | 2 clusters + Front Door + ACR geo-rep + data geo-rep |
| "Ingress HTTPS prod + WAF" | AGIC (App Gateway Ingress Controller) |
| "Évite SNAT port exhaustion outbound AKS" | NAT Gateway outbound type |
DEMO
Demo Portail — Create cluster AKS
Kubernetes services > + Create > Kubernetes cluster- Onglet Basics :
- RG :
rg-aks-prod/ Name :aks-prod/ Region : West Europe - Cluster preset : Production
- Pricing tier : Standard (99.95% SLA) / K8s version : 1.30.x
- RG :
- Onglet Node pools :
- System pool :
Standard_D4s_v5, autoscale Min 3 / Max 5, zones 1,2,3 - User pool
userpool1: autoscale Min 2 / Max 20
- System pool :
- Onglet Authentication : Microsoft Entra ID + Azure RBAC, groupe admin
grp-aks-admins - Onglet Networking :
- Azure CNI Overlay + Cilium dataplane
- VNet
vnet-aks+ subnetsnet-nodes - Private cluster : On
- Outbound type : Managed NAT Gateway
- Onglet Integrations :
- Container Registry :
acrprod(active--attach-acrautomatique) - Container Insights : On + LAW
- Defender for Containers : On
- Container Registry :
- Onglet Advanced :
- OIDC issuer : On (irréversible)
- Workload Identity : On
- KEDA : On
- Review + Create → ~5-10 min
- Validation :
Cluster > Connect→ exécuteraz aks get-credentialslocalement
🚨 OIDC issuer + Workload Identity DOIVENT être activés à la création (sinon recréation cluster).
CLI équivalent (pour IaC) :
az aks create -g rg-aks-prod -n aks-prod \
--network-plugin azure --network-plugin-mode overlay --network-dataplane cilium \
--enable-aad --enable-azure-rbac --enable-private-cluster \
--outbound-type managedNATGateway \
--enable-oidc-issuer --enable-workload-identity \
--enable-cluster-autoscaler --min-count 2 --max-count 10 --attach-acr acrprod
Deploy app YAML
apiVersion: apps/v1
kind: Deployment
metadata: { name: myapp }
spec:
replicas: 3
selector: { matchLabels: { app: myapp } }
template:
metadata: { labels: { app: myapp } }
spec:
containers:
- name: myapp
image: myacr.azurecr.io/myapp:v1
ports: [{ containerPort: 80 }]
---
apiVersion: v1
kind: Service
metadata: { name: myapp-svc }
spec:
type: LoadBalancer
ports: [{ port: 80, targetPort: 80 }]
selector: { app: myapp }
kubectl apply -f deployment.yaml
kubectl get pods,svc
kubectl logs <pod>
kubectl exec -it <pod> -- /bin/sh
Azure Files PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: shared-files }
spec:
accessModes: [ ReadWriteMany ]
storageClassName: azurefile-csi
resources: { requests: { storage: 10Gi } }
Demo Portail — Autoscale (CA + HPA)
Cluster Autoscaler (CA) — nodes :
AKS cluster > Settings > Node pools > <nodepool> > ... > Scale node pool- Scale method : Autoscale
- Minimum node count : 2 / Maximum node count : 20
- Apply
HPA — pods : via kubectl (pas de portail dédié)
kubectl autoscale deployment myapp --cpu-percent=70 --min=2 --max=10
kubectl get hpa
kubectl top pods && kubectl top nodes
Demo Portail — Container Apps
- Environment :
Container Apps > + Create > Container Apps Environment- Name :
aca-env/ Region : East US / LAW :law-aca - Create
- Container App :
Container Apps > + Create > Container App- Onglet Basics : RG, name
aca-worker, Region, Environmentaca-env - Onglet Container : ACR
acrprod+ Imageworker:v1 - Onglet Ingress : Toggle Enabled, traffic External, target port 80
- Review + Create
- KEDA scale rule (après création) :
Container App > Settings > Scale and replicas- Min replicas 0 / Max 30
- + Add scale rule : Type Azure Service Bus, metadata
queueName=orders,messageCount=5, auth Managed Identity - Save
- Traffic split (canary 10/90) :
Container App > Application > Revisions and replicas- Activer Multiple revision mode
- Cliquer la colonne Traffic % : latest = 10%, rev-old = 90% → Save
CLI équivalent :
az containerapp env create -g rg-aca --name aca-env -l eastus
az containerapp create -g rg-aca --name aca-worker --environment aca-env \
--image acrprod.azurecr.io/worker:v1 --target-port 80 --ingress external \
--min-replicas 0 --max-replicas 30 \
--scale-rule-name queue-scaler --scale-rule-type azure-servicebus \
--scale-rule-metadata "queueName=orders" "messageCount=5"
Demo Portail — AGIC (App Gateway Ingress)
AKS cluster > Settings > Networking > Virtual network integration- Section Application Gateway ingress controller → cliquer Enable ingress controller
- Choisir Create new :
- Application Gateway name :
appgw-aks - Subnet :
snet-appgwdans le VNet du cluster (subnet dédié, vide,/24)
- Application Gateway name :
- Save
- Déployer un Ingress K8s avec annotation
kubernetes.io/ingress.class: azure/application-gateway(cf YAML plus bas) → AGIC le détecte et configure App Gateway automatiquement
CLI équivalent :
az aks enable-addons -g rg-aks-prod -n aks-prod --addons ingress-appgw \
--appgw-name appgw-aks --appgw-subnet-cidr 10.225.0.0/24
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
annotations: { kubernetes.io/ingress.class: azure/application-gateway }
spec:
rules:
- host: myapp.contoso.com
http:
paths:
- path: /
pathType: Prefix
backend: { service: { name: myapp-svc, port: { number: 80 } } }