From 4464be82599076e7b1cf57c10802bed1a4e0aea6 Mon Sep 17 00:00:00 2001 From: Glenn Schlereth Date: Sat, 14 Aug 2021 09:26:17 -0300 Subject: [PATCH] Added support for EC2 Spot instances (#14248) If new instance_market_type config.cfg variable specifies 'spot' instead of 'on-demand' then the stack.yml creates a LaunchTemplate resource using spot option. The create EC2 Instance command uses that LaunchTemplate. --- config.cfg | 4 ++++ docs/cloud-amazon-ec2.md | 21 ++++++++++++-------- docs/deploy-from-ansible.md | 6 ++++++ roles/cloud-ec2/files/stack.yaml | 25 ++++++++++++++++++++++++ roles/cloud-ec2/tasks/cloudformation.yml | 1 + 5 files changed, 49 insertions(+), 8 deletions(-) diff --git a/config.cfg b/config.cfg index 9004963..a6b8952 100644 --- a/config.cfg +++ b/config.cfg @@ -177,6 +177,10 @@ cloud_providers: image: name: "ubuntu-focal-20.04" owner: "099720109477" + # Change instance_market_type from "on-demand" to "spot" to take advantage of + # simplified spot launch options + # See https://aws.amazon.com/blogs/compute/new-amazon-ec2-spot-pricing/ + instance_market_type: on-demand gce: size: e2-micro image: ubuntu-2004-lts diff --git a/docs/cloud-amazon-ec2.md b/docs/cloud-amazon-ec2.md index 1bbf30b..2c88560 100644 --- a/docs/cloud-amazon-ec2.md +++ b/docs/cloud-amazon-ec2.md @@ -48,22 +48,27 @@ On the final screen, click the Download CSV button. This file includes the AWS a After you have downloaded Algo and installed its dependencies, the next step is running Algo to provision the VPN server on your AWS account. -First you will be asked which server type to setup. You would want to enter "2" to use Amazon EC2. +First you will be asked which server type to setup. You would want to enter "3" to use Amazon EC2. ``` $ ./algo What provider would you like to use? 1. DigitalOcean - 2. Amazon EC2 - 3. Microsoft Azure - 4. Google Compute Engine - 5. Scaleway - 6. OpenStack (DreamCompute optimised) - 7. Install to existing Ubuntu 16.04 server (Advanced) + 2. Amazon Lightsail + 3. Amazon EC2 + 4. Microsoft Azure + 5. Google Compute Engine + 6. Hetzner Cloud + 7. Vultr + 8. Scaleway + 9. OpenStack (DreamCompute optimised) + 10. CloudStack (Exoscale optimised) + 11. Linode + 12. Install to existing Ubuntu 18.04 or 20.04 server (for more advanced users) Enter the number of your desired provider -: 2 +: 3 ``` Next you will be asked for the AWS Access Key (Access Key ID) and AWS Secret Key (Secret Access Key) that you received in the CSV file when you setup the account (don't worry if you don't see your text entered in the console; the key input is hidden here by Algo). diff --git a/docs/deploy-from-ansible.md b/docs/deploy-from-ansible.md index 8a7151a..a0a58a6 100644 --- a/docs/deploy-from-ansible.md +++ b/docs/deploy-from-ansible.md @@ -111,6 +111,12 @@ Possible options can be gathered via cli `aws ec2 describe-regions` Additional variables: - [encrypted](https://aws.amazon.com/blogs/aws/new-encrypted-ebs-boot-volumes/) - Encrypted EBS boot volume. Boolean (Default: false) +- [size](https://aws.amazon.com/ec2/instance-types/) - EC2 instance type. String (Default: t2.micro) +- [instance_market_type](https://aws.amazon.com/ec2/pricing/) - Two pricing models are supported: on-demand and spot. String (Default: on-demand) + * If using spot instance types, one additional IAM permission along with the below minimum is required for deployment: + ``` + "ec2:CreateLaunchTemplate" + ``` #### Minimum required IAM permissions for deployment: diff --git a/roles/cloud-ec2/files/stack.yaml b/roles/cloud-ec2/files/stack.yaml index 661d5dc..8c6cf47 100644 --- a/roles/cloud-ec2/files/stack.yaml +++ b/roles/cloud-ec2/files/stack.yaml @@ -20,9 +20,17 @@ Parameters: Type: String SshPort: Type: String + InstanceMarketTypeParameter: + Description: Launch a Spot instance or standard on-demand instance + Type: String + Default: on-demand + AllowedValues: + - spot + - on-demand Conditions: AllocateNewEIP: !Equals [!Ref UseThisElasticIP, ''] AssociateExistingEIP: !Not [!Equals [!Ref UseThisElasticIP, '']] + InstanceIsSpot: !Equals [spot, !Ref InstanceMarketTypeParameter] Resources: VPC: Type: AWS::EC2::VPC @@ -146,6 +154,15 @@ Resources: - Key: Name Value: !Ref AWS::StackName + EC2LaunchTemplate: + Type: AWS::EC2::LaunchTemplate + Condition: InstanceIsSpot # Only create this template if requested + Properties: # a spot instance_market_type in config.cfg + LaunchTemplateName: !Ref AWS::StackName + LaunchTemplateData: + InstanceMarketOptions: + MarketType: spot + EC2Instance: Type: AWS::EC2::Instance DependsOn: @@ -169,6 +186,14 @@ Resources: SubnetId: !Ref Subnet Ipv6AddressCount: 1 UserData: !Ref UserData + LaunchTemplate: + !If # Only if Conditions created "EC2LaunchTemplate" + - InstanceIsSpot + - + LaunchTemplateId: + !Ref EC2LaunchTemplate + Version: 1 + - !Ref AWS::NoValue # Else this LaunchTemplate not set Tags: - Key: Name Value: !Ref AWS::StackName diff --git a/roles/cloud-ec2/tasks/cloudformation.yml b/roles/cloud-ec2/tasks/cloudformation.yml index 4ddc8d6..3eb3250 100644 --- a/roles/cloud-ec2/tasks/cloudformation.yml +++ b/roles/cloud-ec2/tasks/cloudformation.yml @@ -16,6 +16,7 @@ EbsEncrypted: "{{ encrypted }}" UserData: "{{ lookup('template', 'files/cloud-init/base.yml') | b64encode }}" SshPort: "{{ ssh_port }}" + InstanceMarketTypeParameter: "{{ cloud_providers.ec2.instance_market_type }}" tags: Environment: Algo register: stack