解决Terragrunt中vsphere_virtual_machine自动更新问题:添加ignore_changes
问题
使用vSphere Provider结合Terragrunt创建虚拟机后,连续执行两次terragrunt apply,即便未修改ept_rvi_mode和hv_mode字段,Terragrunt仍会触发虚拟机的原地更新操作。
原因
vSphere会将ept_rvi_mode和hv_mode字段的值重置为空字符串"",但vSphere Provider定义这些字段时使用的是automatic、on或off这类枚举值,导致Terraform检测到本地配置与远程状态不一致,进而触发不必要的原地更新。
解决方案
在vsphere_virtual_machine资源块中添加lifecycle配置,忽略这两个字段的变更差异。结合你使用的Terraform-VMWare-Modules/vm/vsphere模块,可通过以下方式实现:
在VM目录的terragrunt.hcl中新增generate块,生成资源覆盖配置文件:
generate "vm_lifecycle_override" { path = "vm_lifecycle_override.tf" if_exists = "overwrite" contents = <<EOF resource "vsphere_virtual_machine" "vm" { lifecycle { ignore_changes = [ ept_rvi_mode, hv_mode ] } } EOF }
复现步骤
- 基于给定配置执行首次
terragrunt apply,完成虚拟机创建。 - 不修改任何配置,直接执行第二次
terragrunt apply,可观察到Terragrunt提示将对虚拟机进行原地更新(针对ept_rvi_mode和hv_mode字段)。 - 应用上述解决方案后,再次执行
terragrunt apply,将不再触发这两个字段的更新操作。
相关配置参考
根目录terragrunt.hcl
inputs = { vmrp = "my_cluster/Resources" dc = "dc1" datastore_cluster = "my_cluster" domain = "test.local" dns_suffix_list = ["test.local"] join_domain = true windomain = "test.local" domain_admin_user = "${get_env("vsphere_user")}" domain_admin_password = "${get_env("vsphere_pwd")}" } generate "config" { path = "config.hcl" if_exists = "overwrite" contents = <<EOF locals { env = "xxx" } EOF } generate "backend" { path = "backend.tf" if_exists = "overwrite_terragrunt" contents = <<EOF terraform { backend "gcs" { bucket = "${get_env("cloud_bucket")}" prefix = "terraform/${path_relative_to_include()}/terraform.tfstate" credentials = "${get_env("cloud_confg")}" } } EOF } generate "provider" { path = "provider.tf" if_exists = "overwrite_terragrunt" contents = <<EOF provider "vsphere" { user = "${get_env("vsphere_user")}" password = "${get_env("vsphere_pwd")}" vsphere_server = "192.x.x.x." # 自签名证书允许跳过验证 allow_unverified_ssl = true } EOF }
VM目录terragrunt.hcl
include "root" { path = find_in_parent_folders() } locals { config = read_terragrunt_config(find_in_parent_folders("config.hcl")) } terraform { source = "tfr:///Terraform-VMWare-Modules/vm/vsphere//.?version=3.5.0" } inputs = { vmtemp = "TPL-UBUNTU" instances = 1 cpu_number = 2 ram_size = 4096 cpu_hot_add_enabled = true cpu_hot_remove_enabled = true memory_hot_add_enabled = true vmnameformat = "%02d" # 使用两位带前导零的格式时,虚拟机名称会是类似AdvancedVM01、AdvancedVM02的形式 vmname = "${local.config.locals.envshort}-${basename(get_terragrunt_dir())}-" vmfolder = "FR" is_windows_image = false dns_server_list = ["192.168.2.7"] vmgateway = "192.168.2.254" disk_size_gb = [50] network = { mynetwork= [""] # 使用DHCP时留空列表;也可使用CIDR格式,例如["192.168.2.134/24"] } }
config.hcl
locals { env = "testing" }
内容的提问来源于stack exchange,提问作者Raphyyy
相关产品推荐
相关产品推荐

