AWS cloudformation spot instance parameters - amazon-web-services

I'm trying to add a parameter in my cloud formation stack that will allow the users to choose between on-demand and spot instances for the launch template, which will initiate the EC2 creation. This stack is designed to launch a workstation for a single user.
Currently there only seems to be one value available for the InstanceMarketType Parameter, does anyone know an alternative way of choosing the instance market type?
InstanceMarketTypeParameter:
Type: String
Default: spot
AllowedValues:
- spot
- on-demand
Description: Choose between on-demand and spot instances.
The launch template would look something like this
Ec2LaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateName: LinuxWorkstation
LaunchTemplateData:
InstanceMarketOptions:
MarketType:
Ref: InstanceMarketTypeParameter
Any ideas are welcome!

You can make InstanceMarketOptions optional using If:
Conditions:
IsOnDemand:
!Equals [!Ref InstanceMarketTypeParameter, "on-demand"]
Resources:
Ec2LaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateName: LinuxWorkstation
LaunchTemplateData:
InstanceMarketOptions:
!If
- IsOnDemand
- !Ref "AWS::NoValue"
- MarketType:
Ref: InstanceMarketTypeParameter

Related

How to add conditions in Parameters section in AWS CloudFormation?

So what I am trying to do is, I defined a Parameter called EnvType with allowed values test or production.
What should happen is when the user selects one of these environments test or production, lets say test
then he should be able to select another parameter called InstanceType in which allowed values would be all the 't' type instances in the drop-down list while creating the stack.
If the user selects production as the EnvType then the allowed values under the same parameter called InstanceType must be all instances types except 't' type for eg ('m' type).
And the same must apply for rds as well. Let's say user chooses EnvType as test then allowed values under parameter called DBInstanceType must be 'db.t' type instances otherwise 'db.r' type instances.
Parameters
Parameters:
EnvType:
Default: test
Type: String
AllowedValues:
- production
- test
InstanceType:
Type: String
AllowedValues: !FindInMap
- InstanceTypeMap
- !Ref EnvType
- instanceType
DBInstanceType:
Type: String
AllowedValues: !FindInMap
- InstanceTypeMap
- !Ref EnvType
- dbinstanceType
Mapping
InstanceTypeMap:
production:
instanceType: [m1.small, m1.medium, m1.large, m1.xlarge, m2.xlarge, m2.2xlarge, m2.4xlarge]
dbinstancetype: [db.r5.large, db.r5.xlarge]
test:
instanceType: [t1.micro, t2.nano, t2.micro, t2.small, t2.medium, t2.large]
dbinstancetype: [db.t2.small, db.t2.medium, db.t3.small]
Resources
Resources:
WebServer:
Type: 'AWS::EC2::Instance'
Properties:
InstanceType: !Ref InstanceType
DBInstance:
Type: AWS::RDS::DBInstance
Properties:
DBInstanceClass: !FindInMap
- MyEnvironmentMap
- !Ref EnvType
- dbinstanceType
Well i know the template is not valid, and is prone to errors in allowed values in InstanceType and DBInstanceType parameters but i am seeking an alternative of doing this.
Please help!!
Simply, such functionality is not possible in CloudFormation (CFN). Sadly, there is no alternative in CFN for that. You would have to develop a custom solution for deployment of such templates.

Launch ec2 using cloudformation which should use launch template

I am trying to create a ec2 instance using the launch template :
So I have created a launch template with below data.
LaunchTemplateVerybasic:
When I am trying to run a cloud formation template like below :
AWSTemplateFormatVersion: 2010-09-09
Resources:
TestTemplate:
Type: 'AWS::EC2::Instance'
Properties:
LaunchTemplate:
LaunchTemplateSpecification:
LaunchTemplateId: lt-00d9f13eea240e524
LaunchTemplateName: Testtemplate
Version: '1'
I get this error:
Encountered unsupported property LaunchTemplateSpecification, whereas
in designer it shows that instance can be created.
What is that I am missing? I checked the documentation and this is a property supported by AWS::EC2::instance..
Let me know if there is something I am missing in understanding and in yaml
Since the EC2 is not being launched from the launch template via auto-scaling group, rather its via a resource definition, you need first to remove the and have the config as follows
HostA:
Type: AWS::EC2::Instance
Properties:
LaunchTemplate:
LaunchTemplateId: !Ref HostALaunchTemplate
Version: !GetAtt HostALaunchTemplate.LatestVersionNumber
Launch Template example
When launching a launch template via auto-scaling group, usually there is no need to specify a network interface within the launch template because the auto-scaling group will take care of it.
Inside your launch template, remove the SecurityGroupIds at the LaunchTemplateData
HostALaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateName: HostALaunchTemplate
LaunchTemplateData:
SecurityGroupIds:
- !ImportValue MyASG
And add security group via network interface like so
HostALaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateName: HostALaunchTemplate
NetworkInterfaces:
- DeviceIndex: 0
Groups:
- !ImportValue MyASG
SubnetId: !ImportValue MySubnet
The CloudFormation Linter
catches this with:
E3002 Invalid Property Resources/TestTemplate/Properties/LaunchTemplate/LaunchTemplateSpecification
template.yaml:7:9
Try removing LaunchTemplateSpecification:
AWSTemplateFormatVersion: 2010-09-09
Resources:
TestTemplate:
Type: 'AWS::EC2::Instance'
Properties:
LaunchTemplate:
LaunchTemplateId: lt-00d9f13eea240e524
LaunchTemplateName: Testtemplate
Version: '1'
AWS::EC2::Instance.LaunchTemplate documentation

Can't create ScalingPolicy - No scalable target registered

I've followed the example here but when I try to update my stack I get the following error:
No scalable target registered for service namespace: ecs, resource ID:
service/xxx-prod/xxx-prod-api, scalable dimension: ecs:service:DesiredCount
(Service: AWSApplicationAutoScaling; Status Code: 400; Error Code:
ObjectNotFoundException; Request ID: 1232c749-a7a9-11e9-bd34-dfed08b14539)
All the examples and documentation Ive seen show the resource id as something like :
service/cluster-name-AB678321674/service-AB672345678
e.g.: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-applicationautoscaling-scalabletarget.html
I dont see how or where I can get the resource id in this format.
The CF looks like this:
AutoScalingTarget:
Type: AWS::ApplicationAutoScaling::ScalableTarget
Properties:
MinCapacity: !Ref MinContainers
MaxCapacity: !Ref MaxContainers
ResourceId:
Fn::Join:
- "/"
- - service
- Fn::ImportValue:
!Join [':', [!Ref AppStackName, 'ClusterName']]
- !GetAtt Service.Name
ScalableDimension: ecs:service:DesiredCount
ServiceNamespace: ecs
# "The Amazon Resource Name (ARN) of an AWS Identity and Access Management (IAM) role that allows Application Auto Scaling to modify your scalable target."
RoleARN:
Fn::ImportValue:
!Join [':', [!Ref SecurityStackName, 'AutoScaleRole']]
AutoScalingPolicy:
Type: AWS::ApplicationAutoScaling::ScalingPolicy
Properties:
PolicyName: !Join ['', [!Ref ServiceName, AutoScalingPolicy]]
PolicyType: TargetTrackingScaling
ScalingTargetId: !Ref AutoScalingTarget
TargetTrackingScalingPolicyConfiguration:
PredefinedMetricSpecification:
PredefinedMetricType: ECSServiceAverageCPUUtilization
ScaleInCooldown: 10
ScaleOutCooldown: 10
# Keep things at or lower than 50% CPU utilization, for example
TargetValue: !Ref AutoScalingTargetValue
The cluster is created in a separate stack so I have to export/import that.
Can anyone see what I've done wrong here?
TIA.
Just ran into the same error,
Not too sure what #Jonesie means by adding them together, but there's two ways to solve this:
Either add "DependsOn: AutoScalingTarget" to AutoScalingPolicy, so the scalable target gets created before the AutoScalingPolicy
Or use ScalingTargetId in stead of ServiceNamespace/ScalableDimension/ResourceId. By using ScalingTargetId and then !Ref AutoScalingTarget you're setting up the dependency between the two resources, which is the actual problem ;)
See: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-applicationautoscaling-scalingpolicy.html#cfn-applicationautoscaling-scalingpolicy-scalabledimension
Well, FFS. I removed the target and then added the target and policy together and it works fine.
Sigh

How to create EC2 instance with EBS volume in CloudFormation?

Hi I am trying to create an Amazon EC2 instance with an EBS volume. I have created a CloudFormation template:
AWSTemplateFormatVersion: "2010-09-09"
Description: "First EC2 instance"
Resources:
FirstLinuxEC2instance:
Type: AWS::EC2::Instance
Properties:
AvailabilityZone: 'ap-southeast-2a'
ImageId: 'ami-0c1d8842b9bfc767c'
InstanceInitiatedShutdownBehavior: 'terminate'
InstanceType: 't2.micro'
SecurityGroupIds:
- 'sg-79862305'
Volumes:
Device: "/dev/sdf"
VolumeId: !Ref NewVolume
NewVolume:
Type: AWS::EC2::Volume
Properties:
Size: 1
AvailabilityZone: 'ap-southeast-2a'
Tags:
- Key: MyTag
Value: TagValue
DeletionPolicy: Snapshot
When I upload this template I am getting below error.
Value of property Volumes must be of type List
Can someone help me to figure it out the issue?
Try this!
Volumes:
-
Device: "/dev/sdf"
VolumeId: !Ref NewVolume
Yes volumes is of type array. So even a single volume needs to be in a pair of square brackets (json). You can try cloudkast which is an online cloudformation template generator. It is very useful to make it outright clear which property is of what type with inline description.

Using Conditions and Parameters in CloudFormation

I am trying to create a condition based on an optional parameter. The option is whether to run some additional installation from my userData script for an EC2 deployment.
The parameters and conditions look like this:
Parameters:
EnvType:
Description: Option to install New Relic Infrastructure.
Default: apm
Type: String
AllowedValues:
- apm
- +infra
Then my EC2 Resource with conditional startup scripts
Resources:
Ec2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.micro
ImageId: ami-9c9443e3 #Amazon Linux AMI in Tokyo
KeyName: tokyocloudformation
IamInstanceProfile: 'S3EC2'
SecurityGroupIds:
- !Ref myNewSecurityGroup
UserData:
Condition: apmOnly
Fn::Base64:
|
#!/bin/bash
installstuff
Condition: addInfrastructureAgent
Fn::Base64:
|
#!/bin/bash
installstuff
installsomeotherstuff
The error message I'm getting is:
Template validation error: Template format error: Unresolved dependencies [EnvTyp]. Cannot reference resources in the Conditions block of the template
I get what the error is saying I believe, but it doesn't seem to fit with the examples given by AWS.
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html .
This AWS example clearly uses a !Ref in the Conditions block.
EnvType:
Description: Environment type.
Default: test
Type: String
AllowedValues:
- prod
- test
ConstraintDescription: must specify prod or test.
Conditions:
CreateProdResources: !Equals [ !Ref EnvType, prod ]
Can someone provide some feedback on how to implement this conditional or why this error message is being thrown for this implementation?
According to the docs, Conditions should be used at the top level of the resource you want to conditionally create.
Putting a Condition inside the Instance UserData section isn't supported.
To use Conditions in your situation, you'd want separate Resources conditionally created based on the Parameter.
Resources:
Ec2InstanceAPMOnly:
Type: AWS::EC2::Instance
Condition: apmOnly
Properties:
InstanceType: t2.micro
ImageId: ami-9c9443e3 #Amazon Linux AMI in Tokyo
KeyName: tokyocloudformation
IamInstanceProfile: 'S3EC2'
SecurityGroupIds:
- !Ref myNewSecurityGroup
UserData:
Fn::Base64:
!Sub |
#!/bin/bash
installstuff
Ec2InstanceWithInfrastructureAgent:
Type: AWS::EC2::Instance
Condition: addInfrastructureAgent
Properties:
InstanceType: t2.micro
ImageId: ami-9c9443e3 #Amazon Linux AMI in Tokyo
KeyName: tokyocloudformation
IamInstanceProfile: 'S3EC2'
SecurityGroupIds:
- !Ref myNewSecurityGroup
UserData:
Fn::Base64:
!Sub |
#!/bin/bash
installstuff
installsomeotherstuff
You can use Conditions in userData as well. i followed this post https://www.singlestoneconsulting.com/blog/cloudformation-mapping-and-conditionals-making-your-templates-more-universal/ and it worked perfactlly