Skip to main content

Full Pipeline

Pipeline Overview

The complete pipeline takes code from source to execution in a secure microVM on AWS.

Runner Codes Pipeline

Quick Start

Run the complete pipeline with these commands:

1. Set AWS credentials
export AWS_ACCESS_KEY_ID="your-key"
export AWS_SECRET_ACCESS_KEY="your-secret"
export AWS_DEFAULT_REGION="us-east-1"
2. Build everything locally
task build:all
3. Upload rootfs to S3
task s3:upload
4. Launch EC2 instance
task aws:launch
5. Deploy binaries
task aws:deploy
6. Inject infra.operator into rootfs
task aws:inject-infra-operator
7. Test execution
task aws:test LANG=python CODE='print("Hello from microVM!")'

Pipeline Stages

Stage 1: Build

Build all binaries locally:

Build all binaries
task build:all

This creates:

  • bin/infra.operator - Host-side CLI (darwin)
  • bin/infra.operator-linux - Linux binary for guest (x86_64)

Output:

Build output
Building infra.operator...
go build -o bin/infra.operator ./cmd/infra.operator
Building infra.operator for Linux amd64...
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o bin/infra.operator-linux ./cmd/infra.operator
Build complete!

Stage 2: Create Rootfs Images

Create language-specific rootfs images (requires Linux or EC2):

Create all rootfs images
task aws:create-all-rootfs
Or individual languages
task aws:create-rootfs-python
task aws:create-rootfs-nodejs
task aws:create-rootfs-go
task aws:create-rootfs-rust
task aws:create-rootfs-bash

Each task:

  1. Creates empty ext4 image
  2. Installs Ubuntu minimal
  3. Installs language runtime
  4. Installs infra.operator
  5. Configures systemd service
  6. Uploads to S3

Output:

Rootfs creation output
Creating Python rootfs...
Creating 600MB image file...
Installing Ubuntu 22.04 base...
Installing Python 3.10...
Installing infra.operator...
Configuring systemd service...
Uploading to S3...
upload: rootfs-python.ext4 to s3://llm-infra-operator-rootfs/rootfs-python.ext4
Done!

Stage 3: Upload to S3

Upload all images to S3:

Upload all
task s3:upload
Upload single image
task s3:upload-single LANG=python

S3 Structure:

S3 bucket structure
s3://llm-infra-operator-rootfs/
├── vmlinux # Linux kernel
├── rootfs-python.ext4 # Python rootfs
├── rootfs-nodejs.ext4 # Node.js rootfs
├── rootfs-go.ext4 # Go rootfs
├── rootfs-rust.ext4 # Rust rootfs
└── rootfs-bash.ext4 # Bash rootfs

Stage 4: Launch EC2

Launch a metal instance:

Launch EC2 instance
task aws:launch

This:

  1. Creates security group (firecracker-sg)
  2. Generates SSH key pair
  3. Launches c5.metal instance
  4. Runs user-data script which:
    • Installs Firecracker
    • Loads kernel modules
    • Downloads images from S3
  5. Saves instance ID and IP

Output:

Instance launch output
Creating security group...
Creating key pair...
Launching c5.metal instance...
Waiting for instance to be running...
Instance ID: i-0abc123def456
Public IP: 54.123.45.67
Waiting for setup to complete...
Instance ready!

Stage 5: Deploy Binaries

Deploy infra.operator to EC2:

Deploy binaries to EC2
task aws:deploy

This copies:

  • bin/infra.operator-linux/usr/local/bin/infra.operator

Output:

Deployment output
Deploying to 54.123.45.67...
Copying infra.operator...
Setting permissions...
Deployment complete!

Stage 6: Inject Infra.Operator

Inject infra.operator into all rootfs images:

Inject infra.operator into rootfs
task aws:inject-infra-operator

For each rootfs image:

  1. Mount the ext4 image
  2. Copy infra.operator to /usr/local/bin/
  3. Unmount

Output:

Injection output
Injecting infra.operator into rootfs images...
Processing rootfs-python.ext4...
Processing rootfs-nodejs.ext4...
Processing rootfs-go.ext4...
Processing rootfs-rust.ext4...
Processing rootfs-bash.ext4...
Injection complete!

Stage 7: Test

Run test executions:

Test Python
task aws:test LANG=python CODE='print("Hello Python!")'
Test Node.js
task aws:test LANG=node CODE='console.log("Hello Node!")'
Test Go
task aws:test LANG=go CODE='package main
import "fmt"
func main() { fmt.Println("Hello Go!") }'
Test Rust
task aws:test LANG=rust CODE='fn main() { println!("Hello Rust!"); }'
Test Bash
task aws:test LANG=bash CODE='echo "Hello Bash!"'

Output:

Test execution output
Testing Python execution...
{
"trace_id": "test-py-001",
"stdout": "Hello Python!\n",
"stderr": "",
"exit_code": 0
}
Test successful!

Complete Example

Full pipeline from scratch:

run-pipeline.sh
set -e
echo "=== Runner Codes Full Pipeline ==="
Set AWS credentials
echo "1. Setting up AWS credentials..."
export AWS_ACCESS_KEY_ID="your-key"
export AWS_SECRET_ACCESS_KEY="your-secret"
export AWS_DEFAULT_REGION="us-east-1"
Build binaries
echo "2. Building binaries..."
task build:all
Check S3 bucket
echo "3. Checking S3 bucket..."
task s3:list || {
echo "Creating S3 bucket..."
aws s3 mb s3://llm-infra-operator-rootfs --region us-east-1
}
Upload rootfs images to S3
echo "4. Uploading images to S3..."
task s3:upload
Launch EC2 metal instance
echo "5. Launching EC2 instance..."
task aws:launch
Wait for instance setup
echo "6. Waiting for instance setup (5 minutes)..."
sleep 300
Deploy binaries to EC2
echo "7. Deploying binaries..."
task aws:deploy
Inject infra.operator into rootfs
echo "8. Injecting infra.operator..."
task aws:inject-infra-operator
Run tests for all languages
echo "9. Running tests..."
echo "Testing Python..."
task aws:test LANG=python CODE='print("Hello Python!")'
echo "Testing Node.js..."
task aws:test LANG=node CODE='console.log("Hello Node!")'
echo "Testing Go..."
task aws:test LANG=go CODE='package main; import "fmt"; func main() { fmt.Println("Hello Go!") }'
echo "Testing Bash..."
task aws:test LANG=bash CODE='echo "Hello Bash!"'
echo "=== Pipeline Complete! ==="
echo "Instance IP: $(cat aws/.public-ip)"

Pipeline Diagram

Runner Codes Detailed Pipeline

CI/CD Integration

GitHub Actions

.github/workflows/deploy.yml
# .github/workflows/deploy.yml
name: Deploy Runner Codes

on:
push:
branches: [main]

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version: '1.22'

- name: Install Task
run: |
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin

- name: Build
run: task build:all

- name: Upload to S3
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: us-east-1
run: |
task s3:upload

- name: Deploy to EC2
env:
EC2_HOST: ${{ secrets.EC2_HOST }}
SSH_KEY: ${{ secrets.SSH_KEY }}
run: |
echo "$SSH_KEY" > key.pem
chmod 600 key.pem
scp -i key.pem bin/infra.operator-linux ec2-user@$EC2_HOST:/usr/local/bin/infra.operator

GitLab CI

.gitlab-ci.yml
# .gitlab-ci.yml
stages:
- build
- deploy
- test

build:
stage: build
image: golang:1.22
script:
- go build -o bin/infra.operator ./cmd/infra.operator
- GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o bin/infra.operator-linux ./cmd/infra.operator
artifacts:
paths:
- bin/

deploy:
stage: deploy
script:
- aws s3 sync bin/ s3://llm-infra-operator-rootfs/bin/
- scp bin/infra.operator-linux ec2-user@$EC2_HOST:/usr/local/bin/infra.operator
only:
- main

test:
stage: test
script:
- curl -X POST http://$EC2_HOST:8080/execute -d '{"lang":"python","code":"print(1)"}'
only:
- main

Cleanup

When done, clean up AWS resources:

Terminate instance
task aws:cleanup
Optionally delete S3 bucket
aws s3 rb s3://llm-infra-operator-rootfs --force

Cost Summary

ResourceCostDuration
c5.metal~$4/hrWhile running
S3 storage~$0.02/GB/monthPersistent
Data transfer~$0.09/GBOut to internet

Typical development session:

  • 2 hours of c5.metal: ~$8
  • S3 (10GB): ~$0.20/month
  • Data transfer: ~$0.50
  • Total: ~$8.70