Create an Azure Managed Grafana Using Terraform
Introduction
Azure Managed Grafana is a fully managed service that provides powerful, and flexible tool for visualizing and analyzing data. It allows seamless integration with various Azure services, including Azure Monitor and Log Analytics, making it a great choice for monitoring applications running on Azure Kubernetes Service (AKS).
In this article, we will explore how to create and configure an Azure Managed Grafana workspace using Terraform.
Technical Scenario
As a cloud infrastructure engineer,
I want to set up Azure Managed Grafana for monitoring workloads running on Azure Kubernetes Service (AKS),
So that we can visualize real-time metrics, logs, and health of our AKS clusters and applications.
Acceptance Criteria:
- A dedicated Azure Managed Grafana workspace should be provisioned.
- The workspace should be securely connected to an Azure Monitor and Log Analytics workspace to fetch telemetry data.
- Diagnostic settings for the Grafana workspace should be enabled to capture logs and metrics for troubleshooting.
- Private endpoint access should be configured to ensure secure connectivity.
- Role-based access control (RBAC) should be implemented for Grafana access, with specific permissions granted to users and groups.
- The setup should be automated using terraform to ensure consistency across environments and to simplify maintenance.
Why Azure Managed Grafana?
- Seamless Integration: Azure Managed Grafana integrates effortlessly with Azure services such as Azure Monitor, Log Analytics, and Azure Metrics, offering a smooth experience for visualizing metrics from AKS and other cloud-native applications.
- Scalability: The service automatically scales with your workload, so as your AKS clusters grow, your monitoring infrastructure can scale with it.
- Security: The service provides built-in security features such as RBAC, private endpoints, and audit logging, making it a suitable choice for regulated environments.
Prerequisites
Before proceeding, ensure the following prerequisites are met:
- An active Azure subscription with sufficient permissions (Contributor or Owner role).
- Terraform installed and configured locally.
- Familiarity with terraform syntax and Azure resources.
- Azure CLI installed for authentication purposes.
- Predefined Azure AD groups for managing role assignments.
- Basic knowledge of Azure Monitor and its resources.
- Azure Log Analytics Workspace: You need an existing Azure Log Analytics workspace for setting up diagnostics
Implementation Details
The following steps detail the implementation process:
Task-1: Configure terraform variables for Azure Managed Grafana
Start by defining the necessary variables in the variables.tf
file to make your terraform configuration modular and reusable:
# Configure terraform variables for Azure Managed Grafana
variable "grafana_name_prefix" {
type = string
default = "amg"
description = "Prefix of the Azure Managed Grafana name that's combined with name of the Azure Managed Grafana."
}
variable "grafana_name" {
description = "(Required) Specifies the name which should be used for this Dashboard Grafana"
type = string
default = "grafana"
}
variable "api_key_enabled" {
description = " (Optional) Whether to enable the api key setting of the Grafana instance. Defaults to false."
type = bool
default = false
}
variable "grafana_major_version" {
description = "(Optional) Which major version of Grafana to deploy. Defaults to 9. Possible values are 9, 10"
type = number
default = 10
}
variable "deterministic_outbound_ip_enabled" {
description = "(Optional) Whether to enable the Grafana instance to use deterministic outbound IPs. Defaults to false."
type = bool
default = false
}
variable "grafana_public_access" {
description = "(Optional) Whether to enable traffic over the public interface. Defaults to true."
type = bool
default = true
}
variable "monitoring_tags" {
description = "(Optional) A mapping of tags which should be assigned to the Azure Monitor Workspace."
type = map(any)
default = {
"Application" = "Monitoring"
}
}
variable "diagnostic_setting_name" {
description = "The name of this Diagnostic Setting."
type = string
default = "diag-grafana"
}
variable "diagnostic_setting_enabled_log_categories" {
description = "A list of log categories to be enabled for this diagnostic setting."
type = list(string)
default = ["GrafanaLoginEvents"]
}
variable "grafana_rbac" {}
Task-2: Create an Azure Managed Grafana using terraform
Provision an Azure Managed Grafana, which is the backbone of Azure's monitoring services:
# Step-1: Create the Azure Managed Grafana
resource "azurerm_dashboard_grafana" "grafana" {
name = "${var.grafana_name_prefix}-${var.grafana_name}-${local.environment}"
resource_group_name = azurerm_resource_group.monitoring.name
location = azurerm_resource_group.monitoring.location
sku = "Standard"
public_network_access_enabled = var.grafana_public_access
api_key_enabled = var.api_key_enabled
deterministic_outbound_ip_enabled = var.deterministic_outbound_ip_enabled
grafana_major_version = var.grafana_major_version
tags = merge(local.default_tags, var.monitoring_tags)
lifecycle {
ignore_changes = [
# tags,
]
}
identity {
type = "SystemAssigned"
}
azure_monitor_workspace_integrations {
resource_id = azurerm_monitor_workspace.amw.id
}
depends_on = [
azurerm_resource_group.monitoring,
azurerm_monitor_workspace.amw
]
}
This code will create a Grafana workspace linked to a Log Analytics workspace for monitoring.
Task-4: Configure diagnostic settings for Azure Managed Grafana
Diagnostic settings allow you to monitor and troubleshoot the performance of your Azure Managed Grafana workspace.
# Step-2: Configure diagnostic settings for Azure Managed Grafana
resource "azurerm_monitor_diagnostic_setting" "grafana" {
name = var.diagnostic_setting_name
target_resource_id = azurerm_dashboard_grafana.grafana.id
log_analytics_workspace_id = data.azurerm_log_analytics_workspace.workspace.id
dynamic "enabled_log" {
for_each = toset(var.diagnostic_setting_enabled_log_categories)
content {
category = enabled_log.value
}
}
metric {
category = "AllMetrics"
enabled = false
}
depends_on = [
azurerm_dashboard_grafana.grafana,
data.azurerm_log_analytics_workspace.workspace
]
}
Step 4: Create a private endpoint for Azure Managed Grafana
To ensure secure access to the Azure Managed Grafana workspace, create a private endpoint.
# Step-3 Create a private endpoint for Azure Managed Grafana
resource "azurerm_private_endpoint" "pe_grafana" {
name = lower("${var.private_endpoint_prefix}-${azurerm_dashboard_grafana.grafana.name}")
location = var.location # azurerm_dashboard_grafana.grafana.location
resource_group_name = azurerm_dashboard_grafana.grafana.resource_group_name
subnet_id = data.azurerm_subnet.jumpserver.id
tags = merge(local.default_tags)
private_service_connection {
name = "pe-${azurerm_dashboard_grafana.grafana.name}"
private_connection_resource_id = azurerm_dashboard_grafana.grafana.id
is_manual_connection = false
subresource_names = var.pe_grafana_subresource_names
request_message = try(var.request_message, null)
}
private_dns_zone_group {
name = "default"
private_dns_zone_ids = [data.azurerm_private_dns_zone.pdz_grafana_core_sub.id]
}
lifecycle {
ignore_changes = [
custom_network_interface_name,
# location
]
}
depends_on = [
data.azurerm_subnet.jumpserver,
azurerm_dashboard_grafana.grafana,
data.azurerm_private_dns_zone.pdz_grafana_core_sub
]
}
Step 5: Create role assignment over resource group containing the azure log analytics workspace
To enable access for the Grafana workspace to the Log Analytics workspace, create a role assignment.
# Step-4: Add required role assignment over resource group containing the Azure Monitor Workspace
resource "azurerm_role_assignment" "grafana" {
scope = azurerm_resource_group.monitoring.id
role_definition_name = "Monitoring Reader"
principal_id = azurerm_dashboard_grafana.grafana.identity[0].principal_id
depends_on = [
azurerm_resource_group.monitoring,
azurerm_monitor_workspace.amw,
azurerm_dashboard_grafana.grafana
]
}
Step 6: Create role assignment over resource group containing the Azure Monitor Workspace
Similarly, create role assignments for Azure Monitor.
# Step-5: Add required role assignment over resource group containing the Azure Log Analytics Workspace for AKS logs access
resource "azurerm_role_assignment" "grafana_law" {
scope = data.azurerm_resource_group.workspace.id
role_definition_name = "Monitoring Reader"
principal_id = azurerm_dashboard_grafana.grafana.identity[0].principal_id
depends_on = [
azurerm_resource_group.monitoring,
data.azurerm_resource_group.workspace
]
}
Step 7: Create role assignment over resource group containing the AKS
Grant the necessary permissions to AKS.
# Step-6: Add required role assignment over ewm30 resource group access for AKS
resource "azurerm_role_assignment" "monitoring_reader_ewm30_rg" {
scope = data.azurerm_resource_group.ewm30_rg.id
role_definition_name = "Monitoring Reader"
principal_id = azurerm_dashboard_grafana.grafana.identity[0].principal_id
depends_on = [
azurerm_resource_group.monitoring,
data.azurerm_resource_group.workspace
]
}
Step 8: Create azure AD groups for Grafana Access
Define Azure AD groups to assign users to Grafana.
# Step-7: Create azure ad groups for Grafana access
resource "azuread_group" "grafana_admin" {
for_each = toset(["admin", "editor", "viewer"])
display_name = lower("${local.ad_group_prefix}-grafana-${each.key}-ewm30-${local.environment}")
owners = [data.azurerm_client_config.current.object_id]
security_enabled = true
lifecycle {
ignore_changes = [owners]
}
}
Step 9: Setup RBAC for Grafana Access
Configure RBAC to grant users specific access levels to Grafana dashboards.
# Step-8: RBAC setup for Grafana instance access
resource "azurerm_role_assignment" "grafana_rbac" {
for_each = var.grafana_rbac
principal_id = each.value
role_definition_name = each.key
scope = azurerm_dashboard_grafana.grafana.id
depends_on = [
azurerm_dashboard_grafana.grafana
]
}