From 391635565a6aa4263c3f2051ac6e294a429cc24b Mon Sep 17 00:00:00 2001 From: Peter Deme Date: Thu, 12 Jan 2023 17:14:18 +0100 Subject: [PATCH] Download architecture specific laucher (#30) --- .github/workflows/docs.yaml | 2 +- .spacelift/config.yml | 9 +++-- README.md | 16 ++++++-- ami.tf | 7 +++- asg.tf | 18 +++++++-- examples/amd64/README.md | 3 ++ examples/amd64/main.tf | 46 ++++++++++++++++++++++ examples/arm64/README.md | 3 ++ examples/arm64/main.tf | 69 +++++++++++++++++++++++++++++++++ examples/separate-vpc/README.md | 3 -- examples/separate-vpc/main.tf | 47 ---------------------- variables.tf | 4 +- 12 files changed, 164 insertions(+), 63 deletions(-) create mode 100644 examples/amd64/README.md create mode 100644 examples/amd64/main.tf create mode 100644 examples/arm64/README.md create mode 100644 examples/arm64/main.tf delete mode 100644 examples/separate-vpc/README.md delete mode 100644 examples/separate-vpc/main.tf diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index caa2c79..aaed0bb 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -9,7 +9,7 @@ concurrency: cancel-in-progress: true jobs: - build: + docs: runs-on: ubuntu-latest steps: - uses: actions/checkout@main diff --git a/.spacelift/config.yml b/.spacelift/config.yml index f3693b8..3ec72ea 100644 --- a/.spacelift/config.yml +++ b/.spacelift/config.yml @@ -1,6 +1,9 @@ version: 1 -module_version: 1.2.0 +module_version: 1.3.0 tests: - - name: Set up in a separate VPC - project_root: examples/separate-vpc + - name: AMD64-based workerpool + project_root: examples/amd64 + + - name: ARM64-based workerpool + project_root: examples/arm64 diff --git a/README.md b/README.md index 32b98ba..6d3b1d7 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,16 @@ The default AMI used by this module comes from the [spacelift-worker-image](http repository. You can find the full list of AMIs on the [releases](https://github.com/spacelift-io/spacelift-worker-image/releases) page. +## ARM-based AMI + +You can use an ARM-based AMI by setting the `ami_id` variable to an arm64 AMI, and `ec2_instance_type` to an ARM-based instance type (e.g. `t4g.micro`). + +We recommend using [Spacelift AMIs](https://github.com/spacelift-io/spacelift-worker-image/releases) because they come with every required tool preinstalled. + +You can find an example of ARM-based workerpool in the [examples](./examples/) directory. + +>❗️ If you use [custom runner images](https://docs.spacelift.io/concepts/stack/stack-settings.html#runner-image), make sure they support ARM. The default Spacelift images do support it. + ## How to generate docs The generated documentation is between `BEGIN_TF_DOCS` and `END_TF_DOCS` comments in the `README.md` file. @@ -83,7 +93,7 @@ No requirements. | [configuration](#input\_configuration) | User configuration. This allows you to decide how you want to pass your token
and private key to the environment - be that directly, or using SSM Parameter
Store, Vault etc. Ultimately, here you need to export SPACELIFT\_TOKEN and
SPACELIFT\_POOL\_PRIVATE\_KEY to the environment. | `string` | n/a | yes | | [disable\_container\_credentials](#input\_disable\_container\_credentials) | If true, the run container will not be able to access the instance profile
credentials by talking to the EC2 metadata endpoint. This is done by setting
the number of hops in IMDSv2 to 1. Since the Docker container goes through an
extra NAT step, this still allows the launcher to talk to the endpoint, but
prevents the container from doing so. | `bool` | `false` | no | | [domain\_name](#input\_domain\_name) | Top-level domain name to use for pulling the launcher binary | `string` | `"spacelift.io"` | no | -| [ec2\_instance\_type](#input\_ec2\_instance\_type) | EC2 instance type for the workers | `string` | `"t3.micro"` | no | +| [ec2\_instance\_type](#input\_ec2\_instance\_type) | EC2 instance type for the workers. If an arm64-based AMI is used, this must be an arm64-based instance type. | `string` | `"t3.micro"` | no | | [enabled\_metrics](#input\_enabled\_metrics) | List of CloudWatch metrics enabled on the ASG | `list(string)` |
[
"GroupDesiredCapacity",
"GroupInServiceInstances",
"GroupMaxSize",
"GroupMinSize",
"GroupPendingInstances",
"GroupStandbyInstances",
"GroupTerminatingInstances",
"GroupTotalInstances"
]
| no | | [max\_size](#input\_max\_size) | Maximum number of workers to spin up | `number` | `10` | no | | [min\_size](#input\_min\_size) | Minimum numbers of workers to spin up | `number` | `0` | no | @@ -91,7 +101,7 @@ No requirements. | [volume\_encryption](#input\_volume\_encryption) | Whether to encrypt the EBS volume | `bool` | `false` | no | | [volume\_size](#input\_volume\_size) | Size of instance EBS volume | `number` | `40` | no | | [vpc\_subnets](#input\_vpc\_subnets) | List of VPC subnets to use | `list(string)` | n/a | yes | -| [worker\_pool\_id](#input\_worker\_pool\_id) | ID of the the worker pool | `string` | n/a | yes | +| [worker\_pool\_id](#input\_worker\_pool\_id) | ID of the the worker pool. It is used for the naming convention of the resources. | `string` | n/a | yes | ## Outputs @@ -101,4 +111,4 @@ No requirements. | [instances\_role\_arn](#output\_instances\_role\_arn) | ARN of the IAM role of the EC2 instances | | [instances\_role\_name](#output\_instances\_role\_name) | Name of the IAM role of the EC2 instances | | [launch\_template\_id](#output\_launch\_template\_id) | ID of the launch template | - \ No newline at end of file + diff --git a/ami.tf b/ami.tf index 8f86b56..7fd660e 100644 --- a/ami.tf +++ b/ami.tf @@ -1,6 +1,6 @@ data "aws_ami" "this" { most_recent = true - name_regex = "^spacelift-\\d{10}$" + name_regex = "^spacelift-\\d{10}-x86_64$" owners = ["643313122712"] filter { @@ -12,4 +12,9 @@ data "aws_ami" "this" { name = "virtualization-type" values = ["hvm"] } + + filter { + name = "architecture" + values = ["x86_64"] + } } diff --git a/asg.tf b/asg.tf index c4d9a31..e4ec0e7 100644 --- a/asg.tf +++ b/asg.tf @@ -9,15 +9,27 @@ set -e EOF user_data_tail = <> /var/log/spacelift/error.log + return 1 +fi + +baseURL="https://downloads.${var.domain_name}/spacelift-launcher" +binaryURL=$(printf "%s-%s" "$baseURL" "$currentArch") +shaSumURL=$(printf "%s-%s_%s" "$baseURL" "$currentArch" "SHA256SUMS") +shaSumSigURL=$(printf "%s-%s_%s" "$baseURL" "$currentArch" "SHA256SUMS.sig") + echo "Downloading Spacelift launcher" >> /var/log/spacelift/info.log -curl https://downloads.${var.domain_name}/spacelift-launcher --output /usr/bin/spacelift-launcher 2>>/var/log/spacelift/error.log +curl "$binaryURL" --output /usr/bin/spacelift-launcher 2>>/var/log/spacelift/error.log echo "Importing public GPG key" >> /var/log/spacelift/info.log curl https://keys.openpgp.org/vks/v1/by-fingerprint/175FD97AD2358EFE02832978E302FB5AA29D88F7 | gpg --import 2>>/var/log/spacelift/error.log echo "Downloading Spacelift launcher checksum file and signature" >> /var/log/spacelift/info.log -curl https://downloads.${var.domain_name}/spacelift-launcher_SHA256SUMS --output spacelift-launcher_SHA256SUMS 2>>/var/log/spacelift/error.log -curl https://downloads.${var.domain_name}/spacelift-launcher_SHA256SUMS.sig --output spacelift-launcher_SHA256SUMS.sig 2>>/var/log/spacelift/error.log +curl "$shaSumURL" --output spacelift-launcher_SHA256SUMS 2>>/var/log/spacelift/error.log +curl "$shaSumSigURL" --output spacelift-launcher_SHA256SUMS.sig 2>>/var/log/spacelift/error.log echo "Verifying checksum signature..." >> /var/log/spacelift/info.log gpg --verify spacelift-launcher_SHA256SUMS.sig 1>>/var/log/spacelift/info.log 2>>/var/log/spacelift/error.log diff --git a/examples/amd64/README.md b/examples/amd64/README.md new file mode 100644 index 0000000..1801af7 --- /dev/null +++ b/examples/amd64/README.md @@ -0,0 +1,3 @@ +# AMD64 (x86_64) based worker pool + +In this example, we are setting up an amd64-based EC2 autoscaling group inside a VPC. diff --git a/examples/amd64/main.tf b/examples/amd64/main.tf new file mode 100644 index 0000000..6deb30a --- /dev/null +++ b/examples/amd64/main.tf @@ -0,0 +1,46 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "<5.0" + } + + random = { source = "hashicorp/random" } + } +} + +provider "aws" { + region = "eu-west-1" +} + +data "aws_vpc" "this" { + default = true +} + +data "aws_security_group" "this" { + name = "default" + vpc_id = data.aws_vpc.this.id +} + +data "aws_subnets" "this" { + filter { + name = "vpc-id" + values = [data.aws_vpc.this.id] + } +} + +resource "random_pet" "this" {} + +#### Spacelift worker pool #### + +module "this" { + source = "../../" + + configuration = <<-EOT + export SPACELIFT_TOKEN="" + export SPACELIFT_POOL_PRIVATE_KEY="" + EOT + security_groups = [data.aws_security_group.this.id] + vpc_subnets = data.aws_subnets.this.ids + worker_pool_id = random_pet.this.id +} diff --git a/examples/arm64/README.md b/examples/arm64/README.md new file mode 100644 index 0000000..5626df7 --- /dev/null +++ b/examples/arm64/README.md @@ -0,0 +1,3 @@ +# ARM64 pool + +In this example, we'll create a worker pool that will run on ARM64 instances. We'll use the `t4g.micro` instance type, which is the smallest ARM64 instance type available on AWS. diff --git a/examples/arm64/main.tf b/examples/arm64/main.tf new file mode 100644 index 0000000..902a35e --- /dev/null +++ b/examples/arm64/main.tf @@ -0,0 +1,69 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "<5.0" + } + + random = { source = "hashicorp/random" } + } +} + +provider "aws" { + region = "eu-west-1" +} + +data "aws_vpc" "this" { + default = true +} + +data "aws_security_group" "this" { + name = "default" + vpc_id = data.aws_vpc.this.id +} + +data "aws_subnets" "this" { + filter { + name = "vpc-id" + values = [data.aws_vpc.this.id] + } +} + +data "aws_ami" "this" { + most_recent = true + name_regex = "^spacelift-\\d{10}-arm64$" + owners = ["643313122712"] + + filter { + name = "root-device-type" + values = ["ebs"] + } + + filter { + name = "virtualization-type" + values = ["hvm"] + } + + filter { + name = "architecture" + values = ["arm64"] + } +} + +resource "random_pet" "this" {} + +#### Spacelift worker pool #### + +module "this" { + source = "../../" + + configuration = <<-EOT + export SPACELIFT_TOKEN="" + export SPACELIFT_POOL_PRIVATE_KEY="" + EOT + security_groups = [data.aws_security_group.this.id] + vpc_subnets = data.aws_subnets.this.ids + worker_pool_id = random_pet.this.id + ami_id = data.aws_ami.this.id + ec2_instance_type = "t4g.micro" +} diff --git a/examples/separate-vpc/README.md b/examples/separate-vpc/README.md deleted file mode 100644 index ce1873f..0000000 --- a/examples/separate-vpc/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Separate VPC - -In this example, we are setting up an EC2 autoscaling group inside a separate VPC. diff --git a/examples/separate-vpc/main.tf b/examples/separate-vpc/main.tf deleted file mode 100644 index 41bd5b9..0000000 --- a/examples/separate-vpc/main.tf +++ /dev/null @@ -1,47 +0,0 @@ -terraform { - required_providers { - aws = { - source = "hashicorp/aws" - version = "~> 4.48" - } - - random = { source = "hashicorp/random" } - } -} - -provider "aws" { - region = local.region -} - -locals { - region = "eu-west-1" - vpc_cidr = "10.0.0.0/16" - azs = slice(data.aws_availability_zones.available.names, 0, 3) -} - -module "this" { - source = "../../" - - configuration = "" - security_groups = [module.vpc.default_security_group_id] - vpc_subnets = module.vpc.private_subnets - worker_pool_id = random_pet.this.id -} - -################################################################################ -# Supporting resources -################################################################################ - -data "aws_availability_zones" "available" {} -resource "random_pet" "this" {} - -module "vpc" { - source = "terraform-aws-modules/vpc/aws" - version = "~> 3.18" - - name = random_pet.this.id - cidr = local.vpc_cidr - - azs = local.azs - private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 4, k)] -} diff --git a/variables.tf b/variables.tf index 464f3e0..f64ea42 100644 --- a/variables.tf +++ b/variables.tf @@ -34,7 +34,7 @@ variable "domain_name" { variable "ec2_instance_type" { type = string - description = "EC2 instance type for the workers" + description = "EC2 instance type for the workers. If an arm64-based AMI is used, this must be an arm64-based instance type." default = "t3.micro" } @@ -95,7 +95,7 @@ variable "vpc_subnets" { variable "worker_pool_id" { type = string - description = "ID of the the worker pool" + description = "ID of the the worker pool. It is used for the naming convention of the resources." } locals {