在EC2实例上创建自定义AMI(图像)时遇到问题。如果我使用自定义引导程序/用户数据脚本启动Windows默认2012服务器实例,例如;
<powershell>
PowerShell "(New-Object System.Net.WebClient).DownloadFile('http://download.microsoft.com/download/3/2/2/3224B87F-CFA0-4E70-BDA3-3DE650EFEBA5/vcredist_x64.exe','C:\vcredist_x64.exe')"
</powershell>
它将按预期工作并转到URL并下载文件,并将其存储在C:Drive上。
但是如果我设置一个Windows服务器实例,然后从中创建一个图像,并将其存储为自定义AMI,然后使用完全相同的自定义用户数据脚本进行部署,它将无法正常工作。但是如果我转到实例url(http://169.254.169.254/latest/user-data
),它将显示脚本已成功导入但尚未执行。
检查错误日志后,我经常注意到这一点:
Failed to fetch instance metadata http://169.254.169.254/latest/user-data with exception The remote server returned an error: (404) Not Found.
答案 0 :(得分:30)
针对EC2Launch的每个AWS文档,Windows Server 2016用户可以继续使用EC2Config 2.1.10中引入的持久标记:
对于EC2Config版本2.1.10及更高版本,或者对于EC2Launch,您可以使用 在用户数据中为true以启用插件之后 用户数据执行。
用户数据示例:
<powershell>
insert script here
</powershell>
<persist>true</persist>
对于后续的靴子:
Windows Server 2016用户必须另外启用configure and enable EC2Launch而不是EC2Config。 EC2Config在Windows Server 2016 AMI上被弃用,转而支持EC2Launch。
运行以下powershell来安排将在下次启动时运行用户数据的Windows任务:
C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1 –Schedule
按照设计,此任务在首次运行后被禁用。但是,使用persist标记会导致Invoke-UserData通过Register-FunctionScheduler计划单独的任务,以便在后续引导时保留用户数据。您可以在C:\ProgramData\Amazon\EC2-Windows\Launch\Module\Scripts\Invoke-Userdata.ps1
找到此信息。
进一步排查:
如果您的用户数据脚本存在其他问题,您可以在C:\ProgramData\Amazon\EC2-Windows\Launch\Log\UserdataExecution.log
找到源自WS 2016基础AMI的实例的用户数据执行日志。
初始引导后自动禁用用户数据执行。创建映像时,可能已禁用执行。这可以在C:\Program Files\Amazon\Ec2ConfigService\Settings\Config.xml
内手动配置。
documentation for "Configuring a Windows Instance Using the EC2Config Service"提出了几个选项:
以编程方式创建计划任务,以便在系统启动时使用schtasks.exe /Create
运行,并将计划任务指向C:\Program Files\Amazon\Ec2ConfigServer\Scripts\UserScript.ps1
处的用户数据脚本(或其他脚本)。
以编程方式在Config.xml中启用用户数据插件。
示例,来自文档:
<powershell>
$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 "Ec2SetPassword")
{
$element.State="Enabled"
}
elseif ($element.name -eq "Ec2HandleUserData")
{
$element.State="Enabled"
}
}
$xml.Save($EC2SettingsFile)
</powershell>
<persist>true</persist>
在用户数据执行后启用插件。示例,来自文档:
<powershell>
insert script here
</powershell>
<persist>true</persist>
答案 1 :(得分:5)
另一个对我有用的解决方案是run Sysprep with EC2Launch。
问题是AWS不会在您的自定义AMI中重新建立到配置文件服务(169.254.169.254)的路由。请参阅SanjitPatel在此post中的回复。因此,当我尝试使用自定义AMI创建点请求时,我的新实例无法找到用户数据。
关闭Sysprep,实质上迫使AWS重新对该实例进行所有设置工作,就好像它是第一次运行一样。因此,当您创建实例时,使用Sysprep将其关闭,然后创建自定义AMI,AWS将为新实例正确设置配置文件服务路由并执行您的用户数据。这也可以避免手动更改Windows任务并在后续启动时执行用户数据,就像持久标记一样。
以下是一个快速的步骤:
希望这有帮助!
答案 2 :(得分:4)
在初始引导程序(UserData)脚本结束时,只需附加persist标记,如下所示。 效果很好。
<powershell>
insert script here
</powershell>
<persist>true</persist>
答案 3 :(得分:0)
对于那些从谷歌来到这里且正在运行Server 2016实例的人来说,似乎已经不再可能了。
Server2016没有ec2config服务,因此您无法使用persist标志。
<persist>true</persist>
在Anthony Neace的帖子中描述。
Server 2016使用EC2Launch,我还没有看到每次启动时如何运行脚本。您可以在第一次启动时运行脚本,但后续启动将不会运行它。