Ultima parte din seria despre Azure Container Apps. Am acoperit de ce, configurarea și scaling, și Dapr. Aici legăm totul cu un pipeline complet de deployment automat.
Autentificare fără secrete: OIDC
Consistent cu tot ce am construit în serie, nici pipeline-ul de CI/CD nu trebuie să stocheze secrete. În loc de un service principal cu client secret pus în GitHub Secrets, folosim OIDC (OpenID Connect) cu federated credentials: GitHub Actions primește un token temporar de la Azure la fiecare rulare, fără nicio credențială stocată.
Configurarea federated credential
# Creeaza un app registration (sau foloseste unul existent)
APP_ID=$(az ad app create --display-name "github-actions-my-api" --query appId -o tsv)
az ad sp create --id $APP_ID
# Federated credential legat de repo si branch
az ad app federated-credential create \
--id $APP_ID \
--parameters '{
"name": "github-main",
"issuer": "https://token.actions.githubusercontent.com",
"subject": "repo:myorg/my-repo:ref:refs/heads/main",
"audiences": ["api://AzureADTokenExchange"]
}'
Câmpul subject restricționează cine poate cere token-uri: doar workflow-uri din branch-ul main al repo-ului tău. Un pull request din alt repo nu poate obține acces.
Roluri pentru service principal
PRINCIPAL_ID=$(az ad sp show --id $APP_ID --query id -o tsv)
ACR_ID=$(az acr show --name myregistry --query id -o tsv)
RG_ID=$(az group show --name my-rg --query id -o tsv)
# Push in Container Registry
az role assignment create --assignee $PRINCIPAL_ID \
--role "AcrPush" --scope $ACR_ID
# Deploy in Container Apps (Contributor pe resource group sau mai granular)
az role assignment create --assignee $PRINCIPAL_ID \
--role "Contributor" --scope $RG_ID
Secretele din GitHub
Cu OIDC, în GitHub nu pui niciun secret sensibil — doar identificatori publici:
# Nu sunt secrete reale, doar identificatori
AZURE_CLIENT_ID =
AZURE_TENANT_ID =
AZURE_SUBSCRIPTION_ID =
Workflow-ul complet
# .github/workflows/deploy.yml
name: Build and Deploy to Container Apps
on:
push:
branches: [ main ]
permissions:
id-token: write # necesar pentru OIDC
contents: read
env:
REGISTRY: myregistry.azurecr.io
IMAGE_NAME: my-api
CONTAINER_APP: my-api
RESOURCE_GROUP: my-rg
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Login Azure prin OIDC -- fara secrete
- name: Azure Login
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
# Login la ACR folosind token-ul Azure
- name: ACR Login
run: az acr login --name ${{ env.REGISTRY }}
# Build si push imagine, tag-uita cu SHA-ul commit-ului
- name: Build and push
run: |
IMAGE_TAG=${{ github.sha }}
docker build -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:$IMAGE_TAG .
docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:$IMAGE_TAG
# Deploy noua imagine in Container Apps
- name: Deploy to Container Apps
run: |
az containerapp update \
--name ${{ env.CONTAINER_APP }} \
--resource-group ${{ env.RESOURCE_GROUP }} \
--image ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
Punctul-cheie: imaginea e tag-uită cu github.sha (SHA-ul commit-ului), nu cu latest. Fiecare deploy e trasabil la commit-ul exact, iar rollback-ul înseamnă doar redeploy cu un SHA anterior.
Revizii și traffic splitting
Fiecare containerapp update creează o revizie nouă. În mod implicit, ACA rutează 100% din trafic către ultima revizie. Dar poți face canary releases reale, împărțind traficul între revizii.
Activarea modului multiple revisions
az containerapp revision set-mode \
--name my-api --resource-group my-rg \
--mode multiple
Traffic split: 90% stabil, 10% canary
# Trimite 10% din trafic catre noua revizie, 90% catre cea stabila
az containerapp ingress traffic set \
--name my-api --resource-group my-rg \
--revision-weight \
my-api--stable-rev=90 \
my-api--new-rev=10
Monitorizezi noua revizie în Application Insights câteva ore. Dacă metrici de eroare și latență sunt OK, muți traficul la 100%. Dacă nu, revii la 0% instant — fără redeploy, doar o schimbare de rutare.
# Promoveaza noua revizie la 100%
az containerapp ingress traffic set \
--name my-api --resource-group my-rg \
--revision-weight my-api--new-rev=100
Checklist pipeline Container Apps
- OIDC în loc de client secret — federated credentials, zero secrete în GitHub
- subject restricționat — doar branch-ul și repo-ul tău pot cere token-uri
- Managed Identity pentru pull — Container App trage imaginea din ACR fără credențiale
- Imagini tag-uite cu SHA — trasabilitate la commit, rollback simplu
- Health probes configurate — ACA nu rutează trafic către revizii nesănătoase
- Traffic splitting pentru canary — validare graduală înainte de 100%
Încheierea seriei Container Apps
Cu asta, mini-seria despre Azure Container Apps e completă: am stabilit când merită migrarea, am configurat scaling elastic cu KEDA, am integrat Dapr pentru microservicii și am automatizat deployment-ul cu GitHub Actions — totul construit pe fundația de securitate fără secrete din articolele anterioare.
În continuarea seriei Cloud-native cu Azure și .NET urmează observabilitatea cu Application Insights: distributed tracing, custom metrics și alerts.
Dacă ai întrebări sau vrei să discuți cum structurezi pipeline-ul pentru proiectul tău, scrie-mi la contact@ludoprogramming.com.