Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prebuilt runner image using packer #1444

Merged
merged 36 commits into from
Dec 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
ccf78b3
Initial creation of runner image
ScottGuymer Nov 25, 2021
563391b
Refactored startup script and added it to the per-boot folder
ScottGuymer Nov 25, 2021
d8da7a4
Make the runner location a variable
ScottGuymer Nov 27, 2021
9a4bb2f
Retrieve external config setting via tags
ScottGuymer Nov 27, 2021
45b4aaa
Enable tag based config
ScottGuymer Nov 27, 2021
17e83d9
Add a CI job
ScottGuymer Nov 27, 2021
64a8b59
Fix the CI build
ScottGuymer Nov 27, 2021
e8b3571
Fix the formatting
ScottGuymer Nov 27, 2021
9d4e660
Retain user_data provisioning and remove duplication
ScottGuymer Nov 29, 2021
f8ad58c
Fix interpolation issues in template file
ScottGuymer Nov 29, 2021
b3d2fcf
fix build
ScottGuymer Nov 29, 2021
9e0612e
Fix formatting
ScottGuymer Nov 29, 2021
8233ca9
minor tweaks and fixes
ScottGuymer Nov 29, 2021
4144634
Fixes from testing
ScottGuymer Nov 30, 2021
80b1b90
Enable docker on boot
ScottGuymer Nov 30, 2021
33e9105
Add in output of start time for the runner
ScottGuymer Nov 30, 2021
af9198f
Scoop up the runner log
ScottGuymer Nov 30, 2021
08a0a66
Add a powershell build script for windows users
ScottGuymer Nov 30, 2021
925ffb9
Fix formatting
ScottGuymer Nov 30, 2021
11f5a2c
Use SSM parameters for configuration
ScottGuymer Dec 1, 2021
72e77dc
Make the SSM policy more specific
ScottGuymer Dec 1, 2021
632de43
Update .github/workflows/packer-build.yml
ScottGuymer Dec 2, 2021
318bdde
Added condition to the describe tags policy
ScottGuymer Dec 2, 2021
eb1910f
Dont use templatefile on the tags policy
ScottGuymer Dec 2, 2021
82db546
Added an option to turn off userdata scripting
ScottGuymer Dec 2, 2021
0f8f114
Added/updated documentation
ScottGuymer Dec 2, 2021
eb15f6b
Revert policy as it has no effect on the permissions
ScottGuymer Dec 2, 2021
280a680
Add reference to prebuilt images in the main readme
ScottGuymer Dec 2, 2021
46918e2
Add an example of deploying with prebuilt images
ScottGuymer Dec 2, 2021
a76731f
Update readme
ScottGuymer Dec 2, 2021
55004cd
Use current user as ami_owner
ScottGuymer Dec 3, 2021
cf44a5e
Update example to 5 secs
ScottGuymer Dec 3, 2021
c155774
Updated ami name to include the arch
ScottGuymer Dec 3, 2021
5d5aaa4
Fixed log file variable
ScottGuymer Dec 3, 2021
49b8a5c
Added explicit info about required settings to the readme
ScottGuymer Dec 3, 2021
8e987a8
Change userdata_enabled to enabled_userdata
ScottGuymer Dec 3, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .ci/build.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
$TOP_DIR=$(git rev-parse --show-toplevel)
$OUTPUT_DIR="$TOP_DIR/lambda_output"

New-Item "$OUTPUT_DIR" -ItemType Directory -ErrorAction SilentlyContinue

$env:DOCKER_BUILDKIT=1
docker build --no-cache --target=final --output=type=local,dest="$OUTPUT_DIR" -f "$TOP_DIR/.ci/Dockerfile" "$TOP_DIR"

2 changes: 2 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[*]
end_of_line = lf
35 changes: 35 additions & 0 deletions .github/workflows/packer-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: "Packer checks"
on:
push:
branches:
- master
- develop
pull_request:
paths:
- "images/**"
- ".github/workflows/packer-build.yml"

env:
AWS_REGION: eu-west-1

jobs:
verify_packer:
name: Verify packer
runs-on: ubuntu-latest
container:
image: hashicorp/packer:1.7.8
defaults:
run:
working-directory: images/linux-amzn2
steps:
- name: "Checkout"
uses: actions/checkout@v2

- name: packer init
run: packer init .

- name: check terraform formatting
run: packer fmt -recursive -check=true .

- name: packer validate
run: packer validate .
2 changes: 1 addition & 1 deletion .github/workflows/terraform.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
fail-fast: false
matrix:
terraform: [0.14.3, 0.15.5, 1.0.8]
example: ["default", "ubuntu"]
example: ["default", "ubuntu", "prebuilt"]
defaults:
run:
working-directory: examples/${{ matrix.example }}
Expand Down
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ This [Terraform](https://www.terraform.io/) module creates the required infrastr
- [Install app](#install-app)
- [Encryption](#encryption)
- [Idle runners](#idle-runners)
- [Prebuilt Images](#prebuilt-images)
- [Examples](#examples)
- [Sub modules](#sub-modules)
- [ARM64 configuration for submodules](#arm64-configuration-for-submodules)
Expand Down Expand Up @@ -265,6 +266,10 @@ idle_config = [{
}]
```

### Prebuilt Images

This module also allows you to run agents from a prebuilt AMI to gain faster startup times. You can find more information in [the image README.md](/images/README.md)

#### Supported config <!-- omit in toc -->

Cron expressions are parsed by [cron-parser](https://github.com/harrisiirak/cron-parser#readme). The supported syntax.
Expand All @@ -289,6 +294,7 @@ Examples are located in the [examples](./examples) directory. The following exam

- _[Default](examples/default/README.md)_: The default example of the module
- _[Permissions boundary](examples/permissions-boundary/README.md)_: Example usages of permissions boundaries.
- _[Prebuilt Images](examples/prebuilt/README.md)_: Example usages of deploying runners with a custom prebuilt image.

## Sub modules

Expand Down Expand Up @@ -346,10 +352,10 @@ In case the setup does not work as intended follow the trace of events:

| Name | Source | Version |
|------|--------|---------|
| <a name="module_runner_binaries"></a> [runner\_binaries](#module\_runner\_binaries) | ./modules/runner-binaries-syncer | n/a |
| <a name="module_runners"></a> [runners](#module\_runners) | ./modules/runners | n/a |
| <a name="module_ssm"></a> [ssm](#module\_ssm) | ./modules/ssm | n/a |
| <a name="module_webhook"></a> [webhook](#module\_webhook) | ./modules/webhook | n/a |
| <a name="module_runner_binaries"></a> [runner\_binaries](#module\_runner\_binaries) | ./modules/runner-binaries-syncer | |
| <a name="module_runners"></a> [runners](#module\_runners) | ./modules/runners | |
| <a name="module_ssm"></a> [ssm](#module\_ssm) | ./modules/ssm | |
| <a name="module_webhook"></a> [webhook](#module\_webhook) | ./modules/webhook | |

## Resources

Expand Down Expand Up @@ -422,6 +428,7 @@ In case the setup does not work as intended follow the trace of events:
| <a name="input_syncer_lambda_s3_key"></a> [syncer\_lambda\_s3\_key](#input\_syncer\_lambda\_s3\_key) | S3 key for syncer lambda function. Required if using S3 bucket to specify lambdas. | `any` | `null` | no |
| <a name="input_syncer_lambda_s3_object_version"></a> [syncer\_lambda\_s3\_object\_version](#input\_syncer\_lambda\_s3\_object\_version) | S3 object version for syncer lambda function. Useful if S3 versioning is enabled on source bucket. | `any` | `null` | no |
| <a name="input_tags"></a> [tags](#input\_tags) | Map of tags that will be added to created resources. By default resources will be tagged with name and environment. | `map(string)` | `{}` | no |
| <a name="input_enabled_userdata"></a> [enabled_userdata](#input\_enabled_userdata) | Should the userdata script be enabled for the runner. Set this to false if you are using your own prebuilt AMI | `bool` | `true` | no |
| <a name="input_userdata_post_install"></a> [userdata\_post\_install](#input\_userdata\_post\_install) | Script to be ran after the GitHub Actions runner is installed on the EC2 instances | `string` | `""` | no |
| <a name="input_userdata_pre_install"></a> [userdata\_pre\_install](#input\_userdata\_pre\_install) | Script to be ran before the GitHub Actions runner is installed on the EC2 instances | `string` | `""` | no |
| <a name="input_userdata_template"></a> [userdata\_template](#input\_userdata\_template) | Alternative user-data template, replacing the default template. By providing your own user\_data you have to take care of installing all required software, including the action runner. Variables userdata\_pre/post\_install are ignored. | `string` | `null` | no |
Expand Down
60 changes: 60 additions & 0 deletions examples/prebuilt/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

83 changes: 83 additions & 0 deletions examples/prebuilt/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Action runners deployment with prebuilt image

This module shows how to create GitHub action runners using a prebuilt AMI for the runners

## Usages

Steps for the full setup, such as creating a GitHub app can be found in the root module's [README](../../README.md).

### Lambdas

You can either download the released lambda code or build them locally yourself.

First download the Lambda releases from GitHub. Ensure you have set the version in `lambdas-download/main.tf` for running the example. The version needs to be set to a GitHub release version, see https://github.com/philips-labs/terraform-aws-github-runner/releases

```bash
cd lambdas-download
terraform init
terraform apply
cd ..
```

Alternatively you can build the lambdas locally with Node or Docker, there is a simple build script in `<root>/.ci/build.sh`. In the `main.tf` you need to specify the build location for all of the zip files.

```hcl
webhook_lambda_zip = "../../lambda_output/webhook.zip"
runner_binaries_syncer_lambda_zip = "../../lambda_output/runner-binaries-syncer.zip"
runners_lambda_zip = "../../lambda_output/runners.zip"
```

### GitHub App Configuration

Before running Terraform, ensure the GitHub app is configured. See the [configuration details](../../README.md#usages) for more details.

### Packer Image

You will need to build your image. This example deployment uses the image example in `/images/linux-amz2`. You must build this image with packer in your AWS account first. Once you have built this you need to provider your owner ID as a variable

## Deploy

To use your image in the terraform modules you will need to set some values on the module.

Assuming you have built the `linux-amzn2` image which has a pre-defined AMI name in the following format `github-runner-amzn2-x86_64-YYYYMMDDhhmm` you can use the following values.

```hcl

module "runners" {
...
# set the name of the ami to use
ami_filter = { name = ["github-runner-amzn2-x86_64-2021*"] }
# provide the owner id of
ami_owners = ["<your owner id>"]

enabled_userdata = false
...
}
```

If your owner is the same as the account you are logging into then you can use `aws_caller_identity` to retrieve it dynamically.

```hcl
data "aws_caller_identity" "current" {}

module "runners" {
...
ami_owners = [data.aws_caller_identity.current.account_id]
...
}
```

You can then deploy the terraform

```bash
terraform init
terraform apply
```

You can receive the webhook details by running:

```bash
terraform output -raw webhook_secret
```

Be-aware some shells will print some end of line character `%`.
25 changes: 25 additions & 0 deletions examples/prebuilt/lambdas-download/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
locals {
version = "<REPLACE_BY_GITHUB_RELEASE_VERSION>"
}

module "lambdas" {
source = "../../../modules/download-lambda"
lambdas = [
{
name = "webhook"
tag = local.version
},
{
name = "runners"
tag = local.version
},
{
name = "runner-binaries-syncer"
tag = local.version
}
]
}

output "files" {
value = module.lambdas.files
}
46 changes: 46 additions & 0 deletions examples/prebuilt/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
locals {
environment = "prebuilt"
aws_region = "eu-west-1"
}

resource "random_password" "random" {
length = 28
}

data "aws_caller_identity" "current" {}

module "runners" {
source = "../../"
create_service_linked_role_spot = true
aws_region = local.aws_region
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnets

environment = local.environment

github_app = {
key_base64 = var.github_app_key_base64
id = var.github_app_id
webhook_secret = random_password.random.result
}

webhook_lambda_zip = "../../lambda_output/webhook.zip"
runner_binaries_syncer_lambda_zip = "../../lambda_output/runner-binaries-syncer.zip"
runners_lambda_zip = "../../lambda_output/runners.zip"

runner_extra_labels = "default,example"

# configure your pre-built AMI
enabled_userdata = false
ami_filter = { name = ["github-runner-amzn2-x86_64-2021*"] }
ami_owners = [data.aws_caller_identity.current.account_id]

# enable access to the runners via SSM
enable_ssm_on_runners = true

# override delay of events in seconds
delay_webhook_event = 5

# override scaling down
scale_down_schedule_expression = "cron(* * * * ? *)"
}
15 changes: 15 additions & 0 deletions examples/prebuilt/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
output "runners" {
value = {
lambda_syncer_name = module.runners.binaries_syncer.lambda.function_name
}
}

output "webhook_endpoint" {
value = module.runners.webhook.endpoint
}

output "webhook_secret" {
sensitive = true
value = random_password.random.result
}

3 changes: 3 additions & 0 deletions examples/prebuilt/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
provider "aws" {
region = local.aws_region
}
4 changes: 4 additions & 0 deletions examples/prebuilt/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

variable "github_app_key_base64" {}

variable "github_app_id" {}
15 changes: 15 additions & 0 deletions examples/prebuilt/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 3.27"
}
local = {
source = "hashicorp/local"
}
random = {
source = "hashicorp/random"
}
}
required_version = ">= 0.14"
}
7 changes: 7 additions & 0 deletions examples/prebuilt/vpc.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module "vpc" {
source = "git::https://github.com/philips-software/terraform-aws-vpc.git?ref=2.2.0"

environment = local.environment
aws_region = local.aws_region
create_private_hosted_zone = false
}
Loading