Powershell 在AWS上使用Terraform安装Windows修补程序
我有一个非常简单的PowerShell脚本,它将生成的测试文件从Windows 2008 R2数据中心服务器(干净的AWS实例)上传到AWS S3存储桶。如果我使用Terraform(Powershell 在AWS上使用Terraform安装Windows修补程序,powershell,amazon-web-services,terraform,Powershell,Amazon Web Services,Terraform,我有一个非常简单的PowerShell脚本,它将生成的测试文件从Windows 2008 R2数据中心服务器(干净的AWS实例)上传到AWS S3存储桶。如果我使用Terraform(remote execprovisioner)在服务器上远程运行脚本,则脚本在S3上传时会失败,并出现StackOverflowException。当我直接在服务器上运行脚本时,它运行良好并上传文件 我已经尝试了不同大小的文件,14.5MB似乎是StackOverflowException发生之前的最大值。当我将R
remote exec
provisioner)在服务器上远程运行脚本,则脚本在S3上传时会失败,并出现StackOverflowException
。当我直接在服务器上运行脚本时,它运行良好并上传文件
我已经尝试了不同大小的文件,14.5MB似乎是StackOverflowException发生之前的最大值。当我将RDP导入服务器并直接运行脚本时,几乎任何大小都可以正常工作。我测试了200MB,效果很好
知道为什么会发生这种情况,或者我能做些什么来修复它吗?我需要上传的实际文件是50MB
下面是重现问题的关键部分<代码>地形.tf文件:
resource "aws_instance" "windows" {
count = "1"
ami = "ami-e935fc94" #base win 2008 R2 datacenter
instance_type = "t2.micro"
connection {
type = "winrm"
user = "<username>"
password = "<password>"
timeout = "30m"
}
provisioner "file" {
source = "windows/upload.ps1"
destination = "C:\\scripts\\upload.ps1"
}
provisioner "remote-exec" {
inline = [
"powershell.exe -File C:\\scripts\\upload.ps1"
]
}
}
从Terraform启动脚本时收到的错误(remote exec
provisioner):
在服务器上从RDP运行upload.ps1
可以正常工作,包括更大的文件(测试高达200MB)
以下是版本信息:
Microsoft Windows Server 2008 R2 Datacenter
Powershell Version: 3.0
AWS Tools for Windows PowerShell, Version 3.3.245.0
Amazon Web Services SDK for .NET, Core Runtime Version 3.3.21.15
这个问题是由一个错误引起的。对于标准Windows服务器来说,这一切都很好——您可以修补并继续。但是,使用Terraform的AWS自动化更为棘手 理想的解决方案是1)使用基本AMI,2)将热修复程序应用于自身,3)然后运行WinRM remote exec,所有这些都来自Terraform。另一个解决方案是创建一个安装了修补程序的AMI,并让Terraform使用该AMI生成实例。然而,你却被困在维护AMI上 通常,我使用过滤器获取Microsoft提供的基本AMI:
data "aws_ami" "windows2008" {
most_recent = true
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "name"
values = ["Windows_Server-2008-R2_SP1-English-64Bit-Base*",]
}
owners = ["801119661308", "amazon"]
}
然后我使用该AMI创建AWS实例:
resource "aws_instance" "windows" {
count = "1"
ami = "${data.aws_ami.windows2008.id}"
...
}
但是,基本AMI没有安装允许您避免此WinRM/Windows错误的。这是一个棘手的问题
您可以使用userdata脚本执行多阶段设置。在实例的第一次启动(第1阶段)中,我们将阻塞该实例,以便在准备就绪之前远程执行器不会进入。然后,我们将下载并安装修补程序,然后重新启动(感谢,和)。在第二次启动时(在描述的方法中),我们将取消阻止实例(启用WinRM),以便远程执行器可以连接
以下是我的userdata/PowerShell脚本:
$StateFile = "C:\Temp\userdata_state.txt"
If(-Not (Test-Path -Path $StateFile))
{
# PHASE 1
# Close the instance to WinRM connections until instance is ready (probably already closed, but just in case)
Start-Process -FilePath "winrm" -ArgumentList "set winrm/config/service/auth @{Basic=`"false`"}" -Wait
# Set the admin password for WinRM connections
$Admin = [adsi]("WinNT://./Administrator, user")
$Admin.psbase.invoke("SetPassword", "${tfi_rm_pass}")
# Create state file so after reboot it will know
New-Item -Path $StateFile -ItemType "file" -Force
# Make it so that userdata will run again after reboot
$EC2SettingsFile="C:\Program Files\Amazon\Ec2ConfigService\Settings\Config.xml"
$Xml = [xml](Get-Content $EC2SettingsFile)
$XmlElement = $Xml.get_DocumentElement()
$XmlElementToModify = $XmlElement.Plugins
Foreach ($Element in $XmlElementToModify.Plugin)
{
If ($Element.name -eq "Ec2HandleUserData")
{
$Element.State="Enabled"
}
}
$Xml.Save($EC2SettingsFile)
# Download and install hotfix
# Download self-extractor
$DownloadUrl = "https://hotfixv4.trafficmanager.net/Windows%207/Windows%20Server2008%20R2%20SP1/sp2/Fix467402/7600/free/463984_intl_x64_zip.exe"
$HotfixDir = "C:\hotfix"
$HotfixFile = "$HotfixDir\KB2842230.exe"
mkdir $HotfixDir
(New-Object System.Net.WebClient).DownloadFile($DownloadUrl, $HotfixFile)
# Extract self-extractor
Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::ExtractToDirectory($HotfixFile, $HotfixDir)
# Install - NOTE: wusa returns immediately, before install completes, so you must check process to see when it finishes
Get-Item "$HotfixDir\*.msu" | Foreach { wusa ""$_.FullName /quiet /norestart"" ; While (@(Get-Process wusa -ErrorAction SilentlyContinue).Count -ne 0) { Start-Sleep 3 } }
# Reboot
Restart-Computer
}
Else
{
# PHASE 2
# Open WinRM for remote-exec
Start-Process -FilePath "winrm" -ArgumentList "quickconfig -q"
Start-Process -FilePath "winrm" -ArgumentList "set winrm/config/service @{AllowUnencrypted=`"true`"}" -Wait
Start-Process -FilePath "winrm" -ArgumentList "set winrm/config/service/auth @{Basic=`"true`"}" -Wait
Start-Process -FilePath "winrm" -ArgumentList "set winrm/config @{MaxTimeoutms=`"1900000`"}"
}
您是如何利用powershell获得stackoverflow的?:)由于这个网站的原因,“stackoverflow”并不是很具体,所以谷歌搜索这个问题实际上很棘手
resource "aws_instance" "windows" {
count = "1"
ami = "${data.aws_ami.windows2008.id}"
...
}
$StateFile = "C:\Temp\userdata_state.txt"
If(-Not (Test-Path -Path $StateFile))
{
# PHASE 1
# Close the instance to WinRM connections until instance is ready (probably already closed, but just in case)
Start-Process -FilePath "winrm" -ArgumentList "set winrm/config/service/auth @{Basic=`"false`"}" -Wait
# Set the admin password for WinRM connections
$Admin = [adsi]("WinNT://./Administrator, user")
$Admin.psbase.invoke("SetPassword", "${tfi_rm_pass}")
# Create state file so after reboot it will know
New-Item -Path $StateFile -ItemType "file" -Force
# Make it so that userdata will run again after reboot
$EC2SettingsFile="C:\Program Files\Amazon\Ec2ConfigService\Settings\Config.xml"
$Xml = [xml](Get-Content $EC2SettingsFile)
$XmlElement = $Xml.get_DocumentElement()
$XmlElementToModify = $XmlElement.Plugins
Foreach ($Element in $XmlElementToModify.Plugin)
{
If ($Element.name -eq "Ec2HandleUserData")
{
$Element.State="Enabled"
}
}
$Xml.Save($EC2SettingsFile)
# Download and install hotfix
# Download self-extractor
$DownloadUrl = "https://hotfixv4.trafficmanager.net/Windows%207/Windows%20Server2008%20R2%20SP1/sp2/Fix467402/7600/free/463984_intl_x64_zip.exe"
$HotfixDir = "C:\hotfix"
$HotfixFile = "$HotfixDir\KB2842230.exe"
mkdir $HotfixDir
(New-Object System.Net.WebClient).DownloadFile($DownloadUrl, $HotfixFile)
# Extract self-extractor
Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::ExtractToDirectory($HotfixFile, $HotfixDir)
# Install - NOTE: wusa returns immediately, before install completes, so you must check process to see when it finishes
Get-Item "$HotfixDir\*.msu" | Foreach { wusa ""$_.FullName /quiet /norestart"" ; While (@(Get-Process wusa -ErrorAction SilentlyContinue).Count -ne 0) { Start-Sleep 3 } }
# Reboot
Restart-Computer
}
Else
{
# PHASE 2
# Open WinRM for remote-exec
Start-Process -FilePath "winrm" -ArgumentList "quickconfig -q"
Start-Process -FilePath "winrm" -ArgumentList "set winrm/config/service @{AllowUnencrypted=`"true`"}" -Wait
Start-Process -FilePath "winrm" -ArgumentList "set winrm/config/service/auth @{Basic=`"true`"}" -Wait
Start-Process -FilePath "winrm" -ArgumentList "set winrm/config @{MaxTimeoutms=`"1900000`"}"
}