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

Add AL2023 minimal AMI (beta) #46

Merged
merged 4 commits into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
60 changes: 60 additions & 0 deletions .github/workflows/build_aws_minimal_manual.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: AWS minimal AMI manual publish

on:
workflow_dispatch:

jobs:
timestamp:
name: Get the build timestamp
runs-on: ubuntu-latest
outputs:
timestamp: ${{ steps.timestamp.outputs.timestamp }}
steps:
- name: Get the timestamp
id: timestamp
run: echo "timestamp=$(date +%s)" >> $GITHUB_OUTPUT

build:
# Since we run in parallel, let's make sure we use the same timestamp for all jobs
needs: timestamp
strategy:
matrix:
arch: [x86_64, arm64]
name: Build the AWS AMI using Packer
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- name: Check out the source code
uses: actions/checkout@main

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: ${{ secrets.AWS_REGION }}
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
role-duration-seconds: 3600

- name: Setup packer
uses: hashicorp/setup-packer@main
with:
version: latest

- name: Initialize Packer
run: packer init aws_minimal.pkr.hcl

- name: Build the AWS AMI using Packer (${{ matrix.arch }})
run: packer build aws_minimal.pkr.hcl
env:
PKR_VAR_encrypt_boot: false
PKR_VAR_ami_name_prefix: minimal-beta-spacelift-${{ needs.timestamp.outputs.timestamp }}
PKR_VAR_source_ami_architecture: ${{ matrix.arch }}
PKR_VAR_instance_type: ${{ matrix.arch == 'x86_64' && 't3.micro' || 't4g.micro' }}

- name: Upload manifest
uses: actions/upload-artifact@v3
with:
path: manifest_aws_minimal_${{ matrix.arch }}.json
name: manifest_aws_minimal_${{ matrix.arch }}.json
retention-days: 5
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
name: 👷 ${{ matrix.cloud }}
strategy:
matrix:
cloud: [aws, azure, gcp]
cloud: [aws, aws_minimal, azure, gcp]
runs-on: ubuntu-latest
env:
# AWS
Expand Down
151 changes: 151 additions & 0 deletions aws_minimal.pkr.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
packer {
required_plugins {
amazon-ami-management = {
version = "2.0.0"
source = "github.com/spacelift-io/amazon-ami-management"
}
}
}

variable "ami_name_prefix" {
type = string
default = "minimal-spacelift-{{timestamp}}"
}

variable "ami_regions" {
type = list(string)
default = [
"eu-west-1"
]
}

variable "source_ami_architecture" {
type = string
default = "x86_64"
}

variable "source_ami_owners" {
type = list(string)
default = ["137112412989"] # defaults to Amazon for Amazon Linux, see https://docs.aws.amazon.com/AmazonECR/latest/userguide/amazon_linux_container_image.html
}

variable "ami_groups" {
type = list(string)
default = ["all"]
}

variable "instance_type" {
type = string
default = "t3.micro"
}

variable "encrypt_boot" {
type = bool
default = true
}

variable "shared_credentials_file" {
type = string
default = null
}

variable "subnet_filter" {
type = map(string)
default = null
}

variable "additional_tags" {
type = map(string)
default = {}
}

variable "region" {
type = string
default = "eu-west-1"
}

variable "vpc_id" {
type = string
default = null
}

source "amazon-ebs" "spacelift" {
source_ami_filter {
filters = {
virtualization-type = "hvm"
name = "al2023-ami-minimal-*-kernel-6.1-${var.source_ami_architecture}"
root-device-type = "ebs"
architecture = var.source_ami_architecture
}
owners = var.source_ami_owners
most_recent = true
}

ami_name = "${var.ami_name_prefix}-${var.source_ami_architecture}"
ami_regions = var.ami_regions
ami_groups = var.ami_groups
ami_description = <<EOT
[BETA VERSION] PLEASE DO NOT USE IN PRODUCTION!!!
Spacelift AMI built for ${var.source_ami_architecture}-based private worker pools.
It contains all the neccessary tools to run Spacelift workers.
More information: https://docs.spacelift.io.
EOT

shared_credentials_file = var.shared_credentials_file
encrypt_boot = var.encrypt_boot
instance_type = var.instance_type
ssh_username = "ec2-user"

vpc_id = var.vpc_id
region = var.region

deprecate_at = timeadd(timestamp(), "8736h") # 52 weeks (1 year)

dynamic "subnet_filter" {
for_each = var.subnet_filter == null ? [] : [1]
content {
filters = var.subnet_filter
most_free = true
random = false
}
}

tags = merge(var.additional_tags, {
Architecture = var.source_ami_architecture
Name = "Spacelift minimal AMI"
Purpose = "Spacelift"
BaseAMI = "{{ .SourceAMI }}"
})
}

build {
sources = ["source.amazon-ebs.spacelift"]

provisioner "file" {
source = "aws_minimal/configs/"
destination = "/tmp"
}

provisioner "shell" {
scripts = [
"shared/scripts/data-directories.sh",
"aws_minimal/scripts/dnf-update.sh",
"aws_minimal/scripts/docker.sh",
"shared/scripts/gvisor.sh",
"aws_minimal/scripts/cloudwatch-agent.sh",
"aws_minimal/scripts/ssm-agent.sh"
]
}

post-processor "amazon-ami-management" {
# Deregister old AMIs, keep only the latest 180.
regions = var.ami_regions
tag_key = "Name"
tag_value = "Spacelift minimal AMI"
keep_releases = 180
}

post-processor "manifest" {
output = "manifest_aws_minimal_${var.source_ami_architecture}.json"
}
}
134 changes: 134 additions & 0 deletions aws_minimal/configs/amazon-cloudwatch-agent.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
{
"agent": {
"logfile": "/opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log",
"metrics_collection_interval": 10,
"run_as_user": "root"
},
"metrics": {
"namespace": "DefaultWorkerPool",
"metrics_collected": {
"cpu": {
"resources": ["*"],
"measurement": [
{
"name": "cpu_usage_idle",
"rename": "CPU_USAGE_IDLE",
"unit": "Percent"
},
{
"name": "cpu_usage_nice",
"unit": "Percent"
},
"cpu_usage_guest"
],
"totalcpu": false,
"metrics_collection_interval": 10
},
"disk": {
"resources": ["/", "/tmp"],
"measurement": [
{
"name": "free",
"rename": "DISK_FREE",
"unit": "Gigabytes"
},
"total",
"used"
],
"ignore_file_system_types": ["sysfs", "devtmpfs"],
"metrics_collection_interval": 60
},
"diskio": {
"resources": ["*"],
"measurement": [
"reads",
"writes",
"read_time",
"write_time",
"io_time"
],
"metrics_collection_interval": 60
},
"swap": {
"measurement": [
"swap_used",
"swap_free",
"swap_used_percent"
]
},
"mem": {
"measurement": [
"mem_used",
"mem_cached",
"mem_total"
],
"metrics_collection_interval": 10
},
"net": {
"resources": [
"eth0"
],
"measurement": [
"bytes_sent",
"bytes_recv",
"drop_in",
"drop_out"
]
},
"netstat": {
"measurement": [
"tcp_established",
"tcp_syn_sent",
"tcp_close"
],
"metrics_collection_interval": 60
},
"processes": {
"measurement": [
"running",
"sleeping",
"dead"
]
}
},
"append_dimensions": {
"ImageId": "${aws:ImageId}",
"InstanceId": "${aws:InstanceId}",
"InstanceType": "${aws:InstanceType}",
"AutoScalingGroupName": "${aws:AutoScalingGroupName}"
},
"aggregation_dimensions": [
["ImageId"],
["InstanceId", "InstanceType"],
[]
],
"force_flush_interval": 30
},
"logs": {
"logs_collected": {
"files": {
"collect_list": [
{
"file_path": "/var/log/spacelift/error.log",
"log_group_name": "spacelift-errors.log",
"log_stream_name": "{instance_id}-{ip_address}",
"timezone": "UTC"
},
{
"file_path": "/var/log/spacelift/info.log",
"log_group_name": "spacelift-info.log",
"log_stream_name": "{instance_id}-{ip_address}",
"timezone": "UTC"
},
{
"file_path": "/opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log",
"log_group_name": "amazon-cloudwatch-agent.log",
"log_stream_name": "{instance_id}-{ip_address}",
"timezone": "UTC"
}
]
}
},
"force_flush_interval" : 15
}
}
20 changes: 20 additions & 0 deletions aws_minimal/scripts/cloudwatch-agent.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
CONFIG_DESTINATION=/opt/aws/amazon-cloudwatch-agent/bin/config.json
CONFIG_SOURCE=/tmp/amazon-cloudwatch-agent.json

CURRENTARCH=$(uname -m)
if [ "$CURRENTARCH" = "aarch64" ] || [ "$CURRENTARCH" = "arm64" ]; then
CURRENTARCH="arm64"
else
CURRENTARCH="amd64"
fi

DOWNLOAD_URL=https://s3.amazonaws.com/amazoncloudwatch-agent/amazon_linux/${CURRENTARCH}/latest/amazon-cloudwatch-agent.rpm
RPM_PATH=/tmp/amazon-cloudwatch-agent.rpm

sudo touch /var/log/spacelift/{info,error}.log

curl $DOWNLOAD_URL --output $RPM_PATH
sudo rpm -U $RPM_PATH
rm $RPM_PATH
sudo mv ${CONFIG_SOURCE} ${CONFIG_DESTINATION}
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:${CONFIG_DESTINATION}
peterdeme marked this conversation as resolved.
Show resolved Hide resolved
3 changes: 3 additions & 0 deletions aws_minimal/scripts/dnf-update.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# This script updates the installed packages and package cache on the instance.

sudo dnf update -y
4 changes: 4 additions & 0 deletions aws_minimal/scripts/docker.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# This script installs and starts Docker.

sudo dnf install -y docker
sudo systemctl enable --now docker
10 changes: 10 additions & 0 deletions aws_minimal/scripts/ssm-agent.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
CURRENTARCH=$(uname -m)
if [ "$CURRENTARCH" = "aarch64" ] || [ "$CURRENTARCH" = "arm64" ]; then
CURRENTARCH="arm64"
else
CURRENTARCH="amd64"
fi

sudo dnf install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_${CURRENTARCH}/amazon-ssm-agent.rpm

sudo systemctl status amazon-ssm-agent
Loading