diff --git a/plugin/skills/azure-cloud-migrate/SKILL.md b/plugin/skills/azure-cloud-migrate/SKILL.md index f007195e1..5b87411e2 100644 --- a/plugin/skills/azure-cloud-migrate/SKILL.md +++ b/plugin/skills/azure-cloud-migrate/SKILL.md @@ -1,6 +1,6 @@ --- name: azure-cloud-migrate -description: "Assess and migrate cross-cloud workloads to Azure with reports and code conversion. Supports Lambda→Functions, Beanstalk/Heroku/App Engine→App Service, Fargate/Kubernetes/Cloud Run/Spring Boot→Container Apps. WHEN: migrate Lambda to Functions, AWS to Azure, migrate Beanstalk, migrate Heroku, migrate App Engine, Cloud Run migration, Fargate to ACA, ECS/Kubernetes/GKE/EKS to Container Apps, Spring Boot to Container Apps, cross-cloud migration." +description: "Assess and migrate cross-cloud AWS/GCP workloads to Azure with reports and code conversion. Supports Lambda→Functions, Beanstalk/Heroku/App Engine→App Service, ECS/Fargate/Kubernetes/Cloud Run/Spring Boot→Container Apps. WHEN: migrate Lambda to Azure Functions, AWS to Azure, migrate Beanstalk, migrate Heroku, migrate App Engine, Cloud Run migration, Fargate or ECS to ACA, ECS/Kubernetes/GKE/EKS to Container Apps, Spring Boot to Container Apps, migration readiness report, cross-cloud migration." license: MIT metadata: author: Microsoft @@ -9,18 +9,16 @@ metadata: # Azure Cloud Migrate -> This skill handles **assessment and code migration** of existing cloud workloads to Azure. - ## Rules -1. Follow phases sequentially — do not skip -2. Generate assessment before any code migration -3. Load the scenario reference and follow its rules -4. Use `mcp_azure_mcp_get_azure_bestpractices` and `mcp_azure_mcp_documentation` MCP tools -5. Use the latest supported runtime for the target service -6. Destructive actions require `ask_user` — [functions global-rules](references/services/functions/global-rules.md) | [app-service global-rules](references/services/app-service/global-rules.md) -7. **Report progress to user** — During long-running operations (deployments, image pushes), provide resource-level status updates so the user is never left waiting without feedback — see [workflow-details.md](references/workflow-details.md) -8. **Audit service discovery in app code** — Kubernetes DNS names (e.g., `http://order-service:3001`) do not resolve in Container Apps. During assessment, scan source code for hardcoded hostnames/ports in HTTP clients and flag them for env-var-driven URL injection +1. Follow phases sequentially — do not skip. +2. Generate assessment before any code migration. +3. Load the scenario reference and follow its rules. +4. Use `mcp_azure_mcp_get_azure_bestpractices` and `mcp_azure_mcp_documentation` MCP tools. +5. Use the latest supported runtime for the target service. +6. Destructive actions require `ask_user` — [functions global-rules](references/services/functions/global-rules.md) | [app-service global-rules](references/services/app-service/global-rules.md) | [container-apps global-rules](references/services/container-apps/global-rules.md). +7. **Report progress to user** — During long-running operations (deployments, image pushes), provide resource-level status updates so the user is never left waiting without feedback — see [workflow-details.md](references/workflow-details.md). +8. **Audit service discovery in app code** — Kubernetes DNS names (e.g., `http://order-service:3001`) do not resolve in Container Apps. During assessment, scan source code for hardcoded hostnames/ports in HTTP clients and flag them for env-var-driven URL injection. ## Migration Scenarios @@ -30,9 +28,10 @@ metadata: | AWS Elastic Beanstalk | Azure App Service | [beanstalk-to-app-service.md](references/services/app-service/beanstalk-to-app-service.md) | | Heroku | Azure App Service | [heroku-to-app-service.md](references/services/app-service/heroku-to-app-service.md) | | Google App Engine | Azure App Service | [app-engine-to-app-service.md](references/services/app-service/app-engine-to-app-service.md) | +| AWS ECS/Fargate | Azure Container Apps | [ecs-to-container-apps.md](references/services/container-apps/ecs-to-container-apps.md) | | AWS Fargate (ECS) | Azure Container Apps | [fargate-to-container-apps.md](references/services/container-apps/fargate-to-container-apps.md) ([assessment](references/services/container-apps/fargate-assessment-guide.md), [deployment](references/services/container-apps/fargate-deployment-guide.md)) | | Kubernetes (GKE/EKS/Self-hosted) | Azure Container Apps | [k8s-to-container-apps.md](references/services/container-apps/k8s-to-container-apps.md) | -| GCP Cloud Run | Azure Container Apps | [cloudrun-to-container-apps.md](references/services/container-apps/cloudrun-to-container-apps.md) | +| GCP Cloud Run | Azure Container Apps | [cloud-run-to-container-apps.md](references/services/container-apps/cloud-run-to-container-apps.md) and [cloudrun-to-container-apps.md](references/services/container-apps/cloudrun-to-container-apps.md) | | Spring Boot (Azure Spring Apps/VMs) | Azure Container Apps | [spring-apps-to-aca.md](references/services/container-apps/spring-apps-to-aca.md) | > No matching scenario? Use `mcp_azure_mcp_documentation` and `mcp_azure_mcp_get_azure_bestpractices` tools. @@ -43,10 +42,12 @@ All output goes to `-azure/` at workspace root, where ` ## Steps -1. **Create** `-azure/` at workspace root -2. **Assess** — Analyze source, map services, generate report using the scenario-specific assessment guide → [functions assessment](references/services/functions/assessment.md) | [app-service assessment](references/services/app-service/assessment.md) -3. **Migrate** — Convert code/config using the scenario-specific migration guide → [functions code-migration](references/services/functions/code-migration.md) | [app-service code-migration](references/services/app-service/code-migration.md) +1. **Create** `-azure/` at workspace root. +2. **Assess** — Analyze source, map services, generate report using the scenario-specific assessment guide → [functions assessment](references/services/functions/assessment.md) | [app-service assessment](references/services/app-service/assessment.md) | [container-apps assessment](references/services/container-apps/assessment.md). +3. **Migrate** — Convert code/config using the scenario-specific migration guide → [functions code-migration](references/services/functions/code-migration.md) | [app-service code-migration](references/services/app-service/code-migration.md) | [container-apps code-migration](references/services/container-apps/code-migration.md). 4. **Ask User** — "Migration complete. Test locally or deploy to Azure?" -5. **Hand off** to azure-prepare for infrastructure, testing, and deployment +5. **Hand off** to azure-prepare for infrastructure, testing, and deployment. Track progress in `migration-status.md` — see [workflow-details.md](references/workflow-details.md). + +Container Apps migrations must also load [global-rules.md](references/services/container-apps/global-rules.md), assess with [assessment.md](references/services/container-apps/assessment.md), then migrate with [code-migration.md](references/services/container-apps/code-migration.md). diff --git a/plugin/skills/azure-cloud-migrate/references/services/container-apps/assessment.md b/plugin/skills/azure-cloud-migrate/references/services/container-apps/assessment.md new file mode 100644 index 000000000..46310342b --- /dev/null +++ b/plugin/skills/azure-cloud-migrate/references/services/container-apps/assessment.md @@ -0,0 +1,153 @@ +# Assessment Phase — Container Apps + +Generate a migration assessment report before any code or configuration changes. + +## Prerequisites + +- Workspace contains Dockerfiles, docker-compose files, ECS task definitions, Cloud Run service YAML, or equivalent container specs +- Prompt user to upload relevant files if not present + +## Assessment Steps + +1. **Identify Containers** — List all container services with images, ports, and resource limits +2. **Analyze Dockerfiles** — Check base images, build stages, exposed ports, entrypoints +3. **Map Cloud Services** — Map source services to Azure equivalents (see scenario references) +4. **Map Networking** — Map load balancers, service discovery, and ingress to Container Apps ingress +5. **Check Dependencies** — List external services (databases, caches, queues) and verify Azure equivalents +6. **Map Secrets** — Identify secrets/env vars and plan Key Vault migration +7. **Map Volumes** — Identify persistent storage needs and map to Azure Files or ephemeral storage +8. **Analyze Multi-Container** — Identify sidecar patterns, init containers, and service mesh usage +9. **Map IAM** — Map task/service roles to Managed Identity + RBAC +10. **Map Monitoring** — Map logging/metrics to Application Insights + Log Analytics +11. **Review CI/CD** — Check pipeline compatibility with Azure DevOps or GitHub Actions + +## Image Analysis + +For each container image: + +| Check | Details | +|-------|---------| +| **Base image** | OS, runtime, version — verify Azure compatibility | +| **Multi-stage build** | Identify build vs runtime stages | +| **Exposed ports** | Map to Container Apps ingress (HTTP/TCP) | +| **ENTRYPOINT/CMD** | Verify compatibility with Container Apps | +| **HEALTHCHECK** | Map to Container Apps health probes | +| **Volume mounts** | Map to Azure Files or ephemeral storage | +| **Build args / ENV** | Map to Container Apps env vars and secrets | +| **Image size** | Flag images > 1GB for optimization | + +## Architecture Diagrams + +Generate two diagrams: +1. **Current State** — Source architecture with containers, networking, and integrations +2. **Target State** — Azure Container Apps architecture showing equivalent structure + +## Assessment Report Format + +> ⚠️ **MANDATORY**: Use these exact section headings in every assessment report. Do NOT rename, reorder, or omit sections. + +The report MUST be saved as `migration-assessment-report.md` inside the output directory (`-azure/`). + +```markdown +# Migration Assessment Report + +## 1. Executive Summary + +| Property | Value | +|----------|-------| +| **Total Services** | | +| **Source Platform** | | +| **Container Runtime** | | +| **Target Platform** | Azure Container Apps | +| **Target Environment** | Consumption / Dedicated | +| **Migration Readiness** | | +| **Estimated Effort** | | +| **Assessment Date** | | + +## 2. Container Inventory + +| # | Service Name | Image | Port | CPU | Memory | Replicas | Description | +|---|-------------|-------|------|-----|--------|----------|-------------| +| 1 | | | | | | | | + +## 3. Service Mapping + +| Source Service | Azure Equivalent | Migration Complexity | Notes | +|----------------|------------------|----------------------|-------| +| | | | | + +## 4. Networking & Ingress Mapping + +| # | Service Name | Source LB/Ingress | Azure Ingress | Protocol | External? | Notes | +|---|-------------|-------------------|---------------|----------|-----------|-------| +| 1 | | | | | | | + +## 5. Environment Variables & Secrets + +| # | Variable Name | Source | Purpose | Azure Equivalent | Auth Method | Notes | +|---|--------------|--------|---------|------------------|-------------|-------| +| 1 | | | | | Managed Identity / Key Vault | | + +## 6. Volume & Storage Mapping + +| # | Service | Source Mount | Type | Azure Equivalent | Notes | +|---|---------|------------|------|------------------|-------| +| 1 | | | | Azure Files / Ephemeral | | + +## 7. IAM & Security Mapping + +| Source Role/Policy | Azure RBAC Role | Scope | Notes | +|--------------------|-----------------|-------|-------| +| | | | | + +## 8. Monitoring & Observability Mapping + +| Source Service | Azure Equivalent | Migration Notes | +|----------------|------------------|-----------------| +| | | | + +## 9. Scaling & Performance + +| # | Service | Source Scaling | Azure Scale Rule | Min | Max | Notes | +|---|---------|---------------|------------------|-----|-----|-------| +| 1 | | | HTTP / Queue / Custom | | | | + +## 10. Multi-Container Patterns + +| # | Service | Pattern | Containers | Azure Approach | Notes | +|---|---------|---------|------------|----------------|-------| +| 1 | | Sidecar / Init | | Container Apps sidecar | | + +## 11. Architecture Diagrams + +### 11a. Current State (Source) + + + +### 11b. Target State (Azure) + + + +## 12. CI/CD & Deployment Mapping + +| Source Tool | Azure Equivalent | Notes | +|-------------|------------------|-------| +| | | | + +## 13. Recommendations + +1. **Environment**: +2. **Registry**: +3. **IaC Strategy**: +4. **Auth Strategy**: +5. **Monitoring**: +6. **Networking**: + +## 14. Next Steps + +- [ ] Review and approve this assessment report +- [ ] Proceed to code migration (Phase 2) +- [ ] Hand off to azure-prepare for IaC generation +``` + +> 💡 **Tip:** Use `mcp_azure_mcp_get_bestpractices` tool to learn Container Apps best practices for the recommendations section. diff --git a/plugin/skills/azure-cloud-migrate/references/services/container-apps/cloud-run-to-container-apps.md b/plugin/skills/azure-cloud-migrate/references/services/container-apps/cloud-run-to-container-apps.md new file mode 100644 index 000000000..b891641fe --- /dev/null +++ b/plugin/skills/azure-cloud-migrate/references/services/container-apps/cloud-run-to-container-apps.md @@ -0,0 +1,243 @@ +# GCP Cloud Run to Azure Container Apps Migration + +## Service Mapping + +| GCP Service | Azure Equivalent | +|-------------|------------------| +| Cloud Run Service | Container App | +| Cloud Run Revision | Container App revision | +| Cloud Run Jobs | Container Apps Jobs | +| Artifact Registry / GCR | Azure Container Registry (ACR) | +| Cloud Load Balancing | Container Apps ingress | +| Cloud Run service-to-service | Container Apps internal DNS / Dapr | +| Cloud Run domain mapping | Container Apps custom domains | +| Cloud Logging | Log Analytics | +| Cloud Monitoring | Azure Monitor Metrics | +| Cloud Trace | Application Insights (distributed tracing) | +| IAM service account | Managed Identity + RBAC | +| Secret Manager | Azure Key Vault | +| VPC Connector | Container Apps VNet integration | +| Pub/Sub | Azure Service Bus / Event Grid | +| Cloud Storage | Azure Blob Storage | +| Cloud SQL | Azure Database for PostgreSQL / MySQL | +| Firestore | Azure Cosmos DB | +| Cloud Scheduler | Container Apps Jobs (scheduled) | +| Cloud Build | Azure DevOps Pipelines / GitHub Actions | +| Terraform (GCP) | Bicep / Terraform (Azure) | + +## Cloud Run Service → Container App + +### Cloud Run service YAML (source) + +```yaml +apiVersion: serving.knative.dev/v1 +kind: Service +metadata: + name: my-api +spec: + template: + metadata: + annotations: + autoscaling.knative.dev/maxScale: "10" + autoscaling.knative.dev/minScale: "1" + run.googleapis.com/cpu-throttling: "false" + spec: + containerConcurrency: 80 + timeoutSeconds: 300 + containers: + - image: us-docker.pkg.dev/my-project/my-repo/my-api:v1 + ports: + - containerPort: 8080 + resources: + limits: + cpu: "1" + memory: 512Mi + env: + - name: NODE_ENV + value: production + - name: DB_PASSWORD + valueFrom: + secretKeyRef: + key: latest + name: db-password + startupProbe: + httpGet: + path: /healthz + port: 8080 + initialDelaySeconds: 0 + periodSeconds: 5 + livenessProbe: + httpGet: + path: /healthz + port: 8080 + periodSeconds: 10 +``` + +### Container App YAML (target) + +```yaml +properties: + configuration: + ingress: + external: true + targetPort: 8080 + transport: auto + secrets: + - name: db-password + keyVaultUrl: https://myvault.vault.azure.net/secrets/db-password + identity: + registries: + - server: myacr.azurecr.io + identity: + maxInactiveRevisions: 5 + template: + containers: + - image: myacr.azurecr.io/my-api:v1 + name: my-api + resources: + cpu: 1.0 + memory: 0.5Gi + env: + - name: NODE_ENV + value: production + - name: DB_PASSWORD + secretRef: db-password + probes: + - type: startup + httpGet: + path: /healthz + port: 8080 + periodSeconds: 5 + - type: liveness + httpGet: + path: /healthz + port: 8080 + periodSeconds: 10 + scale: + minReplicas: 1 + maxReplicas: 10 + rules: + - name: concurrent-requests + http: + metadata: + concurrentRequests: "80" +``` + +## Cloud Run Jobs → Container Apps Jobs + +| Cloud Run Jobs | Container Apps Jobs | +|---------------|---------------------| +| Job execution | Job execution | +| Task count | `parallelism` + `replicaCompletionCount` | +| Task timeout | `replicaTimeout` | +| Max retries | `replicaRetryLimit` | +| Scheduled via Cloud Scheduler | `triggerType: Schedule` with cron | +| On-demand execution | `triggerType: Manual` | +| Event-triggered | `triggerType: Event` | + +### Scheduled Job Example + +```yaml +properties: + configuration: + triggerType: Schedule + scheduleTriggerConfig: + cronExpression: "0 */6 * * *" + parallelism: 1 + replicaCompletionCount: 1 + registries: + - server: myacr.azurecr.io + identity: + template: + containers: + - image: myacr.azurecr.io/batch-job:v1 + name: batch-job + resources: + cpu: 1.0 + memory: 2Gi + env: + - name: JOB_MODE + value: scheduled +``` + +## Concurrency & Scaling + +| Cloud Run Setting | Container Apps Equivalent | +|-------------------|--------------------------| +| `containerConcurrency: 80` | HTTP scale rule `concurrentRequests: "80"` | +| `minScale: 0` (scale to zero) | `minReplicas: 0` | +| `maxScale: 10` | `maxReplicas: 10` | +| `cpu-throttling: false` (always-on CPU) | Consumption plan default behavior | +| Pub/Sub push scaling | Queue-based scale rule | +| Scheduled execution | KEDA cron scale rule | + +## Networking + +| Cloud Run | Container Apps | +|-----------|---------------| +| Public HTTPS endpoint | `external: true` ingress | +| Internal-only | `external: false` ingress | +| VPC Connector | VNet-integrated Container Apps Environment | +| Cloud Run → Cloud SQL (private IP) | VNet integration + private endpoint | +| Custom domain | Custom domain binding + managed certificate | +| gRPC support | Ingress with `transport: http2` | + +## Secret Manager → Key Vault + +| GCP Pattern | Azure Pattern | +|-------------|---------------| +| `secretKeyRef` in YAML | `secretRef` + Key Vault reference | +| Secret version `latest` | Key Vault secret (latest version) | +| Secret version pinning | Key Vault secret version URI | +| IAM `secretAccessor` role | `Key Vault Secrets User` RBAC role | +| Per-service secret access | Managed Identity scoped to Key Vault | + +## IAM Service Account → Managed Identity + +| GCP IAM | Azure RBAC | +|---------|------------| +| Cloud Run service account | User Assigned Managed Identity | +| `roles/storage.objectViewer` | `Storage Blob Data Reader` | +| `roles/pubsub.subscriber` | `Service Bus Data Receiver` | +| `roles/secretmanager.secretAccessor` | `Key Vault Secrets User` | +| `roles/cloudsql.client` | Database-specific RBAC | +| `roles/logging.logWriter` | Auto-collected in Log Analytics (no RBAC role needed) | + +## Artifact Registry → ACR + +```bash +# Import directly (no local Docker needed) +az acr import --name \ + --source -docker.pkg.dev///: \ + --username _json_key \ + --password "$(cat gcp-service-account-key.json)" + +# Configure managed identity pull +az role assignment create \ + --assignee \ + --role AcrPull \ + --scope +``` + +## Monitoring Mapping + +| GCP | Azure | Notes | +|-----|-------|-------| +| Cloud Logging | Log Analytics | Container stdout/stderr auto-collected | +| Cloud Monitoring metrics | Azure Monitor Metrics | Built-in CPU, memory, requests | +| Cloud Monitoring alerts | Azure Monitor Alerts | KQL-based alert rules | +| Cloud Trace | Application Insights | Distributed tracing via OpenTelemetry | +| Error Reporting | Application Insights exceptions | Auto-capture with SDK | + +## Key Differences + +| Feature | Cloud Run | Container Apps | +|---------|-----------|---------------| +| Scale-to-zero | Default behavior | `minReplicas: 0` | +| Cold start | Startup CPU boost | Startup probe | +| Request timeout | 3600s max | 240s default (configurable) | +| Concurrency model | Per-instance | Per-replica (HTTP scale rules) | +| gRPC | Native support | `transport: http2` | +| WebSockets | Supported | Supported with sticky sessions | +| GPU | Supported (limited) | Dedicated workload profiles | +| Jobs | Cloud Run Jobs | Container Apps Jobs | diff --git a/plugin/skills/azure-cloud-migrate/references/services/container-apps/code-migration.md b/plugin/skills/azure-cloud-migrate/references/services/container-apps/code-migration.md new file mode 100644 index 000000000..9b242d849 --- /dev/null +++ b/plugin/skills/azure-cloud-migrate/references/services/container-apps/code-migration.md @@ -0,0 +1,178 @@ +# Code Migration Phase — Container Apps + +Migrate container workloads to Azure Container Apps configuration and code. + +## Prerequisites + +- Assessment report completed +- Best practices loaded via `mcp_azure_mcp_get_bestpractices` tool +- ACR instance provisioned (or planned in IaC) + +## Rules + +- Never modify the source directory — all output goes to `-azure/` +- Preserve existing Dockerfiles when possible — optimize, don't rewrite +- Use managed identity for all Azure service connections +- Configure health probes for every container +- Use Key Vault references for secrets — never embed in container specs + +## Steps + +1. **Load Best Practices** — Use `mcp_azure_mcp_get_bestpractices` tool for Container Apps guidance +2. **Create Project Structure** — Set up output directory with Container Apps configuration +3. **Optimize Dockerfiles** — Apply multi-stage builds, minimize image size +4. **Generate Container App YAML** — Convert source specs to Container Apps manifests +5. **Map Environment Variables** — Convert env vars to Container Apps secrets + env config +6. **Configure Ingress** — Map load balancers and routing to Container Apps ingress +7. **Configure Scaling** — Convert autoscaling rules to Container Apps scale rules +8. **Set Up Health Probes** — Map health checks to liveness/readiness/startup probes +9. **Configure Service Discovery** — Map service mesh / service connect to Dapr or internal DNS + +## Dockerfile Analysis + +### Multi-Stage Build Pattern + +```dockerfile +# ✅ Recommended: Multi-stage build +FROM node:20-alpine AS builder +WORKDIR /app +COPY package*.json ./ +RUN npm ci +COPY . . +RUN npm run build + +FROM node:20-alpine +WORKDIR /app +COPY package*.json ./ +RUN npm ci --only=production +COPY --from=builder /app/dist ./dist +EXPOSE 8080 +CMD ["node", "dist/server.js"] +``` + +### Image Optimization Checklist + +| Check | Action | +|-------|--------| +| Use `-alpine` or `-slim` base images | Reduces image size by 50-80% | +| Multi-stage builds | Separate build and runtime stages | +| `.dockerignore` exists | Exclude `node_modules`, `.git`, tests | +| No secrets in image | Use env vars or mounted secrets at runtime | +| Non-root user | Add `USER node` or `USER appuser` | +| Fixed base image tags | Pin versions, avoid `latest` tag | + +## Container App YAML Structure + +```yaml +properties: + configuration: + ingress: + external: true + targetPort: 8080 + transport: auto + allowInsecure: false + secrets: + - name: db-connection + keyVaultUrl: https://.vault.azure.net/secrets/db-connection + identity: + registries: + - server: .azurecr.io + identity: + template: + containers: + - image: .azurecr.io/:latest + name: + resources: + cpu: 0.5 + memory: 1Gi + env: + - name: DATABASE_URL + secretRef: db-connection + - name: PORT + value: "8080" + probes: + - type: liveness + httpGet: + path: /healthz + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 10 + - type: readiness + httpGet: + path: /ready + port: 8080 + initialDelaySeconds: 3 + periodSeconds: 5 + scale: + minReplicas: 1 + maxReplicas: 10 + rules: + - name: http-scaling + http: + metadata: + concurrentRequests: "50" +``` + +## Environment Variable Mapping + +| Source Pattern | Container Apps Equivalent | +|---------------|--------------------------| +| Hardcoded secret in env | Key Vault secret reference | +| Service endpoint URL | Managed identity + env var | +| API key / connection string | Key Vault secret reference | +| Feature flag | Plain env var | +| Port configuration | `targetPort` in ingress config | + +## Health Probe Mapping + +| Source | Container Apps | +|--------|---------------| +| ECS `healthCheck` | `probes` with `type: liveness` | +| Cloud Run startup probe | `probes` with `type: startup` | +| ALB target group health | `probes` with `type: readiness` | +| Docker `HEALTHCHECK` | `probes` with `type: liveness` | +| Custom TCP check | `tcpSocket` probe | + +## Registry Migration + +### Push images to ACR + +```bash +# Login to ACR +az acr login --name + +# Tag and push +docker tag : .azurecr.io/: +docker push .azurecr.io/: +``` + +### ACR import (no local Docker required) + +```bash +# Import from public registry +az acr import --name \ + --source docker.io/library/nginx:latest \ + --image nginx:latest + +# Import from ECR (with credentials) +az acr import --name \ + --source .dkr.ecr..amazonaws.com/: \ + --username AWS --password $(aws ecr get-login-password --region ) + +# Import from GCP Artifact Registry +az acr import --name \ + --source -docker.pkg.dev///: \ + --username _json_key --password "$(cat key.json)" +``` + +## Handoff to azure-prepare + +After code migration is complete: + +1. Update `migration-status.md` — mark Code Migration as ✅ Complete +2. Invoke **azure-prepare** — pass the assessment report context so it can: + - Use the service mapping as requirements input + - Generate IaC (Bicep/Terraform) for Container Apps Environment, apps, and ACR + - Create `azure.yaml` and `.azure/preparation-manifest.md` + - Apply security hardening +3. azure-prepare will then chain to **azure-validate** → **azure-deploy** diff --git a/plugin/skills/azure-cloud-migrate/references/services/container-apps/ecs-to-container-apps.md b/plugin/skills/azure-cloud-migrate/references/services/container-apps/ecs-to-container-apps.md new file mode 100644 index 000000000..37313f569 --- /dev/null +++ b/plugin/skills/azure-cloud-migrate/references/services/container-apps/ecs-to-container-apps.md @@ -0,0 +1,211 @@ +# AWS ECS/Fargate to Azure Container Apps Migration + +Detailed guidance for migrating AWS ECS and Fargate workloads to Azure Container Apps. + +## Service Mapping + +| AWS Service | Azure Equivalent | +|-------------|------------------| +| ECS Service | Container App | +| ECS Task Definition | Container App revision template | +| ECS Task | Container App replica | +| Fargate | Container Apps Consumption plan | +| ECS Capacity Provider | Container Apps Dedicated workload profile | +| ECR | Azure Container Registry (ACR) | +| ALB / NLB | Container Apps ingress | +| ECS Service Connect | Container Apps internal DNS / Dapr | +| App Mesh | Dapr (service invocation, pub/sub, state) | +| CloudWatch Logs | Log Analytics | +| CloudWatch Metrics | Azure Monitor Metrics | +| CloudWatch Alarms | Azure Monitor Alerts | +| X-Ray | Application Insights (distributed tracing) | +| Task IAM Role | Managed Identity + RBAC | +| Execution Role | ACR pull via Managed Identity | +| Secrets Manager | Azure Key Vault | +| Parameter Store | Azure App Configuration | +| ECS Service Auto Scaling | Container Apps scale rules | +| AWS CloudMap | Container Apps internal DNS | +| EFS | Azure Files | +| CloudFormation / CDK | Bicep / ARM Templates | +| CodePipeline / CodeBuild | Azure DevOps Pipelines / GitHub Actions | + +## Task Definition → Container App Template + +### ECS Task Definition (source) + +```json +{ + "family": "my-api", + "networkMode": "awsvpc", + "requiresCompatibilities": ["FARGATE"], + "cpu": "512", + "memory": "1024", + "containerDefinitions": [{ + "name": "api", + "image": "123456789.dkr.ecr.us-east-1.amazonaws.com/my-api:v1", + "portMappings": [{ "containerPort": 8080, "protocol": "tcp" }], + "environment": [ + { "name": "NODE_ENV", "value": "production" } + ], + "secrets": [ + { "name": "DB_PASSWORD", "valueFrom": "arn:aws:secretsmanager:us-east-1:123456789:secret:db-pass" } + ], + "healthCheck": { + "command": ["CMD-SHELL", "curl -f http://localhost:8080/health || exit 1"], + "interval": 30, + "timeout": 5, + "retries": 3 + }, + "logConfiguration": { + "logDriver": "awslogs", + "options": { + "awslogs-group": "/ecs/my-api", + "awslogs-region": "us-east-1" + } + } + }] +} +``` + +### Container App YAML (target) + +```yaml +properties: + configuration: + ingress: + external: true + targetPort: 8080 + transport: auto + secrets: + - name: db-password + keyVaultUrl: https://myvault.vault.azure.net/secrets/db-password + identity: + registries: + - server: myacr.azurecr.io + identity: + template: + containers: + - image: myacr.azurecr.io/my-api:v1 + name: api + resources: + cpu: 0.5 + memory: 1Gi + env: + - name: NODE_ENV + value: production + - name: DB_PASSWORD + secretRef: db-password + probes: + - type: liveness + httpGet: + path: /health + port: 8080 + periodSeconds: 30 + timeoutSeconds: 5 + failureThreshold: 3 + scale: + minReplicas: 1 + maxReplicas: 10 +``` + +## Resource Mapping + +| ECS (Fargate) | Container Apps | +|---------------|---------------| +| `cpu: "256"` (0.25 vCPU) | `cpu: 0.25` | +| `cpu: "512"` (0.5 vCPU) | `cpu: 0.5` | +| `cpu: "1024"` (1 vCPU) | `cpu: 1.0` | +| `cpu: "2048"` (2 vCPU) | `cpu: 2.0` | +| `cpu: "4096"` (4 vCPU) | `cpu: 4.0` (Dedicated plan) | +| `memory: "512"` (MB) | `memory: 0.5Gi` | +| `memory: "1024"` (MB) | `memory: 1Gi` | +| `memory: "2048"` (MB) | `memory: 2Gi` | +| `memory: "4096"` (MB) | `memory: 4Gi` | + +> ⚠️ Container Apps Consumption plan supports up to 4 vCPU / 8 GiB. For larger workloads, use Dedicated workload profiles. + +## Networking & Ingress + +| ECS Pattern | Container Apps Equivalent | +|-------------|--------------------------| +| ALB with path-based routing | Multiple Container Apps with ingress rules | +| ALB with host-based routing | Custom domains on Container Apps | +| NLB (TCP) | Container Apps TCP ingress | +| Internal ALB | `external: false` ingress | +| Public ALB | `external: true` ingress | +| Security Groups | NSG on Container Apps Environment VNet | +| VPC | VNet-integrated Container Apps Environment | + +## ECS Service Connect → Service Discovery + +| ECS Pattern | Container Apps Equivalent | +|-------------|--------------------------| +| Service Connect (HTTP) | Internal ingress (`external: false`) | +| Service Connect (gRPC) | Internal ingress with `transport: http2` | +| CloudMap DNS | `.internal.` | +| App Mesh virtual service | Dapr service invocation | +| App Mesh virtual router | Dapr pub/sub routing | + +Internal service discovery URL pattern: +``` +https://.internal...azurecontainerapps.io +``` + +## Autoscaling Mapping + +| ECS Auto Scaling | Container Apps Scale Rule | +|------------------|--------------------------| +| Target tracking (CPU) | Custom scale rule with CPU metric | +| Target tracking (requests) | HTTP scale rule (`concurrentRequests`) | +| SQS queue depth | Queue scale rule (Service Bus / Storage Queue) | +| Step scaling | Custom scale rule with thresholds | +| Scheduled scaling | KEDA cron scale rule | +| `desiredCount` minimum | `minReplicas` | +| `desiredCount` maximum | `maxReplicas` | + +## ECR → ACR Migration + +```bash +# Import directly (no local Docker needed) +az acr import --name \ + --source .dkr.ecr..amazonaws.com/: \ + --username AWS \ + --password $(aws ecr get-login-password --region ) + +# Configure managed identity pull +az role assignment create \ + --assignee \ + --role AcrPull \ + --scope +``` + +## IAM Role → Managed Identity + +| AWS IAM | Azure RBAC | +|---------|------------| +| Task Role | User Assigned Managed Identity | +| Execution Role (ECR pull) | `AcrPull` on ACR | +| S3 access | `Storage Blob Data Contributor` on Storage Account | +| SQS access | `Service Bus Data Receiver` on Service Bus | +| Secrets Manager access | `Key Vault Secrets User` on Key Vault | +| DynamoDB access | Cosmos DB RBAC data role | +| CloudWatch Logs | Auto-collected in Log Analytics (no RBAC role needed) | + +## Monitoring Mapping + +| AWS | Azure | Notes | +|-----|-------|-------| +| CloudWatch Logs (`awslogs`) | Log Analytics | Container stdout/stderr auto-collected | +| CloudWatch Metrics | Azure Monitor Metrics | CPU, memory, requests built-in | +| CloudWatch Alarms | Azure Monitor Alerts | KQL-based alert rules | +| X-Ray | Application Insights | Distributed tracing via OpenTelemetry | +| Container Insights | Container Apps metrics | Built-in dashboard in Azure Portal | + +## Reference Links + +- [Container Apps overview](https://learn.microsoft.com/en-us/azure/container-apps/overview) +- [Container Apps YAML reference](https://learn.microsoft.com/en-us/azure/container-apps/azure-resource-manager-api-spec) +- [Ingress configuration](https://learn.microsoft.com/en-us/azure/container-apps/ingress-overview) +- [Dapr integration](https://learn.microsoft.com/en-us/azure/container-apps/dapr-overview) +- [Managed identity with ACR](https://learn.microsoft.com/en-us/azure/container-apps/managed-identity) +- [Scale rules](https://learn.microsoft.com/en-us/azure/container-apps/scale-app) diff --git a/plugin/skills/azure-cloud-migrate/references/services/container-apps/global-rules.md b/plugin/skills/azure-cloud-migrate/references/services/container-apps/global-rules.md new file mode 100644 index 000000000..21911d526 --- /dev/null +++ b/plugin/skills/azure-cloud-migrate/references/services/container-apps/global-rules.md @@ -0,0 +1,58 @@ +# Global Rules — Container Apps Migrations + +These rules apply to ALL phases of container migration to Azure Container Apps. + +## Destructive Action Policy + +⛔ **NEVER** perform destructive actions without explicit user confirmation via `ask_user`: +- Deleting container images, registries, or repositories +- Overwriting existing Dockerfiles or compose files +- Deploying to production environments +- Modifying existing Azure resources +- Removing source cloud resources (ECS services, Cloud Run services) + +## User Confirmation Required + +Always use `ask_user` before: +- Selecting Azure subscription +- Selecting Azure region/location +- Deploying infrastructure +- Choosing between Consumption and Dedicated plans +- Making breaking changes to existing container configurations + +## Best Practices + +- Always use `mcp_azure_mcp_get_bestpractices` tool before generating Azure code +- Prefer managed identity over connection strings or API keys +- **Choose the latest stable base image and pin it to an explicit version tag or digest (avoid floating tags like `latest`)** — check official images for newest GA tags +- Follow Azure naming conventions (`ca-`, `cae-`, `acr-` prefixes) +- Use Consumption plan unless workload requires dedicated resources +- Enable Dapr only when service-to-service communication patterns require it + +## Identity-First Authentication (Zero API Keys) + +> Enterprise subscriptions commonly enforce policies that block local auth. Always design for identity-based access from the start. + +- **Container Registry**: Use managed identity for ACR pull — assign `AcrPull` role +- **Storage accounts**: Set `allowSharedKeyAccess: false`. Use identity-based connections +- **Key Vault**: Use managed identity + RBAC (`Key Vault Secrets User`) instead of access policies +- **Application Insights**: Set `disableLocalAuth: true`. Use `APPLICATIONINSIGHTS_AUTHENTICATION_STRING` with AAD auth +- **DefaultAzureCredential with UAMI**: When using User Assigned Managed Identity, always pass `managedIdentityClientId`: + ```javascript + const credential = new DefaultAzureCredential({ + managedIdentityClientId: process.env.AZURE_CLIENT_ID + }); + ``` + +## Container Apps Specifics + +- **Ingress**: Always configure ingress for HTTP-serving containers. Set `external: true` for public, `external: false` for internal-only +- **Secrets**: Use Key Vault references for sensitive values — do NOT embed secrets in container env vars or YAML +- **Scaling rules**: Map source autoscaling (ECS Service Auto Scaling, Cloud Run concurrency) to Container Apps scale rules (HTTP, queue, custom) +- **Revisions**: Use revision-scope changes for zero-downtime deployments +- **Health probes**: Always configure liveness and readiness probes matching source health checks +- **VNet integration**: When source uses private networking (VPC, VPC Connectors), configure Container Apps Environment with VNet integration + +## Output Directory + +All migration output goes to `-azure/` at workspace root. Never modify the source directory. diff --git a/scripts/src/frontmatter/__tests__/frontmatter.test.ts b/scripts/src/frontmatter/__tests__/frontmatter.test.ts index 56dedf4ee..608a89652 100644 --- a/scripts/src/frontmatter/__tests__/frontmatter.test.ts +++ b/scripts/src/frontmatter/__tests__/frontmatter.test.ts @@ -386,6 +386,10 @@ describe("Frontmatter Spec Validator", () => { expect(validateMetadataVersion({ version: "3.2.1" })).toEqual([]); }); + it("passes for NBGV placeholder version", () => { + expect(validateMetadataVersion({ version: "0.0.0-placeholder" })).toEqual([]); + }); + it("warns for missing metadata", () => { const issues = validateMetadataVersion(undefined); expect(issues).toHaveLength(1); diff --git a/scripts/src/frontmatter/cli.ts b/scripts/src/frontmatter/cli.ts index 9df7b5d81..a3cf95c71 100644 --- a/scripts/src/frontmatter/cli.ts +++ b/scripts/src/frontmatter/cli.ts @@ -208,6 +208,7 @@ export function validateDescriptionLength(description: string | null): Validatio } const SEMVER_RE = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/; +const NBGV_PLACEHOLDER_VERSION = "0.0.0-placeholder"; /** * Check 6: Validate that `license` field is present and is a string. @@ -296,7 +297,7 @@ export function validateMetadataVersion(metadata: unknown): ValidationIssue[] { } const versionStr = String(version); - if (!SEMVER_RE.test(versionStr)) { + if (versionStr !== NBGV_PLACEHOLDER_VERSION && !SEMVER_RE.test(versionStr)) { issues.push({ check: "metadata-version", message: `metadata.version "${versionStr}" is not valid semver (expected X.Y.Z)`, diff --git a/tests/azure-cloud-migrate/__snapshots__/triggers.test.ts.snap b/tests/azure-cloud-migrate/__snapshots__/triggers.test.ts.snap index 4d7ae5f1a..2f8e39748 100644 --- a/tests/azure-cloud-migrate/__snapshots__/triggers.test.ts.snap +++ b/tests/azure-cloud-migrate/__snapshots__/triggers.test.ts.snap @@ -2,7 +2,7 @@ exports[`azure-cloud-migrate - Trigger Tests Trigger Keywords Snapshot skill description triggers match snapshot 1`] = ` { - "description": "Assess and migrate cross-cloud workloads to Azure with reports and code conversion. Supports Lambda→Functions, Beanstalk/Heroku/App Engine→App Service, Fargate/Kubernetes/Cloud Run/Spring Boot→Container Apps. WHEN: migrate Lambda to Functions, AWS to Azure, migrate Beanstalk, migrate Heroku, migrate App Engine, Cloud Run migration, Fargate to ACA, ECS/Kubernetes/GKE/EKS to Container Apps, Spring Boot to Container Apps, cross-cloud migration.", + "description": "Assess and migrate cross-cloud AWS/GCP workloads to Azure with reports and code conversion. Supports Lambda→Functions, Beanstalk/Heroku/App Engine→App Service, ECS/Fargate/Kubernetes/Cloud Run/Spring Boot→Container Apps. WHEN: migrate Lambda to Azure Functions, AWS to Azure, migrate Beanstalk, migrate Heroku, migrate App Engine, Cloud Run migration, Fargate or ECS to ACA, ECS/Kubernetes/GKE/EKS to Container Apps, Spring Boot to Container Apps, migration readiness report, cross-cloud migration.", "extractedKeywords": [ "app service", "apps", @@ -27,6 +27,8 @@ exports[`azure-cloud-migrate - Trigger Tests Trigger Keywords Snapshot skill des "mcp", "migrate", "migration", + "readiness", + "report", "reports", "service", "spring", @@ -64,6 +66,8 @@ exports[`azure-cloud-migrate - Trigger Tests Trigger Keywords Snapshot skill key "mcp", "migrate", "migration", + "readiness", + "report", "reports", "service", "spring",