如何通过Terraform为每位开发者创建独立Azure Service Bus Namespace实例
问题描述
需求
开发者可通过terraform apply创建专属Azure Service Bus Namespace,仅需修改main.tf中local变量servicebus_namespace。
问题现状
当前配置下,开发者A创建A-service-bus-dev后,开发者B创建B-service-bus-dev时,A的实例会被销毁替换,不符合每位开发者需独立实例的要求。
环境说明
Terraform状态文件存储在Azure存储容器中,开发环境为手动部署,无自动部署流程。
咨询
该需求是否可通过Terraform实现?需修改哪些配置?
main.tf
locals { subscription_id = "ID" macroservice_name = "name" servicebus_namespace = "A-service-bus-dev" } provider "azurerm" { features {} subscription_id = local.subscription_id } resource "azurerm_resource_group" "this" { name = local.macroservice_name location = "West Europe" } module "account" { source = "../../modules/account" location = "West Europe" resource_group = local.macroservice_name environment_name = "development" storage_account = "dev" storage_container = "terraformstate" subscription_id = local.subscription_id } module "servicebus" { source = "../../modules/servicebus" location = "West Europe" resource_group = azurerm_resource_group.this.name servicebus_namespace = local.servicebus_namespace servicebus_objects = [ { topic_name = "x" subscription_name = "x" }, { topic_name = "y" subscription_name = "y" } ] }
modules/servicebus/servicebus.tf
resource "azurerm_servicebus_namespace" "this" { name = var.servicebus_namespace location = var.location resource_group_name = var.resource_group sku = "Standard" } resource "azurerm_servicebus_topic" "this" { for_each = {for k, v in var.servicebus_objects : k => v} name = each.value.topic_name namespace_id = azurerm_servicebus_namespace.this.id enable_partitioning = true } resource "azurerm_servicebus_subscription" "this" { for_each = azurerm_servicebus_topic.this name = var.servicebus_objects[index(var.servicebus_objects.*.topic_name, each.value.name)].subscription_name topic_id = each.value.id max_delivery_count = 1 dead_lettering_on_message_expiration = true }
注:已添加Account模块将Terraform状态存储到Azure,但未达到预期效果。
解决方案
可以实现,核心问题是所有开发者共用了同一个Terraform状态文件,导致状态冲突。需要从状态文件隔离、资源归属两个维度调整配置:
1. 为每个开发者隔离Terraform状态文件
当前所有开发者共享同一个terraform.tfstate文件,B执行apply时会基于共享状态修改资源。只需让每个开发者的状态文件独立命名即可:
- 直接在main.tf中配置Azure backend,指定
key为包含servicebus_namespace的变量,每个实例对应独立的状态文件 - 替换原
account模块的backend配置作用,修改示例如下:
terraform { backend "azurerm" { resource_group_name = "name" storage_account_name = "dev" container_name = "terraformstate" key = "${local.servicebus_namespace}.tfstate" # 每个开发者的状态文件独立命名 } }
2. 可选:为每个开发者创建独立资源组
当前所有Service Bus都放在同一个资源组里,虽然不影响功能,但为了更清晰的资源隔离,可让资源组名称包含专属命名空间后缀:
resource "azurerm_resource_group" "this" { name = "${local.macroservice_name}-${local.servicebus_namespace}" location = "West Europe" }
3. 修改后的完整main.tf示例
terraform { backend "azurerm" { resource_group_name = "name" storage_account_name = "dev" container_name = "terraformstate" key = "${local.servicebus_namespace}.tfstate" } } locals { subscription_id = "ID" macroservice_name = "name" servicebus_namespace = "A-service-bus-dev" # 开发者修改此处为专属名称 } provider "azurerm" { features {} subscription_id = local.subscription_id } resource "azurerm_resource_group" "this" { name = "${local.macroservice_name}-${local.servicebus_namespace}" location = "West Europe" } module "servicebus" { source = "../../modules/servicebus" location = "West Europe" resource_group = azurerm_resource_group.this.name servicebus_namespace = local.servicebus_namespace servicebus_objects = [ { topic_name = "x" subscription_name = "x" }, { topic_name = "y" subscription_name = "y" } ] }
操作步骤
- 每个开发者修改main.tf中的
servicebus_namespace为自己的专属名称 - 执行
terraform init(因backend key变更,需重新初始化状态连接) - 执行
terraform apply即可创建独立的Service Bus实例
内容的提问来源于stack exchange,提问作者erkanokyay
相关产品推荐
相关产品推荐

