Skip to main content
All posts
KubernetesAzureTerraformArgoCDDevOps

Deploying Production Kubernetes Clusters on Azure AKS

A practical walkthrough of provisioning an AKS cluster with Terraform, wiring up ArgoCD for GitOps delivery, and adding Prometheus + Grafana observability.

November 10, 20258 min read

Running Kubernetes in production on Azure AKS involves more than clicking through the portal. This post covers the infrastructure-as-code path: Terraform for provisioning, Helm for cluster-internal tooling, and ArgoCD for continuous delivery — the same stack I use for client projects.

Why AKS over self-managed Kubernetes

Azure Kubernetes Service offloads the control plane. You pay for worker nodes, not masters, and you get integrated Azure AD authentication, managed node upgrades, and native integration with Azure Container Registry and Azure Monitor. For most projects, that tradeoff makes sense.

Terraform module structure

A minimal AKS setup in Terraform separates concerns into three modules:

module "resource_group" {
  source   = "./modules/resource-group"
  name     = var.resource_group_name
  location = var.location
}

module "aks" {
  source              = "./modules/aks"
  resource_group_name = module.resource_group.name
  cluster_name        = var.cluster_name
  node_count          = var.node_count
  node_vm_size        = "Standard_D2s_v3"
  kubernetes_version  = "1.30"
}

module "acr" {
  source              = "./modules/acr"
  resource_group_name = module.resource_group.name
  acr_name            = var.acr_name
}

The AKS module uses azurerm_kubernetes_cluster with system-assigned identity and a separate node pool for workloads. Keeping the system node pool and workload node pool separate prevents noisy-neighbour resource contention.

Bootstrapping ArgoCD

Once the cluster is up, bootstrap ArgoCD with Helm:

helm repo add argo https://argoproj.github.io/argo-helm
helm upgrade --install argocd argo/argo-cd \
  --namespace argocd --create-namespace \
  --set server.service.type=ClusterIP

Then create an Application CRD pointing at your GitOps repo. Every merge to main triggers a sync — no kubectl apply needed in CI.

Observability stack

For production-grade observability, I deploy the kube-prometheus-stack Helm chart, which bundles Prometheus, Alertmanager, and Grafana:

helm upgrade --install kube-prometheus-stack \
  prometheus-community/kube-prometheus-stack \
  --namespace monitoring --create-namespace \
  --set grafana.adminPassword="$GRAFANA_ADMIN_PASSWORD"

Key dashboards to import: Node Exporter (ID 1860), Kubernetes Cluster Overview (ID 7249), and a custom one for your application's golden signals — latency, traffic, errors, saturation.

Cost guardrails

AKS costs grow quietly. Set budget alerts in Azure Cost Management, use spot node pools for batch workloads, and enable cluster autoscaler so you scale down overnight. A three-node Standard_D2s_v3 cluster running 24/7 costs roughly €150–200/month in West Europe — enabling the autoscaler commonly cuts that 30–40% for non-critical environments.


If you need an AKS cluster set up properly — Terraform state in Azure Storage, ArgoCD GitOps, monitoring, and a hardened network policy — get in touch or book a call.

Ready to fix this for your business?

Fixed scope, fixed price, written handover - websites, full-stack apps, and DevOps pipelines delivered in weeks, not months.