Windows spot instance with persistence request using cloudformation - amazon-web-services

When I try to launch windows server using this template, I get an error:
Property validation failure: [Value of property {/LaunchTemplateData} does not match type {Object}]
I used this template:
Parameters:
1InstanceType:
Type: String
Default: t2.small
AllowedValues:
- t2.small
- m3.medium
- m3.xlarge
- i3.xlarge
2SecurityGroup:
Type: 'AWS::EC2::SecurityGroup::Id'
3KeyName:
Type: 'AWS::EC2::KeyPair::KeyName'
4LatestAmiId:
Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
Default: /aws/service/ami-windows-latest/Windows_Server-2016-English-Full-Base
Resources:
Ec2LaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateName: WindowsDesktop
LaunchTemplateData:
- ImageId: !Ref 4LatestAmiId
InstanceType: !Ref 1InstanceType
SecurityGroups:
- GroupId: !Ref 2SecurityGroup
KeyName: !Ref 3KeyName
InstanceMarketOptions:
MarketType: spot
SpotOptions:
SpotInstanceType: persistent
InstanceInterruptionBehavior: stop
Similar code works for linux servers. It seems that Windows spot instance (or template) with persistence request can not be created using cloudformation.

The error means that your LaunchTemplateData is not an object, but it is a list in your case. This is because extra - before ImageId. So it should be:
Resources:
Ec2LaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateName: WindowsDesktop
LaunchTemplateData:
ImageId: !Ref 4LatestAmiId
InstanceType: !Ref 1InstanceType
SecurityGroups:
- GroupId: !Ref 2SecurityGroup
KeyName: !Ref 3KeyName
InstanceMarketOptions:
MarketType: spot
SpotOptions:
SpotInstanceType: persistent
InstanceInterruptionBehavior: stop

Related

Cannot See Running instances on EC2 Dashboard after launching EC2 Fleet Via CFN Template

I am using following CFN template to create EC2 Infra stack. The stack gets created but I cannot see EC2 Running instances. It says 0 running instances.
---
AWSTemplateFormatVersion: "2010-09-09"
Description: ""
Resources:
WebServerVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: false
EnableDnsHostnames: false
InstanceTenancy: dedicated
Tags:
- Key: stack
Value: production
WebServerSubnet:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: 10.0.1.0/24
MapPublicIpOnLaunch: true
VpcId:
Ref: WebServerVPC
WebServerInternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: stack
Value: production
WebserverIGWandVPCAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId:
Ref: WebServerInternetGateway
VpcId:
Ref: WebServerVPC
WebServerRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId:
Ref: WebServerVPC
Tags:
- Key: stack
Value: production
WebServerSubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId:
Ref: WebServerRouteTable
SubnetId:
Ref: WebServerSubnet
WebServerRoute:
Type: AWS::EC2::Route
DependsOn: WebServerInternetGateway
Properties:
RouteTableId:
Ref: WebServerRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId:
Ref: WebServerInternetGateway
WebServerEC2LaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateData:
ImageId: ami-083ac7c7ecf9bb9b0
InstanceType: t3.micro
KeyName: test_key_pair
NetworkInterfaces:
- SubnetId:
Ref: WebServerSubnet
LaunchTemplateName: WebServerEC2LaunchTemplate
WebServerEC2Fleet:
Type: AWS::EC2::EC2Fleet
DependsOn: WebServerEC2LaunchTemplate
Properties:
LaunchTemplateConfigs:
- LaunchTemplateSpecification:
LaunchTemplateName: WebServerEC2LaunchTemplate
Version: !GetAtt WebServerEC2LaunchTemplate.LatestVersionNumber
TargetCapacitySpecification:
TotalTargetCapacity: 5
OnDemandTargetCapacity: 5
SpotTargetCapacity: 0
DefaultTargetCapacityType: on-demand
Where do we see Instances launched via EC2 Fleet? Is it on EC2 Dashboard or somewhere else? In the above template I am also creating VPC and other routing objects.

Cloudformation : Associate PublicIP to EC2 instance among multiple network interfaces with EIPs

My Setup :
Three Network Interfaces
Two EIPs attached to two network interfaces
Associating both the EIP to the instance using network interface
I am using cloudformation and code snippet for this is below
vSRXEip11:
Type: 'AWS::EC2::EIP'
Properties:
Domain: vpc
Tags:
- Key: Name
Value: ManagementElasticIP
vSRXEip12:
Type: 'AWS::EC2::EIP'
Properties:
Domain: vpc
Tags:
- Key: Name
Value: RevenueDataElasticIP
AssociateEIP11:
Type: 'AWS::EC2::EIPAssociation'
Properties:
AllocationId: !GetAtt
- vSRXEip11
- AllocationId
NetworkInterfaceId: !Ref vSRXInterface11
AssociateEIP12:
Type: 'AWS::EC2::EIPAssociation'
Properties:
AllocationId: !GetAtt
- vSRXEip12
- AllocationId
NetworkInterfaceId: !Ref vSRXInterface12
VpcvSRXEC2Instance1:
Type: 'AWS::EC2::Instance'
Metadata:
Comment1: Launch Juniper VSRX1
Properties:
InstanceType: !FindInMap
- vSRXInstance
- !Ref VSRXType
- Type
KeyName: !Ref KeyName
DisableApiTermination: !If
- EnableTerm
- true
- false
ImageId: !FindInMap
- JunipervSRXAMI
- !Ref 'AWS::Region'
- byol
#https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-network-iface-embedded.html
NetworkInterfaces:
- NetworkInterfaceId: !Ref vSRXInterface11
DeviceIndex: '0'
- NetworkInterfaceId: !Ref vSRXInterface12
DeviceIndex: '1'
- NetworkInterfaceId: !Ref vSRXInterface13
DeviceIndex: '2'
Tags:
- Key: Name
Value: Juniper VSRX1
DependsOn: IGW
When I deploy above cloudformation template, I see sometimes vSRXEip11 attached as public IP and sometimes vSRXEip12.
How should I make the public IP address of EC2 instance to either vSRXEip11 or vSRXEip12 ?
I tried with associatePublicIPAddress for one of the network interface like below.
VpcvSRXEC2Instance1:
Type: 'AWS::EC2::Instance'
Metadata:
Comment1: Launch Juniper VSRX1
Properties:
InstanceType: !FindInMap
- vSRXInstance
- !Ref VSRXType
- Type
KeyName: !Ref KeyName
DisableApiTermination: !If
- EnableTerm
- true
- false
ImageId: !FindInMap
- JunipervSRXAMI
- !Ref 'AWS::Region'
- byol
#https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-network-iface-embedded.html
NetworkInterfaces:
- NetworkInterfaceId: !Ref vSRXInterface11
DeviceIndex: '0'
AssociatePublicIPAddress: true
- NetworkInterfaceId: !Ref vSRXInterface12
DeviceIndex: '1'
- NetworkInterfaceId: !Ref vSRXInterface13
DeviceIndex: '2'
But got an error saying "The associatePublicIPAddress parameter cannot be specified when launching with multiple network interfaces"

Resizing root volume size of ec2 instance with cloudformation

I have an instance created with cloudformation like below:
EC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref ServerAMI
InstanceType: !Ref ServerInstanceType
KeyName: !Ref KeyName
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
VolumeSize: 30
NetworkInterfaces:
- AssociatePublicIpAddress: 'false'
DeleteOnTermination: 'true'
DeviceIndex: '0'
GroupSet:
- Ref: ServerSecurityGroup
SubnetId: !Ref SubnetID
Tags:
- { Key: Name, Value: !Ref AWS::StackName }
My root volume in this case is created at 30GB. If I try increase this root volume size by setting the VolumeSize value then my ec2 instance is terminated and recreated.
Yet in the console I am able to increase the size of my root volume without recreation of my instance.
Is there any work around for this in order to prevent ec2 instance from being terminated when trying to increase root volume size via cloudformation?
Edit:
Here is a small test stack I'm using to test this again. Deployed once, then change VolumeSize and redeploy - it wants to replace the instance:
AWSTemplateFormatVersion: '2010-09-09'
Description: Test stack for a single ec2 instance
Parameters:
ServerAMI:
Type: String
Default: ami-096f43ef67d75e998
ServerInstanceType:
Type: String
Default: t2.small
DefaultVPCID:
Type: String
SubnetID:
Type: String
KeyName:
Type: AWS::EC2::KeyPair::KeyName
Resources:
EC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref ServerAMI
InstanceType: !Ref ServerInstanceType
KeyName: !Ref KeyName
BlockDeviceMappings:
- DeviceName: /dev/xvda #Linux
Ebs:
VolumeSize: 30
NetworkInterfaces:
- AssociatePublicIpAddress: 'false'
DeleteOnTermination: 'true'
DeviceIndex: '0'
GroupSet:
- Ref: ServerSecurityGroup
SubnetId: !Ref SubnetID
Tags:
- { Key: Name, Value: !Ref AWS::StackName }
ServerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Webserver security group
VpcId: !Ref DefaultVPCID
SecurityGroupIngress:
- { IpProtocol: tcp, FromPort: '22', ToPort: '22', CidrIp: '127.0.0.1/32', Description: 'Test Instance' }
Unfortunately, I don't believe you can - per the CloudFormation documentation:
After the instance is running, you can modify only the DeleteOnTermination parameter for the attached volumes without interrupting the instance. Modifying any other parameter results in instance replacement.

How do I solve "Incompatible launch template: The network interface's device index must be zero" when updating a CloudFormation template?

I have an existing stack that created an auto-scale group that uses a Launch Configuration. I am now trying to switch this stack so the auto-scale group will use a Launch Template instead of Launch Configuration, but the update is giving this error:
Incompatible launch template: The network interface's device index
must be zero. (Service: AmazonAutoScaling; Status Code: 400; Error
Code: InvalidQueryParameter; Request ID:
97bdf4cf-5c90-4035-v234-806367461438; Proxy: null)'
The launch configuration defined in the current CloudFormation template sets AssociatePublicIpAddress: true and the instance created by this template has a public IP. The launch template in the CloudFormation template I am trying to use for the update specifies AssociatePublicIpAddress: true under NetworkNetworkInterfaces.
What does this error mean and how do I fix it?
Relevant parts of template:
LaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateName: my-launch-template
LaunchTemplateData:
EbsOptimized: false
IamInstanceProfile:
Arn: !GetAtt MyInstanceProfile.Arn
ImageId: !FindInMap [RegionMap, !Ref "AWS::Region", AMI]
InstanceType: !Ref InstanceType
KeyName: !Ref KeyName
NetworkInterfaces:
- AssociatePublicIpAddress: true
If you want to explicitly set NetworkInterfaces, the it should be:
LaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateName: my-launch-template
LaunchTemplateData:
EbsOptimized: false
IamInstanceProfile:
Arn: !GetAtt MyInstanceProfile.Arn
ImageId: !FindInMap [RegionMap, !Ref "AWS::Region", AMI]
InstanceType: !Ref InstanceType
KeyName: !Ref KeyName
NetworkInterfaces:
- DeviceIndex: 0
AssociatePublicIpAddress: true
Groups: [<security-group-id>]

CodeDeploy does not deploy to new ASG group because of CloudFormation resources creation order

I am trying to develop an entire AWS architecture by usin CloudFormation only, however I am having some issues with the integration of CodeDeploy with CloudFormation and AutoScaling Group.
The problem is that, since I need to associate the CodeDeploy DeploymentGroup to an AutoScaling Group in order for the auto-deployment to work, CloudFormation recognizes the group as being required before creating the deployment group.
What happens is that the ASG gets created, instances start to spin up BEFORE the deployment group has been created, which means that these instances will never get deployed. I tried to think of a Lambda function to forcefully deploy these instances, however the problems persists because the CodeDeploy Deployment Group will still not be available yet most likely, or if it was, it's not reliable.
This problem only occurs when the stack is created for the first time.
This is my CloudFormation template:
[...]
UpdateApiAutoscalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
AutoScalingGroupName:
Fn::Join:
- ''
- - !ImportValue UpdateApiCodeDeployApplication
- -autoscaling-group
- !Ref Environment
DesiredCapacity: !Ref MinimumApiAmount
HealthCheckGracePeriod: 30
HealthCheckType: ELB
LaunchConfigurationName: !Ref UpdateApiAutoscalingLaunchConfiguration
TargetGroupARNs:
- !Ref UpdateApiTargetGroup
MaxSize: !Ref MaximumApiAmount
MinSize: !Ref MinimumApiAmount
VPCZoneIdentifier:
- Fn::Select:
- 0
- !Split
- ","
- Fn::ImportValue:
!Sub "PrivateSubnets-${Environment}"
Tags:
- Key: Environment
Value: !Ref Environment
PropagateAtLaunch: true
- Key: CompanySshAccess
Value: 1
PropagateAtLaunch: true
- Key: Application
Value: update-api
PropagateAtLaunch: true
# Defines how the Update API servers should be provisioned in the scaling group.
UpdateApiAutoscalingLaunchConfiguration:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
AssociatePublicIpAddress: false
IamInstanceProfile: !Ref UpdateApiInstanceRole
ImageId: !FindInMap [Api, Image, !Ref Environment]
InstanceType: !FindInMap [Api, InstanceType, !Ref Environment]
LaunchConfigurationName: !Sub 'update-api-launchconfig-${Environment}'
SecurityGroups:
- Fn::ImportValue: !Sub 'InternalBastionSecurityGroupId-${Environment}'
- !GetAtt LoadBalancerProtectedSecurityGroup.GroupId
UpdateApiCodeDeploymentGroup:
Type: AWS::CodeDeploy::DeploymentGroup
Properties:
DeploymentGroupName: !Ref Environment
DeploymentConfigName: "atleast-one-instance-online"
ServiceRoleArn: !Ref CodeDeployServiceRoleArn # TODO: create CodeDeployServiceRole using CloudFormation
ApplicationName: !ImportValue UpdateApiCodeDeployApplication
LoadBalancerInfo:
ElbInfoList:
- Name: !GetAtt UpdateApiLoadBalancer.LoadBalancerName
DeploymentStyle:
DeploymentOption: !FindInMap [Api, DeploymentStyleOption, !Ref Environment]
DeploymentType: !FindInMap [Api, DeploymentStyleType, !Ref Environment]
AutoScalingGroups:
- !Ref UpdateApiAutoscalingGroup
[...]