Skip to content

Commit

Permalink
AWS: Add support for spot instances
Browse files Browse the repository at this point in the history
if 'aws_ec2_spot_instance' is 'true'
  • Loading branch information
vitabaks committed Jan 11, 2024
1 parent 79ec920 commit fb7f7ab
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 13 deletions.
6 changes: 3 additions & 3 deletions roles/cloud-resources/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ server_image: "" # (required) OS image for the server. For Azure, use variables
server_location: "" # (required) Server location or region.
server_network: "" # (optional) If provided, the server will be added to this network (needs to be created beforehand).

volume_size: "" # (required) Storage size for the data directory (in gigabytes).
volume_type: "" # (optional) Volume type. Defaults: 'gp3' for AWS, 'pd-ssd' for GCP, 'StandardSSD_LRS' for Azure.
system_volume_size: "80" # (optional) System disk size (in gigabytes). Applicable for AWS, GCP, Azure.
volume_type: "" # Volume type. Defaults: 'gp3' for AWS, 'pd-ssd' for GCP, 'StandardSSD_LRS' for Azure.
volume_size: 100 # Storage size for the data directory (in gigabytes).
system_volume_size: 100 # System disk size (in gigabytes). Applicable for AWS, GCP, Azure.

ssh_key_name: "" # Name of the SSH key to be added to the server.
# Note: If not provided, all cloud available SSH keys will be added (applicable to DigitalOcean, Hetzner).
Expand Down
94 changes: 87 additions & 7 deletions roles/cloud-resources/tasks/aws.yml
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@
'cidr_ip': vpc_subnet_info.subnets[0].cidr_block
}]
}}
register: ec2_security_group_result
when: firewall | bool

# S3 bucket
Expand Down Expand Up @@ -219,7 +220,7 @@
image_id: "{{ server_image }}"
key_name: "{{ ssh_key_name }}"
region: "{{ server_location }}"
security_groups: "{{ security_groups_list }}"
security_groups: "{{ ([] if not firewall | bool else [patroni_cluster_name + '-security-group']) }}"
vpc_subnet_id: "{{ server_network }}"
network:
assign_public_ip: true
Expand All @@ -228,7 +229,7 @@
- device_name: /dev/sda1
ebs:
volume_type: "{{ volume_type | default('gp3', true) }}"
volume_size: "{{ system_volume_size | default('40') }}" # system disk size
volume_size: "{{ system_volume_size | int }}"
delete_on_termination: true
- device_name: /dev/sdb
ebs:
Expand All @@ -245,11 +246,90 @@
- server_result.instances[0].public_ip_address | length > 0
retries: 3
delay: 10
vars:
security_groups_list: >-
{{
([] if not firewall | bool else [patroni_cluster_name + '-security-group'])
}}
when: not aws_ec2_spot_instance | default(false) | bool

# Spot instance (if 'aws_ec2_spot_instance' is 'true')
- block:
- name: "AWS: Gather information about EC2 Spot instances"
amazon.aws.ec2_instance_info:
access_key: "{{ lookup('ansible.builtin.env', 'AWS_ACCESS_KEY_ID') }}"
secret_key: "{{ lookup('ansible.builtin.env', 'AWS_SECRET_ACCESS_KEY') }}"
region: "{{ server_location }}"
filters:
instance-lifecycle: "spot"
instance-type: "{{ server_type }}"
image-id: "{{ server_image }}"
instance-state-name: ["pending", "running", "shutting-down", "stopping", "stopped"]
"tag:Name": "{{ server_name | lower }}{{ '%02d' % (idx + 1) }}"
loop: "{{ range(0, servers_count | int) | list }}"
loop_control:
index_var: idx
label: "{{ server_name | lower }}{{ '%02d' % (idx + 1) }}"
register: ec2_instance_info

# if spot instances are still created, create them
- name: "AWS: Create a request for EC2 Spot instance"
amazon.aws.ec2_spot_instance:
access_key: "{{ lookup('ansible.builtin.env', 'AWS_ACCESS_KEY_ID') }}"
secret_key: "{{ lookup('ansible.builtin.env', 'AWS_SECRET_ACCESS_KEY') }}"
region: "{{ server_location }}"
state: present
launch_specification:
instance_type: "{{ server_type }}"
image_id: "{{ server_image }}"
key_name: "{{ ssh_key_name }}"
network_interfaces:
- subnet_id: "{{ server_network }}"
groups: "{{ ec2_security_group_result.group_id }}"
associate_public_ip_address: true
delete_on_termination: true
device_index: 0
block_device_mappings:
- device_name: /dev/sda1
ebs:
volume_type: "{{ volume_type | default('gp3', true) }}"
volume_size: 100 # TODO: use 'system_volume_size' variable (https://github.com/ansible-collections/amazon.aws/issues/1949)
delete_on_termination: true
- device_name: /dev/sdb
ebs:
volume_type: "{{ volume_type | default('gp3', true) }}"
volume_size: 100 # TODO: use 'volume_size' variable (https://github.com/ansible-collections/amazon.aws/issues/1949)
delete_on_termination: true
tags:
Name: "{{ server_name | lower }}{{ '%02d' % (idx + 1) }}"
loop: "{{ ec2_instance_info.results }}"
loop_control:
index_var: idx
label: "{{ server_name | lower }}{{ '%02d' % (idx + 1) }}"
register: ec2_spot_instance_result
when: item.instances[0] | default('') | length < 1

- name: "AWS: Rename the EC2 Spot instance"
amazon.aws.ec2_instance:
access_key: "{{ lookup('ansible.builtin.env', 'AWS_ACCESS_KEY_ID') }}"
secret_key: "{{ lookup('ansible.builtin.env', 'AWS_SECRET_ACCESS_KEY') }}"
region: "{{ server_location }}"
name: "{{ server_name | lower }}{{ '%02d' % (idx + 1) }}"
filters:
spot-instance-request-id: "{{ item.spot_request.spot_instance_request_id }}"
loop: "{{ ec2_spot_instance_result.results }}"
loop_control:
index_var: idx
label: "{{ server_name | lower }}{{ '%02d' % (idx + 1) }}"
register: server_result
until:
- server_result.instances[0].public_ip_address is defined
- server_result.instances[0].public_ip_address | length > 0
retries: 3
delay: 10
when: item.spot_request.spot_instance_request_id is defined

# if spot instances have already been created, use them
- name: "Set variable: server_result"
ansible.builtin.set_fact:
server_result: "{{ ec2_instance_info }}"
when: not server_result.changed
when: aws_ec2_spot_instance | default(false) | bool
when: state == 'present'

- name: Wait for EC2 instance to be available via SSH
Expand Down
5 changes: 2 additions & 3 deletions roles/cloud-resources/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@
ansible.builtin.fail:
msg:
- "One or more required variables have empty values."
- "Please specify value for variables: 'server_type', 'server_image', 'server_location', 'volume_size'."
- "Please specify value for variables: 'server_type', 'server_image', 'server_location'."
when: state == 'present' and
(server_type | length < 1 or
(server_image | length < 1 and cloud_provider != 'azure') or
server_location | length < 1 or
volume_size | length < 1)
server_location | length < 1)

# if ssh_key_name is not specified
# with each new execution of the playbook, a new temporary ssh key is created
Expand Down

0 comments on commit fb7f7ab

Please sign in to comment.