Using Elastic Beanstalk is the easiest and fastest way to deploy an application on Amazon Web Services (AWS). It takes care of everything from spinning up EC2 instances, to setting up monitoring. All you need to do is pass it your application and a few details. By making things simple, there are a lot of (sensible) defaults under the hood that you may wish to change as you become more comfortable with AWS.
A key customisation is the operating system image used to host the application – the Amazon Machine Image (AMI). By default, Amazon provides an up-to-date operating system with the applications (such as a web server) and scripts needed to get started. Since it is fairly basic, customising the AMI can be useful for a number of reasons:
- Pre-installing any required software, such as application dependencies or monitoring agents
- Installing new patches or making significant OS changes that aren’t available with the default image
- Dealing with Beanstalk quirks, like all instances having the same hostname (problematic when connecting your Windows instance to a Directory Service)
A custom AMI is faster to spin up and more convenient to manage. The downside is that now you have to ensure the custom AMI is kept up to date with patches and the like, since Amazon is no longer looking after it for you.
Creating a Custom AMI
There are a few options to build a custom AMI. The easiest is to spin up a standard Amazon Elastic Beanstalk AMI, customise it, and then create the custom AMI from that. The process of finding the current Beanstalk AMI for your platform is a little round-about – Amazon suggests spinning up a Beanstalk, then checking the AMI used in the Beanstalk configuration page in the console. If you are familiar with the AWS CLI, one user has found a way to use that to find the latest AMI ID.
If you are using Linux, you can use any community AMI (Amazon Linux is recommended) and Elastic Beanstalk will attempt to install the required scripts automatically. Since installing the scripts adds to the start-up time, it is more efficient to get the current AMI and creating a custom AMI from that as described above.
Using a Custom AMI in Elastic Beanstalk
Once you have built a custom AMI, it can be used in an Elastic Beanstalk deployment. How the custom AMI is configured depends on your preferred Elastic Beanstalk launch method.
Console
When using the AWS Console to launch an Elastic Beanstalk, a custom AMI can only be set after the application has been deployed. Once the environment is running, select it in the Console and navigate to Configuration > Instances and then edit the Custom AMI ID. The application will then be redeployed on the defined AMI.
AWS API / SDK
When using an AWS SDK (or the API directly), the AMI ID can be passed in via the OptionSettings parameter while creating the environment. To do this, use the Namespace aws:autoscaling:launchconfiguration with the OptionName ImageId. The Value is the AMI ID.
A simple example using the JavaScript SDK looks like this:
var params = { ApplicationName: "my-app", CNAMEPrefix: "my-app", EnvironmentName: "my-env", SolutionStackName: "64bit Windows Server 2016 v1.2.0 running IIS 10.0", VersionLabel: "v1", OptionSettings: [ { Namespace: 'aws:autoscaling:launchconfiguration', OptionName: 'ImageId', Value: 'ami-xxxxxxx' }, ], }; elasticbeanstalk.createEnvironment(params, function(err, data) { if (err) console.log(err, err.stack); // an error occurred else console.log(data); // successful response });
The same OptionSettings are used to pass through a wealth of other options when spinning up an Elastic Beanstalk environment, including settings such as the EC2 instance type, security groups, VPC and environment variables. The full list can be perused in the General Options documentation.
Given the AWS API is at the heart of all interactions with AWS, the syntax is similar for the following methods.
AWS CLI
If you using the AWS Command Line Interface, there is the entertainingly verbose –option-settings option to pass the AMI ID. The parameters passed to it (Namespace, OptionName and Value) are the same as when using the API:
aws elasticbeanstalk create-environment --region us-west-2 --application-name my-app --environment-name my-env --version-label v1 --solution-stack-name "64bit Windows Server 2016 v1.2.0 running IIS 10.0" --option-settings Namespace=aws:autoscaling:launchconfiguration,OptionName=ImageId,Value="ami-xxxxxxx"
The –option-settings option also accepts a JSON file, which can simplify the command if you don’t need to make changes to the options often. The format for the JSON file is the same as the API as well:
[ { "Namespace": "aws:autoscaling:launchconfiguration", "OptionName": "ImageId", "Value": "ami-xxxxxxx" } ]
Which can then be passed through like so:
aws elasticbeanstalk create-environment --region us-west-2 --application-name my-app --environment-name my-env --version-label v1 --solution-stack-name "64bit Windows Server 2016 v1.2.0 running IIS 10.0" --option-settings file://options.json
ebextensions
When packaging your application for deployment, you can include config files in an .ebextensions directory to perform additional setup of the instance when deploying. Using the Option Settings, which are used to modify the Elastic Beanstalk environment prior to launch, the AMI can be set:
option_settings: - namespace: aws:autoscaling:launchconfiguration option_name: ImageId value: ami-xxxxxxx
This method does mean the Image ID is saved as part of your application, which might be regarded as a pro or a con, depending on how you manage your application/deployments.
Conclusion
Using a custom AMI is a great way of taking advantage of the Elastic Beanstalk deployment tools, while creating the exact environment needed for your application. As usual, AWS provides a plethora of ways of doing so which are covered in this post. Just remember, while using a custom AMI, keeping it up to date is your responsibility. Happy Beanstalking!
Hello John I am trying to integrate eway sdk on swift I couldn’t find any solution except the one you shared i tried to implement it but i am stuck when i am trying to set the end ki and public api key
RapidAPI.sharedManager().setRapidEndpoint(Endpoint as NSString)
RapidAPI.sharedManager().setPublicAPIKey(PublicAPIKey as NSString)
i am getting the error message Value of type ‘Any?’ has no member ‘setRapidEndpoint’ If you can please help me i would be really great ful since you are my only hope Thank you
But then do I go back to using a non-custom ami for an existing beanstalk?
should have been: _how_ do I go back
Hi,
I am trying to deploy custom AMI in beanstalk but i am getting an error. As a run time i want php and by default it creates centos server but i want to use Ubuntu. so, after deployment when i replace default AMI to custom AMI i get time out error which says instance is unable to connect to beanstalk.
option_settings:
– namespace: aws:autoscaling:launchconfiguration
option_name: ImageId
value: ami-xxxxxxx
How this config is working? when there is a precedence of elasticbeanstalk as explained here https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options.html#configuration-options-precedence>
I tried this config, it is not working for me. if I am missing anything please let me know.