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)
- 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
- Call Deployment Best Practices FIRST
Tool: mcp_azure_mcp_get_azure_bestpractices Intent: "Azure API Management deployment best practices Bicep"
- 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: production with 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