From 0bb2242cf5dc136415c71f7cb69b1377ad0bfd5e Mon Sep 17 00:00:00 2001 From: krishna-sunkavalli Date: Thu, 9 Apr 2026 00:51:35 -0500 Subject: [PATCH 1/4] feat: add azure-container-apps skill for serverless container workloads --- docs/README.skills.md | 1 + skills/azure-container-apps/SKILL.md | 688 +++++++++++++++++++++++++++ 2 files changed, 689 insertions(+) create mode 100644 skills/azure-container-apps/SKILL.md diff --git a/docs/README.skills.md b/docs/README.skills.md index 78f3d71a2..7590a9a2b 100644 --- a/docs/README.skills.md +++ b/docs/README.skills.md @@ -52,6 +52,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-skills) for guidelines on how to | [aws-cdk-python-setup](../skills/aws-cdk-python-setup/SKILL.md) | Setup and initialization guide for developing AWS CDK (Cloud Development Kit) applications in Python. This skill enables users to configure environment prerequisites, create new CDK projects, manage dependencies, and deploy to AWS. | None | | [az-cost-optimize](../skills/az-cost-optimize/SKILL.md) | Analyze Azure resources used in the app (IaC files and/or resources in a target rg) and optimize costs - creating GitHub issues for identified optimizations. | None | | [azure-architecture-autopilot](../skills/azure-architecture-autopilot/SKILL.md) | Design Azure infrastructure using natural language, or analyze existing Azure resources to auto-generate architecture diagrams, refine them through conversation, and deploy with Bicep.
When to use this skill: - "Create X on Azure", "Set up a RAG architecture" (new design) - "Analyze my current Azure infrastructure", "Draw a diagram for rg-xxx" (existing analysis) - "Foundry is slow", "I want to reduce costs", "Strengthen security" (natural language modification) - Azure resource deployment, Bicep template generation, IaC code generation - Microsoft Foundry, AI Search, OpenAI, Fabric, ADLS Gen2, Databricks, and all Azure services | `.gitignore`
`README.md`
`assets/06-architecture-diagram.png`
`assets/07-azure-portal-resources.png`
`assets/08-deployment-succeeded.png`
`references/ai-data.md`
`references/architecture-guidance-sources.md`
`references/azure-common-patterns.md`
`references/azure-dynamic-sources.md`
`references/bicep-generator.md`
`references/bicep-reviewer.md`
`references/phase0-scanner.md`
`references/phase1-advisor.md`
`references/phase4-deployer.md`
`references/service-gotchas.md`
`scripts/cli.py`
`scripts/generator.py`
`scripts/icons.py` | +| [azure-container-apps](../skills/azure-container-apps/SKILL.md) | Guide for building, deploying, scaling, and troubleshooting Azure Container Apps. Use when creating container apps, configuring ingress, setting up scaling rules, enabling Dapr sidecars, deploying container images, creating jobs, configuring custom domains, managing revisions, traffic splitting, or troubleshooting ACA workloads. | None | | [azure-deployment-preflight](../skills/azure-deployment-preflight/SKILL.md) | Performs comprehensive preflight validation of Bicep deployments to Azure, including template syntax validation, what-if analysis, and permission checks. Use this skill before any deployment to Azure to preview changes, identify potential issues, and ensure the deployment will succeed. Activate when users mention deploying to Azure, validating Bicep files, checking deployment permissions, previewing infrastructure changes, running what-if, or preparing for azd provision. | `references/ERROR-HANDLING.md`
`references/REPORT-TEMPLATE.md`
`references/VALIDATION-COMMANDS.md` | | [azure-devops-cli](../skills/azure-devops-cli/SKILL.md) | Manage Azure DevOps resources via CLI including projects, repos, pipelines, builds, pull requests, work items, artifacts, and service endpoints. Use when working with Azure DevOps, az commands, devops automation, CI/CD, or when user mentions Azure DevOps CLI. | `references/advanced-usage.md`
`references/boards-and-iterations.md`
`references/org-and-security.md`
`references/pipelines-and-builds.md`
`references/repos-and-prs.md`
`references/variables-and-agents.md`
`references/workflows-and-patterns.md` | | [azure-pricing](../skills/azure-pricing/SKILL.md) | Fetches real-time Azure retail pricing using the Azure Retail Prices API (prices.azure.com) and estimates Copilot Studio agent credit consumption. Use when the user asks about the cost of any Azure service, wants to compare SKU prices, needs pricing data for a cost estimate, mentions Azure pricing, Azure costs, Azure billing, or asks about Copilot Studio pricing, Copilot Credits, or agent usage estimation. Covers compute, storage, networking, databases, AI, Copilot Studio, and all other Azure service families. | `references/COPILOT-STUDIO-RATES.md`
`references/COST-ESTIMATOR.md`
`references/REGIONS.md`
`references/SERVICE-NAMES.md` | diff --git a/skills/azure-container-apps/SKILL.md b/skills/azure-container-apps/SKILL.md new file mode 100644 index 000000000..174c18216 --- /dev/null +++ b/skills/azure-container-apps/SKILL.md @@ -0,0 +1,688 @@ +--- +name: azure-container-apps +description: 'Guide for building, deploying, scaling, and troubleshooting Azure Container Apps. Use when creating container apps, configuring ingress, setting up scaling rules, enabling Dapr sidecars, deploying container images, creating jobs, configuring custom domains, managing revisions, traffic splitting, or troubleshooting ACA workloads.' +--- + +# Azure Container Apps + +Azure Container Apps (ACA) is a serverless container platform for running microservices, APIs, background jobs, and event-driven workloads without managing infrastructure. + +## Key Concepts + +| Concept | Description | +|---------|-------------| +| **Environment** | Shared boundary for container apps. Apps in the same environment share a virtual network, logging destination, and Dapr configuration. | +| **Container App** | The deployable unit. Each app has one or more containers, ingress settings, scaling rules, and secrets. | +| **Revision** | An immutable snapshot of a container app version. New revisions are created when template-scope properties change (image, env vars, scaling rules). | +| **Replica** | A running instance of a revision. Scaling rules control how many replicas run. | +| **Job** | A container that runs to completion — on-demand, scheduled (cron), or event-driven. Jobs do not serve traffic. | + +## Prerequisites + +```bash +# Install or upgrade the Azure CLI extension +az extension add --name containerapp --upgrade + +# Register required providers +az provider register --namespace Microsoft.App +az provider register --namespace Microsoft.OperationalInsights +``` + +## Quick Start + +### Create and deploy in one command + +```bash +az containerapp up \ + --name my-app \ + --resource-group my-rg \ + --location eastus \ + --environment my-env \ + --image mcr.microsoft.com/k8se/quickstart:latest \ + --target-port 80 \ + --ingress external +``` + +`containerapp up` creates the environment, Log Analytics workspace, and container app if they don't already exist. + +### Step-by-step creation + +```bash +# 1. Create environment +az containerapp env create \ + --name my-env \ + --resource-group my-rg \ + --location eastus + +# 2. Create container app +az containerapp create \ + --name my-app \ + --resource-group my-rg \ + --environment my-env \ + --image myregistry.azurecr.io/myapp:latest \ + --target-port 8080 \ + --ingress external \ + --registry-server myregistry.azurecr.io \ + --min-replicas 1 \ + --max-replicas 10 \ + --cpu 0.5 \ + --memory 1.0Gi \ + --env-vars "DB_HOST=mydb.postgres.database.azure.com" "APP_ENV=production" +``` + +## Container Image Sources + +### Azure Container Registry (ACR) + +```bash +# Use managed identity (recommended — no credentials stored) +az containerapp create \ + --name my-app \ + --resource-group my-rg \ + --environment my-env \ + --image myregistry.azurecr.io/myapp:v1 \ + --registry-server myregistry.azurecr.io \ + --registry-identity system-environment + +# Use admin credentials (not recommended for production) +az containerapp create \ + --name my-app \ + --resource-group my-rg \ + --environment my-env \ + --image myregistry.azurecr.io/myapp:v1 \ + --registry-server myregistry.azurecr.io \ + --registry-username \ + --registry-password +``` + +### Docker Hub or other registries + +```bash +az containerapp create \ + --name my-app \ + --resource-group my-rg \ + --environment my-env \ + --image docker.io/myuser/myapp:latest \ + --registry-server docker.io \ + --registry-username \ + --registry-password +``` + +## Ingress Configuration + +| Setting | Description | +|---------|-------------| +| `--ingress external` | Accessible from the internet and within the environment | +| `--ingress internal` | Accessible only within the environment (service-to-service) | +| `--target-port` | The port your container listens on | +| `--transport auto` | Auto-detect HTTP/1.1 or HTTP/2 (default) | +| `--transport http2` | Force HTTP/2 | +| `--transport tcp` | TCP-only (no HTTP features) | + +```bash +# External HTTPS endpoint +az containerapp ingress enable \ + --name my-app \ + --resource-group my-rg \ + --type external \ + --target-port 8080 \ + --transport auto + +# Internal-only (microservice backend) +az containerapp ingress enable \ + --name my-app \ + --resource-group my-rg \ + --type internal \ + --target-port 8080 +``` + +### Custom Domains + +```bash +# Add custom domain with managed certificate +az containerapp hostname add \ + --name my-app \ + --resource-group my-rg \ + --hostname api.example.com + +az containerapp hostname bind \ + --name my-app \ + --resource-group my-rg \ + --hostname api.example.com \ + --environment my-env \ + --validation-method CNAME +``` + +## Scaling Rules + +ACA uses KEDA (Kubernetes Event-driven Autoscaling) for scale decisions. Default: 0–10 replicas with HTTP scaling. + +### HTTP scaling + +```bash +az containerapp create \ + --name my-app \ + --resource-group my-rg \ + --environment my-env \ + --image myapp:latest \ + --min-replicas 0 \ + --max-replicas 20 \ + --scale-rule-name http-rule \ + --scale-rule-type http \ + --scale-rule-http-concurrency 50 +``` + +When concurrent requests exceed 50 per replica, a new replica is created. Apps with HTTP scaling can scale to zero when idle. + +### TCP scaling + +```bash +az containerapp create \ + --name my-app \ + --resource-group my-rg \ + --environment my-env \ + --image myapp:latest \ + --min-replicas 0 \ + --max-replicas 10 \ + --transport tcp \ + --ingress external \ + --target-port 9090 \ + --scale-rule-name tcp-rule \ + --scale-rule-type tcp \ + --scale-rule-tcp-concurrency 100 +``` + +### Custom scaling (event-driven) + +Use any KEDA-supported scaler. Common examples: + +**Azure Service Bus queue:** + +```bash +az containerapp create \ + --name my-worker \ + --resource-group my-rg \ + --environment my-env \ + --image myworker:latest \ + --min-replicas 0 \ + --max-replicas 30 \ + --secrets "sb-conn=" \ + --scale-rule-name servicebus-rule \ + --scale-rule-type azure-servicebus \ + --scale-rule-metadata "queueName=orders" \ + "namespace=my-sb-ns" \ + "messageCount=5" \ + --scale-rule-auth "connection=sb-conn" +``` + +**Azure Queue Storage (with managed identity):** + +```bash +az containerapp create \ + --name my-processor \ + --resource-group my-rg \ + --environment my-env \ + --image myprocessor:latest \ + --user-assigned \ + --min-replicas 0 \ + --max-replicas 15 \ + --scale-rule-name queue-rule \ + --scale-rule-type azure-queue \ + --scale-rule-metadata "accountName=mystorageacct" \ + "queueName=work-items" \ + "queueLength=10" \ + --scale-rule-identity +``` + +### Scale behavior reference + +| Parameter | Value | +|-----------|-------| +| Polling interval | 30 seconds | +| Cool down period | 300 seconds (applies only when scaling from 1 to 0) | +| Scale up step | 1, 4, 8, 16, 32, ... up to max replicas | +| Scale down step | 100% of excess replicas removed | +| Algorithm | `desiredReplicas = ceil(currentMetricValue / targetMetricValue)` | + +**Important:** If ingress is disabled and no custom scale rule or `minReplicas >= 1` is set, the app scales to zero with no way to restart. + +## Revisions and Traffic Splitting + +```bash +# Enable multi-revision mode +az containerapp revision set-mode \ + --name my-app \ + --resource-group my-rg \ + --mode multiple + +# Deploy a new revision +az containerapp update \ + --name my-app \ + --resource-group my-rg \ + --image myapp:v2 + +# Split traffic (blue/green or canary) +az containerapp ingress traffic set \ + --name my-app \ + --resource-group my-rg \ + --revision-weight my-app--v1=80 my-app--v2=20 + +# Promote new revision to 100% +az containerapp ingress traffic set \ + --name my-app \ + --resource-group my-rg \ + --revision-weight my-app--v2=100 + +# Deactivate old revision +az containerapp revision deactivate \ + --name my-app \ + --resource-group my-rg \ + --revision my-app--v1 +``` + +## Jobs + +Jobs are for tasks that run to completion rather than serving traffic. + +```bash +# Scheduled job (cron) +az containerapp job create \ + --name nightly-cleanup \ + --resource-group my-rg \ + --environment my-env \ + --image mytools:latest \ + --trigger-type Schedule \ + --cron-expression "0 2 * * *" \ + --replica-timeout 1800 \ + --replica-retry-limit 1 \ + --cpu 0.5 \ + --memory 1.0Gi + +# Manual (on-demand) job +az containerapp job create \ + --name data-migration \ + --resource-group my-rg \ + --environment my-env \ + --image mymigration:latest \ + --trigger-type Manual \ + --replica-timeout 3600 \ + --replica-retry-limit 0 \ + --cpu 1.0 \ + --memory 2.0Gi + +# Start a manual job execution +az containerapp job start \ + --name data-migration \ + --resource-group my-rg + +# Event-driven job (processes queue messages then exits) +az containerapp job create \ + --name queue-processor \ + --resource-group my-rg \ + --environment my-env \ + --image myprocessor:latest \ + --trigger-type Event \ + --min-executions 0 \ + --max-executions 10 \ + --scale-rule-name queue-trigger \ + --scale-rule-type azure-queue \ + --scale-rule-metadata "accountName=mystorage" \ + "queueName=jobs" \ + "queueLength=1" \ + --scale-rule-auth "connection=storage-conn" \ + --secrets "storage-conn=" +``` + +## Secrets Management + +```bash +# Add secrets during creation +az containerapp create \ + --name my-app \ + --resource-group my-rg \ + --environment my-env \ + --image myapp:latest \ + --secrets "db-password=" "api-key=" \ + --env-vars "DB_PASSWORD=secretref:db-password" "API_KEY=secretref:api-key" + +# Reference Key Vault secrets (managed identity required) +az containerapp create \ + --name my-app \ + --resource-group my-rg \ + --environment my-env \ + --image myapp:latest \ + --user-assigned \ + --secrets "db-pass=keyvaultref:,identityref:" \ + --env-vars "DB_PASSWORD=secretref:db-pass" +``` + +## Managed Identity + +```bash +# Enable system-assigned identity +az containerapp identity assign \ + --name my-app \ + --resource-group my-rg \ + --system-assigned + +# Enable user-assigned identity +az containerapp identity assign \ + --name my-app \ + --resource-group my-rg \ + --user-assigned +``` + +Use managed identity for: +- Pulling images from ACR (via `--registry-identity`) +- Accessing Key Vault secrets +- Authenticating KEDA scale rules to Azure services +- Connecting to Azure databases without passwords + +## Dapr Integration + +Enable Dapr sidecars for microservice communication patterns: + +```bash +# Enable Dapr on a container app +az containerapp dapr enable \ + --name my-api \ + --resource-group my-rg \ + --dapr-app-id my-api \ + --dapr-app-port 8080 \ + --dapr-app-protocol http + +# Create a Dapr component (e.g., state store) +az containerapp env dapr-component set \ + --name my-env \ + --resource-group my-rg \ + --dapr-component-name statestore \ + --yaml dapr-statestore.yaml +``` + +### Example Dapr component YAML (state store with Cosmos DB) + +```yaml +componentType: state.azure.cosmosdb +version: v1 +metadata: + - name: url + value: "https://myaccount.documents.azure.com:443/" + - name: database + value: "mydb" + - name: collection + value: "mystate" + - name: masterKey + secretRef: cosmos-key +secrets: + - name: cosmos-key + value: "" +scopes: + - my-api + - my-worker +``` + +### Supported Dapr building blocks in ACA + +| API | Status | Use Case | +|-----|--------|----------| +| Service-to-service invocation | GA | Direct calls between apps with mTLS | +| State management | GA | Key-value CRUD operations | +| Pub/sub | GA | Async messaging via message brokers | +| Bindings | GA | Trigger/output from external systems | +| Actors | GA | Stateful, single-threaded units of work | +| Secrets | GA | Access secrets from Dapr components | +| Configuration | GA | Retrieve/subscribe to config items | + +**Tier 1 components** (fully supported): +- **State**: Azure Cosmos DB, Blob Storage, Table Storage, SQL Server +- **Pub/sub**: Azure Service Bus Queues/Topics, Event Hubs +- **Bindings**: Azure Storage Queues, Service Bus Queues, Blob Storage, Event Hubs +- **Secrets**: Azure Key Vault + +### Dapr limitations in ACA + +- Dapr is **not supported for jobs** +- Actor reminders require `minReplicas >= 1` +- Dapr server extensions, actor SDK, and workflow SDK are not compatible with ACA + +## Networking + +### VNet integration + +```bash +# Create environment with custom VNet +az containerapp env create \ + --name my-env \ + --resource-group my-rg \ + --location eastus \ + --infrastructure-subnet-resource-id +``` + +### Service-to-service communication + +Apps in the same environment can reach each other using the app name as hostname: + +``` +http:// # Internal URL (within environment) +https://. # FQDN (if external ingress) +``` + +## Health Probes + +```json +{ + "template": { + "containers": [{ + "name": "my-app", + "image": "myapp:latest", + "probes": [ + { + "type": "liveness", + "httpGet": { + "path": "/healthz", + "port": 8080 + }, + "initialDelaySeconds": 5, + "periodSeconds": 10 + }, + { + "type": "readiness", + "httpGet": { + "path": "/ready", + "port": 8080 + }, + "initialDelaySeconds": 3, + "periodSeconds": 5 + }, + { + "type": "startup", + "httpGet": { + "path": "/startup", + "port": 8080 + }, + "initialDelaySeconds": 0, + "periodSeconds": 1, + "failureThreshold": 30 + } + ] + }] + } +} +``` + +## Environment Variables and Resource Limits + +```bash +az containerapp update \ + --name my-app \ + --resource-group my-rg \ + --cpu 1.0 \ + --memory 2.0Gi \ + --env-vars "NODE_ENV=production" "LOG_LEVEL=info" +``` + +| CPU | Memory options | +|-----|----------------| +| 0.25 | 0.5Gi | +| 0.5 | 1.0Gi | +| 0.75 | 1.5Gi | +| 1.0 | 2.0Gi | +| 1.25 | 2.5Gi | +| 1.5 | 3.0Gi | +| 1.75 | 3.5Gi | +| 2.0 | 4.0Gi | + +Higher CPU/memory options are available on workload-profile environments (Dedicated plan). + +## Monitoring and Logs + +```bash +# View app logs (real-time) +az containerapp logs show \ + --name my-app \ + --resource-group my-rg \ + --type console \ + --follow + +# View system logs +az containerapp logs show \ + --name my-app \ + --resource-group my-rg \ + --type system + +# Query logs via Log Analytics (KQL) +az monitor log-analytics query \ + --workspace \ + --analytics-query "ContainerAppConsoleLogs_CL | where ContainerAppName_s == 'my-app' | where TimeGenerated > ago(1h) | project TimeGenerated, Log_s | order by TimeGenerated desc" \ + --output table +``` + +## Scenarios + +### Deploy a multi-container microservice with Dapr + +```bash +# Create environment +az containerapp env create --name prod-env --resource-group my-rg --location eastus + +# Deploy API gateway (external) +az containerapp create \ + --name api-gateway \ + --resource-group my-rg \ + --environment prod-env \ + --image myregistry.azurecr.io/gateway:v1 \ + --target-port 8080 \ + --ingress external \ + --min-replicas 2 \ + --max-replicas 20 \ + --scale-rule-name http-scale \ + --scale-rule-type http \ + --scale-rule-http-concurrency 100 \ + --registry-server myregistry.azurecr.io \ + --registry-identity system-environment \ + --dapr-app-id api-gateway \ + --dapr-app-port 8080 + +# Deploy backend service (internal) +az containerapp create \ + --name order-service \ + --resource-group my-rg \ + --environment prod-env \ + --image myregistry.azurecr.io/orders:v1 \ + --target-port 3000 \ + --ingress internal \ + --min-replicas 1 \ + --max-replicas 10 \ + --registry-server myregistry.azurecr.io \ + --registry-identity system-environment \ + --dapr-app-id order-service \ + --dapr-app-port 3000 + +# Deploy event-driven worker (no ingress) +az containerapp create \ + --name order-processor \ + --resource-group my-rg \ + --environment prod-env \ + --image myregistry.azurecr.io/processor:v1 \ + --min-replicas 0 \ + --max-replicas 30 \ + --registry-server myregistry.azurecr.io \ + --registry-identity system-environment \ + --secrets "sb-conn=" \ + --scale-rule-name orders-queue \ + --scale-rule-type azure-servicebus \ + --scale-rule-metadata "queueName=new-orders" \ + "namespace=my-sb" \ + "messageCount=5" \ + --scale-rule-auth "connection=sb-conn" \ + --dapr-app-id order-processor \ + --dapr-app-port 3000 +``` + +### Blue/green deployment + +```bash +# Ensure multi-revision mode +az containerapp revision set-mode --name my-app --resource-group my-rg --mode multiple + +# Deploy new version (creates new revision, initial 0% traffic) +az containerapp update \ + --name my-app \ + --resource-group my-rg \ + --image myapp:v2 \ + --revision-suffix v2 + +# Send 10% canary traffic +az containerapp ingress traffic set \ + --name my-app \ + --resource-group my-rg \ + --revision-weight my-app--v1=90 my-app--v2=10 + +# Promote after validation +az containerapp ingress traffic set \ + --name my-app \ + --resource-group my-rg \ + --revision-weight my-app--v2=100 + +# Clean up old revision +az containerapp revision deactivate --name my-app --resource-group my-rg --revision my-app--v1 +``` + +### Deploy from source code (cloud build) + +```bash +az containerapp up \ + --name my-app \ + --resource-group my-rg \ + --environment my-env \ + --source . \ + --ingress external \ + --target-port 8080 +``` + +ACA auto-detects the language, builds the container image in the cloud, pushes to a managed registry, and deploys. + +## Troubleshooting + +| Issue | Cause | Solution | +|-------|-------|----------| +| App stuck at 0 replicas | No ingress + no scale rule + no `minReplicas` | Set `--min-replicas 1` or add a scale rule | +| 404 on requests | Ingress not enabled, or wrong `target-port` | Enable ingress and match `--target-port` to the port your app listens on | +| Container crash loop | App exits immediately | Check logs with `az containerapp logs show --type console`; verify health probes and startup time | +| Slow cold starts | Scale-to-zero + heavy container | Set `--min-replicas 1` or optimize image size | +| Image pull failure | Wrong registry credentials or image tag | Verify registry server, credentials, and image name/tag | +| Inter-service connectivity | Wrong app name or ingress type | Use internal ingress; reference services by app name within environment | +| Revision not receiving traffic | Single-revision mode or no traffic weight | Switch to multi-revision mode; set traffic weights explicitly | +| Scaling not triggering | Incorrect KEDA scaler metadata | Verify `--scale-rule-metadata` values match your Azure resource names | +| Dapr sidecar not starting | Dapr not enabled or port mismatch | Verify `--dapr-app-port` matches actual container port | + +## Reference Documentation + +- [Azure Container Apps overview](https://learn.microsoft.com/azure/container-apps/overview) +- [Scaling rules](https://learn.microsoft.com/azure/container-apps/scale-app) +- [Dapr integration](https://learn.microsoft.com/azure/container-apps/dapr-overview) +- [Jobs](https://learn.microsoft.com/azure/container-apps/jobs) +- [Networking](https://learn.microsoft.com/azure/container-apps/networking) +- [Health probes](https://learn.microsoft.com/azure/container-apps/health-probes) +- [Managed identity](https://learn.microsoft.com/azure/container-apps/managed-identity) +- [KEDA scalers](https://keda.sh/docs/scalers/) From 053547e4d810618812e2221479ac91f409715708 Mon Sep 17 00:00:00 2001 From: krishna-sunkavalli Date: Thu, 9 Apr 2026 17:29:16 -0500 Subject: [PATCH 2/4] refactor: split SKILL.md into slim router (<500 lines) + references - Reduced SKILL.md from 684 lines to 280 lines - Added numbered workflow steps (Steps 1-6) - Moved detailed scaling examples to references/scaling-rules.md - Moved Dapr building blocks/components to references/dapr-integration.md - Moved jobs, revisions, scenarios to references/scenarios.md - Addresses CI feedback: line count, BPE tokens, numbered steps --- docs/README.skills.md | 2 +- skills/azure-container-apps/SKILL.md | 676 ++++-------------- .../references/dapr-integration.md | 78 ++ .../references/scaling-rules.md | 92 +++ .../references/scenarios.md | 189 +++++ 5 files changed, 494 insertions(+), 543 deletions(-) create mode 100644 skills/azure-container-apps/references/dapr-integration.md create mode 100644 skills/azure-container-apps/references/scaling-rules.md create mode 100644 skills/azure-container-apps/references/scenarios.md diff --git a/docs/README.skills.md b/docs/README.skills.md index 7590a9a2b..6e52a84d3 100644 --- a/docs/README.skills.md +++ b/docs/README.skills.md @@ -52,7 +52,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-skills) for guidelines on how to | [aws-cdk-python-setup](../skills/aws-cdk-python-setup/SKILL.md) | Setup and initialization guide for developing AWS CDK (Cloud Development Kit) applications in Python. This skill enables users to configure environment prerequisites, create new CDK projects, manage dependencies, and deploy to AWS. | None | | [az-cost-optimize](../skills/az-cost-optimize/SKILL.md) | Analyze Azure resources used in the app (IaC files and/or resources in a target rg) and optimize costs - creating GitHub issues for identified optimizations. | None | | [azure-architecture-autopilot](../skills/azure-architecture-autopilot/SKILL.md) | Design Azure infrastructure using natural language, or analyze existing Azure resources to auto-generate architecture diagrams, refine them through conversation, and deploy with Bicep.
When to use this skill: - "Create X on Azure", "Set up a RAG architecture" (new design) - "Analyze my current Azure infrastructure", "Draw a diagram for rg-xxx" (existing analysis) - "Foundry is slow", "I want to reduce costs", "Strengthen security" (natural language modification) - Azure resource deployment, Bicep template generation, IaC code generation - Microsoft Foundry, AI Search, OpenAI, Fabric, ADLS Gen2, Databricks, and all Azure services | `.gitignore`
`README.md`
`assets/06-architecture-diagram.png`
`assets/07-azure-portal-resources.png`
`assets/08-deployment-succeeded.png`
`references/ai-data.md`
`references/architecture-guidance-sources.md`
`references/azure-common-patterns.md`
`references/azure-dynamic-sources.md`
`references/bicep-generator.md`
`references/bicep-reviewer.md`
`references/phase0-scanner.md`
`references/phase1-advisor.md`
`references/phase4-deployer.md`
`references/service-gotchas.md`
`scripts/cli.py`
`scripts/generator.py`
`scripts/icons.py` | -| [azure-container-apps](../skills/azure-container-apps/SKILL.md) | Guide for building, deploying, scaling, and troubleshooting Azure Container Apps. Use when creating container apps, configuring ingress, setting up scaling rules, enabling Dapr sidecars, deploying container images, creating jobs, configuring custom domains, managing revisions, traffic splitting, or troubleshooting ACA workloads. | None | +| [azure-container-apps](../skills/azure-container-apps/SKILL.md) | Guide for building, deploying, scaling, and troubleshooting Azure Container Apps. Use when creating container apps, configuring ingress, setting up scaling rules, enabling Dapr sidecars, deploying container images, creating jobs, configuring custom domains, managing revisions, traffic splitting, or troubleshooting ACA workloads. | `references/dapr-integration.md`
`references/scaling-rules.md`
`references/scenarios.md` | | [azure-deployment-preflight](../skills/azure-deployment-preflight/SKILL.md) | Performs comprehensive preflight validation of Bicep deployments to Azure, including template syntax validation, what-if analysis, and permission checks. Use this skill before any deployment to Azure to preview changes, identify potential issues, and ensure the deployment will succeed. Activate when users mention deploying to Azure, validating Bicep files, checking deployment permissions, previewing infrastructure changes, running what-if, or preparing for azd provision. | `references/ERROR-HANDLING.md`
`references/REPORT-TEMPLATE.md`
`references/VALIDATION-COMMANDS.md` | | [azure-devops-cli](../skills/azure-devops-cli/SKILL.md) | Manage Azure DevOps resources via CLI including projects, repos, pipelines, builds, pull requests, work items, artifacts, and service endpoints. Use when working with Azure DevOps, az commands, devops automation, CI/CD, or when user mentions Azure DevOps CLI. | `references/advanced-usage.md`
`references/boards-and-iterations.md`
`references/org-and-security.md`
`references/pipelines-and-builds.md`
`references/repos-and-prs.md`
`references/variables-and-agents.md`
`references/workflows-and-patterns.md` | | [azure-pricing](../skills/azure-pricing/SKILL.md) | Fetches real-time Azure retail pricing using the Azure Retail Prices API (prices.azure.com) and estimates Copilot Studio agent credit consumption. Use when the user asks about the cost of any Azure service, wants to compare SKU prices, needs pricing data for a cost estimate, mentions Azure pricing, Azure costs, Azure billing, or asks about Copilot Studio pricing, Copilot Credits, or agent usage estimation. Covers compute, storage, networking, databases, AI, Copilot Studio, and all other Azure service families. | `references/COPILOT-STUDIO-RATES.md`
`references/COST-ESTIMATOR.md`
`references/REGIONS.md`
`references/SERVICE-NAMES.md` | diff --git a/skills/azure-container-apps/SKILL.md b/skills/azure-container-apps/SKILL.md index 174c18216..c5bb44030 100644 --- a/skills/azure-container-apps/SKILL.md +++ b/skills/azure-container-apps/SKILL.md @@ -5,56 +5,44 @@ description: 'Guide for building, deploying, scaling, and troubleshooting Azure # Azure Container Apps -Azure Container Apps (ACA) is a serverless container platform for running microservices, APIs, background jobs, and event-driven workloads without managing infrastructure. +Azure Container Apps (ACA) is a serverless container platform for microservices, APIs, background jobs, and event-driven workloads. ## Key Concepts | Concept | Description | |---------|-------------| -| **Environment** | Shared boundary for container apps. Apps in the same environment share a virtual network, logging destination, and Dapr configuration. | -| **Container App** | The deployable unit. Each app has one or more containers, ingress settings, scaling rules, and secrets. | -| **Revision** | An immutable snapshot of a container app version. New revisions are created when template-scope properties change (image, env vars, scaling rules). | -| **Replica** | A running instance of a revision. Scaling rules control how many replicas run. | -| **Job** | A container that runs to completion — on-demand, scheduled (cron), or event-driven. Jobs do not serve traffic. | +| **Environment** | Shared boundary — apps share a VNet, logging, and Dapr config | +| **Container App** | Deployable unit with containers, ingress, scaling rules, and secrets | +| **Revision** | Immutable snapshot created when template properties change | +| **Replica** | Running instance of a revision; controlled by scaling rules | +| **Job** | Runs to completion (scheduled, manual, or event-driven) | ## Prerequisites ```bash -# Install or upgrade the Azure CLI extension az extension add --name containerapp --upgrade - -# Register required providers az provider register --namespace Microsoft.App az provider register --namespace Microsoft.OperationalInsights ``` -## Quick Start - -### Create and deploy in one command - -```bash -az containerapp up \ - --name my-app \ - --resource-group my-rg \ - --location eastus \ - --environment my-env \ - --image mcr.microsoft.com/k8se/quickstart:latest \ - --target-port 80 \ - --ingress external -``` +## Workflow -`containerapp up` creates the environment, Log Analytics workspace, and container app if they don't already exist. +Follow these numbered steps to deploy a container app: -### Step-by-step creation +### Step 1: Create an Environment ```bash -# 1. Create environment az containerapp env create \ --name my-env \ --resource-group my-rg \ --location eastus +``` -# 2. Create container app +For VNet integration, add `--infrastructure-subnet-resource-id `. + +### Step 2: Create the Container App + +```bash az containerapp create \ --name my-app \ --resource-group my-rg \ @@ -63,618 +51,222 @@ az containerapp create \ --target-port 8080 \ --ingress external \ --registry-server myregistry.azurecr.io \ + --registry-identity system-environment \ --min-replicas 1 \ --max-replicas 10 \ - --cpu 0.5 \ - --memory 1.0Gi \ - --env-vars "DB_HOST=mydb.postgres.database.azure.com" "APP_ENV=production" + --cpu 0.5 --memory 1.0Gi \ + --env-vars "APP_ENV=production" ``` -## Container Image Sources +Use `--registry-identity system-environment` for managed-identity-based ACR pulls (recommended over credentials). -### Azure Container Registry (ACR) +**Quick alternative** — single command that creates everything: ```bash -# Use managed identity (recommended — no credentials stored) -az containerapp create \ - --name my-app \ - --resource-group my-rg \ - --environment my-env \ - --image myregistry.azurecr.io/myapp:v1 \ - --registry-server myregistry.azurecr.io \ - --registry-identity system-environment - -# Use admin credentials (not recommended for production) -az containerapp create \ - --name my-app \ - --resource-group my-rg \ - --environment my-env \ - --image myregistry.azurecr.io/myapp:v1 \ - --registry-server myregistry.azurecr.io \ - --registry-username \ - --registry-password -``` - -### Docker Hub or other registries - -```bash -az containerapp create \ +az containerapp up \ --name my-app \ --resource-group my-rg \ --environment my-env \ - --image docker.io/myuser/myapp:latest \ - --registry-server docker.io \ - --registry-username \ - --registry-password + --image mcr.microsoft.com/k8se/quickstart:latest \ + --target-port 80 --ingress external ``` -## Ingress Configuration +### Step 3: Configure Ingress -| Setting | Description | -|---------|-------------| -| `--ingress external` | Accessible from the internet and within the environment | -| `--ingress internal` | Accessible only within the environment (service-to-service) | -| `--target-port` | The port your container listens on | +| Flag | Purpose | +|------|---------| +| `--ingress external` | Internet-accessible + within environment | +| `--ingress internal` | Within environment only (service-to-service) | +| `--target-port` | Port the container listens on | | `--transport auto` | Auto-detect HTTP/1.1 or HTTP/2 (default) | | `--transport http2` | Force HTTP/2 | | `--transport tcp` | TCP-only (no HTTP features) | ```bash -# External HTTPS endpoint az containerapp ingress enable \ - --name my-app \ - --resource-group my-rg \ - --type external \ - --target-port 8080 \ - --transport auto - -# Internal-only (microservice backend) -az containerapp ingress enable \ - --name my-app \ - --resource-group my-rg \ - --type internal \ - --target-port 8080 + --name my-app --resource-group my-rg \ + --type external --target-port 8080 --transport auto ``` -### Custom Domains +**Custom domain:** ```bash -# Add custom domain with managed certificate -az containerapp hostname add \ - --name my-app \ - --resource-group my-rg \ - --hostname api.example.com - -az containerapp hostname bind \ - --name my-app \ - --resource-group my-rg \ - --hostname api.example.com \ - --environment my-env \ - --validation-method CNAME +az containerapp hostname add --name my-app --resource-group my-rg --hostname api.example.com +az containerapp hostname bind --name my-app --resource-group my-rg \ + --hostname api.example.com --environment my-env --validation-method CNAME ``` -## Scaling Rules +### Step 4: Add Scaling Rules -ACA uses KEDA (Kubernetes Event-driven Autoscaling) for scale decisions. Default: 0–10 replicas with HTTP scaling. +ACA uses KEDA for autoscaling. Default: 0-10 replicas with HTTP scaling. -### HTTP scaling +**HTTP scaling:** ```bash az containerapp create \ - --name my-app \ - --resource-group my-rg \ - --environment my-env \ + --name my-app --resource-group my-rg --environment my-env \ --image myapp:latest \ - --min-replicas 0 \ - --max-replicas 20 \ - --scale-rule-name http-rule \ - --scale-rule-type http \ + --min-replicas 0 --max-replicas 20 \ + --scale-rule-name http-rule --scale-rule-type http \ --scale-rule-http-concurrency 50 ``` -When concurrent requests exceed 50 per replica, a new replica is created. Apps with HTTP scaling can scale to zero when idle. - -### TCP scaling - -```bash -az containerapp create \ - --name my-app \ - --resource-group my-rg \ - --environment my-env \ - --image myapp:latest \ - --min-replicas 0 \ - --max-replicas 10 \ - --transport tcp \ - --ingress external \ - --target-port 9090 \ - --scale-rule-name tcp-rule \ - --scale-rule-type tcp \ - --scale-rule-tcp-concurrency 100 -``` - -### Custom scaling (event-driven) - -Use any KEDA-supported scaler. Common examples: - -**Azure Service Bus queue:** +**Event-driven scaling (Service Bus):** ```bash az containerapp create \ - --name my-worker \ - --resource-group my-rg \ - --environment my-env \ + --name my-worker --resource-group my-rg --environment my-env \ --image myworker:latest \ - --min-replicas 0 \ - --max-replicas 30 \ + --min-replicas 0 --max-replicas 30 \ --secrets "sb-conn=" \ - --scale-rule-name servicebus-rule \ - --scale-rule-type azure-servicebus \ - --scale-rule-metadata "queueName=orders" \ - "namespace=my-sb-ns" \ - "messageCount=5" \ + --scale-rule-name sb-rule --scale-rule-type azure-servicebus \ + --scale-rule-metadata "queueName=orders" "namespace=my-sb-ns" "messageCount=5" \ --scale-rule-auth "connection=sb-conn" ``` -**Azure Queue Storage (with managed identity):** +> **Important:** If ingress is disabled and no scale rule or `minReplicas >= 1` is set, the app scales to zero permanently. -```bash -az containerapp create \ - --name my-processor \ - --resource-group my-rg \ - --environment my-env \ - --image myprocessor:latest \ - --user-assigned \ - --min-replicas 0 \ - --max-replicas 15 \ - --scale-rule-name queue-rule \ - --scale-rule-type azure-queue \ - --scale-rule-metadata "accountName=mystorageacct" \ - "queueName=work-items" \ - "queueLength=10" \ - --scale-rule-identity -``` +See `references/scaling-rules.md` for TCP scaling, Queue Storage with managed identity, and scale behavior details. -### Scale behavior reference - -| Parameter | Value | -|-----------|-------| -| Polling interval | 30 seconds | -| Cool down period | 300 seconds (applies only when scaling from 1 to 0) | -| Scale up step | 1, 4, 8, 16, 32, ... up to max replicas | -| Scale down step | 100% of excess replicas removed | -| Algorithm | `desiredReplicas = ceil(currentMetricValue / targetMetricValue)` | - -**Important:** If ingress is disabled and no custom scale rule or `minReplicas >= 1` is set, the app scales to zero with no way to restart. - -## Revisions and Traffic Splitting +### Step 5: Configure Secrets and Identity ```bash -# Enable multi-revision mode -az containerapp revision set-mode \ - --name my-app \ - --resource-group my-rg \ - --mode multiple - -# Deploy a new revision -az containerapp update \ - --name my-app \ - --resource-group my-rg \ - --image myapp:v2 - -# Split traffic (blue/green or canary) -az containerapp ingress traffic set \ - --name my-app \ - --resource-group my-rg \ - --revision-weight my-app--v1=80 my-app--v2=20 - -# Promote new revision to 100% -az containerapp ingress traffic set \ - --name my-app \ - --resource-group my-rg \ - --revision-weight my-app--v2=100 - -# Deactivate old revision -az containerapp revision deactivate \ - --name my-app \ - --resource-group my-rg \ - --revision my-app--v1 -``` - -## Jobs - -Jobs are for tasks that run to completion rather than serving traffic. - -```bash -# Scheduled job (cron) -az containerapp job create \ - --name nightly-cleanup \ - --resource-group my-rg \ - --environment my-env \ - --image mytools:latest \ - --trigger-type Schedule \ - --cron-expression "0 2 * * *" \ - --replica-timeout 1800 \ - --replica-retry-limit 1 \ - --cpu 0.5 \ - --memory 1.0Gi - -# Manual (on-demand) job -az containerapp job create \ - --name data-migration \ - --resource-group my-rg \ - --environment my-env \ - --image mymigration:latest \ - --trigger-type Manual \ - --replica-timeout 3600 \ - --replica-retry-limit 0 \ - --cpu 1.0 \ - --memory 2.0Gi - -# Start a manual job execution -az containerapp job start \ - --name data-migration \ - --resource-group my-rg - -# Event-driven job (processes queue messages then exits) -az containerapp job create \ - --name queue-processor \ - --resource-group my-rg \ - --environment my-env \ - --image myprocessor:latest \ - --trigger-type Event \ - --min-executions 0 \ - --max-executions 10 \ - --scale-rule-name queue-trigger \ - --scale-rule-type azure-queue \ - --scale-rule-metadata "accountName=mystorage" \ - "queueName=jobs" \ - "queueLength=1" \ - --scale-rule-auth "connection=storage-conn" \ - --secrets "storage-conn=" -``` - -## Secrets Management - -```bash -# Add secrets during creation -az containerapp create \ - --name my-app \ - --resource-group my-rg \ - --environment my-env \ +# Inline secrets +az containerapp create --name my-app --resource-group my-rg --environment my-env \ --image myapp:latest \ --secrets "db-password=" "api-key=" \ --env-vars "DB_PASSWORD=secretref:db-password" "API_KEY=secretref:api-key" -# Reference Key Vault secrets (managed identity required) -az containerapp create \ - --name my-app \ - --resource-group my-rg \ - --environment my-env \ - --image myapp:latest \ - --user-assigned \ - --secrets "db-pass=keyvaultref:,identityref:" \ +# Key Vault reference (requires managed identity) +az containerapp create --name my-app --resource-group my-rg --environment my-env \ + --image myapp:latest --user-assigned \ + --secrets "db-pass=keyvaultref:,identityref:" \ --env-vars "DB_PASSWORD=secretref:db-pass" ``` -## Managed Identity +**Enable managed identity:** ```bash -# Enable system-assigned identity -az containerapp identity assign \ - --name my-app \ - --resource-group my-rg \ - --system-assigned - -# Enable user-assigned identity -az containerapp identity assign \ - --name my-app \ - --resource-group my-rg \ - --user-assigned +az containerapp identity assign --name my-app --resource-group my-rg --system-assigned ``` -Use managed identity for: -- Pulling images from ACR (via `--registry-identity`) -- Accessing Key Vault secrets -- Authenticating KEDA scale rules to Azure services -- Connecting to Azure databases without passwords +Use managed identity for: ACR pulls (`--registry-identity`), Key Vault secrets, KEDA auth, passwordless DB connections. -## Dapr Integration - -Enable Dapr sidecars for microservice communication patterns: +### Step 6: Monitor and Troubleshoot ```bash -# Enable Dapr on a container app -az containerapp dapr enable \ - --name my-api \ - --resource-group my-rg \ - --dapr-app-id my-api \ - --dapr-app-port 8080 \ - --dapr-app-protocol http +# Real-time console logs +az containerapp logs show --name my-app --resource-group my-rg --type console --follow -# Create a Dapr component (e.g., state store) -az containerapp env dapr-component set \ - --name my-env \ - --resource-group my-rg \ - --dapr-component-name statestore \ - --yaml dapr-statestore.yaml -``` +# System logs +az containerapp logs show --name my-app --resource-group my-rg --type system -### Example Dapr component YAML (state store with Cosmos DB) - -```yaml -componentType: state.azure.cosmosdb -version: v1 -metadata: - - name: url - value: "https://myaccount.documents.azure.com:443/" - - name: database - value: "mydb" - - name: collection - value: "mystate" - - name: masterKey - secretRef: cosmos-key -secrets: - - name: cosmos-key - value: "" -scopes: - - my-api - - my-worker +# KQL query +az monitor log-analytics query --workspace \ + --analytics-query "ContainerAppConsoleLogs_CL | where ContainerAppName_s == 'my-app' | where TimeGenerated > ago(1h) | project TimeGenerated, Log_s | order by TimeGenerated desc" \ + --output table ``` -### Supported Dapr building blocks in ACA - -| API | Status | Use Case | -|-----|--------|----------| -| Service-to-service invocation | GA | Direct calls between apps with mTLS | -| State management | GA | Key-value CRUD operations | -| Pub/sub | GA | Async messaging via message brokers | -| Bindings | GA | Trigger/output from external systems | -| Actors | GA | Stateful, single-threaded units of work | -| Secrets | GA | Access secrets from Dapr components | -| Configuration | GA | Retrieve/subscribe to config items | - -**Tier 1 components** (fully supported): -- **State**: Azure Cosmos DB, Blob Storage, Table Storage, SQL Server -- **Pub/sub**: Azure Service Bus Queues/Topics, Event Hubs -- **Bindings**: Azure Storage Queues, Service Bus Queues, Blob Storage, Event Hubs -- **Secrets**: Azure Key Vault +## Revisions and Traffic Splitting -### Dapr limitations in ACA +```bash +# Enable multi-revision mode +az containerapp revision set-mode --name my-app --resource-group my-rg --mode multiple -- Dapr is **not supported for jobs** -- Actor reminders require `minReplicas >= 1` -- Dapr server extensions, actor SDK, and workflow SDK are not compatible with ACA +# Deploy new revision +az containerapp update --name my-app --resource-group my-rg --image myapp:v2 -## Networking +# Canary traffic split +az containerapp ingress traffic set --name my-app --resource-group my-rg \ + --revision-weight my-app--v1=80 my-app--v2=20 -### VNet integration +# Full cutover +az containerapp ingress traffic set --name my-app --resource-group my-rg \ + --revision-weight my-app--v2=100 -```bash -# Create environment with custom VNet -az containerapp env create \ - --name my-env \ - --resource-group my-rg \ - --location eastus \ - --infrastructure-subnet-resource-id +# Deactivate old revision +az containerapp revision deactivate --name my-app --resource-group my-rg --revision my-app--v1 ``` -### Service-to-service communication +See `references/scenarios.md` for blue/green deployment patterns and revision labels. -Apps in the same environment can reach each other using the app name as hostname: - -``` -http:// # Internal URL (within environment) -https://. # FQDN (if external ingress) -``` - -## Health Probes - -```json -{ - "template": { - "containers": [{ - "name": "my-app", - "image": "myapp:latest", - "probes": [ - { - "type": "liveness", - "httpGet": { - "path": "/healthz", - "port": 8080 - }, - "initialDelaySeconds": 5, - "periodSeconds": 10 - }, - { - "type": "readiness", - "httpGet": { - "path": "/ready", - "port": 8080 - }, - "initialDelaySeconds": 3, - "periodSeconds": 5 - }, - { - "type": "startup", - "httpGet": { - "path": "/startup", - "port": 8080 - }, - "initialDelaySeconds": 0, - "periodSeconds": 1, - "failureThreshold": 30 - } - ] - }] - } -} -``` +## Dapr Integration -## Environment Variables and Resource Limits +Enable Dapr sidecars for microservice communication: ```bash -az containerapp update \ - --name my-app \ - --resource-group my-rg \ - --cpu 1.0 \ - --memory 2.0Gi \ - --env-vars "NODE_ENV=production" "LOG_LEVEL=info" +az containerapp dapr enable \ + --name my-api --resource-group my-rg \ + --dapr-app-id my-api --dapr-app-port 8080 --dapr-app-protocol http ``` -| CPU | Memory options | -|-----|----------------| -| 0.25 | 0.5Gi | -| 0.5 | 1.0Gi | -| 0.75 | 1.5Gi | -| 1.0 | 2.0Gi | -| 1.25 | 2.5Gi | -| 1.5 | 3.0Gi | -| 1.75 | 3.5Gi | -| 2.0 | 4.0Gi | - -Higher CPU/memory options are available on workload-profile environments (Dedicated plan). +Key facts: +- Dapr is **not supported for jobs**; actor reminders require `minReplicas >= 1` +- Apps communicate via Dapr service invocation with automatic mTLS +- Tier 1 components (fully supported): Cosmos DB, Service Bus, Event Hubs, Key Vault, Blob Storage -## Monitoring and Logs +See `references/dapr-integration.md` for component YAML examples, building blocks table, and component tiers. -```bash -# View app logs (real-time) -az containerapp logs show \ - --name my-app \ - --resource-group my-rg \ - --type console \ - --follow +## Jobs -# View system logs -az containerapp logs show \ - --name my-app \ - --resource-group my-rg \ - --type system +Jobs run to completion rather than serving traffic. Three trigger types: -# Query logs via Log Analytics (KQL) -az monitor log-analytics query \ - --workspace \ - --analytics-query "ContainerAppConsoleLogs_CL | where ContainerAppName_s == 'my-app' | where TimeGenerated > ago(1h) | project TimeGenerated, Log_s | order by TimeGenerated desc" \ - --output table +```bash +# Scheduled (cron) +az containerapp job create --name nightly-job --resource-group my-rg --environment my-env \ + --image mytools:latest --trigger-type Schedule --cron-expression "0 2 * * *" \ + --replica-timeout 1800 --cpu 0.5 --memory 1.0Gi + +# Manual +az containerapp job create --name migration --resource-group my-rg --environment my-env \ + --image mymigration:latest --trigger-type Manual --replica-timeout 3600 +az containerapp job start --name migration --resource-group my-rg + +# Event-driven +az containerapp job create --name processor --resource-group my-rg --environment my-env \ + --image myprocessor:latest --trigger-type Event \ + --min-executions 0 --max-executions 10 \ + --scale-rule-name queue-trigger --scale-rule-type azure-queue \ + --scale-rule-metadata "accountName=mystorage" "queueName=jobs" "queueLength=1" \ + --scale-rule-auth "connection=storage-conn" --secrets "storage-conn=" ``` -## Scenarios +See `references/scenarios.md` for full job examples and multi-container deployment patterns. -### Deploy a multi-container microservice with Dapr +## Networking ```bash -# Create environment -az containerapp env create --name prod-env --resource-group my-rg --location eastus - -# Deploy API gateway (external) -az containerapp create \ - --name api-gateway \ - --resource-group my-rg \ - --environment prod-env \ - --image myregistry.azurecr.io/gateway:v1 \ - --target-port 8080 \ - --ingress external \ - --min-replicas 2 \ - --max-replicas 20 \ - --scale-rule-name http-scale \ - --scale-rule-type http \ - --scale-rule-http-concurrency 100 \ - --registry-server myregistry.azurecr.io \ - --registry-identity system-environment \ - --dapr-app-id api-gateway \ - --dapr-app-port 8080 - -# Deploy backend service (internal) -az containerapp create \ - --name order-service \ - --resource-group my-rg \ - --environment prod-env \ - --image myregistry.azurecr.io/orders:v1 \ - --target-port 3000 \ - --ingress internal \ - --min-replicas 1 \ - --max-replicas 10 \ - --registry-server myregistry.azurecr.io \ - --registry-identity system-environment \ - --dapr-app-id order-service \ - --dapr-app-port 3000 - -# Deploy event-driven worker (no ingress) -az containerapp create \ - --name order-processor \ - --resource-group my-rg \ - --environment prod-env \ - --image myregistry.azurecr.io/processor:v1 \ - --min-replicas 0 \ - --max-replicas 30 \ - --registry-server myregistry.azurecr.io \ - --registry-identity system-environment \ - --secrets "sb-conn=" \ - --scale-rule-name orders-queue \ - --scale-rule-type azure-servicebus \ - --scale-rule-metadata "queueName=new-orders" \ - "namespace=my-sb" \ - "messageCount=5" \ - --scale-rule-auth "connection=sb-conn" \ - --dapr-app-id order-processor \ - --dapr-app-port 3000 +# VNet-integrated environment +az containerapp env create --name my-env --resource-group my-rg --location eastus \ + --infrastructure-subnet-resource-id ``` -### Blue/green deployment - -```bash -# Ensure multi-revision mode -az containerapp revision set-mode --name my-app --resource-group my-rg --mode multiple - -# Deploy new version (creates new revision, initial 0% traffic) -az containerapp update \ - --name my-app \ - --resource-group my-rg \ - --image myapp:v2 \ - --revision-suffix v2 - -# Send 10% canary traffic -az containerapp ingress traffic set \ - --name my-app \ - --resource-group my-rg \ - --revision-weight my-app--v1=90 my-app--v2=10 - -# Promote after validation -az containerapp ingress traffic set \ - --name my-app \ - --resource-group my-rg \ - --revision-weight my-app--v2=100 +Service-to-service: apps in the same environment reach each other at `http://`. -# Clean up old revision -az containerapp revision deactivate --name my-app --resource-group my-rg --revision my-app--v1 -``` - -### Deploy from source code (cloud build) +## Resource Limits -```bash -az containerapp up \ - --name my-app \ - --resource-group my-rg \ - --environment my-env \ - --source . \ - --ingress external \ - --target-port 8080 -``` +| CPU | Memory | Profile | +|-----|--------|---------| +| 0.25 | 0.5Gi | Lightweight APIs | +| 0.5 | 1.0Gi | Standard web apps | +| 1.0 | 2.0Gi | Moderate workloads | +| 2.0 | 4.0Gi | Heavy processing | -ACA auto-detects the language, builds the container image in the cloud, pushes to a managed registry, and deploys. +Workload-profile environments support up to 16 vCPU / 32 GiB (D-series, E-series). ## Troubleshooting | Issue | Cause | Solution | |-------|-------|----------| | App stuck at 0 replicas | No ingress + no scale rule + no `minReplicas` | Set `--min-replicas 1` or add a scale rule | -| 404 on requests | Ingress not enabled, or wrong `target-port` | Enable ingress and match `--target-port` to the port your app listens on | -| Container crash loop | App exits immediately | Check logs with `az containerapp logs show --type console`; verify health probes and startup time | -| Slow cold starts | Scale-to-zero + heavy container | Set `--min-replicas 1` or optimize image size | -| Image pull failure | Wrong registry credentials or image tag | Verify registry server, credentials, and image name/tag | -| Inter-service connectivity | Wrong app name or ingress type | Use internal ingress; reference services by app name within environment | -| Revision not receiving traffic | Single-revision mode or no traffic weight | Switch to multi-revision mode; set traffic weights explicitly | -| Scaling not triggering | Incorrect KEDA scaler metadata | Verify `--scale-rule-metadata` values match your Azure resource names | -| Dapr sidecar not starting | Dapr not enabled or port mismatch | Verify `--dapr-app-port` matches actual container port | +| 404 on requests | Ingress not enabled or wrong `target-port` | Enable ingress; match `--target-port` to app port | +| Container crash loop | App exits immediately | Check `az containerapp logs show --type console`; verify probes | +| Slow cold starts | Scale-to-zero + heavy image | Set `--min-replicas 1` or optimize image size | +| Image pull failure | Wrong registry/credentials/tag | Verify registry server, credentials, image name | +| Inter-service connectivity | Wrong app name or ingress type | Use internal ingress; reference by app name | +| Revision not receiving traffic | Single-revision mode | Switch to multi-revision mode; set traffic weights | +| Scaling not triggering | Wrong KEDA metadata | Verify `--scale-rule-metadata` matches resource names | +| Dapr sidecar not starting | Dapr disabled or port mismatch | Check `--dapr-app-port` matches container port | ## Reference Documentation diff --git a/skills/azure-container-apps/references/dapr-integration.md b/skills/azure-container-apps/references/dapr-integration.md new file mode 100644 index 000000000..189b750b7 --- /dev/null +++ b/skills/azure-container-apps/references/dapr-integration.md @@ -0,0 +1,78 @@ +# Dapr Integration Reference + +Enable Dapr sidecars for microservice communication patterns. + +## Enable Dapr + +```bash +az containerapp dapr enable \ + --name my-api \ + --resource-group my-rg \ + --dapr-app-id my-api \ + --dapr-app-port 8080 \ + --dapr-app-protocol http +``` + +## Create a Dapr Component + +```bash +az containerapp env dapr-component set \ + --name my-env \ + --resource-group my-rg \ + --dapr-component-name statestore \ + --yaml dapr-statestore.yaml +``` + +### Example: Cosmos DB State Store + +```yaml +componentType: state.azure.cosmosdb +version: v1 +metadata: + - name: url + value: "https://myaccount.documents.azure.com:443/" + - name: database + value: "mydb" + - name: collection + value: "mystate" + - name: masterKey + secretRef: cosmos-key +secrets: + - name: cosmos-key + value: "" +scopes: + - my-api + - my-worker +``` + +## Supported Building Blocks + +| API | Status | Use Case | +| ----------------------------- | ------ | --------------------------------------- | +| Service-to-service invocation | GA | Direct calls between apps with mTLS | +| State management | GA | Key-value CRUD operations | +| Pub/sub | GA | Async messaging via message brokers | +| Bindings | GA | Trigger/output from external systems | +| Actors | GA | Stateful, single-threaded units of work | +| Secrets | GA | Access secrets from Dapr components | +| Configuration | GA | Retrieve/subscribe to config items | + +## Tier 1 Components (Fully Supported) + +- **State**: Azure Cosmos DB, Blob Storage, Table Storage, SQL Server +- **Pub/sub**: Azure Service Bus Queues/Topics, Event Hubs +- **Bindings**: Azure Storage Queues, Service Bus Queues, Blob Storage, Event Hubs +- **Secrets**: Azure Key Vault + +## Tier 2 Components + +- **State**: PostgreSQL, MySQL/MariaDB, Redis +- **Pub/sub**: Apache Kafka, Redis Streams +- **Bindings**: Event Grid, Cosmos DB, Kafka, PostgreSQL, Redis, Cron +- **Configuration**: PostgreSQL, Redis + +## Limitations + +- Dapr is **not supported for jobs** +- Actor reminders require `minReplicas >= 1` +- Dapr server extensions, actor SDK, and workflow SDK are not compatible with ACA diff --git a/skills/azure-container-apps/references/scaling-rules.md b/skills/azure-container-apps/references/scaling-rules.md new file mode 100644 index 000000000..9077ceec5 --- /dev/null +++ b/skills/azure-container-apps/references/scaling-rules.md @@ -0,0 +1,92 @@ +# Scaling Rules Reference + +ACA uses KEDA (Kubernetes Event-driven Autoscaling) for scale decisions. Default: 0–10 replicas with HTTP scaling. + +## HTTP Scaling + +```bash +az containerapp create \ + --name my-app \ + --resource-group my-rg \ + --environment my-env \ + --image myapp:latest \ + --min-replicas 0 \ + --max-replicas 20 \ + --scale-rule-name http-rule \ + --scale-rule-type http \ + --scale-rule-http-concurrency 50 +``` + +When concurrent requests exceed 50 per replica, a new replica is created. Apps with HTTP scaling can scale to zero when idle. + +## TCP Scaling + +```bash +az containerapp create \ + --name my-app \ + --resource-group my-rg \ + --environment my-env \ + --image myapp:latest \ + --min-replicas 0 \ + --max-replicas 10 \ + --transport tcp \ + --ingress external \ + --target-port 9090 \ + --scale-rule-name tcp-rule \ + --scale-rule-type tcp \ + --scale-rule-tcp-concurrency 100 +``` + +## Custom Scaling (Event-Driven) + +Use any KEDA-supported scaler. Common examples: + +### Azure Service Bus Queue + +```bash +az containerapp create \ + --name my-worker \ + --resource-group my-rg \ + --environment my-env \ + --image myworker:latest \ + --min-replicas 0 \ + --max-replicas 30 \ + --secrets "sb-conn=" \ + --scale-rule-name servicebus-rule \ + --scale-rule-type azure-servicebus \ + --scale-rule-metadata "queueName=orders" \ + "namespace=my-sb-ns" \ + "messageCount=5" \ + --scale-rule-auth "connection=sb-conn" +``` + +### Azure Queue Storage (Managed Identity) + +```bash +az containerapp create \ + --name my-processor \ + --resource-group my-rg \ + --environment my-env \ + --image myprocessor:latest \ + --user-assigned \ + --min-replicas 0 \ + --max-replicas 15 \ + --scale-rule-name queue-rule \ + --scale-rule-type azure-queue \ + --scale-rule-metadata "accountName=mystorageacct" \ + "queueName=work-items" \ + "queueLength=10" \ + --scale-rule-identity +``` + +## Scale Behavior + +| Parameter | Value | +| ---------------- | ---------------------------------------------------------------- | +| Polling interval | 30 seconds | +| Cool down period | 300 seconds (applies only when scaling from 1 to 0) | +| Scale up step | 1, 4, 8, 16, 32, ... up to max replicas | +| Scale down step | 100% of excess replicas removed | +| Algorithm | `desiredReplicas = ceil(currentMetricValue / targetMetricValue)` | + +**Important:** If ingress is disabled and no custom scale rule or `minReplicas >= 1` is set, the app scales to zero with no way to restart. diff --git a/skills/azure-container-apps/references/scenarios.md b/skills/azure-container-apps/references/scenarios.md new file mode 100644 index 000000000..d8cd5b301 --- /dev/null +++ b/skills/azure-container-apps/references/scenarios.md @@ -0,0 +1,189 @@ +# Scenarios & Advanced Patterns + +## Container Apps Jobs + +Jobs execute tasks that run to completion and exit. + +### Scheduled Job (Cron) + +```bash +az containerapp job create \ + --name my-scheduled-job \ + --resource-group my-rg \ + --environment my-env \ + --image myregistry.azurecr.io/my-job:latest \ + --trigger-type Schedule \ + --cron-expression "0 */6 * * *" \ + --cpu 0.25 --memory 0.5Gi \ + --replica-timeout 1800 \ + --replica-retry-limit 1 +``` + +### Manual Job + +```bash +az containerapp job create \ + --name my-manual-job \ + --resource-group my-rg \ + --environment my-env \ + --image myregistry.azurecr.io/my-job:latest \ + --trigger-type Manual \ + --cpu 0.5 --memory 1.0Gi \ + --replica-timeout 3600 \ + --replica-retry-limit 2 + +# Start a manual execution +az containerapp job start --name my-manual-job --resource-group my-rg +``` + +### Event-Driven Job (KEDA) + +```bash +az containerapp job create \ + --name my-event-job \ + --resource-group my-rg \ + --environment my-env \ + --image myregistry.azurecr.io/my-processor:latest \ + --trigger-type Event \ + --cpu 0.5 --memory 1.0Gi \ + --replica-timeout 600 \ + --replica-retry-limit 1 \ + --min-executions 0 \ + --max-executions 10 \ + --scale-rule-name queue-trigger \ + --scale-rule-type azure-queue \ + --scale-rule-metadata "queueName=work-items" "queueLength=5" "connectionFromEnv=QUEUE_CONN" \ + --scale-rule-auth "connection=queue-connection" \ + --secrets "queue-connection=" +``` + +## Revisions & Traffic Splitting + +### Create a New Revision + +```bash +az containerapp update \ + --name my-app \ + --resource-group my-rg \ + --image myregistry.azurecr.io/my-app:v2 \ + --revision-suffix v2 +``` + +### Split Traffic (Blue/Green & Canary) + +```bash +# 80/20 canary split +az containerapp ingress traffic set \ + --name my-app \ + --resource-group my-rg \ + --revision-weight my-app--v1=80 my-app--v2=20 + +# Full cutover +az containerapp ingress traffic set \ + --name my-app \ + --resource-group my-rg \ + --revision-weight my-app--v2=100 + +# Rollback +az containerapp ingress traffic set \ + --name my-app \ + --resource-group my-rg \ + --revision-weight my-app--v1=100 +``` + +### Revision Labels + +```bash +az containerapp revision label add \ + --name my-app \ + --resource-group my-rg \ + --label blue --revision my-app--v1 + +# Access labeled revision: my-app---blue. +``` + +## Multi-Container Microservice Deployment + +```bash +# Deploy frontend +az containerapp create \ + --name frontend \ + --resource-group my-rg \ + --environment my-env \ + --image myregistry.azurecr.io/frontend:latest \ + --target-port 3000 \ + --ingress external \ + --min-replicas 1 --max-replicas 5 + +# Deploy backend API (internal ingress) +az containerapp create \ + --name backend-api \ + --resource-group my-rg \ + --environment my-env \ + --image myregistry.azurecr.io/api:latest \ + --target-port 8080 \ + --ingress internal \ + --min-replicas 1 --max-replicas 10 \ + --env-vars "DATABASE_URL=secretref:db-url" \ + --secrets "db-url=" + +# Frontend reaches backend at: http://backend-api +``` + +## Deploy from Source Code + +```bash +az containerapp up \ + --name my-app \ + --resource-group my-rg \ + --environment my-env \ + --source . \ + --ingress external --target-port 8080 +``` + +Supported runtimes: Python, Node.js, .NET, Java, Go. + +## Health Probes + +```json +{ + "containers": [ + { + "probes": [ + { + "type": "liveness", + "httpGet": { "path": "/healthz", "port": 8080 }, + "initialDelaySeconds": 10, + "periodSeconds": 30, + "failureThreshold": 3 + }, + { + "type": "readiness", + "httpGet": { "path": "/ready", "port": 8080 }, + "initialDelaySeconds": 5, + "periodSeconds": 10 + }, + { + "type": "startup", + "httpGet": { "path": "/startup", "port": 8080 }, + "initialDelaySeconds": 0, + "periodSeconds": 5, + "failureThreshold": 30 + } + ] + } + ] +} +``` + +## Resource Configuration + +| vCPU | Memory Options | Profile | +| ---- | -------------- | ------------------------------------ | +| 0.25 | 0.5 Gi | Lightweight APIs, background workers | +| 0.5 | 1.0 Gi | Standard web apps | +| 1.0 | 2.0 Gi | Moderate workloads | +| 2.0 | 4.0 Gi | Heavy processing | +| 4.0 | 8.0 Gi | Maximum (Consumption plan) | + +Dedicated workload profiles allow up to 16 vCPU / 32 GiB per container (D-series, E-series). From 10fee737e47a56bf466ad661f0fc3262f3e198bc Mon Sep 17 00:00:00 2001 From: krishna-sunkavalli Date: Thu, 9 Apr 2026 17:34:53 -0500 Subject: [PATCH 3/4] feat: improve skill description trigger coverage Add KEDA, serverless containers, microservices, blue-green, and canary keywords to description for better invocation matching. --- skills/azure-container-apps/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skills/azure-container-apps/SKILL.md b/skills/azure-container-apps/SKILL.md index c5bb44030..dc1ac1c0f 100644 --- a/skills/azure-container-apps/SKILL.md +++ b/skills/azure-container-apps/SKILL.md @@ -1,6 +1,6 @@ --- name: azure-container-apps -description: 'Guide for building, deploying, scaling, and troubleshooting Azure Container Apps. Use when creating container apps, configuring ingress, setting up scaling rules, enabling Dapr sidecars, deploying container images, creating jobs, configuring custom domains, managing revisions, traffic splitting, or troubleshooting ACA workloads.' +description: 'Guide for building, deploying, scaling, and troubleshooting Azure Container Apps. Use when creating container apps, configuring ingress, setting up KEDA scaling rules, enabling Dapr sidecars, deploying container images, creating jobs, configuring custom domains, managing revisions, blue-green or canary deployments, traffic splitting, deploying serverless containers or microservices, or troubleshooting ACA workloads.' --- # Azure Container Apps From a67255af64e97f51a94228e2acc8619deae062cd Mon Sep 17 00:00:00 2001 From: krishna-sunkavalli Date: Thu, 9 Apr 2026 17:41:59 -0500 Subject: [PATCH 4/4] chore: regenerate README after description update --- docs/README.skills.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.skills.md b/docs/README.skills.md index 6e52a84d3..2f63bf7ac 100644 --- a/docs/README.skills.md +++ b/docs/README.skills.md @@ -52,7 +52,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-skills) for guidelines on how to | [aws-cdk-python-setup](../skills/aws-cdk-python-setup/SKILL.md) | Setup and initialization guide for developing AWS CDK (Cloud Development Kit) applications in Python. This skill enables users to configure environment prerequisites, create new CDK projects, manage dependencies, and deploy to AWS. | None | | [az-cost-optimize](../skills/az-cost-optimize/SKILL.md) | Analyze Azure resources used in the app (IaC files and/or resources in a target rg) and optimize costs - creating GitHub issues for identified optimizations. | None | | [azure-architecture-autopilot](../skills/azure-architecture-autopilot/SKILL.md) | Design Azure infrastructure using natural language, or analyze existing Azure resources to auto-generate architecture diagrams, refine them through conversation, and deploy with Bicep.
When to use this skill: - "Create X on Azure", "Set up a RAG architecture" (new design) - "Analyze my current Azure infrastructure", "Draw a diagram for rg-xxx" (existing analysis) - "Foundry is slow", "I want to reduce costs", "Strengthen security" (natural language modification) - Azure resource deployment, Bicep template generation, IaC code generation - Microsoft Foundry, AI Search, OpenAI, Fabric, ADLS Gen2, Databricks, and all Azure services | `.gitignore`
`README.md`
`assets/06-architecture-diagram.png`
`assets/07-azure-portal-resources.png`
`assets/08-deployment-succeeded.png`
`references/ai-data.md`
`references/architecture-guidance-sources.md`
`references/azure-common-patterns.md`
`references/azure-dynamic-sources.md`
`references/bicep-generator.md`
`references/bicep-reviewer.md`
`references/phase0-scanner.md`
`references/phase1-advisor.md`
`references/phase4-deployer.md`
`references/service-gotchas.md`
`scripts/cli.py`
`scripts/generator.py`
`scripts/icons.py` | -| [azure-container-apps](../skills/azure-container-apps/SKILL.md) | Guide for building, deploying, scaling, and troubleshooting Azure Container Apps. Use when creating container apps, configuring ingress, setting up scaling rules, enabling Dapr sidecars, deploying container images, creating jobs, configuring custom domains, managing revisions, traffic splitting, or troubleshooting ACA workloads. | `references/dapr-integration.md`
`references/scaling-rules.md`
`references/scenarios.md` | +| [azure-container-apps](../skills/azure-container-apps/SKILL.md) | Guide for building, deploying, scaling, and troubleshooting Azure Container Apps. Use when creating container apps, configuring ingress, setting up KEDA scaling rules, enabling Dapr sidecars, deploying container images, creating jobs, configuring custom domains, managing revisions, blue-green or canary deployments, traffic splitting, deploying serverless containers or microservices, or troubleshooting ACA workloads. | `references/dapr-integration.md`
`references/scaling-rules.md`
`references/scenarios.md` | | [azure-deployment-preflight](../skills/azure-deployment-preflight/SKILL.md) | Performs comprehensive preflight validation of Bicep deployments to Azure, including template syntax validation, what-if analysis, and permission checks. Use this skill before any deployment to Azure to preview changes, identify potential issues, and ensure the deployment will succeed. Activate when users mention deploying to Azure, validating Bicep files, checking deployment permissions, previewing infrastructure changes, running what-if, or preparing for azd provision. | `references/ERROR-HANDLING.md`
`references/REPORT-TEMPLATE.md`
`references/VALIDATION-COMMANDS.md` | | [azure-devops-cli](../skills/azure-devops-cli/SKILL.md) | Manage Azure DevOps resources via CLI including projects, repos, pipelines, builds, pull requests, work items, artifacts, and service endpoints. Use when working with Azure DevOps, az commands, devops automation, CI/CD, or when user mentions Azure DevOps CLI. | `references/advanced-usage.md`
`references/boards-and-iterations.md`
`references/org-and-security.md`
`references/pipelines-and-builds.md`
`references/repos-and-prs.md`
`references/variables-and-agents.md`
`references/workflows-and-patterns.md` | | [azure-pricing](../skills/azure-pricing/SKILL.md) | Fetches real-time Azure retail pricing using the Azure Retail Prices API (prices.azure.com) and estimates Copilot Studio agent credit consumption. Use when the user asks about the cost of any Azure service, wants to compare SKU prices, needs pricing data for a cost estimate, mentions Azure pricing, Azure costs, Azure billing, or asks about Copilot Studio pricing, Copilot Credits, or agent usage estimation. Covers compute, storage, networking, databases, AI, Copilot Studio, and all other Azure service families. | `references/COPILOT-STUDIO-RATES.md`
`references/COST-ESTIMATOR.md`
`references/REGIONS.md`
`references/SERVICE-NAMES.md` |