Terraform部署OpenStack多实例并挂载多附加磁盘问题求助
问题:Terraform部署OpenStack实例时多附加磁盘挂载失败
我尝试通过Terraform在OpenStack中部署多个云实例,并为这些实例挂载多块附加磁盘,但当前配置仅能处理第一块附加磁盘,尝试遍历磁盘列表时配置失败,仅配置单块附加磁盘时可正常运行。
原配置代码
variable "instances" { description = "要部署的实例" type = map(object({ name = string image = string flavor = string volume_size = number security_groups = list(string) network = string keypair_name = string floating_ip_pool = string tags = list(string) additional_disks = list(object({ disk = string volume_size = number })) })) } instances = { "Websrv01" = { name = "websrv01" image = "Ubuntu 22.04" flavor = "SCS-2V-4-20s" volume_size = 20 security_groups = ["default"] network = "test-intern" keypair_name = "ssh-pub" floating_ip_pool = "public" tags = ["general", "webserver"] additional_disks = [] }, "dbsrv01" = { name = "dbsrv01" image = "Ubuntu 22.04" flavor = "SCS-2V-4-20s" volume_size = 20 security_groups = ["default"] network = "test-intern" keypair_name = "ssh-pub" floating_ip_pool = "public" tags = ["general", "dbserver"] additional_disks = [ { disk = "db_data", volume_size = 30 }, { disk = "db_log", volume_size = 10 } ] } } resource "openstack_compute_instance_v2" "instances" { for_each = var.instances name = each.value.name flavor_id = data.openstack_compute_flavor_v2.flavor[each.key].id key_pair = each.value.keypair_name security_groups = each.value.security_groups ## 系统盘 block_device { uuid = data.openstack_images_image_v2.image[each.key].id source_type = "image" volume_size = each.value.volume_size boot_index = 0 destination_type = "volume" delete_on_termination = true } lifecycle { prevent_destroy = true } network { name = each.value.network } tags = each.value.tags } ## 按需申请浮动IP resource "openstack_networking_floatingip_v2" "floating_ip" { for_each = { for k, v in var.instances : k => v if v.floating_ip_pool != "" } pool = each.value.floating_ip_pool } ## 绑定浮动IP到实例 resource "openstack_compute_floatingip_associate_v2" "associate" { for_each = openstack_networking_floatingip_v2.floating_ip instance_id = openstack_compute_instance_v2.instances[each.key].id floating_ip = each.value.address } ## 附加磁盘 resource "openstack_blockstorage_volume_v3" "additional_disks" { for_each = { for instance, disks in var.instances : instance => disks.additional_disks if length(disks.additional_disks) > 0 } name = "${each.key}-${each.value[0].disk}" size = each.value[0].volume_size enable_online_resize = true } ## 挂载附加磁盘到实例 resource "openstack_compute_volume_attach_v2" "attach_additional_disks" { for_each = { for instance, disks in var.instances : instance => disks.additional_disks if length(disks.additional_disks) > 0 } instance_id = openstack_compute_instance_v2.instances[each.key].id volume_id = openstack_blockstorage_volume_v3.additional_disks[each.key].id }
问题根源
原配置中,openstack_blockstorage_volume_v3.additional_disks和openstack_compute_volume_attach_v2.attach_additional_disks的for_each是按实例分组,每个实例对应一组磁盘列表,后续代码中直接取each.value[0]只处理了列表中第一块磁盘,导致多磁盘场景下只有第一块被创建和挂载。
要实现多磁盘处理,需要将每个磁盘作为独立的资源实例,因此需要构造一个包含实例ID-磁盘名称的唯一键值对集合,确保每块磁盘都能生成对应的资源。
修正后的配置
1. 创建附加磁盘
resource "openstack_blockstorage_volume_v3" "additional_disks" { # 构造包含实例和磁盘的唯一映射:key格式为"实例名-磁盘名" for_each = flatten([ for instance_name, instance in var.instances : [ for disk in instance.additional_disks : { key = "${instance_name}-${disk.disk}" instance_id = instance_name disk_name = disk.disk size = disk.volume_size } ] ]) name = each.value.key size = each.value.size enable_online_resize = true }
2. 挂载附加磁盘到实例
resource "openstack_compute_volume_attach_v2" "attach_additional_disks" { # 复用磁盘资源的for_each,确保每块磁盘对应一个挂载资源 for_each = openstack_blockstorage_volume_v3.additional_disks instance_id = openstack_compute_instance_v2.instances[each.value.instance_id].id volume_id = each.value.id }
说明
- 通过
flatten和嵌套循环,将每个实例的每块磁盘转换为独立的键值对,确保for_each为每块磁盘生成单独的资源实例。 - 磁盘名称使用
实例名-磁盘名格式,保证全局唯一。 - 挂载资源直接复用磁盘资源的
for_each,自动关联对应的实例和磁盘,无需手动指定索引。
内容的提问来源于stack exchange,提问作者Eddy
相关产品推荐
相关产品推荐

