Guides deployment of Azure API Management infrastructure using Infrastructure as Code (Bicep/Terraform), CI/CD pipelines (GitHub Actions/Azure DevOps), and APIOps workflows. Use when deploying APIM, creating pipelines, or implementing dev→test→prod promotion strategies.
Provides Infrastructure as Code (Bicep/Terraform) templates and CI/CD pipeline patterns for deploying Azure API Management following APIOps principles and phased deployment strategies.
Activate this skill when users need:
See DEPLOYMENT_PLANNING_GUIDE.md for complete 17-week, 7-phase plan
| Phase | Duration | Focus | Key Deliverables | |-------|----------|-------|------------------| | 1 | Week 1-2 | Core Infrastructure | VNet, APIM(dev), Front Door, Key Vault, monitoring | | 2 | Week 3-4 | Authentication & IAM | Entra ID, Entra External ID, OAuth policies| | 3 | Week 5-8 | API Onboarding (Dev) | 5 pilot APIs, policies, developer portal | | 4 | Week 9-10 | Production Infrastructure | APIM(prod) Premium 3u, zone-redundant | | 5 | Week 11-12 | Production APIs | Migrate 5 pilot APIs, performance testing | | 6 | Week 13-15 | Governance & Scaling | API Center, additional APIs, APIOps automation | | 7 | Week 16-17 | Operations Handoff | Runbooks, training, monitoring dashboards |
BEFORE writing any Bicep, check for Azure Verified Modules:
Tool: azure_bicep-get_azure_verified_module
ResourceType: "Microsoft.ApiManagement/service"
Why: AVM modules follow Microsoft best practices, reduce code duplication, tested at scale
Tool: mcp_azure_mcp_get_azure_bestpractices
Intent: "Azure API Management deployment best practices Bicep"
Tool: mcp_azure_mcp_documentation search
Query: "APIM VNet Internal Bicep deployment"
See references/IaC_TEMPLATES.md for complete Bicep/Terraform templates
param location string = 'uksouth'
param apimName string = 'apim-api-marketplace-prod-uks'
param publisherEmail string = 'admin@example.com'
param publisherName string = 'API Marketplace Team'
param vnetName string = 'vnet-apim-prod-uks'
param subnetName string = 'snet-apim'
resource vnet 'Microsoft.Network/virtualNetworks@2023-04-01' existing = {
name: vnetName
}
resource apim 'Microsoft.ApiManagement/service@2023-05-01-preview' = {
name: apimName
location: location
sku: {
name: 'Premium'
capacity: 3 // Zone-redundant: 3 units across 3 availability zones
}
properties: {
publisherEmail: publisherEmail
publisherName: publisherName
virtualNetworkType: 'Internal' // VNet Internal mode
virtualNetworkConfiguration: {
subnetResourceId: '${vnet.id}/subnets/${subnetName}'
}
customProperties: {
'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Protocols.Tls10': 'False'
'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Protocols.Tls11': 'False'
'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Protocols.Ssl30': 'False'
'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Backend.Protocols.Tls10': 'False'
'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Backend.Protocols.Tls11': 'False'
'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Backend.Protocols.Ssl30': 'False'
'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Ciphers.TripleDes168': 'False'
}
disableGateway: false
}
identity: {
type: 'SystemAssigned' // Managed Identity for Key Vault access
}
zones: [
'1'
'2'
'3'
] // Zone redundancy for 99.99% SLA
}
output apimId string = apim.id
output managedIdentityPrincipalId string = apim.identity.principalId
Key Configuration:
virtualNetworkType: 'Internal')[1, 2, 3] for 99.99% SLAname: APIOps - Deploy APIM Infrastructure
on:
workflow_dispatch:
push:
branches: [main]
paths:
- 'infra/**'
- '.github/workflows/deploy-infra.yml'
env:
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
jobs:
# ===== Dev Environment =====
deploy-dev:
runs-on: ubuntu-latest
environment: development
steps:
- uses: actions/checkout@v4
- name: Azure Login
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ env.AZURE_TENANT_ID }}
subscription-id: ${{ env.AZURE_SUBSCRIPTION_ID }}
- name: Deploy Bicep
uses: azure/arm-deploy@v2
with:
scope: resourcegroup
resourceGroupName: rg-apim-dev-uks
template: ./infra/main.bicep
parameters: ./infra/params/dev.bicepparam
failOnStdErr: false
- name: Smoke Test
run: |
# Verify APIM health endpoint
curl -f https://management.azure.com/subscriptions/${{ env.AZURE_SUBSCRIPTION_ID }}/resourceGroups/rg-apim-dev-uks/providers/Microsoft.ApiManagement/service/apim-api-marketplace-dev-uks?api-version=2023-05-01-preview \
-H "Authorization: Bearer $(az account get-access-token --query accessToken -o tsv)"
# ===== Test Environment (After Dev) =====
deploy-test:
needs: deploy-dev
runs-on: ubuntu-latest
environment: test
steps:
# Same steps as dev, use test.bicepparam
- uses: actions/checkout@v4
- uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ env.AZURE_TENANT_ID }}
subscription-id: ${{ env.AZURE_SUBSCRIPTION_ID }}
- uses: azure/arm-deploy@v2
with:
scope: resourcegroup
resourceGroupName: rg-apim-test-uks
template: ./infra/main.bicep
parameters: ./infra/params/test.bicepparam
failOnStdErr: false
# ===== Production (Manual Approval Required) =====
deploy-prod:
needs: deploy-test
runs-on: ubuntu-latest
environment:
name: production
# GitHub environment protection rule: Require manual approval
steps:
- uses: actions/checkout@v4
- uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ env.AZURE_TENANT_ID }}
subscription-id: ${{ env.AZURE_SUBSCRIPTION_ID }}
- name: Deploy Production APIM
uses: azure/arm-deploy@v2
with:
scope: resourcegroup
resourceGroupName: rg-apim-prod-uks
template: ./infra/main.bicep
parameters: ./infra/params/prod.bicepparam
failOnStdErr: false
- name: Production Smoke Test
run: |
# Verify Front Door → APIM connectivity
curl -f https://api.yourdomain.com/health
- name: Tag Release
run: |
git tag -a "apim-prod-$(date +%Y%m%d-%H%M%S)" -m "Production deployment"
git push origin --tags
Key Features:
needs)environment: production with protection rules)using './main.bicep'
param location = 'uksouth'
param environment = 'dev'
param apimSku = 'Developer' // £45/month
param apimCapacity = 1
param virtualNetworkType = 'Internal'
param enableFrontDoor = false // Dev: Direct APIM access
param tags = {
Environment: 'Development'
ManagedBy: 'IaC'
CostCenter: 'Engineering'
}
using './main.bicep'
param location = 'uksouth'
param environment = 'prod'
param apimSku = 'Premium' // £1,944/month (3 units)
param apimCapacity = 3 // Zone-redundant
param virtualNetworkType = 'Internal'
param enableFrontDoor = true // Prod: Front Door + Private Link
param enableApiCenter = true // £135/month
param tags = {
Environment: 'Production'
ManagedBy: 'IaC'
CostCenter: 'Operations'
Criticality: 'High'
}
Pattern: Single main.bicep template, environment-specific .bicepparam files for configuration
#!/bin/bash
# backup-apim.sh - Schedule daily via Azure Automation or GitHub Actions
APIM_NAME="apim-api-marketplace-prod-uks"
RESOURCE_GROUP="rg-apim-prod-uks"
STORAGE_ACCOUNT="stapimproduksbkp"
CONTAINER="apim-backups"
BACKUP_NAME="apim-backup-$(date +%Y%m%d-%H%M%S)"
# Trigger APIM backup to Storage Account
az apim backup create \
--name "$APIM_NAME" \
--resource-group "$RESOURCE_GROUP" \
--storage-account-name "$STORAGE_ACCOUNT" \
--storage-account-container "$CONTAINER" \
--backup-name "$BACKUP_NAME"
echo "Backup created: $BACKUP_NAME"
#!/bin/bash
# restore-apim.sh - Run during DR scenario
APIM_NAME="apim-api-marketplace-prod-uks"
RESOURCE_GROUP="rg-apim-prod-uks"
STORAGE_ACCOUNT="stapimproduksbkp"
CONTAINER="apim-backups"
BACKUP_NAME="apim-backup-20260128-120000" # Latest successful backup
# Restore APIM from backup
az apim backup restore \
--name "$APIM_NAME" \
--resource-group "$RESOURCE_GROUP" \
--storage-account-name "$STORAGE_ACCOUNT" \
--storage-account-container "$CONTAINER" \
--backup-name "$BACKUP_NAME"
echo "APIM restored from backup: $BACKUP_NAME"
Backup Retention:
Before production deployment, verify:
az bicep build, terraform validate)Error: The subnet is not valid for API Management instance
Solution:
Microsoft.ApiManagement/service:
delegations: [
{
name: 'delegation'
properties: {
serviceName: 'Microsoft.ApiManagement/service'
}
}
]
Error: Front Door → APIM Private Link status Pending Approval
Solution:
az network private-endpoint-connection approve \
--resource-name apim-api-marketplace-prod-uks \
--resource-group rg-apim-prod-uks \
--name <connection-name> \
--type Microsoft.ApiManagement/service
az network private-endpoint-connection list \
--name apim-api-marketplace-prod-uks \
--resource-group rg-apim-prod-uks \
--type Microsoft.ApiManagement/service
Cause: APIM Premium with zone redundancy takes 30-60 minutes to deploy
Solution: Expected behavior. Use incremental deployments:
Optimization: Use --what-if flag to preview changes without deploying
Skill Version: 1.0
Last Updated: 29 January 2026
Primary Knowledge: DEPLOYMENT_PLANNING_GUIDE.md, references/IaC_TEMPLATES.md
npx skills add thomast1906/apiops-deployment下载完整 Skill 目录,包含 SKILL.md 及所有相关文件
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer