Amazon EC2自定义AMI未运行bootstrap(用户数据)

Joe*_*ton 19 amazon-ec2 amazon-web-services

在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>
Run Code Online (Sandbox Code Playgroud)

它将按预期工作并转到URL并下载文件,并将其存储在C:Drive上.

但是,如果我设置了一个Windows Server实例,然后从中创建一个映像,并将其存储为自定义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.
Run Code Online (Sandbox Code Playgroud)

Ant*_*ace 36

更新4/15/2017:适用于EC2Launch和Windows Server 2016 AMI

对于EC2Launch的每个AWS文档,Windows Server 2016用户可以继续使用EC2Config 2.1.10中引入的持久标记:

对于EC2Config版本2.1.10及更高版本或EC2Launch,您可以在用户数据中使用true以在用户数据执行后启用插件.

用户数据示例:

<powershell>
    insert script here 
</powershell> 
<persist>true</persist>
Run Code Online (Sandbox Code Playgroud)

对于后续靴子:

Windows Server 2016用户还必须启用配置并启用EC2Launch而不是EC2Config.EC2Config在Windows Server 2016 AMI上被弃用,转而支持EC2Launch.

运行以下powershell以安排将在下次启动时运行用户数据的Windows任务:

C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1 –Schedule
Run Code Online (Sandbox Code Playgroud)

按照设计,此任务在首次运行后将被禁用.但是,使用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的实例的用户数据执行日志.


原始答案:适用于EC2Config和旧版Windows Server

初始引导后,用户数据执行将自动禁用.创建映像时,可能已禁用执行.这可以手动配置C:\Program Files\Amazon\Ec2ConfigService\Settings\Config.xml.

"使用EC2Config服务配置Windows实例"文档提供了几个选项:

  • 以编程方式创建计划任务以在系统启动时运行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>
Run Code Online (Sandbox Code Playgroud)
  • 从EC2Config版本2.1.10开始,您可以使用<persist>true</persist>在用户数据执行后启用插件.

例子,来自文档:

<powershell>
    insert script here
</powershell>
<persist>true</persist>
Run Code Online (Sandbox Code Playgroud)

  • @JeremyThompson啊:)不,不,那不是那么说的.请允许我澄清一下:我提到了EC2Config的版本,以表明EC2Launch继续支持相同的功能 - 通过用户数据脚本支持以前的持久标签解决方案.你是正确的,WS 2016需要使用EC2Launch - 并且答案并不反对该断言 - EC2Config 2.1.10仅被提及用于绘制此功能最初来自的上下文,同样的解决方案也适用于EC2Launch ,为什么呢.希望有所帮助. (2认同)

小智 6

另一个对我有用的解决方案是使用EC2Launch运行Sysprep.

问题是AWS不会在您的自定义AMI中重新建立到配置文件服务(169.254.169.254)的路由.请参阅本由SanjitPatel响应.因此,当我尝试使用自定义AMI创建点请求时,我的新实例无法找到用户数据.

关闭Sysprep,实质上是强制AWS重新对该实例进行所有设置工作,就好像它是第一次运行一样.因此,当您创建实例时,使用Sysprep将其关闭,然后创建自定义AMI,AWS将为新实例正确设置配置文件服务路由并执行您的用户数据.这也可以避免手动更改Windows任务并在后续启动时执行用户数据,就像持久标记一样.

这是一个快速的步骤:

  1. 使用其中一个AWS Windows AMI(Windows Server 2016 Nano Server不支持Sysprep)创建实例并传递所需的用户数据(这可能是可选的,但可以确保AWS网络正确设置脚本以处理用户数据).
  2. 根据需要自定义您的实例.
  3. 使用Sysprep关闭您的实例.只需打开EC2LaunchSettings应用程序,然后单击"使用Sysprep关闭".这里有完整说明.
  4. 从刚刚关闭的实例创建自定义AMI.
  5. 使用自定义AMI创建其他实例,在实例创建时传递用户数据.用户数据将在实例启动时执行.在我的例子中,我使用了Spot Request屏幕,它有一个User Data文本框.

希望这可以帮助!