如何在PowerShell脚本中使用Terraform变量?Windows环境遇阻
Windows环境下Terraform变量无法注入PowerShell脚本的解决办法
问题背景
原本在Linux(Bash)环境下能用的Terraform传变量到脚本的方案,迁移到Windows(PowerShell)环境后失效了。已经配置了对应的template_file模板,PS1脚本里用$RunnerTags = "${RUNNER_TAGS}"读取变量,部署Windows VM扩展后,变量却没成功注入。
现有代码参考
Linux侧资源配置
resource "azurerm_virtual_machine_extension" "runner_server" { count = length(var.runner_vm_name) name = "runnerSettings" virtual_machine_id = azurerm_linux_virtual_machine.runner_server[count.index].id publisher = "Microsoft.Azure.Extensions" type = "CustomScript" type_handler_version = "2.0" protected_settings = <<PROT { "script": "${base64encode(data.template_file.runner_settings.rendered)}" } PROT }
模板文件
data "template_file" "runner_settings" { template = file("${var.runner_script_file}") vars = { REGISTRATION_TOKEN = var.gitlab_runner_reg_token, GITLAB_URL = var.gitlab_url, DEPLOY_ENV = replace(var.resource_name_prefix, "-cicd", ""), RUNNER_TAGS = join(",", var.gitlab_runner_tags) } }
Windows侧PS1读取方式
$RunnerTags = "${RUNNER_TAGS}"
Windows VM扩展配置
resource "azurerm_virtual_machine_extension" "windows_runner_server_ext" { count = length(var.windows_runner_vm_name) name = "Settings" virtual_machine_id = azurerm_windows_virtual_machine.windows_runner_server[count.index].id publisher = "Microsoft.Compute" type = "CustomScriptExtension" type_handler_version = "1.9" settings = <<SETTINGS { "commandToExecute": "powershell -command \"[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('${base64encode(data.template_file.windows_runner_settings.rendered)}')) | Out-File -filepath postBuild.ps1\" && powershell -ExecutionPolicy Unrestricted -File postBuild.ps1'" } SETTINGS }
问题原因
- VM扩展参数转义混乱:Windows的CustomScriptExtension和Linux的CustomScript参数结构不同,手动编写JSON时的引号嵌套、转义符处理错误,导致脚本内容解析异常
- 文件编码问题:
Out-File默认用ANSI编码保存脚本,模板渲染后的UTF8内容可能乱码,变量无法被识别 - PowerShell变量读取逻辑:模板替换后的变量在PS1中被多余的引号包裹,无法正确解析为实际值
修复方案
1. 修正VM扩展配置,解决转义和编码问题
改用jsonencode自动处理JSON转义,同时指定文件编码为UTF8:
resource "azurerm_virtual_machine_extension" "windows_runner_server_ext" { count = length(var.windows_runner_vm_name) name = "Settings" virtual_machine_id = azurerm_windows_virtual_machine.windows_runner_server[count.index].id publisher = "Microsoft.Compute" type = "CustomScriptExtension" type_handler_version = "1.9" settings = jsonencode({ commandToExecute = <<-EOT powershell -Command "$([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('${base64encode(data.template_file.windows_runner_settings.rendered)}'))) | Out-File -FilePath postBuild.ps1 -Encoding UTF8; powershell -ExecutionPolicy Unrestricted -File postBuild.ps1" EOT }) }
2. 确认模板文件的变量定义
确保Windows侧的模板定义和Linux侧一致,变量能正确渲染:
data "template_file" "windows_runner_settings" { template = file("${var.windows_runner_script_file}") vars = { REGISTRATION_TOKEN = var.gitlab_runner_reg_token, GITLAB_URL = var.gitlab_url, DEPLOY_ENV = replace(var.resource_name_prefix, "-cicd", ""), RUNNER_TAGS = join(",", var.gitlab_runner_tags) } }
3. 调整PS1脚本的变量读取方式
去掉多余的引号包裹,让模板直接替换为实际变量值:
# 模板渲染后会直接替换${RUNNER_TAGS}为实际标签内容 $RunnerTags = ${RUNNER_TAGS} # 如果变量包含特殊字符,保留引号也可以,但要确保模板替换正确 # $RunnerTags = "${RUNNER_TAGS}"
4. 备选方案:用环境变量传递变量(更稳定)
如果模板替换还是有问题,直接通过环境变量传值:
- Terraform扩展配置:
settings = jsonencode({ commandToExecute = <<-EOT setx RUNNER_TAGS "${join(",", var.gitlab_runner_tags)}" && powershell -ExecutionPolicy Unrestricted -File postBuild.ps1 EOT })
- PS1脚本读取:
$RunnerTags = $env:RUNNER_TAGS
内容的提问来源于stack exchange,提问作者user15824359
相关产品推荐
相关产品推荐

