我们需要为通过 terraform 部署在 Azure 中的 vm 配置静态私有 ip。原因是我们需要通过 ansible 管道在 Ansible 中使用这些。
我在这里找到的一个解决方案是先创建一个具有“动态”地址的 nic,然后在 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/xxxxxxxxxxxxxxxxxx/providers/Microsoft.Network/networkInterfaces/xxxxxxxxxxxxxxxxxxx-NIC”的资源已经存在 - 将通过 Terraform 进行管理资源需要进口到国家。有关详细信息,请参阅“azurerm_network_interface”的资源文档。 在 ../../modules/main.tf 第 58 行,在资源“azurerm_network_interface”“staticnic”中: 58:资源“azurerm_network_interface”“静态”{
有没有人知道我做错了什么或有更好的方法来处理这个问题?
亲切的问候, RB
答案 0 :(得分:2)
在网络接口连接到正在运行的虚拟机(或其他资源)之前,Azure 不会分配动态 IP 地址,请参阅 this。所以我认为我们不能在创建VM之前将动态IP转换为静态IP,因为IP地址暂时不存在。
相反,我们可以通过在该子网范围内分配一些 IP 地址,将一些静态 IP 地址直接关联到 Azure VM。阅读private IP分配方法。
<块引用>Azure 保留每个子网地址范围中的前四个地址。 地址不能分配给资源。例如,如果 子网的地址范围是 10.0.0.0/16,地址 10.0.0.0-10.0.0.3 和 10.0.255.255 不可用。
例如,您可以参考此模板为虚拟机配置静态私有 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"]
}
}
答案 1 :(得分:0)
为了便于阅读,我们做了这些。
首先,我使用此处列出的步骤在 azure 中创建了一个服务原则Creating a Service Principal
变量.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"
此服务主体变量将用于在 Windows 工作代理上运行 az network 命令之前进行 az 登录。
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 static
# 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 阶段的顶部添加了 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