Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Amazon EC2 custom AMI not running bootstrap (user-data)

Tags:

I have encountered an issue when creating custom AMIs (images) on EC2 instances. If I start up a Windows default 2012 server instance with a custom bootstrap/user-data script such as;

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

It will work as intended and go to the URL and download the file, and store it on the C: Drive.

But if I setup a Windows Server Instance, then create a image from it, and store it as a Custom AMI, then deploy it with the exact same custom user-data script it will not work. But if I go to the instance url (http://169.254.169.254/latest/user-data) it will show the script has imported successfully but has not been executed.

After checking the error logs I have noticed this on a regular occasion:

Failed to fetch instance metadata http://169.254.169.254/latest/user-data with exception The remote server returned an error: (404) Not Found. 
like image 238
Joe Chatterton Avatar asked Oct 02 '14 09:10

Joe Chatterton


People also ask

Does user data run as root?

Scripts entered as user data are run as the root user, so do not use the sudo command in the script. Remember that any files you create will be owned by root ; if you need non-root users to have file access, you should modify the permissions accordingly in the script.

What will happen if you modify user data of an already running EC2 instance?

The new user data is visible on your instance after you restart it; however, user data scripts are not executed.

Can we change user data in EC2 instance?

Choose Actions, choose Instance Settings, and then choose Edit User Data. 6. Copy your user script into the Edit user data box, and then choose Save.


2 Answers

Update 4/15/2017: For EC2Launch and Windows Server 2016 AMIs

Per AWS documentation for EC2Launch, Windows Server 2016 users can continue using the persist tags introduced in EC2Config 2.1.10:

For EC2Config version 2.1.10 and later, or for EC2Launch, you can use true in the user data to enable the plug-in after user data execution.

User data example:

<powershell>     insert script here  </powershell>  <persist>true</persist> 

For subsequent boots:

Windows Server 2016 users must additionally enable configure and enable EC2Launch instead of EC2Config. EC2Config was deprecated on Windows Server 2016 AMIs in favor of EC2Launch.

Run the following powershell to schedule a Windows Task that will run the user data on next boot:

C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1 –Schedule 

By design, this task is disabled after it is run for the first time. However, using the persist tag causes Invoke-UserData to schedule a separate task via Register-FunctionScheduler, to persist your user data on subsequent boots. You can see this for yourself at C:\ProgramData\Amazon\EC2-Windows\Launch\Module\Scripts\Invoke-Userdata.ps1.

Further troubleshooting:

If you're having additional issues with your user data scripts, you can find the user data execution logs at C:\ProgramData\Amazon\EC2-Windows\Launch\Log\UserdataExecution.log for instances sourced from the WS 2016 base AMI.


Original Answer: For EC2Config and older versions of Windows Server

User data execution is automatically disabled after the initial boot. When you created your image, it is probable that execution had already been disabled. This is configurable manually within C:\Program Files\Amazon\Ec2ConfigService\Settings\Config.xml.

The documentation for "Configuring a Windows Instance Using the EC2Config Service" suggests several options:

  • Programmatically create a scheduled task to run at system start using schtasks.exe /Create, and point the scheduled task to the user data script (or another script) at C:\Program Files\Amazon\Ec2ConfigServer\Scripts\UserScript.ps1.

  • Programmatically enable the user data plug-in in Config.xml.

Example, from the documentation:

<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> 
  • Starting with EC2Config version 2.1.10, you can use <persist>true</persist> to enable the plug-in after user data execution.

Example, from the documentation:

<powershell>     insert script here </powershell> <persist>true</persist> 
like image 159
Anthony Neace Avatar answered Oct 03 '22 21:10

Anthony Neace


Another solution that worked for me is to run Sysprep with EC2Launch.

The issue is that AWS doesn't reestablish the route to the profile service (169.254.169.254) in your custom AMI. See response by SanjitPatel in this post. So when I tried to use my custom AMI to create spot requests, my new instances were failing to find user data.

Shutting down with Sysprep, essentially forces AWS re-do all setup work on the instance, as if it were run for the first time. So when you create your instance, shut it down with Sysprep and then create your custom AMI, AWS will setup the profile service route correctly for the new instances and execute your user data. This also avoids manually changing Windows Tasks and executing user data on subsequent boots, as persist tag does.

Here is a quick step-by-step:

  1. Create an instance using one of the AWS Windows AMIs (Windows Server 2016 Nano Server doesn't support Sysprep) and passing your desired user data (this may be optional, but good to make sure AWS wires setup scripts correctly to handle user data).
  2. Customize your instance as needed.
  3. Shut down your instance with Sysprep. Just open EC2LaunchSettings application and click "Shutdown with Sysprep". Full instructions here.
  4. Create your custom AMI from the instance you just shut down.
  5. Use your custom AMI to create other instances, passing user data on instance creation. User data will be executed on instance launch. In my case, I used Spot Request screen, which had a User Data text box.

Hope this helps!

like image 39
Yuri Danilchenko Avatar answered Oct 03 '22 20:10

Yuri Danilchenko