Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid fleet option while generating spot instances?

I am using this cloudformation template to create spot instances and it is working as expected.

https://github.com/shantanuo/cloudformation/blob/master/updated/linux_training.tpl.txt

The only change I would like is to remove "Fleet" part from the type here...

Type: 'AWS::EC2::SpotFleet

The reason: When I try to stop an instance, I get a message that says "Fleet instances can not be stopped".

How do I buy spot instances using "normal" or default option?

The (AWS User interface) wizard allows me to generate spot instances those can be stopped and started as and when required. Looking for the same functionality from cloudformation template.


As suggested in the comments, I have modified the template to look like this. It works as expected. But it will create only a "template". I will still need to login to console to initiate a new instance using the template. I need to automate end-to-end process.

Parameters:
  LatestAmiId:
    Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
    Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-minimal-hvm-arm64-ebs
  OksoftSG:
    Type: 'AWS::EC2::SecurityGroup::Id'
  KeyName:
    Type: 'AWS::EC2::KeyPair::KeyName'
  MyInstanceType:
    Type: String
    Default: r6g.medium
    AllowedValues:
      - r6g.medium
      - r6g.4xlarge
      - r6g.12xlarge
  MyIpAddress:
    Type: String
 
Resources:
  MySpotInstance:
    Type: 'AWS::EC2::LaunchTemplate'
    Properties:
      LaunchTemplateData:
        ImageId: !Ref LatestAmiId
        KeyName: !Ref KeyName
        SecurityGroupIds: 
          - !Ref OksoftSG
        InstanceType: !Ref MyInstanceType

        BlockDeviceMappings:
          - DeviceName: /dev/xvda
            Ebs:
              DeleteOnTermination: true
              VolumeType: standard
              VolumeSize: 400

        InstanceMarketOptions: 
          MarketType: spot
          SpotOptions:
            InstanceInterruptionBehavior: stop
            SpotInstanceType: persistent

  MyInstance:
    Type: 'AWS::EC2::Instance'
    Properties:
      "LaunchTemplate" : 
        LaunchTemplateId: !Ref MySpotInstance
        Version: !GetAtt MySpotInstance.LatestVersionNumber

When I delete the cloudformation template, it does not remove the spot request that it has created.


update:

The code mentioned in the answer works only for linux server. When I try to launch windows server, 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

like image 731
shantanuo Avatar asked Dec 15 '25 04:12

shantanuo


2 Answers

Here is working example of creating LaunchTemplate with persistent spot request which creates an instance based on the template. The instances running on persistent spot request can be stopped, but not terminated (a replacement will be launch as soon as there is a spot place):

Parameters:
  LatestAmiId:
    Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
    Default: /aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-ebs
  OksoftSG:
    Type: 'AWS::EC2::SecurityGroup::Id'
  KeyName:
    Type: 'AWS::EC2::KeyPair::KeyName'
  MyInstanceType:
    Type: String
    Default: m3.medium
    AllowedValues:
      - t2.small
      - m3.medium
      - m3.xlarge
      - m3.2xlarge
      - i3.xlarge
  MyIpAddress:
    Type: String    
 
Resources:

  SpotPersistantLaunchTemplate:
    Type: AWS::EC2::LaunchTemplate
    Properties:  
      LaunchTemplateData:
        InstanceType: !Ref MyInstanceType
        ImageId: !Ref LatestAmiId
        SecurityGroupIds:
          - !Ref OksoftSG
        KeyName: !Ref KeyName
        InstanceMarketOptions: 
          MarketType: spot
          SpotOptions:           
            InstanceInterruptionBehavior: stop
            SpotInstanceType: persistent
        BlockDeviceMappings:
          - DeviceName: /dev/xvda
            Ebs:
              DeleteOnTermination: true
              VolumeType: standard
              VolumeSize: 400                  
        UserData: !Base64 
          'Fn::Join':
            - ''
            - - |
                #!/bin/bash -xe
              - >
                yum install -y docker mysql git python-pip >
                /tmp/line1_succ.txt 2> /tmp/line1_err.txt
              - >
                service docker start > /tmp/line2_succ.txt 2>
                /tmp/line2_err.txt 
              - >
                echo 'india' | passwd ec2-user --stdin >
                /tmp/line4a_succ.txt 2> /tmp/line4a_err.txt 
              - >
                sed -i 's|[#]*PasswordAuthentication
                no|PasswordAuthentication yes|g' /etc/ssh/sshd_config >
                /tmp/line4b_succ.txt 2> /tmp/line4b_err.txt 
              - >
                /etc/init.d/sshd restart > /tmp/line4c_succ.txt 2>
                /tmp/line4c_err.txt 
              - >
                docker run -d -p 8887:8888 -v /tmp:/tmp shantanuo/notebook >
                /tmp/line3_succ.txt 2> /tmp/line3_err.txt 
              - >-
                pip install aws-ec2-assign-elastic-ip > /tmp/line4_succ.txt
                2> /tmp/line4_err.txt 
                 
              - 'sudo sh -c "echo '
              - !ImportValue secretKey
              - |2
                 >> /home/ec2-user/mysecret.txt" 
              - 'sudo sh -c "echo '
              - !ImportValue accessKey
              - |2
                 >> /home/ec2-user/myaccesskey.txt" 
              - >-
                /usr/local/bin/aws-ec2-assign-elastic-ip --access-key ''`cat
                /home/ec2-user/myaccesskey.txt`''  --secret-key ''`cat
                /home/ec2-user/mysecret.txt`'' --valid-ips '
              - !Ref MyIpAddress
              - |
                '                

  MyPersistantSpotInstance:
    Type: AWS::EC2::Instance    
    Properties:
      LaunchTemplate:
        LaunchTemplateId: !Ref SpotPersistantLaunchTemplate
        Version: 1

like image 117
Marcin Avatar answered Dec 16 '25 21:12

Marcin


A Spot Fleet is a way of requesting a certain amount of compute resources (RAM, CPU) that will "keep running" even if some Spot Instances are removed. This is why you cannot request to stop an instance -- because it will be automatically replaced.

Normally, a request for Spot Instance can be specified in a RunInstances() command. However, I was unable to find this option in AWS::EC2::Instance.

The closest I could find was using AWS::EC2::Instance and specifying a AWS::EC2::LaunchTemplate, which contains SpotOptions for specifying Spot Instances.

Frankly, I think that it is quite unusual to use a CloudFormation template to launch Spot Instances. This is because CloudFormation is normally used to launch resources in a reliable, consistent manner. In contrast, Spot Instances can disappear with very little notice. Therefore, Spot Instances are normally launched via specific API requests rather than via CloudFormation templates.

like image 45
John Rotenstein Avatar answered Dec 16 '25 23:12

John Rotenstein



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!