From 17a4ab004ceafe3d789baee21a53840479a5293c Mon Sep 17 00:00:00 2001 From: Niek Palm Date: Sun, 26 Apr 2020 16:23:52 +0200 Subject: [PATCH 01/11] Create infra code for runenrs --- examples/default/main.tf | 24 ++++ examples/default/outputs.tf | 8 ++ examples/default/providers.tf | 5 + examples/default/vpc.tf | 7 ++ modules/runners/main.tf | 116 ++++++++++++++++++ modules/runners/outputs.tf | 7 ++ modules/runners/policies.tf | 64 ++++++++++ .../policies/instance-role-trust-policy.json | 13 ++ .../policies/instance-runner-s3-policy.json | 11 ++ .../instance-session-manager-policy.json | 15 +++ .../instance-ssm-parameters-policy.json | 15 +++ modules/runners/runner-dist.tf | 7 ++ modules/runners/templates/user-data.sh | 50 ++++++++ modules/runners/variables.tf | 72 +++++++++++ 14 files changed, 414 insertions(+) create mode 100644 examples/default/outputs.tf create mode 100644 examples/default/providers.tf create mode 100644 examples/default/vpc.tf create mode 100644 modules/runners/main.tf create mode 100644 modules/runners/outputs.tf create mode 100644 modules/runners/policies.tf create mode 100644 modules/runners/policies/instance-role-trust-policy.json create mode 100644 modules/runners/policies/instance-runner-s3-policy.json create mode 100644 modules/runners/policies/instance-session-manager-policy.json create mode 100644 modules/runners/policies/instance-ssm-parameters-policy.json create mode 100644 modules/runners/runner-dist.tf create mode 100644 modules/runners/templates/user-data.sh create mode 100644 modules/runners/variables.tf diff --git a/examples/default/main.tf b/examples/default/main.tf index e69de29bb2..13a84c1824 100644 --- a/examples/default/main.tf +++ b/examples/default/main.tf @@ -0,0 +1,24 @@ +locals { + environment = "test.default" + aws_region = "eu-west-1" +} + +resource "random_string" "random" { + length = 24 + special = false + upper = false +} + +module "runners" { + source = "../../modules/runners" + + aws_region = local.aws_region + vpc_id = module.vpc.vpc_id + + environment = local.environment + tags = { + Project = "ProjectX" + } + distribution_bucket_name = random_string.random.result +} + diff --git a/examples/default/outputs.tf b/examples/default/outputs.tf new file mode 100644 index 0000000000..aa0cc34653 --- /dev/null +++ b/examples/default/outputs.tf @@ -0,0 +1,8 @@ +output "runners" { + value = { + launch_template_name = module.runners.launch_template.name + launch_template_id = module.runners.launch_template.id + launch_template_version = module.runners.launch_template.latest_version + action_runner_distribution = module.runners.s3_location_runner_distribution + } +} diff --git a/examples/default/providers.tf b/examples/default/providers.tf new file mode 100644 index 0000000000..582241f0ed --- /dev/null +++ b/examples/default/providers.tf @@ -0,0 +1,5 @@ +provider "aws" { + region = local.aws_region + version = "2.59" +} + diff --git a/examples/default/vpc.tf b/examples/default/vpc.tf new file mode 100644 index 0000000000..3a9fba6c1f --- /dev/null +++ b/examples/default/vpc.tf @@ -0,0 +1,7 @@ +module "vpc" { + source = "git::https://github.com/philips-software/terraform-aws-vpc.git?ref=2.1.0" + + environment = local.environment + aws_region = local.aws_region +} + diff --git a/modules/runners/main.tf b/modules/runners/main.tf new file mode 100644 index 0000000000..def214daea --- /dev/null +++ b/modules/runners/main.tf @@ -0,0 +1,116 @@ + +resource "aws_resourcegroups_group" "resourcegroups_group" { + name = "${var.environment}-group" + + resource_query { + query = <<-JSON +{ + "ResourceTypeFilters": [ + "AWS::AllSupported" + ], + "TagFilters": [ + { + "Key": "ResourceGroup", + "Values": ["${var.environment}"] + } + ] +} + JSON + } +} + + +locals { + s3_location_runner_distribution = "s3://${aws_s3_bucket.action_dist.id}/${var.action_runner_dist_bucket_location}" +} + +data "aws_ami" "runner" { + most_recent = "true" + + dynamic "filter" { + for_each = var.ami_filter + content { + name = filter.key + values = filter.value + } + } + + owners = var.ami_owners +} + +resource "aws_launch_template" "runner" { + name = "${var.environment}-action-runner" + + dynamic "block_device_mappings" { + for_each = [var.block_device_mappings] + content { + device_name = "/dev/xvda" + + ebs { + delete_on_termination = lookup(block_device_mappings.value, "delete_on_termination", true) + volume_type = lookup(block_device_mappings.value, "volume_type", "gp2") + volume_size = lookup(block_device_mappings.value, "volume_size", 30) + encrypted = lookup(block_device_mappings.value, "encrypted", true) + iops = lookup(block_device_mappings.value, "iops", null) + } + } + } + + iam_instance_profile { + name = aws_iam_instance_profile.runner.name + } + + instance_initiated_shutdown_behavior = "terminate" + + instance_market_options { + market_type = var.market_options + } + + image_id = data.aws_ami.runner.id + instance_type = var.instance_type + + vpc_security_group_ids = [aws_security_group.runner_sg.id] + + tag_specifications { + resource_type = "instance" + tags = local.tags + } + + user_data = base64encode(templatefile("${path.module}/templates/user-data.sh", { + environment = var.environment + s3_location_runner_distribution = local.s3_location_runner_distribution + })) +} + +resource "aws_security_group" "runner_sg" { + name_prefix = "${var.environment}-github-actions-runner-sg" + description = "Github Actions Runner security group" + + vpc_id = var.vpc_id + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + tags = merge( + local.tags, + { + "Name" = format("%s", local.name_sg) + }, + ) +} + +locals { + name_sg = var.overrides["name_sg"] == "" ? local.tags["Name"] : var.overrides["name_sg"] + tags = merge( + { + "Name" = format("%s", var.environment) + }, + { + "Environment" = format("%s", var.environment) + }, + var.tags, + ) +} diff --git a/modules/runners/outputs.tf b/modules/runners/outputs.tf new file mode 100644 index 0000000000..3f03edc054 --- /dev/null +++ b/modules/runners/outputs.tf @@ -0,0 +1,7 @@ +output "s3_location_runner_distribution" { + value = local.s3_location_runner_distribution +} + +output "launch_template" { + value = aws_launch_template.runner +} diff --git a/modules/runners/policies.tf b/modules/runners/policies.tf new file mode 100644 index 0000000000..5cba6b43d1 --- /dev/null +++ b/modules/runners/policies.tf @@ -0,0 +1,64 @@ +data "aws_caller_identity" "current" {} + +resource "aws_iam_role" "runner" { + name = "${var.environment}-github-action-runners-runner-role" + assume_role_policy = templatefile("${path.module}/policies/instance-role-trust-policy.json", {}) + tags = local.tags +} + +resource "aws_iam_instance_profile" "runner" { + name = "${var.environment}-github-action-runners-profile" + role = aws_iam_role.runner.name +} + +resource "aws_iam_policy" "runner_session_manager_policy" { + name = "${var.environment}-github-action-runners-session-manager" + path = "/" + description = "Policy session manager." + + policy = templatefile("${path.module}/policies/instance-session-manager-policy.json", {}) +} + +resource "aws_iam_role_policy_attachment" "runner_session_manager_policy" { + role = aws_iam_role.runner.name + policy_arn = aws_iam_policy.runner_session_manager_policy.arn +} + +resource "aws_iam_role_policy_attachment" "runner_session_manager_aws_managed" { + role = aws_iam_role.runner.name + policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" +} + +resource "aws_iam_policy" "dist_bucket" { + name = "${var.environment}-gh-distribution-bucket" + path = "/" + description = "Policy for the runner to download the github action runner." + + policy = templatefile("${path.module}/policies/instance-runner-s3-policy.json", + { + s3_arn = aws_s3_bucket.action_dist.arn + } + ) +} + +resource "aws_iam_role_policy_attachment" "dist_bucket" { + role = aws_iam_role.runner.name + policy_arn = aws_iam_policy.dist_bucket.arn +} + +resource "aws_iam_policy" "ssm_parameters" { + name = "${var.environment}-runner-ssm-parameters" + path = "/" + description = "Policy for the runner to download the github action runner." + + policy = templatefile("${path.module}/policies/instance-ssm-parameters-policy.json", + { + arn_ssm_parameters = "arn:aws:ssm:${var.aws_region}:${data.aws_caller_identity.current.account_id}:parameter/${var.environment}-*" + } + ) +} + +resource "aws_iam_role_policy_attachment" "ssm_parameters" { + role = aws_iam_role.runner.name + policy_arn = aws_iam_policy.ssm_parameters.arn +} diff --git a/modules/runners/policies/instance-role-trust-policy.json b/modules/runners/policies/instance-role-trust-policy.json new file mode 100644 index 0000000000..45bf82b081 --- /dev/null +++ b/modules/runners/policies/instance-role-trust-policy.json @@ -0,0 +1,13 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "", + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + }, + "Action": "sts:AssumeRole" + } + ] +} diff --git a/modules/runners/policies/instance-runner-s3-policy.json b/modules/runners/policies/instance-runner-s3-policy.json new file mode 100644 index 0000000000..68d21ebce6 --- /dev/null +++ b/modules/runners/policies/instance-runner-s3-policy.json @@ -0,0 +1,11 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "githubActionDist", + "Effect": "Allow", + "Action": ["s3:GetObject", "s3:GetObjectAcl"], + "Resource": ["${s3_arn}/*"] + } + ] +} diff --git a/modules/runners/policies/instance-session-manager-policy.json b/modules/runners/policies/instance-session-manager-policy.json new file mode 100644 index 0000000000..63ac8ca941 --- /dev/null +++ b/modules/runners/policies/instance-session-manager-policy.json @@ -0,0 +1,15 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ssmmessages:CreateControlChannel", + "ssmmessages:CreateDataChannel", + "ssmmessages:OpenControlChannel", + "ssmmessages:OpenDataChannel" + ], + "Resource": "*" + } + ] +} \ No newline at end of file diff --git a/modules/runners/policies/instance-ssm-parameters-policy.json b/modules/runners/policies/instance-ssm-parameters-policy.json new file mode 100644 index 0000000000..bb43708b64 --- /dev/null +++ b/modules/runners/policies/instance-ssm-parameters-policy.json @@ -0,0 +1,15 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": ["ssm:DeleteParameter"], + "Resource": "${arn_ssm_parameters}" + }, + { + "Effect": "Allow", + "Action": ["ssm:GetParameters"], + "Resource": "${arn_ssm_parameters}" + } + ] +} diff --git a/modules/runners/runner-dist.tf b/modules/runners/runner-dist.tf new file mode 100644 index 0000000000..5305a658c1 --- /dev/null +++ b/modules/runners/runner-dist.tf @@ -0,0 +1,7 @@ +resource "aws_s3_bucket" "action_dist" { + bucket = var.distribution_bucket_name + acl = "private" + force_destroy = true + tags = var.tags +} + diff --git a/modules/runners/templates/user-data.sh b/modules/runners/templates/user-data.sh new file mode 100644 index 0000000000..2aca7d35b2 --- /dev/null +++ b/modules/runners/templates/user-data.sh @@ -0,0 +1,50 @@ +#!/bin/bash -e +exec > >(tee /var/log/user-data.log | logger -t user-data -s 2>/dev/console) 2>&1 + +yum update -y + +# Install docker +amazon-linux-extras install docker +service docker start +usermod -a -G docker ec2-user + +# Install runner +yum install -y curl jq git +cd /home/ec2-user +mkdir actions-runner && cd actions-runner +#!/bin/bash -ex +exec > >(tee /var/log/user-data.log | logger -t user-data -s 2>/dev/console) 2>&1 + +yum update -y + +# Install docker +amazon-linux-extras install docker +service docker start +usermod -a -G docker ec2-user + +# Install runner +yum install -y curl jq git + +cd /home/ec2-user +mkdir actions-runner && cd actions-runner +aws s3 cp ${s3_location_runner_distribution} actions-runner.tar.gz +tar xzf ./actions-runner.tar.gz +rm actions-runner.tar.gz + +INSTANCE_ID=$(wget -q -O - http://169.254.169.254/latest/meta-data/instance-id) +REGION=$(curl -s 169.254.169.254/latest/dynamic/instance-identity/document | jq -r .region) + +echo wait for configuration +while [[ $(aws ssm get-parameters --names ${environment}-$INSTANCE_ID --with-decryption --region $REGION | jq -r ".Parameters | .[0] | .Value") == null ]]; do + echo Waiting for configuration ... + sleep 1 +done +config=$(aws ssm get-parameters --names ${environment}-$INSTANCE_ID --with-decryption --region $REGION | jq -r ".Parameters | .[0] | .Value") + +export RUNNER_ALLOW_RUNASROOT=1 +./config.sh --unattended --name $INSTANCE_ID --work "_work" $config + +chown -R ec2-user:ec2-user . + +./svc.sh install ec2-user +./svc.sh start diff --git a/modules/runners/variables.tf b/modules/runners/variables.tf new file mode 100644 index 0000000000..c5d739e698 --- /dev/null +++ b/modules/runners/variables.tf @@ -0,0 +1,72 @@ +variable "aws_region" { + description = "AWS region." + type = string +} + +variable "vpc_id" { + description = "The VPC to spin up instances in" +} + + +variable "overrides" { + description = "This maps provides the possibility to override some defaults. The following attributes are supported: `name_sg` overwrite the `Name` tag for all security groups created by this module. `name_runner_agent_instance` override the `Name` tag for the ec2 instance defined in the auto launch configuration. `name_docker_machine_runners` ovverrid the `Name` tag spot instances created by the runner agent." + type = map(string) + + default = { + name_sg = "" + } +} + +variable "tags" { + description = "Map of tags that will be added to created resources. By default resources will be tagged with name and environment." + type = map(string) + default = {} +} + +variable "environment" { + description = "A name that identifies the environment, used as prefix and for tagging." + type = string +} + +variable "distribution_bucket_name" { + type = string +} + +variable "block_device_mappings" { + description = "The EC2 instance block device configuration. Takes the following keys: `delete_on_termination`, `volume_type`, `volume_size`, `encrypted`, `iops`" + type = map(string) + default = {} +} + +variable "market_options" { + default = "spot" +} + +variable "instance_type" { + default = "m5.large" +} + +variable "associate_public_ip_address" { + type = bool + default = false +} + +variable "action_runner_dist_bucket_location" { + default = "actions-runner-linux.tar.gz" +} + + +variable "ami_filter" { + description = "List of maps used to create the AMI filter for the runner AMI. Currently Amazon Linux 2 `amzn2-ami-hvm-2.0.????????-x86_64-ebs` looks to *not* be working for this configuration." + type = map(list(string)) + + default = { + name = ["amzn2-ami-hvm-2.*-x86_64-ebs"] + } +} + +variable "ami_owners" { + description = "The list of owners used to select the AMI of runner instances." + type = list(string) + default = ["amazon"] +} From cf098b4eb2e7b015123ba3e9d10a0eaad0733d14 Mon Sep 17 00:00:00 2001 From: Niek Palm Date: Sun, 26 Apr 2020 21:52:06 +0200 Subject: [PATCH 02/11] Add pre / post install and delete parameter --- modules/runners/main.tf | 2 ++ modules/runners/templates/user-data.sh | 7 ++++++- modules/runners/variables.tf | 13 +++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/modules/runners/main.tf b/modules/runners/main.tf index def214daea..c9d826be2d 100644 --- a/modules/runners/main.tf +++ b/modules/runners/main.tf @@ -74,6 +74,8 @@ resource "aws_launch_template" "runner" { tag_specifications { resource_type = "instance" tags = local.tags + pre_install = var.userdata_pre_install + post_install = var.userdata_post_install } user_data = base64encode(templatefile("${path.module}/templates/user-data.sh", { diff --git a/modules/runners/templates/user-data.sh b/modules/runners/templates/user-data.sh index 2aca7d35b2..a97b5bc65e 100644 --- a/modules/runners/templates/user-data.sh +++ b/modules/runners/templates/user-data.sh @@ -17,6 +17,8 @@ exec > >(tee /var/log/user-data.log | logger -t user-data -s 2>/dev/console) 2>& yum update -y +${pre_install} + # Install docker amazon-linux-extras install docker service docker start @@ -40,11 +42,14 @@ while [[ $(aws ssm get-parameters --names ${environment}-$INSTANCE_ID --with-dec sleep 1 done config=$(aws ssm get-parameters --names ${environment}-$INSTANCE_ID --with-decryption --region $REGION | jq -r ".Parameters | .[0] | .Value") +aws ssm delete-parameter --names ${environment}-$INSTANCE_ID --with-decryption --region $REGION export RUNNER_ALLOW_RUNASROOT=1 ./config.sh --unattended --name $INSTANCE_ID --work "_work" $config chown -R ec2-user:ec2-user . - ./svc.sh install ec2-user + +${post_install} + ./svc.sh start diff --git a/modules/runners/variables.tf b/modules/runners/variables.tf index c5d739e698..27ebaf7b5f 100644 --- a/modules/runners/variables.tf +++ b/modules/runners/variables.tf @@ -70,3 +70,16 @@ variable "ami_owners" { type = list(string) default = ["amazon"] } + + +variable "userdata_pre_install" { + description = "User-data script snippet to insert before GitLab runner install" + type = string + default = "" +} + +variable "userdata_post_install" { + description = "User-data script snippet to insert after GitLab runner install" + type = string + default = "" +} From 05fd3758390fe45ddbdf107bcd659d95951c9649 Mon Sep 17 00:00:00 2001 From: Niek Palm Date: Sun, 26 Apr 2020 21:53:07 +0200 Subject: [PATCH 03/11] Add pre / post install and delete parameter --- modules/runners/variables.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/runners/variables.tf b/modules/runners/variables.tf index 27ebaf7b5f..4d4efc3448 100644 --- a/modules/runners/variables.tf +++ b/modules/runners/variables.tf @@ -73,13 +73,13 @@ variable "ami_owners" { variable "userdata_pre_install" { - description = "User-data script snippet to insert before GitLab runner install" + description = "User-data script snippet to insert before GitHub acton runner install" type = string default = "" } variable "userdata_post_install" { - description = "User-data script snippet to insert after GitLab runner install" + description = "User-data script snippet to insert after GitHub acton runner install" type = string default = "" } From b44f4b304b88c83b985439c99a24c4ceab0191c5 Mon Sep 17 00:00:00 2001 From: Niek Palm Date: Sun, 26 Apr 2020 21:53:48 +0200 Subject: [PATCH 04/11] Add pre / post install and delete parameter --- modules/runners/main.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/runners/main.tf b/modules/runners/main.tf index c9d826be2d..03f83634d8 100644 --- a/modules/runners/main.tf +++ b/modules/runners/main.tf @@ -74,12 +74,12 @@ resource "aws_launch_template" "runner" { tag_specifications { resource_type = "instance" tags = local.tags - pre_install = var.userdata_pre_install - post_install = var.userdata_post_install } user_data = base64encode(templatefile("${path.module}/templates/user-data.sh", { environment = var.environment + pre_install = var.userdata_pre_install + post_install = var.userdata_post_install s3_location_runner_distribution = local.s3_location_runner_distribution })) } From 3684eac54054223d1d698f318d67d293ca324147 Mon Sep 17 00:00:00 2001 From: Niek Palm Date: Sun, 26 Apr 2020 21:55:50 +0200 Subject: [PATCH 05/11] Add pre / post install and delete parameter --- modules/runners/main.tf | 60 +++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/modules/runners/main.tf b/modules/runners/main.tf index 03f83634d8..bdb9b2413d 100644 --- a/modules/runners/main.tf +++ b/modules/runners/main.tf @@ -1,27 +1,16 @@ - -resource "aws_resourcegroups_group" "resourcegroups_group" { - name = "${var.environment}-group" - - resource_query { - query = <<-JSON -{ - "ResourceTypeFilters": [ - "AWS::AllSupported" - ], - "TagFilters": [ - { - "Key": "ResourceGroup", - "Values": ["${var.environment}"] - } - ] -} - JSON - } -} - - locals { + name_sg = var.overrides["name_sg"] == "" ? local.tags["Name"] : var.overrides["name_sg"] s3_location_runner_distribution = "s3://${aws_s3_bucket.action_dist.id}/${var.action_runner_dist_bucket_location}" + + tags = merge( + { + "Name" = format("%s", var.environment) + }, + { + "Environment" = format("%s", var.environment) + }, + var.tags, + ) } data "aws_ami" "runner" { @@ -104,15 +93,22 @@ resource "aws_security_group" "runner_sg" { ) } -locals { - name_sg = var.overrides["name_sg"] == "" ? local.tags["Name"] : var.overrides["name_sg"] - tags = merge( - { - "Name" = format("%s", var.environment) - }, +resource "aws_resourcegroups_group" "resourcegroups_group" { + name = "${var.environment}-group" + + resource_query { + query = <<-JSON +{ + "ResourceTypeFilters": [ + "AWS::AllSupported" + ], + "TagFilters": [ { - "Environment" = format("%s", var.environment) - }, - var.tags, - ) + "Key": "ResourceGroup", + "Values": ["${var.environment}"] + } + ] +} + JSON + } } From 0e95c597e2f76d3476360e45b263436e38052a24 Mon Sep 17 00:00:00 2001 From: Niek Palm Date: Mon, 27 Apr 2020 12:53:41 +0200 Subject: [PATCH 06/11] Refactor, update docs --- examples/default/main.tf | 12 +++-------- examples/default/outputs.tf | 7 ++----- main.tf | 17 ++++++++++++++++ modules/runners/README.md | 9 +++++++++ modules/runners/templates/user-data.sh | 6 +++--- modules/runners/variables.tf | 28 +++++++++++++------------- outputs.tf | 8 ++++++++ variables.tf | 21 +++++++++++++++++++ 8 files changed, 77 insertions(+), 31 deletions(-) create mode 100644 modules/runners/README.md diff --git a/examples/default/main.tf b/examples/default/main.tf index 13a84c1824..6b96a39a98 100644 --- a/examples/default/main.tf +++ b/examples/default/main.tf @@ -1,16 +1,10 @@ locals { - environment = "test.default" + environment = "default-action-runners" aws_region = "eu-west-1" } -resource "random_string" "random" { - length = 24 - special = false - upper = false -} - module "runners" { - source = "../../modules/runners" + source = "../../" aws_region = local.aws_region vpc_id = module.vpc.vpc_id @@ -19,6 +13,6 @@ module "runners" { tags = { Project = "ProjectX" } - distribution_bucket_name = random_string.random.result + } diff --git a/examples/default/outputs.tf b/examples/default/outputs.tf index aa0cc34653..08e04595ed 100644 --- a/examples/default/outputs.tf +++ b/examples/default/outputs.tf @@ -1,8 +1,5 @@ -output "runners" { +output "action_runners" { value = { - launch_template_name = module.runners.launch_template.name - launch_template_id = module.runners.launch_template.id - launch_template_version = module.runners.launch_template.latest_version - action_runner_distribution = module.runners.s3_location_runner_distribution + runners = module.runners.runners } } diff --git a/main.tf b/main.tf index e69de29bb2..e0a97a898a 100644 --- a/main.tf +++ b/main.tf @@ -0,0 +1,17 @@ +resource "random_string" "random" { + length = 24 + special = false + upper = false +} + +module "runners" { + source = "./modules/runners" + + aws_region = var.aws_region + vpc_id = var.vpc_id + + environment = var.environment + tags = var.tags + distribution_bucket_name = random_string.random.result +} + diff --git a/modules/runners/README.md b/modules/runners/README.md new file mode 100644 index 0000000000..cb85f1a11e --- /dev/null +++ b/modules/runners/README.md @@ -0,0 +1,9 @@ +# Action runner module + +The module create resources to facilitate the `orchestrator labmda` to recreate action runners. + +- *launch template* : A launch template is creates that can crate an action runner, by default a spot instance is requested. For configuration parameters SSM is used. +- *security group* : Security groups attached to the action runner. +- *s3 bucket* : To avoid the action runner distribution have to be download a cached version is expected in a S3 bucket. +- *policies and roles* : Policies and roles for the action runner. By default the session manager is enabled + diff --git a/modules/runners/templates/user-data.sh b/modules/runners/templates/user-data.sh index a97b5bc65e..3d390fb174 100644 --- a/modules/runners/templates/user-data.sh +++ b/modules/runners/templates/user-data.sh @@ -41,11 +41,11 @@ while [[ $(aws ssm get-parameters --names ${environment}-$INSTANCE_ID --with-dec echo Waiting for configuration ... sleep 1 done -config=$(aws ssm get-parameters --names ${environment}-$INSTANCE_ID --with-decryption --region $REGION | jq -r ".Parameters | .[0] | .Value") -aws ssm delete-parameter --names ${environment}-$INSTANCE_ID --with-decryption --region $REGION +CONFIG=$(aws ssm get-parameters --names ${environment}-$INSTANCE_ID --with-decryption --region $REGION | jq -r ".Parameters | .[0] | .Value") +aws ssm delete-parameter --name ${environment}-$INSTANCE_ID --region $REGION export RUNNER_ALLOW_RUNASROOT=1 -./config.sh --unattended --name $INSTANCE_ID --work "_work" $config +./config.sh --unattended --name $INSTANCE_ID --work "_work" $CONFIG chown -R ec2-user:ec2-user . ./svc.sh install ec2-user diff --git a/modules/runners/variables.tf b/modules/runners/variables.tf index 4d4efc3448..32fe43b6b1 100644 --- a/modules/runners/variables.tf +++ b/modules/runners/variables.tf @@ -4,10 +4,10 @@ variable "aws_region" { } variable "vpc_id" { - description = "The VPC to spin up instances in" + description = "The VPC for the security groupss." + type = string } - variable "overrides" { description = "This maps provides the possibility to override some defaults. The following attributes are supported: `name_sg` overwrite the `Name` tag for all security groups created by this module. `name_runner_agent_instance` override the `Name` tag for the ec2 instance defined in the auto launch configuration. `name_docker_machine_runners` ovverrid the `Name` tag spot instances created by the runner agent." type = map(string) @@ -29,7 +29,8 @@ variable "environment" { } variable "distribution_bucket_name" { - type = string + description = "Bucket for storing the action runner distribution." + type = string } variable "block_device_mappings" { @@ -39,25 +40,24 @@ variable "block_device_mappings" { } variable "market_options" { - default = "spot" + description = "Market options for the action runner instances." + type = string + default = "spot" } variable "instance_type" { - default = "m5.large" -} - -variable "associate_public_ip_address" { - type = bool - default = false + description = "Default instance type for the action runner." + type = string + default = "m5.large" } variable "action_runner_dist_bucket_location" { - default = "actions-runner-linux.tar.gz" + description = "Default location action runner distribution." + default = "actions-runner-linux.tar.gz" } - variable "ami_filter" { - description = "List of maps used to create the AMI filter for the runner AMI. Currently Amazon Linux 2 `amzn2-ami-hvm-2.0.????????-x86_64-ebs` looks to *not* be working for this configuration." + description = "List of maps used to create the AMI filter for the action runner AMI." type = map(list(string)) default = { @@ -66,7 +66,7 @@ variable "ami_filter" { } variable "ami_owners" { - description = "The list of owners used to select the AMI of runner instances." + description = "The list of owners used to select the AMI of action runner instances." type = list(string) default = ["amazon"] } diff --git a/outputs.tf b/outputs.tf index e69de29bb2..aa0cc34653 100644 --- a/outputs.tf +++ b/outputs.tf @@ -0,0 +1,8 @@ +output "runners" { + value = { + launch_template_name = module.runners.launch_template.name + launch_template_id = module.runners.launch_template.id + launch_template_version = module.runners.launch_template.latest_version + action_runner_distribution = module.runners.s3_location_runner_distribution + } +} diff --git a/variables.tf b/variables.tf index e69de29bb2..3b664c05a5 100644 --- a/variables.tf +++ b/variables.tf @@ -0,0 +1,21 @@ +variable "aws_region" { + description = "AWS region." + type = string +} + +variable "vpc_id" { + description = "The VPC for security groups of the action runners." + type = string +} + +variable "tags" { + description = "Map of tags that will be added to created resources. By default resources will be tagged with name and environment." + type = map(string) + default = {} +} + +variable "environment" { + description = "A name that identifies the environment, used as prefix and for tagging." + type = string +} + From 559e8108deac4294fe5d8b2c8e89cded2d38aca2 Mon Sep 17 00:00:00 2001 From: Niek Palm Date: Mon, 27 Apr 2020 17:24:11 +0200 Subject: [PATCH 07/11] Refactor distribution out of the runner --- main.tf | 37 +++++++++++++++++++++++++++++----- modules/runners/main.tf | 5 ++--- modules/runners/outputs.tf | 8 ++++---- modules/runners/policies.tf | 17 ---------------- modules/runners/runner-dist.tf | 7 ------- modules/runners/variables.tf | 9 ++------- outputs.tf | 2 +- 7 files changed, 41 insertions(+), 44 deletions(-) delete mode 100644 modules/runners/runner-dist.tf diff --git a/main.tf b/main.tf index e0a97a898a..4718fb685a 100644 --- a/main.tf +++ b/main.tf @@ -4,14 +4,41 @@ resource "random_string" "random" { upper = false } +module "dsitrubtion_cache" { + source = "./modules/action-runner-binary-cache" + + aws_region = var.aws_region + environment = var.environment + tags = var.tags + + distribution_bucket_name = random_string.random.result +} + module "runners" { source = "./modules/runners" - aws_region = var.aws_region - vpc_id = var.vpc_id + aws_region = var.aws_region + vpc_id = var.vpc_id + environment = var.environment + tags = var.tags - environment = var.environment - tags = var.tags - distribution_bucket_name = random_string.random.result + s3_location_runner_distribution = module.dsitrubtion_cache.s3_location_runner_distribution } + +resource "aws_iam_policy" "dist_bucket" { + name = "${var.environment}-gh-distribution-bucket" + path = "/" + description = "Policy for the runner to download the github action runner." + + policy = templatefile("${path.module}/policies/action-runner-s3-policy.json", + { + s3_arn = module.dsitrubtion_cache.distribution_bucket.arn + } + ) +} + +resource "aws_iam_role_policy_attachment" "dist_bucket" { + role = module.runners.role.name + policy_arn = aws_iam_policy.dist_bucket.arn +} diff --git a/modules/runners/main.tf b/modules/runners/main.tf index bdb9b2413d..125317caa5 100644 --- a/modules/runners/main.tf +++ b/modules/runners/main.tf @@ -1,6 +1,5 @@ locals { - name_sg = var.overrides["name_sg"] == "" ? local.tags["Name"] : var.overrides["name_sg"] - s3_location_runner_distribution = "s3://${aws_s3_bucket.action_dist.id}/${var.action_runner_dist_bucket_location}" + name_sg = var.overrides["name_sg"] == "" ? local.tags["Name"] : var.overrides["name_sg"] tags = merge( { @@ -69,7 +68,7 @@ resource "aws_launch_template" "runner" { environment = var.environment pre_install = var.userdata_pre_install post_install = var.userdata_post_install - s3_location_runner_distribution = local.s3_location_runner_distribution + s3_location_runner_distribution = var.s3_location_runner_distribution })) } diff --git a/modules/runners/outputs.tf b/modules/runners/outputs.tf index 3f03edc054..2417f29b0e 100644 --- a/modules/runners/outputs.tf +++ b/modules/runners/outputs.tf @@ -1,7 +1,7 @@ -output "s3_location_runner_distribution" { - value = local.s3_location_runner_distribution -} - output "launch_template" { value = aws_launch_template.runner } + +output "role" { + value = aws_iam_role.runner +} diff --git a/modules/runners/policies.tf b/modules/runners/policies.tf index 5cba6b43d1..080bbbd98e 100644 --- a/modules/runners/policies.tf +++ b/modules/runners/policies.tf @@ -29,23 +29,6 @@ resource "aws_iam_role_policy_attachment" "runner_session_manager_aws_managed" { policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" } -resource "aws_iam_policy" "dist_bucket" { - name = "${var.environment}-gh-distribution-bucket" - path = "/" - description = "Policy for the runner to download the github action runner." - - policy = templatefile("${path.module}/policies/instance-runner-s3-policy.json", - { - s3_arn = aws_s3_bucket.action_dist.arn - } - ) -} - -resource "aws_iam_role_policy_attachment" "dist_bucket" { - role = aws_iam_role.runner.name - policy_arn = aws_iam_policy.dist_bucket.arn -} - resource "aws_iam_policy" "ssm_parameters" { name = "${var.environment}-runner-ssm-parameters" path = "/" diff --git a/modules/runners/runner-dist.tf b/modules/runners/runner-dist.tf deleted file mode 100644 index 5305a658c1..0000000000 --- a/modules/runners/runner-dist.tf +++ /dev/null @@ -1,7 +0,0 @@ -resource "aws_s3_bucket" "action_dist" { - bucket = var.distribution_bucket_name - acl = "private" - force_destroy = true - tags = var.tags -} - diff --git a/modules/runners/variables.tf b/modules/runners/variables.tf index 32fe43b6b1..19a8785043 100644 --- a/modules/runners/variables.tf +++ b/modules/runners/variables.tf @@ -28,8 +28,8 @@ variable "environment" { type = string } -variable "distribution_bucket_name" { - description = "Bucket for storing the action runner distribution." +variable "s3_location_runner_distribution" { + description = "S3 location of runner distribution." type = string } @@ -51,11 +51,6 @@ variable "instance_type" { default = "m5.large" } -variable "action_runner_dist_bucket_location" { - description = "Default location action runner distribution." - default = "actions-runner-linux.tar.gz" -} - variable "ami_filter" { description = "List of maps used to create the AMI filter for the action runner AMI." type = map(list(string)) diff --git a/outputs.tf b/outputs.tf index aa0cc34653..24c1ba34a9 100644 --- a/outputs.tf +++ b/outputs.tf @@ -3,6 +3,6 @@ output "runners" { launch_template_name = module.runners.launch_template.name launch_template_id = module.runners.launch_template.id launch_template_version = module.runners.launch_template.latest_version - action_runner_distribution = module.runners.s3_location_runner_distribution + action_runner_distribution = module.dsitrubtion_cache.s3_location_runner_distribution } } From c8eaaeaec2aa8c109edf9e81d7a1eacfd7a049ec Mon Sep 17 00:00:00 2001 From: Niek Palm Date: Mon, 27 Apr 2020 17:24:46 +0200 Subject: [PATCH 08/11] Refactor distribution out of the runner --- modules/action-runner-binary-cache/main.tf | 11 ++++++++++ modules/action-runner-binary-cache/outputs.tf | 7 +++++++ .../action-runner-binary-cache/variables.tf | 21 +++++++++++++++++++ .../action-runner-s3-policy.json | 0 4 files changed, 39 insertions(+) create mode 100644 modules/action-runner-binary-cache/main.tf create mode 100644 modules/action-runner-binary-cache/outputs.tf create mode 100644 modules/action-runner-binary-cache/variables.tf rename modules/runners/policies/instance-runner-s3-policy.json => policies/action-runner-s3-policy.json (100%) diff --git a/modules/action-runner-binary-cache/main.tf b/modules/action-runner-binary-cache/main.tf new file mode 100644 index 0000000000..d2fc57bf2f --- /dev/null +++ b/modules/action-runner-binary-cache/main.tf @@ -0,0 +1,11 @@ +locals { + action_runner_distribution_object_key = "actions-runner-linux.tar.gz" +} + +resource "aws_s3_bucket" "action_dist" { + bucket = var.distribution_bucket_name + acl = "private" + force_destroy = true + tags = var.tags +} + diff --git a/modules/action-runner-binary-cache/outputs.tf b/modules/action-runner-binary-cache/outputs.tf new file mode 100644 index 0000000000..66873c4807 --- /dev/null +++ b/modules/action-runner-binary-cache/outputs.tf @@ -0,0 +1,7 @@ +output "distribution_bucket" { + value = aws_s3_bucket.action_dist +} + +output "s3_location_runner_distribution" { + value = "s3://${aws_s3_bucket.action_dist.id}/${local.action_runner_distribution_object_key}" +} diff --git a/modules/action-runner-binary-cache/variables.tf b/modules/action-runner-binary-cache/variables.tf new file mode 100644 index 0000000000..8fc974a157 --- /dev/null +++ b/modules/action-runner-binary-cache/variables.tf @@ -0,0 +1,21 @@ +variable "aws_region" { + description = "AWS region." + type = string +} + +variable "tags" { + description = "Map of tags that will be added to created resources. By default resources will be tagged with name and environment." + type = map(string) + default = {} +} + +variable "environment" { + description = "A name that identifies the environment, used as prefix and for tagging." + type = string +} + +variable "distribution_bucket_name" { + description = "Bucket for storing the action runner distribution." + type = string +} + diff --git a/modules/runners/policies/instance-runner-s3-policy.json b/policies/action-runner-s3-policy.json similarity index 100% rename from modules/runners/policies/instance-runner-s3-policy.json rename to policies/action-runner-s3-policy.json From c69f42fcf8565e23cb1edc948c0ca872d60352a0 Mon Sep 17 00:00:00 2001 From: Niek Palm Date: Tue, 28 Apr 2020 07:51:03 +0200 Subject: [PATCH 09/11] Update modules/runners/README.md Co-Authored-By: Gertjan Maas --- modules/runners/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/runners/README.md b/modules/runners/README.md index cb85f1a11e..c93a466c10 100644 --- a/modules/runners/README.md +++ b/modules/runners/README.md @@ -2,8 +2,7 @@ The module create resources to facilitate the `orchestrator labmda` to recreate action runners. -- *launch template* : A launch template is creates that can crate an action runner, by default a spot instance is requested. For configuration parameters SSM is used. +- *launch template* : A launch template is created that can create an action runner, by default a spot instance is requested. For configuration parameters SSM is used. - *security group* : Security groups attached to the action runner. - *s3 bucket* : To avoid the action runner distribution have to be download a cached version is expected in a S3 bucket. - *policies and roles* : Policies and roles for the action runner. By default the session manager is enabled - From ee9cf4211eb124aed444e6d390afe393e0ea0304 Mon Sep 17 00:00:00 2001 From: Niek Palm Date: Tue, 28 Apr 2020 07:57:58 +0200 Subject: [PATCH 10/11] Update modules/runners/README.md Co-Authored-By: Gertjan Maas --- modules/runners/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/runners/README.md b/modules/runners/README.md index c93a466c10..e19418db31 100644 --- a/modules/runners/README.md +++ b/modules/runners/README.md @@ -4,5 +4,5 @@ The module create resources to facilitate the `orchestrator labmda` to recreate - *launch template* : A launch template is created that can create an action runner, by default a spot instance is requested. For configuration parameters SSM is used. - *security group* : Security groups attached to the action runner. -- *s3 bucket* : To avoid the action runner distribution have to be download a cached version is expected in a S3 bucket. +- *s3 bucket* : To avoid the action runner distribution to be downloaded from Github every time (which could be slow), a version is cached in a S3 bucket. - *policies and roles* : Policies and roles for the action runner. By default the session manager is enabled From 630af6efc012b90d327727a72bd401ad91156a44 Mon Sep 17 00:00:00 2001 From: Niek Palm Date: Tue, 28 Apr 2020 08:01:04 +0200 Subject: [PATCH 11/11] Review fixes --- main.tf | 22 +++++++++++++++++++++- modules/runners/main.tf | 20 -------------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/main.tf b/main.tf index 4718fb685a..73913bb76c 100644 --- a/main.tf +++ b/main.tf @@ -11,7 +11,7 @@ module "dsitrubtion_cache" { environment = var.environment tags = var.tags - distribution_bucket_name = random_string.random.result + distribution_bucket_name = "${var.environment}-dist-${random_string.random.result}" } module "runners" { @@ -42,3 +42,23 @@ resource "aws_iam_role_policy_attachment" "dist_bucket" { role = module.runners.role.name policy_arn = aws_iam_policy.dist_bucket.arn } + +resource "aws_resourcegroups_group" "resourcegroups_group" { + name = "${var.environment}-group" + + resource_query { + query = <<-JSON +{ + "ResourceTypeFilters": [ + "AWS::AllSupported" + ], + "TagFilters": [ + { + "Key": "Environment", + "Values": ["${var.environment}"] + } + ] +} + JSON + } +} diff --git a/modules/runners/main.tf b/modules/runners/main.tf index 125317caa5..f9e91d6b91 100644 --- a/modules/runners/main.tf +++ b/modules/runners/main.tf @@ -91,23 +91,3 @@ resource "aws_security_group" "runner_sg" { }, ) } - -resource "aws_resourcegroups_group" "resourcegroups_group" { - name = "${var.environment}-group" - - resource_query { - query = <<-JSON -{ - "ResourceTypeFilters": [ - "AWS::AllSupported" - ], - "TagFilters": [ - { - "Key": "ResourceGroup", - "Values": ["${var.environment}"] - } - ] -} - JSON - } -}