Azure VM删除或自定义脚本扩展卸载时执行自定义脚本的问题
问题描述
能否在卸载Azure VM自定义脚本扩展 或 删除VM时,执行与安装阶段不同的独立脚本?
我们的使用场景如下:
- 扩展安装时:使用
install.ps1安装软件并激活许可 - 扩展卸载时:使用
uninstall.ps1注销许可
我们暂未找到可在扩展卸载/VM删除时自动执行清理脚本的合理方案。
以下是我们用于创建VM的Terraform示例,标注部分为我们无法正常实现的问题区域:
当前遇到的报错:
timeout - last error: http response error: 401 - invalid content type
Terraform版本信息:
Terraform v1.0.9 on windows_amd64 + provider registry.terraform.io/hashicorp/azurerm v2.82.0
解决方案
1 修复配置错误
你当前的401和超时问题全部来自配置错误,依次修改即可:
1.1 修正自动登录XML的用户名密码错位
你当前的additional_unattend_content中把用户名和密码的取值写反了,导致自动登录失败,WinRM身份验证返回401,修改如下:
additional_unattend_content { setting = "AutoLogon" content = "<AutoLogon><Password><Value>${local.password}</Value></Password><Enabled>true</Enabled><LogonCount>1</LogonCount><Username>${local.username}</Username></AutoLogon>" }
1.2 新增NSG的WinRM HTTP端口放行规则
你当前的NSG只放行了HTTPS的5986端口,但你用的是HTTP WinRM的5985端口,端口未开导致连接超时,新增以下规则:
resource "azurerm_network_security_rule" "AllowWinRMHTTP" { access = "Allow" destination_address_prefix = "*" destination_port_range = "5985" direction = "Inbound" name = "AllowWinRMHTTP" network_security_group_name = azurerm_network_security_group.test.name priority = 300 protocol = "Tcp" resource_group_name = azurerm_resource_group.test.name source_address_prefix = "*" # 生产环境建议替换为运行Terraform的设备公网出口IP,降低安全风险 source_port_range = "*" }
1.3 完善首次登录的WinRM配置
你当前的首次登录脚本只开了防火墙端口,没有配置WinRM服务本身,补充配置:
first_logon_script = <<-SCRIPT # 启用WinRM服务并完成基础配置 winrm quickconfig -force # 允许非加密的HTTP连接 winrm set winrm/config/service @{AllowUnencrypted="true"} # 开启基础身份验证支持 winrm set winrm/config/service/auth @{Basic="true"} # 放行WinRM HTTP端口防火墙规则 netsh advfirewall firewall add rule name=WinRM_HTTP_5985 protocol=TCP dir=in localport=5985 action=allow SCRIPT
1.4 修正文件复制路径和执行逻辑
你当前的文件provisioner把脚本复制成了.txt后缀,后续执行.ps1文件时会找不到目标,同时指定PowerShell执行策略避免脚本被拦截:
# 复制安装脚本 provisioner "file" { source = local_file.install_script.filename destination = "C:/install.ps1" when = create } # 执行安装脚本 provisioner "remote-exec" { when = create inline = ["powershell -ExecutionPolicy Bypass -File C:/install.ps1"] } # 复制卸载脚本 provisioner "file" { source = local_file.uninstall_script.filename destination = "C:/uninstall.ps1" when = create } # 销毁时执行卸载脚本 provisioner "remote-exec" { when = destroy inline = ["powershell -ExecutionPolicy Bypass -File C:/uninstall.ps1"] }
2 额外注意事项
- 如果你的Terraform是在本地运行,无法直接访问Azure VM的私有IP,需要为VM绑定公网IP,并将connection块中的
host改为VM的公网IP,否则仍然会连接超时。 - Terraform的destroy provisioner仅在执行
terraform destroy命令时触发,如果你直接在Azure门户/API中删除VM,卸载脚本不会执行。如果需要覆盖全场景的许可注销,建议搭配Azure Event Grid监听VM删除事件,触发Azure Function或自动化账户执行注销逻辑,可靠性更高。
内容的提问来源于stack exchange,提问作者Rohit Mistry
相关产品推荐
相关产品推荐

