Menggunakan AWS Spot Instance sebagai CI/CD Runner
4 min read

Menggunakan AWS Spot Instance sebagai CI/CD Runner

Solusi Efisien untuk Pipeline Berat (Terraform, Sonar, Java, dll)

Dalam banyak organisasi, CI/CD pipeline perlahan berubah dari sekadar build & test menjadi mini data center sementara:

  • Terraform → plan/apply besar, provider banyak
  • SonarQube → static analysis berat, butuh CPU & RAM tinggi
  • Java / Gradle / Maven → build lambat, memory hungry
  • Docker build → layer besar, I/O intensif

Masalah klasik yang sering muncul:

  1. Runner self-hosted mahal

    • Harus always-on
    • Over-provisioned demi peak load
  2. Shared runner bottleneck

    • Job saling antre
    • Pipeline makin lama → developer frustrasi
  3. Inefficient cost

    • Resource besar tapi dipakai sebentar
    • Idle > 70% waktu

Dari sinilah ide menggunakan AWS Spot Instance sebagai ephemeral CI/CD runner jadi sangat masuk akal.


Kenapa Spot Instance Cocok untuk CI/CD?

Karakteristik CI/CD Job

CI/CD job umumnya:

  • Stateless
  • Ephemeral
  • Bisa di-retry
  • Tidak butuh uptime panjang

Ini sangat cocok dengan karakteristik Spot Instance:

  • Harga hingga 70–90% lebih murah
  • Bisa terminate kapan saja
  • Tidak cocok untuk long-running critical workload

CI/CD runner yang:

dibuat → dipakai → dihancurkan adalah spot workload by design.


Konsep Arsitektur

Garis besar arsitekturnya:

GitHub Action Trigger
        |
        v
Request Runner
        |
        v
AWS EC2 Spot Instance
(Self-hosted Runner)
        |
        v
Run CI Job
        |
        v
Terminate Instance

Prinsip utamanya:

  • Runner tidak selalu hidup
  • Runner dibuat hanya saat job akan jalan
  • Runner mati setelah job selesai

Manfaat Utama

Cost Reduction yang Signifikan

Contoh kasar:

Instance TypeOn-DemandSpot
c6i.4xlarge~$0.68/hr~$0.18/hr

CI job 15 menit:

  • On-Demand: ~$0.17
  • Spot: ~$0.045

Kalikan ratusan pipeline per hari → penghematan brutal.

Scalability Tanpa Drama

  • Parallel job? → parallel instance
  • Tidak perlu mikir capacity planning runner
  • Tidak ada antrean panjang

Clean Environment per Job

Setiap job:

  • VM fresh
  • Tidak ada “sisa state”
  • Lebih reproducible
  • Lebih aman (credential tidak bocor antar job)

Risiko & Trade-off (Harus Jujur)

Spot Interruption

AWS bisa terminate instance kapan saja (2 menit notice).

Mitigasi:

  • Job idempotent

  • Retry strategy di GitHub Actions

  • Split pipeline (build → test → deploy)

  • Jangan pakai untuk:

    • Production deploy critical tanpa retry
    • Long migration job

Startup Time

  • Cold start EC2 ±1–2 menit

Solusi:

  • Custom AMI (runner + tools sudah terinstall)
  • Atau snapshot golden image

Kompleksitas Setup

  • Lebih kompleks dibanding shared runner
  • Tapi worth it untuk workload berat

Contoh Implementasi: GitHub Actions + AWS Spot Runner

Gunakan ephemeral self-hosted runner:

  • 1 workflow untuk:

    • Request EC2 Spot
    • Register runner ke GitHub
  • Runner otomatis self-terminate setelah job

IAM Role untuk EC2

EC2 butuh permission:

  • Register GitHub runner
  • Terminate dirinya sendiri

Contoh policy minimal:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:TerminateInstances"
      ],
      "Resource": "*"
    }
  ]
}

User Data Script (Runner Bootstrap)

Contoh user-data.sh:

#!/bin/bash
set -e

# Install dependencies
yum update -y
yum install -y docker git jq
systemctl start docker

# Install GitHub Runner
RUNNER_VERSION="2.316.0"
mkdir /actions-runner
cd /actions-runner

curl -o actions-runner.tar.gz -L \
  https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz

tar xzf actions-runner.tar.gz

# Register runner
./config.sh \
  --url https://github.com/ORG/REPO \
  --token ${RUNNER_TOKEN} \
  --name spot-runner-$(hostname) \
  --labels spot,large \
  --unattended \
  --ephemeral

# Run runner
./run.sh

# After job finish, terminate instance
INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
aws ec2 terminate-instances --instance-ids $INSTANCE_ID --region ap-southeast-1

--ephemeral penting supaya runner auto-unregister.

GitHub Action – Request Spot Instance

Workflow contoh:

name: Heavy CI with Spot Runner

on:
  workflow_dispatch:
  push:
    branches: [ main ]

jobs:
  request-runner:
    runs-on: ubuntu-latest
    outputs:
      runner-label: ${{ steps.set-label.outputs.label }}
    steps:
      - id: set-label
        run: echo "label=spot" >> $GITHUB_OUTPUT

      - name: Launch Spot Instance
        run: |
          aws ec2 run-instances \
            --instance-type c6i.4xlarge \
            --image-id ami-xxxx \
            --instance-market-options MarketType=spot \
            --iam-instance-profile Name=ci-runner-role \
            --user-data file://user-data.sh \
            --region ap-southeast-1          

  build:
    needs: request-runner
    runs-on: [self-hosted, spot]
    steps:
      - uses: actions/checkout@v4

      - name: Terraform Plan
        run: terraform plan

      - name: Sonar Scan
        run: ./gradlew sonar

Best Practice Tambahan

Gunakan Label Runner

Pisahkan:

  • spot-small
  • spot-large
  • spot-java

Supaya workflow jelas resource-nya.


Custom AMI

Preinstall:

  • Java
  • Terraform
  • Docker
  • Sonar scanner

Startup time jauh lebih cepat.


Retry Strategy

strategy:
  fail-fast: false
  max-parallel: 3

Dan di level job:

timeout-minutes: 60

Kapan Pendekatan Ini Sangat Layak?

✅ Sangat direkomendasikan jika:

  • CI berat
  • Cost mulai tidak masuk akal
  • Banyak parallel job
  • Tim mature secara DevOps

❌ Kurang cocok jika:

  • CI kecil & jarang
  • Tim belum siap operasional EC2
  • Tidak toleran terhadap retry

Kesimpulan

Menggunakan AWS Spot Instance sebagai CI/CD runner bukan sekadar optimasi cost — ini perubahan mindset:

CI/CD bukan server permanen, tapi compute on demand.

Dengan pendekatan ini:

  • Pipeline lebih cepat
  • Cost jauh lebih murah
  • Infrastructure lebih bersih
  • Developer experience naik

Dan yang paling penting: resource besar dipakai hanya saat dibutuhkan, bukan 24/7.