使用Terraform Libvirt Provider获取域实例IP的问题
我通过Terraform使用libvirt provider创建了若干实例,配置代码如下:
resource "libvirt_domain" "node" { for_each = { for idx, vm_name in var.kvm_names: vm_name => idx} name = format("%s", each.key) vcpu = var.vcpu memory = var.memoryMB cloudinit = libvirt_cloudinit_disk.commoninit[each.key].id disk { volume_id = "${libvirt_volume.image[each.key].id}" } network_interface { network_name = "default" } network_interface { network_id = libvirt_network.test_network.id network_name = libvirt_network.test_network.name } }
我希望输出实例的IP地址以便传递给Ansible进行配置,但使用以下输出代码时出现错误:
output "ips" { value = "${libvirt_domain.node[*].network_interface[*].addresses[0]}" }
错误信息:
│ Error: Unsupported attribute
│
│ on kvm.tf line 66, in output "ips":
│ 66: value = "${libvirt_domain.node[].network_interface[].addresses[0]}"
│
│ This object does not have an attribute named "network_interface".
而使用以下输出代码可以正常运行,并且能看到预期的interface属性:
output "ips" { value = "${libvirt_domain.node[*]}" }
请问如何正确获取并使用这些虚拟机的网卡IP地址?
错误原因
你混淆了资源配置块名称和输出属性名称:network_interface是定义资源时的配置块名称,而libvirt_domain实例的网络接口输出属性名称是interfaces,这就是报错提示找不到network_interface属性的原因。
正确的IP提取方式
因为你使用了for_each创建实例,libvirt_domain.node是一个键为虚拟机名称的映射(map),需要用for表达式遍历处理:
1. 按虚拟机名称映射IP(推荐给Ansible使用)
这种方式输出键值对,清晰对应每个虚拟机的网卡IP,适配Ansible的inventory需求:
output "vm_ips" { value = { for vm_name, vm in libvirt_domain.node : vm_name => vm.interfaces[*].addresses[0] } }
输出示例:
vm_ips = { "vm-1" = ["192.168.122.10", "10.0.0.10"] "vm-2" = ["192.168.122.11", "10.0.0.11"] }
2. 提取所有IP的扁平化列表
如果只需要所有实例的所有网卡IP组成的纯列表:
output "all_ips" { value = flatten([ for vm in libvirt_domain.node : vm.interfaces[*].addresses[0] ]) }
输出示例:
all_ips = ["192.168.122.10", "10.0.0.10", "192.168.122.11", "10.0.0.11"]
3. 提取指定网络的IP
如果只需要test_network下的IP,可以添加过滤条件精准提取:
output "test_network_ips" { value = { for vm_name, vm in libvirt_domain.node : vm_name => [ for iface in vm.interfaces : iface.addresses[0] if iface.network_name == libvirt_network.test_network.name ][0] } }
输出示例:
test_network_ips = { "vm-1" = "10.0.0.10" "vm-2" = "10.0.0.11" }
补充说明
interfaces属性包含实例所有网络接口的详细信息,每个接口的addresses是IP列表,addresses[0]通常对应IPv4地址- 用for表达式处理
for_each创建的资源映射,能灵活控制输出格式,满足不同场景的使用需求
内容的提问来源于stack exchange,提问作者ascub

