resource "azurerm_resource_group" "rg" { location = var.resource_group_location name = "defaultPrometheusOnboardingResourceGroup" } resource "azurerm_kubernetes_cluster" "k8s" { location = azurerm_resource_group.rg.location name = var.cluster_name resource_group_name = azurerm_resource_group.rg.name dns_prefix = var.dns_prefix tags = { Environment = "Development" } default_node_pool { name = "agentpool" vm_size = "Standard_D2_v2" node_count = var.agent_count } monitor_metrics { annotations_allowed = var.metric_annotations_allowlist labels_allowed = var.metric_labels_allowlist } network_profile { network_plugin = "kubenet" load_balancer_sku = "standard" } identity { type = "SystemAssigned" } } resource "azurerm_monitor_workspace" "amw" { name = var.monitor_workspace_name resource_group_name = azurerm_resource_group.rg.name location = azurerm_resource_group.rg.location } resource "azurerm_monitor_data_collection_endpoint" "dce" { name = substr("MSProm-${azurerm_resource_group.rg.location}-${var.cluster_name}", 0, min(44, length("MSProm-${azurerm_resource_group.rg.location}-${var.cluster_name}"))) resource_group_name = azurerm_resource_group.rg.name location = azurerm_resource_group.rg.location kind = "Linux" } # Logic to determine region mismatch locals { dce_region_mismatch = var.cluster_region != var.amw_region } # Create another DCE if the regions don't match and is_private_cluster is true resource "azurerm_monitor_data_collection_endpoint" "dce_mismatch" { count = (local.dce_region_mismatch && var.is_private_cluster) ? 1 : 0 name = substr("MSProm-PL-${azurerm_resource_group.rg.location}-${var.cluster_name}", 0, min(44, length("MSProm-PL-${azurerm_resource_group.rg.location}-${var.cluster_name}"))) resource_group_name = azurerm_resource_group.rg.name location = var.cluster_region kind = "Linux" } resource "azurerm_monitor_data_collection_rule" "dcr" { name = substr("MSProm-${azurerm_resource_group.rg.location}-${var.cluster_name}", 0, min(64, length("MSProm-${azurerm_resource_group.rg.location}-${var.cluster_name}"))) resource_group_name = azurerm_resource_group.rg.name location = azurerm_resource_group.rg.location data_collection_endpoint_id = azurerm_monitor_data_collection_endpoint.dce.id kind = "Linux" destinations { monitor_account { monitor_account_id = azurerm_monitor_workspace.amw.id name = "MonitoringAccount1" } } data_flow { streams = ["Microsoft-PrometheusMetrics"] destinations = ["MonitoringAccount1"] } data_sources { prometheus_forwarder { streams = ["Microsoft-PrometheusMetrics"] name = "PrometheusDataSource" } } description = "DCR for Azure Monitor Metrics Profile (Managed Prometheus)" depends_on = [ azurerm_monitor_data_collection_endpoint.dce ] } resource "azurerm_monitor_data_collection_rule_association" "dcra" { name = "MSProm-${azurerm_resource_group.rg.location}-${var.cluster_name}" target_resource_id = azurerm_kubernetes_cluster.k8s.id data_collection_rule_id = azurerm_monitor_data_collection_rule.dcr.id description = "Association of data collection rule. Deleting this association will break the data collection for this AKS Cluster." depends_on = [ azurerm_monitor_data_collection_rule.dcr ] } # This association is required only if the cluster is private and the DCE region differs from the cluster region. # In this case, we associate the cluster with the DCE created in the cluster's region (dce_mismatch). # If there is no region mismatch, this resource is not created. resource "azurerm_monitor_data_collection_rule_association" "dcra_mismatch" { count = (local.dce_region_mismatch && var.is_private_cluster) ? 1 : 0 target_resource_id = azurerm_kubernetes_cluster.k8s.id data_collection_endpoint_id = azurerm_monitor_data_collection_endpoint.dce_mismatch[0].id description = "Association of data collection endpoint for private link clusters. Deleting this association will break the data collection for this AKS Cluster." depends_on = [ azurerm_monitor_data_collection_endpoint.dce_mismatch ] } # The azurerm monitor_metrics block does not expose control plane metrics, so # azureMonitorProfile.metrics.controlPlane.enabled is set via the azapi provider. # This runs after the DCRA is created so the control-plane-metrics (CCP) collection # pod is not scheduled before its DCRA exists (which would crash-loop until reconcile). resource "azapi_update_resource" "control_plane_metrics" { count = var.enable_control_plane_metrics ? 1 : 0 type = "Microsoft.ContainerService/managedClusters@2026-06-01" resource_id = azurerm_kubernetes_cluster.k8s.id body = jsonencode({ properties = { azureMonitorProfile = { metrics = { controlPlane = { enabled = true } } } } }) depends_on = [ azurerm_monitor_data_collection_rule_association.dcra ] } resource "azurerm_dashboard_grafana" "grafana" { name = var.grafana_name resource_group_name = azurerm_resource_group.rg.name location = var.grafana_location grafana_major_version = var.grafana_version identity { type = "SystemAssigned" } azure_monitor_workspace_integrations { resource_id = azurerm_monitor_workspace.amw.id } } resource "azurerm_role_assignment" "datareaderrole" { scope = azurerm_monitor_workspace.amw.id role_definition_id = "/subscriptions/${split("/", azurerm_monitor_workspace.amw.id)[2]}/providers/Microsoft.Authorization/roleDefinitions/b0d8363b-8ddd-447d-831f-62ca05bff136" principal_id = azurerm_dashboard_grafana.grafana.identity.0.principal_id } resource "azurerm_monitor_alert_prometheus_rule_group" "node_recording_rules_rule_group" { name = "NodeRecordingRulesRuleGroup-${var.cluster_name}" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name cluster_name = var.cluster_name description = "Node Recording Rules Rule Group" rule_group_enabled = true interval = "PT1M" scopes = [azurerm_monitor_workspace.amw.id,azurerm_kubernetes_cluster.k8s.id] rule { enabled = true record = "instance:node_num_cpu:sum" expression = <