Terraform - Azure 上的静态 IP 地址
Terraform - Static ip addresses on Azure
我们需要为通过 Terraform 部署在 Azure 中的虚拟机配置静态私有 IP。原因是我们需要通过一个 ansible 管道在 Ansible 中使用这些。
我在这里找到的一个解决方案是先创建一个带有“动态”地址的网卡,然后在 Terraform 的下一步中将其转换为“静态”IP。
# Create network interfaces with Private IP's
resource "azurerm_network_interface" "nic" {
for_each = { for vm in var.vms : vm.hostname => vm }
name = "${each.value.hostname}-NIC"
location = var.network_location
resource_group_name = var.vm_resource_group
ip_configuration {
name = "monitoringConfg"
subnet_id = data.azurerm_subnet.vm_subnet.id
private_ip_address_allocation = "dynamic"
}
tags = each.value.extra_tag
}
#Convert Dynamic Private IP's to Static
resource "azurerm_network_interface" "staticnic" {
for_each = { for vm in var.vms : vm.hostname => vm }
name = "${each.value.hostname}-NIC"
location = var.network_location
resource_group_name = var.vm_resource_group
ip_configuration {
name = "monitoringConfg"
subnet_id = data.azurerm_subnet.vm_subnet.id
private_ip_address_allocation = "static"
private_ip_address = azurerm_network_interface.nic[each.key].private_ip_address
}
tags = each.value.extra_tag
但是当我运行这个时,我得到以下错误:
ID 为“/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/xxxxxxxxxxxxxxxx/providers/Microsoft.Network/networkInterfaces/xxxxxxxxxxxxxxxxxxx-NIC”的资源已存在 - 要通过 Terraform 管理此资源,需要将其导入国家。请参阅“azurerm_network_interface”的资源文档以获取更多信息。
在 ../../modules/main.tf 第 58 行,资源“azurerm_network_interface”“staticnic”中:
58:资源“azurerm_network_interface”“staticnic”{
有没有人知道我做错了什么或有更好的方法来处理这个问题?
亲切的问候,
RB
Azure 不会分配动态 IP 地址,直到网络接口附加到 运行 虚拟机(或其他资源),请参阅 this.所以我认为我们不能在创建VM之前将动态IP转换为静态IP,因为IP地址暂时不存在。
相反,我们可以通过在该子网范围内分配一些 IP 地址,直接将一些静态 IP 地址关联到 Azure VM。阅读private IP分配方法。
Azure reserves the first four addresses in each subnet address range.
The addresses can't be assigned to resources. For example, if the
subnet's address range is 10.0.0.0/16, addresses 10.0.0.0-10.0.0.3 and
10.0.255.255 are unavailable.
例如,您可以参考此模板为 vms 配置静态私有 ip:
variable "vmlist" {
type = map(object({
hostname = string
IP_address = string
}))
default = {
vm1 ={
hostname = "vma"
IP_address = "10.0.2.4"
},
vm2 = {
hostname = "vmb"
IP_address = "10.0.2.5"
}
}
}
#...
resource "azurerm_network_interface" "staticnic" {
for_each = var.vmlist
name = "${each.value.hostname}-nic"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
ip_configuration {
name = "testconfiguration1"
subnet_id = azurerm_subnet.internal.id
private_ip_address_allocation = "Static"
private_ip_address = each.value.IP_address
}
}
#...
resource "azurerm_virtual_machine" "main" {
for_each = var.vmlist
name = each.value.hostname
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
network_interface_ids = [azurerm_network_interface.staticnic[each.key].id]
vm_size = "Standard_DS1_v2"
# Uncomment this line to delete the OS disk automatically when deleting the VM
# delete_os_disk_on_termination = true
# Uncomment this line to delete the data disks automatically when deleting the VM
# delete_data_disks_on_termination = true
storage_image_reference {
publisher = "MicrosoftWindowsServer"
offer = "WindowsServer"
sku = "2016-Datacenter"
version = "latest"
}
storage_os_disk {
name = "${each.value.hostname}-osdisk"
caching = "ReadWrite"
create_option = "FromImage"
managed_disk_type = "Standard_LRS"
}
os_profile {
computer_name = each.value.hostname
admin_username = "testadmin"
admin_password = "Password1234!"
}
os_profile_windows_config {
provision_vm_agent = "true"
}
}
我正在使用
Terraform v0.14.7
+ provider registry.terraform.io/hashicorp/azurerm v2.52.0
更新
如果要让Azure分配动态IP,然后将其转换为静态IP,可以使用local-exec Provisioner在创建资源后调用本地可执行文件。
resource "null_resource" "example" {
for_each = var.vmlist
provisioner "local-exec" {
command = <<EOT
$Nic = Get-AzNetworkInterface -ResourceGroupName ${azurerm_resource_group.main.name} -Name ${azurerm_network_interface.nic[each.key].name}
$Nic.IpConfigurations[0].PrivateIpAllocationMethod = "Static"
Set-AzNetworkInterface -NetworkInterface $Nic
EOT
interpreter = ["PowerShell", "-Command"]
}
}
为了便于阅读,我们这样做了。
首先,我使用此处列出的步骤在 Azure 中创建了一个服务原则 Creating a Service Principal
variables.TF
命令输出已添加到 variables.TF 作为
variable APP_ID {
default = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx"
}
variable SP_PASSWORD {
default = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
variable TENANT_ID {
default = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
此服务主体变量将用于在 运行 az network 命令之前执行 az login windows工人代理。
Main.TF
resource "azurerm_network_interface" "nic" {
for_each = { for vm in var.vms : vm.hostname => vm }
name = "${each.value.hostname}-NIC"
location = var.network_location
resource_group_name = var.vm_resource_group
ip_configuration {
name = var.nic_ip_config
subnet_id = data.azurerm_subnet.vm_subnet.id
private_ip_address_allocation = "dynamic"
}
tags = each.value.extra_tag
}
将上述动态ip的tp静态化
# Convert All Private IP's from Dynamic to Static using powershell
resource "null_resource" "StaticIPsPrivateVMs" {
for_each = { for vm in var.vms : vm.hostname => vm }
provisioner "local-exec" {
command = <<EOT
az login --service-principal --username ${var.APP_ID} --password ${var.SP_PASSWORD} --tenant ${var.TENANT_ID}
az network nic ip-config update -g ${var.vm_resource_group} --nic-name ${azurerm_network_interface.nic[each.key].name} --name ${var.nic_ip_config} --set privateIpAllocationMethod="Static"
EOT
interpreter = ["powershell", "-Command"]
}
depends_on = [
azurerm_virtual_machine.vm
]
}
#AZ logout
resource "null_resource" "AzLogout" {
provisioner "local-exec" {
command = <<EOT
az logout
EOT
interpreter = ["powershell", "-Command"]
}
depends_on = [
null_resource.StaticIPsPrivateVMs
]
}
Azure-pipelines.yml
我在 validate 和 deploy[=42] 的顶部添加了 vmImage: 'windows-latest' =] 阶段,这样我们就不会最终使用 linux 代理,这将抛出 powershell not found 错误:
- stage: validate
jobs:
- job: validate
pool:
vmImage: 'windows-latest'
continueOnError: false
steps:
- stage: deploy
jobs:
- deployment: deploy
pool:
vmImage: 'windows-latest'
continueOnError: false
所以这似乎是对 Azure 中私有 IP 的“动态”含义的误解。在 Azure 中使用“动态”专用 ip 创建 NIC 意味着 IP 在创建接口时分配,并且仅在删除接口时释放。
这意味着它的行为与“静态”接口完全一样。
唯一的区别是“静态”接口有一个用户分配的(如输入参数)IP,“动态”接口自动从子网分配一个空闲 IP。我已经发送了一个 PR 来更新 tf 文档 https://github.com/hashicorp/terraform-provider-azurerm/pull/15264
(来自 )
我们需要为通过 Terraform 部署在 Azure 中的虚拟机配置静态私有 IP。原因是我们需要通过一个 ansible 管道在 Ansible 中使用这些。
我在这里找到的一个解决方案是先创建一个带有“动态”地址的网卡,然后在 Terraform 的下一步中将其转换为“静态”IP。
# Create network interfaces with Private IP's
resource "azurerm_network_interface" "nic" {
for_each = { for vm in var.vms : vm.hostname => vm }
name = "${each.value.hostname}-NIC"
location = var.network_location
resource_group_name = var.vm_resource_group
ip_configuration {
name = "monitoringConfg"
subnet_id = data.azurerm_subnet.vm_subnet.id
private_ip_address_allocation = "dynamic"
}
tags = each.value.extra_tag
}
#Convert Dynamic Private IP's to Static
resource "azurerm_network_interface" "staticnic" {
for_each = { for vm in var.vms : vm.hostname => vm }
name = "${each.value.hostname}-NIC"
location = var.network_location
resource_group_name = var.vm_resource_group
ip_configuration {
name = "monitoringConfg"
subnet_id = data.azurerm_subnet.vm_subnet.id
private_ip_address_allocation = "static"
private_ip_address = azurerm_network_interface.nic[each.key].private_ip_address
}
tags = each.value.extra_tag
但是当我运行这个时,我得到以下错误:
ID 为“/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/xxxxxxxxxxxxxxxx/providers/Microsoft.Network/networkInterfaces/xxxxxxxxxxxxxxxxxxx-NIC”的资源已存在 - 要通过 Terraform 管理此资源,需要将其导入国家。请参阅“azurerm_network_interface”的资源文档以获取更多信息。 在 ../../modules/main.tf 第 58 行,资源“azurerm_network_interface”“staticnic”中: 58:资源“azurerm_network_interface”“staticnic”{
有没有人知道我做错了什么或有更好的方法来处理这个问题?
亲切的问候, RB
Azure 不会分配动态 IP 地址,直到网络接口附加到 运行 虚拟机(或其他资源),请参阅 this.所以我认为我们不能在创建VM之前将动态IP转换为静态IP,因为IP地址暂时不存在。
相反,我们可以通过在该子网范围内分配一些 IP 地址,直接将一些静态 IP 地址关联到 Azure VM。阅读private IP分配方法。
Azure reserves the first four addresses in each subnet address range. The addresses can't be assigned to resources. For example, if the subnet's address range is 10.0.0.0/16, addresses 10.0.0.0-10.0.0.3 and 10.0.255.255 are unavailable.
例如,您可以参考此模板为 vms 配置静态私有 ip:
variable "vmlist" {
type = map(object({
hostname = string
IP_address = string
}))
default = {
vm1 ={
hostname = "vma"
IP_address = "10.0.2.4"
},
vm2 = {
hostname = "vmb"
IP_address = "10.0.2.5"
}
}
}
#...
resource "azurerm_network_interface" "staticnic" {
for_each = var.vmlist
name = "${each.value.hostname}-nic"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
ip_configuration {
name = "testconfiguration1"
subnet_id = azurerm_subnet.internal.id
private_ip_address_allocation = "Static"
private_ip_address = each.value.IP_address
}
}
#...
resource "azurerm_virtual_machine" "main" {
for_each = var.vmlist
name = each.value.hostname
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
network_interface_ids = [azurerm_network_interface.staticnic[each.key].id]
vm_size = "Standard_DS1_v2"
# Uncomment this line to delete the OS disk automatically when deleting the VM
# delete_os_disk_on_termination = true
# Uncomment this line to delete the data disks automatically when deleting the VM
# delete_data_disks_on_termination = true
storage_image_reference {
publisher = "MicrosoftWindowsServer"
offer = "WindowsServer"
sku = "2016-Datacenter"
version = "latest"
}
storage_os_disk {
name = "${each.value.hostname}-osdisk"
caching = "ReadWrite"
create_option = "FromImage"
managed_disk_type = "Standard_LRS"
}
os_profile {
computer_name = each.value.hostname
admin_username = "testadmin"
admin_password = "Password1234!"
}
os_profile_windows_config {
provision_vm_agent = "true"
}
}
我正在使用
Terraform v0.14.7
+ provider registry.terraform.io/hashicorp/azurerm v2.52.0
更新
如果要让Azure分配动态IP,然后将其转换为静态IP,可以使用local-exec Provisioner在创建资源后调用本地可执行文件。
resource "null_resource" "example" {
for_each = var.vmlist
provisioner "local-exec" {
command = <<EOT
$Nic = Get-AzNetworkInterface -ResourceGroupName ${azurerm_resource_group.main.name} -Name ${azurerm_network_interface.nic[each.key].name}
$Nic.IpConfigurations[0].PrivateIpAllocationMethod = "Static"
Set-AzNetworkInterface -NetworkInterface $Nic
EOT
interpreter = ["PowerShell", "-Command"]
}
}
为了便于阅读,我们这样做了。
首先,我使用此处列出的步骤在 Azure 中创建了一个服务原则 Creating a Service Principal
variables.TF
命令输出已添加到 variables.TF 作为
variable APP_ID {
default = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx"
}
variable SP_PASSWORD {
default = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
variable TENANT_ID {
default = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
此服务主体变量将用于在 运行 az network 命令之前执行 az login windows工人代理。
Main.TF
resource "azurerm_network_interface" "nic" {
for_each = { for vm in var.vms : vm.hostname => vm }
name = "${each.value.hostname}-NIC"
location = var.network_location
resource_group_name = var.vm_resource_group
ip_configuration {
name = var.nic_ip_config
subnet_id = data.azurerm_subnet.vm_subnet.id
private_ip_address_allocation = "dynamic"
}
tags = each.value.extra_tag
}
将上述动态ip的tp静态化
# Convert All Private IP's from Dynamic to Static using powershell
resource "null_resource" "StaticIPsPrivateVMs" {
for_each = { for vm in var.vms : vm.hostname => vm }
provisioner "local-exec" {
command = <<EOT
az login --service-principal --username ${var.APP_ID} --password ${var.SP_PASSWORD} --tenant ${var.TENANT_ID}
az network nic ip-config update -g ${var.vm_resource_group} --nic-name ${azurerm_network_interface.nic[each.key].name} --name ${var.nic_ip_config} --set privateIpAllocationMethod="Static"
EOT
interpreter = ["powershell", "-Command"]
}
depends_on = [
azurerm_virtual_machine.vm
]
}
#AZ logout
resource "null_resource" "AzLogout" {
provisioner "local-exec" {
command = <<EOT
az logout
EOT
interpreter = ["powershell", "-Command"]
}
depends_on = [
null_resource.StaticIPsPrivateVMs
]
}
Azure-pipelines.yml
我在 validate 和 deploy[=42] 的顶部添加了 vmImage: 'windows-latest' =] 阶段,这样我们就不会最终使用 linux 代理,这将抛出 powershell not found 错误:
- stage: validate
jobs:
- job: validate
pool:
vmImage: 'windows-latest'
continueOnError: false
steps:
- stage: deploy
jobs:
- deployment: deploy
pool:
vmImage: 'windows-latest'
continueOnError: false
所以这似乎是对 Azure 中私有 IP 的“动态”含义的误解。在 Azure 中使用“动态”专用 ip 创建 NIC 意味着 IP 在创建接口时分配,并且仅在删除接口时释放。
这意味着它的行为与“静态”接口完全一样。
唯一的区别是“静态”接口有一个用户分配的(如输入参数)IP,“动态”接口自动从子网分配一个空闲 IP。我已经发送了一个 PR 来更新 tf 文档 https://github.com/hashicorp/terraform-provider-azurerm/pull/15264
(来自 )