Azure Patterns
AKS Cluster (Bicep)
resource aks 'Microsoft.ContainerService/managedClusters@2023-10-01' = {
name: 'myapp-aks'
location: resourceGroup().location
identity: { type: 'SystemAssigned' }
properties: {
dnsPrefix: 'myapp'
enableRBAC: true
aadProfile: {
managed: true
enableAzureRBAC: true
}
agentPoolProfiles: [
{
name: 'system'
count: 2
vmSize: 'Standard_D4s_v3'
osType: 'Linux'
mode: 'System'
enableAutoScaling: true
minCount: 2
maxCount: 5
}
]
networkProfile: {
networkPlugin: 'azure'
networkPolicy: 'azure'
}
addonProfiles: {
azureKeyvaultSecretsProvider: { enabled: true }
omsagent: {
enabled: true
config: { logAnalyticsWorkspaceResourceID: workspace.id }
}
}
}
}
Azure Functions (Python)
import azure.functions as func
import logging
app = func.FunctionApp(http_auth_level=func.AuthLevel.FUNCTION)
@app.route(route="orders/{order_id}", methods=["GET"])
@app.cosmos_db_input(
arg_name="order",
database_name="mydb",
container_name="orders",
id="{order_id}",
partition_key="{order_id}",
connection="CosmosDbConnectionSetting",
)
def get_order(req: func.HttpRequest, order: func.DocumentList) -> func.HttpResponse:
if not order:
return func.HttpResponse("Not found", status_code=404)
return func.HttpResponse(order[0].to_json(), mimetype="application/json")
Key Vault Secrets in AKS
# SecretProviderClass
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: myapp-secrets
spec:
provider: azure
parameters:
usePodIdentity: "false"
clientID: ${MANAGED_IDENTITY_CLIENT_ID}
keyvaultName: myapp-kv
objects: |
array:
- |
objectName: db-password
objectType: secret
tenantId: ${TENANT_ID}
secretObjects:
- secretName: myapp-secrets
type: Opaque
data:
- objectName: db-password
key: DB_PASSWORD
Application Insights (SDK)
from azure.monitor.opentelemetry import configure_azure_monitor
from opentelemetry import trace
configure_azure_monitor(
connection_string=os.environ["APPLICATIONINSIGHTS_CONNECTION_STRING"]
)
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("process-order") as span:
span.set_attribute("order.id", order_id)
result = process(order_id)
span.set_attribute("order.status", result.status)
Azure DevOps Pipeline
trigger:
branches:
include: [main]
pool:
vmImage: ubuntu-latest
variables:
- group: prod-secrets
- name: IMAGE_TAG
value: $(Build.SourceVersion)
stages:
- stage: Build
jobs:
- job: BuildAndPush
steps:
- task: Docker@2
inputs:
command: buildAndPush
repository: $(ACR_REPO)
containerRegistry: $(ACR_SERVICE_CONNECTION)
tags: $(IMAGE_TAG)
- stage: Deploy
dependsOn: Build
environment: production
jobs:
- deployment: DeployAKS
strategy:
runOnce:
deploy:
steps:
- task: KubernetesManifest@1
inputs:
action: deploy
manifests: k8s/*.yaml
containers: $(ACR_REPO):$(IMAGE_TAG)
Key Rules
- Use Managed Identities instead of service principal secrets for AKS workloads
- Enable Defender for Containers on all AKS clusters
- Use Private Endpoints for Key Vault, Storage, and SQL in production
- Azure Policy: enforce tagging, region restrictions, and allowed VM sizes
- Application Insights sampling: set adaptive sampling to avoid cost overruns on high-traffic services