Azure AKS
Deploy the Watchlight AI Agent Runtime Governance control plane (Beacon) on Azure Kubernetes Service.
Prerequisites
| Requirement | Details |
|---|---|
| AKS cluster | Kubernetes 1.27+ |
| Azure CLI | v2.x, authenticated with appropriate subscription |
| kubectl | Configured for your AKS cluster |
| Helm | v3.12+ |
| Application Gateway Ingress Controller (AGIC) | Installed as an AKS add-on or via Helm |
| GHCR access | Image pull secret for ghcr.io/watchlight-ai-beacon |
Required Azure RBAC roles
The deploying principal needs:
Contributoron the resource group (or scoped to AKS, PostgreSQL, Application Gateway)Key Vault Secrets User(if using Azure Key Vault for secrets)Network Contributor(for Application Gateway integration)
Infrastructure Setup
1. Create a resource group
az group create \
--name watchlight-beacon-rg \
--location eastus
2. Create the AKS cluster with AGIC
az aks create \
--resource-group watchlight-beacon-rg \
--name watchlight-beacon \
--node-count 3 \
--node-vm-size Standard_D4s_v5 \
--enable-managed-identity \
--enable-addons ingress-appgw \
--appgw-name beacon-appgw \
--appgw-subnet-cidr "10.225.0.0/16" \
--network-plugin azure \
--generate-ssh-keys
az aks get-credentials \
--resource-group watchlight-beacon-rg \
--name watchlight-beacon
3. Provision Azure Database for PostgreSQL (Flexible Server)
az postgres flexible-server create \
--resource-group watchlight-beacon-rg \
--name beacon-db \
--location eastus \
--sku-name Standard_D2ds_v4 \
--tier GeneralPurpose \
--version 16 \
--storage-size 64 \
--admin-user beacon \
--admin-password "$(openssl rand -base64 24)" \
--high-availability ZoneRedundant \
--backup-retention 7
az postgres flexible-server db create \
--resource-group watchlight-beacon-rg \
--server-name beacon-db \
--database-name beacon
Allow access from the AKS cluster's VNet:
# Get the AKS VNet
AKS_VNET=$(az aks show \
--resource-group watchlight-beacon-rg \
--name watchlight-beacon \
--query 'agentPoolProfiles[0].vnetSubnetId' -o tsv | sed 's|/subnets/.*||')
az postgres flexible-server vnet-rule create \
--resource-group watchlight-beacon-rg \
--server-name beacon-db \
--vnet "$AKS_VNET" \
--subnet aks-subnet \
--rule-name allow-aks
4. Create the GHCR image pull secret
kubectl create namespace watchlight
kubectl create secret docker-registry ghcr-credentials \
-n watchlight \
--docker-server=ghcr.io \
--docker-username=YOUR_GITHUB_USERNAME \
--docker-password=YOUR_GITHUB_PAT
5. Create the database connection secret
kubectl create secret generic beacon-db-credentials \
-n watchlight \
--from-literal=DATABASE_URL="postgres://beacon:PASSWORD@beacon-db.postgres.database.azure.com:5432/beacon?sslmode=require"
6. (Optional) Azure Key Vault for secrets management
Instead of storing secrets directly in Kubernetes, use the Azure Key Vault Provider for Secrets Store CSI Driver:
az aks enable-addons \
--resource-group watchlight-beacon-rg \
--name watchlight-beacon \
--addons azure-keyvault-secrets-provider
az keyvault create \
--resource-group watchlight-beacon-rg \
--name beacon-vault \
--location eastus
az keyvault secret set \
--vault-name beacon-vault \
--name beacon-db-url \
--value "postgres://beacon:PASSWORD@beacon-db.postgres.database.azure.com:5432/beacon?sslmode=require"
Then create a SecretProviderClass to sync Key Vault secrets into Kubernetes:
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: beacon-secrets
namespace: watchlight
spec:
provider: azure
parameters:
usePodIdentity: "false"
useVMManagedIdentity: "true"
userAssignedIdentityID: "<MANAGED_IDENTITY_CLIENT_ID>"
keyvaultName: beacon-vault
objects: |
array:
- |
objectName: beacon-db-url
objectType: secret
tenantId: "<TENANT_ID>"
secretObjects:
- secretName: beacon-db-credentials
type: Opaque
data:
- objectName: beacon-db-url
key: DATABASE_URL
Helm Installation
Review the values file
The Azure-specific values file is at deploy/helm/watchlight-beacon/values-azure.yaml. Key settings:
global:
imageRegistry: ghcr.io/watchlight-ai-beacon
imagePullSecrets:
- name: ghcr-credentials
storageClass: managed-premium
ingress:
className: azure-application-gateway
annotations:
kubernetes.io/ingress.class: azure/application-gateway
appgw.ingress.kubernetes.io/ssl-redirect: "true"
# For Azure-managed certificates:
# appgw.ingress.kubernetes.io/appgw-ssl-certificate: beacon-cert
Before installing, update the values file with:
- Your TLS certificate name (uncomment
appgw.ingress.kubernetes.io/appgw-ssl-certificateor configure cert-manager) - Your domain name under
wl-registry.ingress.hosts[].hostandwl-registry-frontend.ingress.hosts[].host - Your PostgreSQL connection string under
global.externalDatabase.url(and setpostgresql.enabled: false)
Configure TLS on Application Gateway
Upload your TLS certificate to Application Gateway:
az network application-gateway ssl-cert create \
--resource-group MC_watchlight-beacon-rg_watchlight-beacon_eastus \
--gateway-name beacon-appgw \
--name beacon-cert \
--cert-file ./cert.pfx \
--cert-password "CERT_PASSWORD"
Alternatively, use cert-manager with Let's Encrypt for automated certificate management.
Install
helm install beacon ./deploy/helm/watchlight-beacon \
-n watchlight \
-f ./deploy/helm/watchlight-beacon/values-azure.yaml
To use Azure Database for PostgreSQL instead of the built-in chart:
helm install beacon ./deploy/helm/watchlight-beacon \
-n watchlight \
-f ./deploy/helm/watchlight-beacon/values-azure.yaml \
--set postgresql.enabled=false \
--set global.externalDatabase.url="postgres://beacon:PASSWORD@beacon-db.postgres.database.azure.com:5432/beacon?sslmode=require"
Validation
Check pod status
kubectl get pods -n watchlight
All pods should reach Running status within a few minutes.
Verify the ingress
kubectl get ingress -n watchlight
The ADDRESS column should show the Application Gateway's public IP.
Health checks
# Registry API
curl -s https://registry.example.com/api/v1/health | jq .
# Registry frontend
curl -s -o /dev/null -w "%{http_code}" https://registry.example.com/
Smoke test
# List registered agents
curl -s https://registry.example.com/api/v1/agents | jq .
# Check wl-discover logs
kubectl logs -n watchlight -l app.kubernetes.io/name=wl-discover --tail=20
Production Hardening
High availability
The Azure values file enables HPA and PodDisruptionBudgets:
wl-registry: 2-10 replicas, minimum 1 available during disruptionswl-registry-frontend: 2 replicas
AKS distributes pods across availability zones when using zone-redundant node pools:
az aks nodepool update \
--resource-group watchlight-beacon-rg \
--cluster-name watchlight-beacon \
--name nodepool1 \
--zones 1 2 3
Monitoring
Enable Azure Monitor for containers:
az aks enable-addons \
--resource-group watchlight-beacon-rg \
--name watchlight-beacon \
--addons monitoring \
--workspace-resource-id /subscriptions/SUB_ID/resourceGroups/RG/providers/Microsoft.OperationalInsights/workspaces/WORKSPACE
For Prometheus-based monitoring, enable the Azure Monitor managed service for Prometheus:
az aks update \
--resource-group watchlight-beacon-rg \
--name watchlight-beacon \
--enable-azure-monitor-metrics
Beacon services expose /metrics endpoints. The Helm chart includes ServiceMonitor resources that the managed Prometheus collector scrapes automatically.
Backup
- Azure Database for PostgreSQL: Automated backups are enabled by default with 7-day retention. Geo-redundant backup is available for disaster recovery.
- Configuration: Store your values file in version control.
Scaling considerations
| Component | Scaling strategy |
|---|---|
| wl-registry | HPA on CPU (included in values). |
| wl-registry-frontend | HPA or fixed 2+ replicas. |
| wl-discover | DaemonSet -- scales automatically with cluster size. |
| PostgreSQL (Flexible Server) | Vertical scaling via SKU change. Read replicas for read-heavy workloads. |
Network security
- Use Azure CNI for pod-level network policies.
- Azure Database for PostgreSQL Flexible Server supports VNet integration -- the database is not exposed to the public internet.
- Apply Kubernetes
NetworkPolicyresources to restrict pod-to-pod traffic. - Consider using a private AKS cluster with an internal load balancer if Beacon should not be exposed publicly.
Managed identity best practices
AKS managed identity provides keyless authentication to Azure services. Avoid storing Azure credentials as Kubernetes secrets when possible:
# Assign the managed identity access to Key Vault
IDENTITY_ID=$(az aks show \
--resource-group watchlight-beacon-rg \
--name watchlight-beacon \
--query 'identityProfile.kubeletidentity.objectId' -o tsv)
az keyvault set-policy \
--name beacon-vault \
--object-id "$IDENTITY_ID" \
--secret-permissions get list