WIKI Retour au Portfolio

Dernière mise à jour : 23 juin 2026

3 — Container Services

Les services de containers Azure → ACI, Container Apps, Web App for Containers, AKS (+ registre ACR) : choisir selon one-shot simple, microservices scale-to-zero ou orchestration Kubernetes full control.


A. Decision tree containers

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).
  • 🚨 Zone redundancy ACR = par défaut sur TOUS les tiers (Basic/Standard/Premium) dans les régions à AZ, sans surcoût. Seuls geo-replication, Private Endpoint, Content Trust, CMK sont Premium-only. → « Standard single-region » ≠ « sans HA zonale ».

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, mettre OnFailure ou Never.

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

E.6 Pièges ACA 305

  • 🚨 Pas d'accès K8s direct (pas de kubectl, pas de CRDs custom).
  • 🚨 Pas de StatefulSet équivalent → workloads stateful → AKS.
  • 🚨 VNet integration = à la création de l'Environment (irréversible).
  • 🚨 Revisions immutables : pour update, on crée une nouvelle revision.

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 Best-effort (aucun SLA/SLO chiffré) Dev/test
Standard SLA 99.95% (avec AZ) / 99.9% (sans AZ) Prod
Premium + LTS (K8s 2 ans support long-terme) Compliance / lifecycle long

🎯 Piège dispo : Free = best-effort, aucun SLA/SLO garanti (l'ancien « SLO 99.5% » n'existe plus dans la doc). Standard/Premium = vrai SLA avec crédits (99.95% avec AZ / 99.9% sans). "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 (Linux only?) 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 :

  1. Pod accède à Azure (KV, SQL, Storage) → Workload Identity (le pod reçoit une identité Entra, zéro secret).
  2. 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 :

  1. 2 clusters dans 2 régions (CI/CD parallèle)
  2. Front Door / Traffic Manager devant → failover (fiche 6)
  3. Données geo-replicated : ACR Premium geo-rep, Cosmos multi-region, SQL Auto-FG
  4. 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).
  • 🚨 Disques LRS pinned 1 AZ → ZRS pour cross-AZ PVCs.
  • 🚨 Local accounts = legacy → Entra + RBAC.
  • 🚨 Free tier = best-effort (aucun SLA/SLO garanti). Prod → Standard.
  • 🚨 AKS vs VM : si app containerisable + scale rapide + déploiements fréquents → AKS (pas VM). VM = uniquement si deps OS lourdes incompatibles container (driver kernel, legacy binaires).

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

🏢 Scénarios d'entreprise (CAF/WAF)

Scénario 1 : Retail e-commerce — Microservices event-driven sans gérer K8s

Contexte business : Retailer, petite équipe dev, zéro compétence Kubernetes. Charge très saisonnière (Black Friday x20, quasi-zéro la nuit). Besoin : traiter les commandes depuis une file Service Bus, livrer vite, minimiser l'ops. Choix architectural : Azure Container Apps (ACA) Consumption + KEDA (scale-to-zero) + ACR Standard. → microservices sans avoir à gérer un cluster. Architecture / pattern :

  • ACA Environment Workload Profiles, subnet dédié, /24 (prévoir large : les déploiements zero-downtime doublent temporairement les IPs).
  • Worker : min 0 / max 30 replicas, scale rule KEDA azure-servicebus (queueName=orders), auth par Managed Identity.
  • Front API : revisions immutables + traffic split pour le canary 10/90.
  • ACR Standard (geo-rep inutile en mono-région), pull via MI + AcrPull. Trade-offs assumés :
  • Gain : scale-to-zero (coût nuit ≈ 0), pas de control plane à gérer, Dapr/KEDA intégrés.
  • Perte : pas de kubectl/CRDs, pas de StatefulSet, taille du subnet figée à la création. Pièges à éviter :
  • Subnet trop petit (un /27 ≈ 18 IPs) → saturation pendant un déploiement. Dimensionner large dès le départ.
  • Type d'Environment irréversible : choisir Workload Profiles à la création.
  • Le scale-to-zero ajoute un cold-start sur la première requête. 📐 Réf. WAF — Service guide / choix du service container : ACA est le PaaS recommandé pour les équipes sans besoin CNCF qui veulent service discovery, autoscaling event-driven et Dapr sans opérer un cluster. Lien

Scénario 2 : Banque/Assurance — AKS prod régulé, VNet-only, économie d'IPs

Contexte business : Assureur régulé avec des workloads qui exigent le full control K8s (operators, Helm). Besoin : SLA financier sur l'API server, zéro control plane public, accès audités. Choix architectural : AKS Standard (SLA), private cluster, Azure CNI Overlay + Cilium, Entra ID + RBAC, ACR Premium + Private Endpoint. Architecture / pattern :

  • Standard tier (SLA 99,95% avec AZ) sur 3 zones (--zones 1 2 3) — jamais Free en prod.
  • CNI Overlay (pods hors VNet → économie massive d'IPs) + Cilium (Network Policy L3-L7).
  • Private cluster (API server privé), sortie via NAT Gateway (évite SNAT exhaustion), egress filtré par Azure Firewall.
  • Workload Identity + OIDC activés à la création (pods → KV/SQL sans secret). Humains : Entra + RBAC, local accounts off.
  • ACR Premium (Private Endpoint, CMK), pull MI + AcrPull. PVCs sur disques ZRS (pas LRS). Trade-offs assumés :
  • Gain : full contrôle K8s + compliance + SLA + surface d'attaque réduite (zero public).
  • Perte : ops jour-2 à la charge de l'équipe (upgrades, CVEs), CI/CD via agents privés, coût Premium + NAT + Firewall. Pièges à éviter :
  • Plugin réseau, private cluster, zone redundancy, OIDC/Workload Identity = irréversibles à la création → tout cadrer avant az aks create.
  • Sous-dimensionner le CIDR Overlay (chaque node consomme un /24 de pods).
  • Private cluster = à gérer : DNS privé + accès depuis le réseau d'entreprise. 📐 Réf. CAF — AKS landing zone accelerator / design areas : ancre le cluster dans une application landing zone (identity, hub-and-spoke, policy, BCDR) alignée enterprise-scale. Lien

Scénario 3 : Média/Data — Batch GPU ponctuel + burst depuis AKS

Contexte business : Studio média : traitements d'encodage/ML par lots, déclenchés irrégulièrement, sans service permanent. Un AKS existant gère déjà les apps web ; besoin de calcul ponctuel sans surprovisionner de nodes. Choix architectural : ACI pour les jobs one-shot + Virtual Nodes pour le burst depuis AKS. Jobs récurrents → Container Apps Jobs. Architecture / pattern :

  • Jobs isolés : ACI container group, facturé à la seconde, restartPolicy: Never. GPU/multi-container = Linux only.
  • Burst depuis AKS : Virtual Nodes (ACI) → impose Azure CNI (incompatible kubenet, retiré le 31 mars 2028).
  • Jobs récurrents : Container Apps Jobs (trigger Schedule/Event KEDA), scale-to-zero entre les runs. Trade-offs assumés :
  • Gain : zéro node permanent pour le batch, démarrage rapide, paiement strict à l'usage.
  • Perte : ACI = pas d'orchestration/autoscale/Helm ; Windows en ACI = mono-container. Pièges à éviter :
  • Héberger une app web long-running sur ACI → préférer ACA / Web App for Containers.
  • Virtual Nodes sur kubenet : impossible → planifier Azure CNI.
  • Mélanger Linux + Windows dans un même container group ACI : interdit. 📐 Réf. CAF/AAC — Choisir un service container Azure : arbre de décision PaaS vs AKS vs ACI selon contrôle, ops et nature du workload (batch one-shot → ACI). Lien

DEMO

Demo Portail — Create cluster AKS

  1. Kubernetes services > + Create > Kubernetes cluster
  2. 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
  3. 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
  4. Onglet Authentication : Microsoft Entra ID + Azure RBAC, groupe admin grp-aks-admins
  5. Onglet Networking :
    • Azure CNI Overlay + Cilium dataplane
    • VNet vnet-aks + subnet snet-nodes
    • Private cluster : On
    • Outbound type : Managed NAT Gateway
  6. Onglet Integrations :
    • Container Registry : acrprod (active --attach-acr automatique)
    • Container Insights : On + LAW
    • Defender for Containers : On
  7. Onglet Advanced :
    • OIDC issuer : On (irréversible)
    • Workload Identity : On
    • KEDA : On
  8. Review + Create → ~5-10 min
  9. Validation : Cluster > Connect → exécuter az aks get-credentials localement

🚨 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 :

  1. AKS cluster > Settings > Node pools > <nodepool> > ... > Scale node pool
  2. Scale method : Autoscale
  3. Minimum node count : 2 / Maximum node count : 20
  4. 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

  1. Environment :
    • Container Apps > + Create > Container Apps Environment
    • Name : aca-env / Region : East US / LAW : law-aca
    • Create
  2. Container App :
    • Container Apps > + Create > Container App
    • Onglet Basics : RG, name aca-worker, Region, Environment aca-env
    • Onglet Container : ACR acrprod + Image worker:v1
    • Onglet Ingress : Toggle Enabled, traffic External, target port 80
    • Review + Create
  3. 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
  4. 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)

  1. AKS cluster > Settings > Networking > Virtual network integration
  2. Section Application Gateway ingress controller → cliquer Enable ingress controller
  3. Choisir Create new :
    • Application Gateway name : appgw-aks
    • Subnet : snet-appgw dans le VNet du cluster (subnet dédié, vide, /24)
  4. Save
  5. 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 } } }