Azure中Packer多PowerShell配置器重复映射共享的优化方法咨询
问题描述
我的Packer模板里有多个PowerShell配置器,这些配置器都依赖Azure Files网络共享里的脚本。目前我是通过以下PowerShell代码把共享映射到VM的:
"$securePass = ConvertTo-SecureString \"${var.storage_account_key}\" -AsPlainText -Force", "$creds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList \"${var.storage_account_name}\",$securePass", "New-PSDrive -Credential $creds -Name F -PSProvider FileSystem -Root \"${var.storage_path}\" | Out-Null",
因为多个PowerShell配置器之间需要用windows-restart配置器重启VM,每次重启后都得重复跑一遍上面的映射步骤,既冗余又麻烦。我知道可以把所有脚本复制到VM本地执行来简化模板,但就是好奇有没有别的办法能替代重复输入这三行代码?比如在Packer模板里整个函数,或者从Azure DevOps流水线传个代码片段插进模板里?
可行的替代方案
1. 用Packer变量定义复用代码片段
在Packer的变量块里把映射驱动器的代码定义成一个变量,之后每个需要映射的PowerShell配置器直接引用这个变量就行,不用重复写代码。
示例模板代码:
variable "map_azure_files_drive" { type = string default = <<EOF $securePass = ConvertTo-SecureString "${var.storage_account_key}" -AsPlainText -Force $creds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "${var.storage_account_name}",$securePass New-PSDrive -Credential $creds -Name F -PSProvider FileSystem -Root "${var.storage_path}" | Out-Null EOF } # 第一次映射并执行业务脚本 provisioner "powershell" { inline = [ "${var.map_azure_files_drive}", "F:\\scripts\\your-script.ps1" ] } provisioner "windows-restart" {} # 重启后再次映射并执行后续脚本 provisioner "powershell" { inline = [ "${var.map_azure_files_drive}", "F:\\scripts\\another-script.ps1" ] }
2. 把映射逻辑封装成本地PS脚本
写一个本地的PowerShell脚本(比如命名为Map-AzureFilesDrive.ps1),把映射驱动器的逻辑都塞进去,先用Packer的file配置器把这个脚本传到VM上,之后每次需要映射的时候直接调用这个脚本就行。
本地脚本内容:
param( [string]$StorageAccountName, [string]$StorageAccountKey, [string]$StoragePath ) $securePass = ConvertTo-SecureString $StorageAccountKey -AsPlainText -Force $creds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $StorageAccountName,$securePass New-PSDrive -Credential $creds -Name F -PSProvider FileSystem -Root $StoragePath | Out-Null
Packer模板里的配置:
# 先把脚本上传到VM临时目录 provisioner "file" { source = "./Map-AzureFilesDrive.ps1" destination = "C:\\temp\\Map-AzureFilesDrive.ps1" } # 第一次调用脚本映射并执行业务逻辑 provisioner "powershell" { inline = [ "C:\\temp\\Map-AzureFilesDrive.ps1 -StorageAccountName '${var.storage_account_name}' -StorageAccountKey '${var.storage_account_key}' -StoragePath '${var.storage_path}'", "F:\\scripts\\your-script.ps1" ] } provisioner "windows-restart" {} # 重启后再次调用脚本映射 provisioner "powershell" { inline = [ "C:\\temp\\Map-AzureFilesDrive.ps1 -StorageAccountName '${var.storage_account_name}' -StorageAccountKey '${var.storage_account_key}' -StoragePath '${var.storage_path}'", "F:\\scripts\\another-script.ps1" ] }
3. 从Azure DevOps流水线传递代码片段
如果是用Azure DevOps流水线跑Packer,可以在流水线里定义一个变量存映射驱动器的代码片段,然后通过参数传递给Packer模板。
比如在Azure DevOps流水线的变量里加一个MapDriveScript,值填映射逻辑的PowerShell代码:
$securePass = ConvertTo-SecureString "$(storage_account_key)" -AsPlainText -Force $creds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "$(storage_account_name)",$securePass New-PSDrive -Credential $creds -Name F -PSProvider FileSystem -Root "$(storage_path)" | Out-Null
然后在流水线的Packer任务里,用-var参数把这个变量传给模板:
packer build -var "map_drive_script=$(MapDriveScript)" your-template.pkr.hcl
最后在Packer模板里定义对应的变量并引用:
variable "map_drive_script" { type = string } provisioner "powershell" { inline = [ "${var.map_drive_script}", "F:\\scripts\\your-script.ps1" ] }
内容的提问来源于stack exchange,提问作者theillien
相关产品推荐
相关产品推荐

