AizuDemy

Tutorial Deploy Microservice WebAssembly Pakai Spin & Rust di VPS Linux

Tutorial Deploy Microservice WebAssembly Pakai Spin & Rust di VPS Linux
๐ŸŽง
Dengarkan Artikel Ini
Suara AI Otomatis โ€ข 6 mnt baca baca
โšก TL;DR

Poin Kunci Artikel Ini:

  • Overhead Resource Container: Docker vs WebAssembly SandboxDocker standar industri isolasi microservice.
  • Container jalankan OS userspace, dependency library, dan container engine runtime.
  • Implikasi: overhead konsumsi memory tinggi.
๐Ÿ“‹ Daftar Isi Materi Tutup โ–ด

Overhead Resource Container: Docker vs WebAssembly Sandbox

Docker standar industri isolasi microservice. Container jalankan OS userspace, dependency library, dan container engine runtime. Implikasi: overhead konsumsi memory tinggi. VPS spesifikasi entry-level (1 vCPU, 512MB RAM) cepat alami Out Of Memory (OOM) saat jalankan 3-5 container Docker bersamaan.

WebAssembly (Wasm) dengan WASI (WebAssembly System Interface) ubah paradigma eksekusi server-side. Rust kompilasi kode langsung ke bytecode Wasm platform-agnostic. Wasmtime jalankan bytecode langsung di atas kernel host tanpa OS virtualization. Sandboxing berlaku pada level instruction set dan linear memory space. Akses sistem (network, disk, environment variable) diblokir total kecuali diizinkan eksplisit.

Metric PerformaDocker Container (Minimal App)WASM Spin Microservice
Memory Footprint (Idle)50 MB - 150 MB3 MB - 8 MB
Cold Start Time1000 ms - 3000 ms< 1 ms
Ukuran Artifact Binary100 MB - 500 MB1 MB - 5 MB
Isolasi KeamananKernel cgroups & namespacesCapability-based WASI sandbox
Density Per Core VPS10 - 20 Container100 - 500 Instance

Arsitektur Execution Model: Spin Framework & Wasmtime Engine

Spin framework buatan Fermyon pakai Wasmtime sebagai execution engine underlying. Spin terapkan trigger model untuk handle HTTP request. Request masuk ke Spin HTTP listener, dioper ke instansi Wasm component melalui memory snapshot instant, lalu diproses fungsi handler Rust. Setelah response dikirim, instansi memory di-wipe instan.

Metode instansiasi copy-on-write Wasmtime hilangkan overhead proses booting app. Startup latency turun ke skala sub-milidetik (~100 microsecond). Pola ini izinkan ratusan service aktif bersamaan pada server spesifikasi minim tanpa kuras RAM.

Praktek Build Microservice HTTP Spin Rust & Deploy ke VPS

1. Setup Toolchain Local Machine

Pasang Rust toolchain, target kompilasi WASI, dan Spin CLI pada mesin lokal pengembang.

# Install Rust toolchain
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source $HOME/.cargo/env

# Tambahkan target wasm32-wasip1
rustup target add wasm32-wasip1

# Install Spin CLI
curl -fsSL https://developer.fermyon.com/downloads/install.sh | bash
sudo mv ./spin /usr/local/bin/

2. Inisialisasi Project Spin Rust & Struktur Kode

Buat project baru pakai template http-rust:

spin new -t http-rust my-wasm-api --accept-defaults
cd my-wasm-api

Edit manifest spin.toml untuk konfigurasi routing dan kapabilitas akses:

spin_manifest_version = 2

[application]
name = "my-wasm-api"
version = "1.0.0"
authors = ["Dev Team <dev@example.com>"]

[[trigger.http]]
route = "/..."
component = "my-wasm-api"

[component.my-wasm-api]
source = "target/wasm32-wasip1/release/my_wasm_api.wasm"
[component.my-wasm-api.build]
command = "cargo build --target wasm32-wasip1 --release"
watch = ["src/**/*.rs", "Cargo.toml"]

Edit Cargo.toml untuk optimasi ukuran binary Wasm:

[package]
name = "my-wasm-api"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
spin-sdk = "3.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

[profile.release]
opt-level = "z"
lto = true
codegen-units = 1
panic = "abort"

Tulis logika handler HTTP JSON pada src/lib.rs:

use spin_sdk::http::{Fields, Request, Response, IntoResponse};
use spin_sdk::http_component;
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct HealthResponse {
    status: String,
    runtime: String,
    framework: String,
    memory_usage_approx: String,
}

#[http_component]
fn handle_my_wasm_api(req: Request) -> impl IntoResponse {
    println!("LOG: Request masuk URI: {:?}", req.uri());

    let payload = HealthResponse {
        status: "ok".to_string(),
        runtime: "Wasmtime WASI".to_string(),
        framework: "Spin 3.0".to_string(),
        memory_usage_approx: "< 5MB".to_string(),
    };

    let json_body = match serde_json::to_string(&payload) {
        Ok(body) => body,
        Err(_) => return Response::builder()
            .status(500)
            .header("content-type", "text/plain")
            .body("Internal Server Error")
            .build(),
    };

    Response::builder()
        .status(200)
        .header("content-type", "application/json")
        .header("x-wasm-engine", "wasmtime")
        .body(json_body)
        .build()
}

3. Build Artifact WASM & Optimisasi Binary

Jalankan proses kompilasi binary Wasm:

spin build

Kompilasi hasilkan file target/wasm32-wasip1/release/my_wasm_api.wasm. Kompresi ukuran binary pakai tool wasm-opt jika binaryen terinstall:

wasm-opt -Oz target/wasm32-wasip1/release/my_wasm_api.wasm -o target/wasm32-wasip1/release/my_wasm_api.wasm

Konfigurasi Systemd, Nginx Reverse Proxy, & Benchmark Resource

1. Deploy ke VPS & Setup Systemd Service

Transfer berkas project ke VPS Linux menggunakan rsync:

rsync -avz --exclude='target' ./my-wasm-api user@vps-ip-address:/opt/my-wasm-api

Login via SSH ke VPS, install Spin CLI di VPS, lalu buat unit file systemd /etc/systemd/system/spin-app.service:

[Unit]
Description=Spin WebAssembly Microservice Engine
After=network.target

[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/my-wasm-api
ExecStart=/usr/local/bin/spin up --listen 127.0.0.1:8080
Restart=always
RestartSec=3
LimitNOFILE=65535
CapabilityBoundingSet=
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/my-wasm-api

[Install]
WantedBy=multi-user.target

Muat ulang daemon systemd dan jalankan service:

sudo systemctl daemon-reload
sudo systemctl enable --now spin-app
sudo systemctl status spin-app

2. Konfigurasi Nginx Reverse Proxy

Pasang Nginx sebagai reverse proxy front-facing untuk atasi SSL termination dan header routing. Buat file /etc/nginx/sites-available/spin-api:

server {
    listen 80;
    server_name api.domainAnda.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'keep-alive';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }
}

Aktifkan konfigurasi Nginx dan reload service:

sudo ln -s /etc/nginx/sites-available/spin-api /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

3. Load Testing & Profiling Resource

Uji ketahanan service dari client luar menggunakan tool benchmark hey:

hey -n 100000 -c 500 http://api.domainAnda.com/

Pantau penggunaan CPU dan RAM via htop atau systemd-cgtop pada VPS saat pengujian berlangsung.

  • Throughput: Mencapai 12.000 - 18.000 Request/second pada VPS 1 vCPU.
  • RAM Usage: Alokasi memory total proses Spin tetap stabil pada kisaran 8MB - 12MB meski menangani 500 concurrent connections.
  • Error Rate: 0% dropped connection under high concurrency.

Mitigasi Limitas WASI & Keamanan Level Capability

Sistem keamanan WASI bersifat deny-all default. Aplikasi Wasm tidak bisa panggil socket jaringan atau akses sistem berkas VPS tanpa deklarasi tegas di spin.toml.

1. Outbound Network Access

WASI memblokir request HTTP outbound secara bawaan. Izinkan endpoint spesifik di spin.toml:

[component.my-wasm-api]
source = "target/wasm32-wasip1/release/my_wasm_api.wasm"
allowed_outbound_hosts = [
    "https://api.stripe.com",
    "https://api.sendgrid.com",
    "postgres://db.example.com:5432"
]

2. Akses Database Persistence

WASI Preview 1 belum mendukung socket TCP arbitrer secara native tanpa abstraction layer. Opsi integrasi database:

  • Spin Key-Value Store: Pakai key-value bawaan Spin backed by SQLite/Redis.
    key_value_stores = ["default"]
  • HTTP-based Database API: Akses Supabase, PlanetScale, atau HTTP Relational Proxy.
  • WASI Postgres Driver: Gunakan driver PostgreSQL murni Rust yang dikompilasi khusus ke target WASI socket layer.

3. System File Access Sandbox

Petakan direktori lokal yang diizinkan dibaca aplikasi:

[component.my-wasm-api]
files = [ { source = "assets/static", destination = "/static