Managing Azure Service Bus with Terraform
Learn how to set up and manage Azure Service Bus using Terraform, including topics, subscriptions, and security configurations
Managing Azure Service Bus with Terraform
Azure Service Bus is a fully managed enterprise message broker. This guide demonstrates how to set up and manage Azure Service Bus using Terraform.
Video Tutorial
Learn more about managing Azure Service Bus with Terraform in this comprehensive video tutorial:
Prerequisites
- Azure CLI configured with appropriate permissions
- Terraform installed (version 1.0.0 or later)
- Resource group created
- Understanding of messaging concepts
Project Structure
terraform-azure-servicebus/
├── main.tf
├── variables.tf
├── outputs.tf
├── modules/
│ └── servicebus/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── policies/
└── security.json
Service Bus Configuration
Create modules/servicebus/main.tf
:
# Service Bus Namespace
resource "azurerm_servicebus_namespace" "main" {
name = "${var.project_name}-sb"
location = var.location
resource_group_name = var.resource_group_name
sku = "Premium"
capacity = var.capacity
identity {
type = "SystemAssigned"
}
customer_managed_key {
key_vault_key_id = azurerm_key_vault_key.servicebus.id
identity_id = azurerm_user_assigned_identity.servicebus.id
}
public_network_access_enabled = false
minimum_tls_version = "1.2"
zone_redundant = true
tags = var.tags
}
# Topics
resource "azurerm_servicebus_topic" "main" {
for_each = var.topics
name = each.key
namespace_id = azurerm_servicebus_namespace.main.id
enable_partitioning = true
max_size_in_megabytes = each.value.max_size_mb
default_message_ttl = each.value.message_ttl
enable_batched_operations = true
requires_duplicate_detection = true
duplicate_detection_history_time_window = "PT10M"
enable_express = false
status = "Active"
}
# Subscriptions
resource "azurerm_servicebus_subscription" "main" {
for_each = {
for sub in local.subscriptions : "${sub.topic_name}.${sub.name}" => sub
}
name = each.value.name
topic_id = azurerm_servicebus_topic.main[each.value.topic_name].id
max_delivery_count = 10
enable_batched_operations = true
requires_session = true
forward_to = each.value.forward_to
dead_lettering_on_message_expiration = true
status = "Active"
}
# Queues
resource "azurerm_servicebus_queue" "main" {
for_each = var.queues
name = each.key
namespace_id = azurerm_servicebus_namespace.main.id
enable_partitioning = true
max_size_in_megabytes = each.value.max_size_mb
enable_express = false
enable_batched_operations = true
requires_duplicate_detection = true
duplicate_detection_history_time_window = "PT10M"
dead_lettering_on_message_expiration = true
max_delivery_count = 10
requires_session = true
status = "Active"
}
# Rules
resource "azurerm_servicebus_subscription_rule" "main" {
for_each = {
for rule in local.rules : "${rule.topic_name}.${rule.subscription_name}.${rule.name}" => rule
}
name = each.value.name
subscription_id = azurerm_servicebus_subscription.main["${each.value.topic_name}.${each.value.subscription_name}"].id
filter_type = "SqlFilter"
sql_filter = each.value.sql_filter
action = each.value.action
}
Network Configuration
- Virtual Network Integration
resource "azurerm_virtual_network" "main" {
name = "${var.project_name}-vnet"
location = var.location
resource_group_name = var.resource_group_name
address_space = ["10.0.0.0/16"]
subnet {
name = "servicebus-subnet"
address_prefix = "10.0.1.0/24"
service_endpoints = ["Microsoft.ServiceBus"]
}
tags = var.tags
}
resource "azurerm_private_endpoint" "servicebus" {
name = "${var.project_name}-pe"
location = var.location
resource_group_name = var.resource_group_name
subnet_id = azurerm_virtual_network.main.subnet.*.id[0]
private_service_connection {
name = "${var.project_name}-psc"
private_connection_resource_id = azurerm_servicebus_namespace.main.id
is_manual_connection = false
subresource_names = ["namespace"]
}
private_dns_zone_group {
name = "default"
private_dns_zone_ids = [azurerm_private_dns_zone.servicebus.id]
}
}
resource "azurerm_private_dns_zone" "servicebus" {
name = "privatelink.servicebus.windows.net"
resource_group_name = var.resource_group_name
}
resource "azurerm_private_dns_zone_virtual_network_link" "servicebus" {
name = "${var.project_name}-vnet-link"
resource_group_name = var.resource_group_name
private_dns_zone_name = azurerm_private_dns_zone.servicebus.name
virtual_network_id = azurerm_virtual_network.main.id
}
Security Configuration
- Role Assignments
resource "azurerm_role_assignment" "servicebus_sender" {
scope = azurerm_servicebus_namespace.main.id
role_definition_name = "Azure Service Bus Data Sender"
principal_id = var.sender_principal_id
}
resource "azurerm_role_assignment" "servicebus_receiver" {
scope = azurerm_servicebus_namespace.main.id
role_definition_name = "Azure Service Bus Data Receiver"
principal_id = var.receiver_principal_id
}
- Customer-Managed Keys
resource "azurerm_key_vault_key" "servicebus" {
name = "${var.project_name}-key"
key_vault_id = var.key_vault_id
key_type = "RSA"
key_size = 2048
key_opts = [
"decrypt",
"encrypt",
"sign",
"unwrapKey",
"verify",
"wrapKey",
]
}
resource "azurerm_user_assigned_identity" "servicebus" {
name = "${var.project_name}-identity"
resource_group_name = var.resource_group_name
location = var.location
}
resource "azurerm_key_vault_access_policy" "servicebus" {
key_vault_id = var.key_vault_id
tenant_id = data.azurerm_client_config.current.tenant_id
object_id = azurerm_user_assigned_identity.servicebus.principal_id
key_permissions = [
"Get",
"UnwrapKey",
"WrapKey"
]
}
Monitoring Configuration
- Diagnostic Settings
resource "azurerm_monitor_diagnostic_setting" "servicebus" {
name = "${var.project_name}-diag"
target_resource_id = azurerm_servicebus_namespace.main.id
log_analytics_workspace_id = var.log_analytics_workspace_id
log {
category = "OperationalLogs"
enabled = true
retention_policy {
enabled = true
days = 30
}
}
metric {
category = "AllMetrics"
enabled = true
retention_policy {
enabled = true
days = 30
}
}
}
resource "azurerm_monitor_metric_alert" "servicebus" {
name = "${var.project_name}-messages-alert"
resource_group_name = var.resource_group_name
scopes = [azurerm_servicebus_namespace.main.id]
description = "Alert when active message count is high"
criteria {
metric_namespace = "Microsoft.ServiceBus/namespaces"
metric_name = "ActiveMessages"
aggregation = "Average"
operator = "GreaterThan"
threshold = 1000
}
action {
action_group_id = var.action_group_id
}
}
Advanced Features
- Geo-Disaster Recovery
resource "azurerm_servicebus_namespace_disaster_recovery_config" "main" {
name = "primary"
primary_namespace_id = azurerm_servicebus_namespace.main.id
partner_namespace_id = azurerm_servicebus_namespace.secondary.id
}
- Auto-Forwarding
resource "azurerm_servicebus_subscription" "forward" {
name = "forward-subscription"
topic_id = azurerm_servicebus_topic.main["source"].id
forward_to = azurerm_servicebus_queue.main["destination"].name
forward_dead_lettered_messages_to = azurerm_servicebus_queue.main["dlq"].name
}
Best Practices
-
Performance
- Enable partitioning
- Use sessions for ordering
- Configure batching
- Monitor message count
-
Security
- Enable private endpoints
- Use RBAC
- Enable encryption
- Implement network isolation
-
High Availability
- Use Premium tier
- Enable zone redundancy
- Configure geo-disaster recovery
- Monitor health
-
Cost Optimization
- Use appropriate tier
- Clean up unused queues
Conclusion
You’ve learned how to set up and manage Azure Service Bus using Terraform. This setup provides:
- Enterprise messaging
- Security and encryption
- Monitoring and alerts
- High availability
Remember to:
- Monitor message counts
- Review security settings
- Maintain dead-letter queues
- Update access controls