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

时间:2014-10-02 09:54:03

标签: amazon-web-services amazon-ec2

在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.

4 个答案:

答案 0 :(得分:30)

Update 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>

对于后续的靴子:

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的实例的用户数据执行日志。


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

初始引导后自动禁用用户数据执行。创建映像时,可能已禁用执行。这可以在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处的用户数据脚本(或其他脚本)。

    < / LI>
  • 以编程方式在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>
  • 从EC2Config版本2.1.10开始,您可以使用<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任务并在后续启动时执行用户数据,就像持久标记一样。

以下是一个快速的步骤:

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

答案 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,我还没有看到每次启动时如何运行脚本。您可以在第一次启动时运行脚本,但后续启动将不会运行它。