You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

更新azurerm_linux_virtual_machine的SSH公钥为何触发VM替换?

问题解答

核心结论

这确实是你使用的AzureRM Provider 2.50.0版本的预期行为。在该版本中,azurerm_linux_virtual_machine的admin_ssh_key块被标记为ForceNew属性——也就是说,一旦该块内的任何值(比如公钥)发生变更,Terraform会强制销毁并重建整个虚拟机,这和Azure门户直接修改VM配置的逻辑不同。

原因分析

早期版本的AzureRM Provider对VM的SSH密钥配置采用了强制替换的设计,因为当时Terraform还未实现对Azure VM SSH密钥的原地更新逻辑。而Azure门户或CLI是直接调用Azure API修改VM的操作系统配置,不需要重建实例,所以不会触发VM替换和IP地址变更。

解决方案

根据你的需求(避免VM替换、后续用密钥保管库管理密钥),可以选择以下几种方案:

1. 升级AzureRM Provider版本(推荐)

在AzureRM Provider 3.x及以上的版本中,已经修复了这个限制,支持对admin_ssh_key进行原地更新,不需要替换VM。升级后,修改公钥只会触发VM的配置更新,不会重建实例。

注意:升级Provider前请仔细阅读官方版本变更日志,处理可能的配置兼容性问题(比如资源属性重命名、参数变更等),建议在测试环境验证后再应用到生产环境。

2. 临时绕过Terraform同步密钥(应急方案)

如果暂时无法升级Provider,可以通过Azure CLI或门户手动更新VM的SSH公钥,然后执行以下命令让Terraform同步本地状态:

terraform refresh

这样后续的terraform plan就不会再触发VM替换,但这种方式会导致Terraform配置文件与实际资源状态不一致,仅适合临时场景。

3. 使用Key Vault+VM扩展管理密钥(长期最优方案)

既然你计划将公钥存储到密钥保管库,可以通过azurerm_virtual_machine_extension实现密钥的动态同步,完全避免VM替换:

# 从Key Vault获取最新的SSH公钥
data "azurerm_key_vault_secret" "ssh_public_key" {
  name         = "your-ssh-public-key-secret-name"
  key_vault_id = azurerm_key_vault.your_key_vault.id
}

# 通过自定义脚本扩展将公钥注入VM的authorized_keys
resource "azurerm_virtual_machine_extension" "ssh_key_sync" {
  for_each             = azurerm_linux_virtual_machine.linux_vms
  name                 = "SSHKeySync"
  virtual_machine_id   = each.value.id
  publisher            = "Microsoft.Azure.Extensions"
  type                 = "CustomScript"
  type_handler_version = "2.1"

  # 给VM分配访问Key Vault的托管身份权限(需提前配置Managed Identity)
  identity {
    type = "SystemAssigned"
  }

  settings = jsonencode({
    commandToExecute = <<-EOT
      # 清空旧密钥并写入新密钥(或追加,根据需求调整)
      echo "${data.azurerm_key_vault_secret.ssh_public_key.value}" > /home/username/.ssh/authorized_keys
      chmod 600 /home/username/.ssh/authorized_keys
      chown username:username /home/username/.ssh/authorized_keys
    EOT
  })
}

使用该方案时,只需更新Key Vault中的密钥,再重新应用Terraform即可触发扩展同步密钥到VM,全程不需要重建VM。

额外说明

你标记tls_private_key为tainted会强制Terraform重新生成密钥,由于VM的admin_ssh_key依赖该资源的输出值,所以会触发VM的替换逻辑,这是Terraform依赖链的正常行为。

内容的提问来源于stack exchange,提问作者thetechguy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 06:55:28