In AWS CloudFormation is it possible to create a number of EC2 instances with the values from Mappings without AutoScaling group?
Solution 1
No it is not possible, there is no iteration you can specify in a template. You can, however, create an instance resource for each instance type. It's a matter of copy and paste. To make it easy to tell CloudFormation which instances to run on stack creation, you can specify functions and conditions in a template. For example, you could create a parameter or parameters that indicate which instance types to start, and use conditions to start only the ones you specify.
Solution 2
It sounds like you want to loop through each instance type, creating one of each. This is not possible in a CloudFormation template.
You could programmatically generate a template. The troposphere
Python library provides a nice abstraction to generate templates. For example:
import json
from troposphere import Template, ec2
types = [
"t1.micro",
"m1.small",
"m1.medium",
"m1.large",
"m1.xlarge",
"m3.xlarge",
"m3.2xlarge",
"m2.xlarge",
"m2.2xlarge",
"m2.4xlarge",
"c1.medium",
"c1.xlarge",
"cc1.4xlarge",
"cc2.8xlarge",
"cg1.4xlarge",
"hi1.4xlarge",
"hs1.8xlarge"]
ami = "ami-12345678"
t = Template()
for type in types:
t.add_resource(ec2.Instance(
type.replace('.', ''), #resource names must be alphanumeric
ImageId=ami,
InstanceType=type,
))
print t.to_json()
Solution 3
We also encountered same challenger after working with a few cloudformation templates for client. Essentially, we'd like to loop over a list instances type to generate spotfleet launch configuration, but we don't want to manually duplicate those code in our template.
We have tried troposphere as @Ben Whaley mentioned, but it wasn't too suitable to our scenario as we need to rewrite existing cloudformation template with python.
After some investigation, we decided to use EJS template with ejs-cli to generate programmatic cloudformation template, which allows us interpolate variables and include different fragment into target CFT.
-
Fragment management
Resources: <% include ./partials/resources.yml %> ...
-
Variable interpolation
apiTaskDefinition: Type: AWS::ECS::TaskDefinition DependsOn: ECSTaskRole Properties: ContainerDefinitions: - Name: api Essential: true Image: <%= container_path %>/api Memory: <%= container.api.memory %>
-
Loop over list
Properties: SpotFleetRequestConfigData: IamFleetRole: !GetAtt iamFleetRole.Arn SpotPrice: !Ref 'ECSSpotPrice' TargetCapacity: !Ref 'DesiredCapacity' TerminateInstancesWithExpiration: false AllocationStrategy: lowestPrice LaunchSpecifications: <% for(var i in instancesTypes) {%> <% include ./partials/instance-launch-specification.yml %> <% } %>
You can find demo source code here and our blog post.
user1249170
Updated on June 26, 2022Comments
-
user1249170 almost 2 years
Let's say I want to create EC2 instances one per each InstanceType and otherwise they are the same.
So I would create a Mapping like this:
"Mappings" : { "MyAWSInstanceTypes" : [ "t1.micro", "m1.small", "m1.medium", "m1.large", "m1.xlarge", "m3.xlarge", "m3.2xlarge", "m2.xlarge", "m2.2xlarge", "m2.4xlarge", "c1.medium", "c1.xlarge", "cc1.4xlarge", "cc2.8xlarge", "cg1.4xlarge", "hi1.4xlarge", "hs1.8xlarge" ],
and later on I would like to have
"Resources" : { "MyEc2Instances" : { "Type" : "AWS::EC2::Instance",
where I would magically get all my instance types created as per mapping.
Is that possible without AutoScaling?
-
user1249170 about 10 yearsThanks for the tip. Functions and conditions are definitely good features which I wasn't aware of, but unfortunately wouldn't eliminate copy-pasting in my case.
-
Gert van den Berg over 4 yearsdocs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/… is the link you should have included ;)
-
Miguel Conde over 4 yearsRight now is possible using macros with lambda functions