apiops-deployment
APIOps Deployment Skill
Provides Infrastructure as Code (Bicep/Terraform) templates and CI/CD pipeline patterns for deploying Azure API Management following APIOps principles and phased deployment strategies.
When to Use This Skill
Activate this skill when users need:
- Infrastructure deployment: Generate Bicep/Terraform for APIM, Front Door, VNet, supporting services
- CI/CD pipelines: Create GitHub Actions or Azure DevOps workflows for APIOps
- Environment promotion: Implement dev → test → prod deployment workflows
- Configuration management: Environment-specific parameters (dev/test/prod)
- Disaster recovery: Backup/restore procedures, blue-green deployments
- Phased rollout: Follow deployment planning guide with 7 phases over 17 weeks
Phased Deployment Strategy
See DEPLOYMENT_PLANNING_GUIDE.md for complete 17-week, 7-phase plan
Phase Summary
| 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 |
Important: MCP Tools (ALWAYS Use Before Code Generation)
1. Get Azure Verified Modules (AVM)
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
2. Call Deployment Best Practices FIRST
Tool: mcp_azure_mcp_get_azure_bestpractices
Intent: "Azure API Management deployment best practices Bicep"
3. Search Deployment Documentation
Tool: mcp_azure_mcp_documentation search
Query: "APIM VNet Internal Bicep deployment"
Infrastructure as Code Templates
See references/IaC_TEMPLATES.md for complete Bicep/Terraform templates
Quick Bicep Example: Production APIM
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:
- VNet Internal mode (
virtualNetworkType: 'Internal') - Premium SKU with 3 units (zone-redundant)
- TLS 1.2+ only (disable weak protocols)
- Managed Identity (no service accounts)
- Zones
[1, 2, 3]for 99.99% SLA
APIOps CI/CD Pipeline Pattern
GitHub Actions Workflow (Recommended)
name: 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:
- Dev → Test → Prod progression (serial jobs with
needs) - Manual approval for production (
environment: productionwith protection rules) - Smoke tests after each deployment
- Git tags for production releases (audit trail)
- Federated credential authentication (no secrets in code)
Environment-Specific Parameters
dev.bicepparam
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'
}
prod.bicepparam
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
Backup & Restore Procedures
APIM Backup (Automated)
#!/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"
APIM Restore (Disaster Recovery)
#!/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:
- Daily backups for 30 days (Azure Storage lifecycle policy)
- Weekly backups for 12 weeks
- Monthly backups for 12 months
- Geo-redundant storage (GRS) to UK West
Deployment Validation Checklist
Before production deployment, verify:
- Infrastructure Code: Bicep/Terraform linted and validated (
az bicep build,terraform validate) - Network Configuration: VNet Internal mode, Private Link configured
- Security: TLS 1.2+, weak protocols disabled, Key Vault integration
- Authentication: OAuth policies deployed, Entra ID/External ID configured
- Rate Limiting: All APIs have rate-limit-by-key policies
- Monitoring: Application Insights, diagnostic logs, alerts configured
- Backups: Automated daily backups to GRS storage
- Smoke Tests: Health endpoints responding, Front Door → APIM connectivity verified
- Manual Approval: Production deployment requires human approval (GitHub environment protection)
- Rollback Plan: Previous Bicep/Terraform state in Git, APIM backup available
Common Deployment Issues & Solutions
Issue: APIM VNet Integration Fails
Error: The subnet is not valid for API Management instance
Solution:
- Ensure subnet size ≥ /27 (32 IPs minimum)
- Subnet must not have any other resources
- Delegate subnet to
Microsoft.ApiManagement/service:delegations: [ { name: 'delegation' properties: { serviceName: 'Microsoft.ApiManagement/service' } } ]
Issue: Private Link Connection Pending
Error: Front Door → APIM Private Link status Pending Approval
Solution:
- Approve Private Endpoint connection in APIM:
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 - Verify status:
az network private-endpoint-connection list \ --name apim-api-marketplace-prod-uks \ --resource-group rg-apim-prod-uks \ --type Microsoft.ApiManagement/service
Issue: Deployment Takes 45+ Minutes
Cause: APIM Premium with zone redundancy takes 30-60 minutes to deploy
Solution: Expected behavior. Use incremental deployments:
- Day 1: Deploy APIM infrastructure (wait 45 min)
- Day 2+: Deploy API configurations (fast, minutes)
Optimization: Use --what-if flag to preview changes without deploying
Related Skills
- azure-apim-architecture - Understand architecture before deploying
- apim-policy-authoring - Deploy policies as part of APIOps workflow
- api-security-review - Validate security before production deployment
Microsoft Documentation
- APIOps Guide
- APIM Bicep Reference
- APIM Backup/Restore
- Azure Verified Modules
- GitHub Actions for Azure
Skill Version: 1.0
Last Updated: 29 January 2026
Primary Knowledge: DEPLOYMENT_PLANNING_GUIDE.md, references/IaC_TEMPLATES.md