Files
harmony/docs/use-cases/rustfs-on-local-k3d.md

4.5 KiB

Use Case: RustFS (S3-Compatible Store) on Local K3D

Deploy a RustFS object store on a local Kubernetes cluster (K3D) using Harmony. RustFS is a Rust-based S3-compatible storage server, a modern alternative to MinIO for local development.

What you'll have at the end

A fully operational S3-compatible object store with:

  • 1 standalone instance with 1 GiB of storage
  • S3 API endpoint on port 9000
  • Web console on port 9001
  • Ingress-based access at http://rustfs.local
  • Default credentials: rustfsadmin / rustfsadmin

Prerequisites

  • Rust 2024 edition
  • Docker running locally
  • ~5 minutes

The Score

The entire deployment is expressed in ~20 lines of Rust:

use harmony::{
    inventory::Inventory,
    modules::rustfs::{K8sRustFsScore, RustFsConfig},
    topology::K8sAnywhereTopology,
};

#[tokio::main]
async fn main() {
    let rustfs = K8sRustFsScore {
        config: RustFsConfig {
            release_name: "harmony-rustfs".to_string(),
            namespace: "harmony-rustfs".to_string(),
            ..Default::default()
        },
    };

    harmony_cli::run(
        Inventory::autoload(),
        K8sAnywhereTopology::from_env(),
        vec![Box::new(rustfs)],
        None,
    )
    .await
    .unwrap();
}

What Harmony does

When you run this, Harmony:

  1. Connects to K8sAnywhereTopology — auto-provisions a K3D cluster if none exists
  2. Creates a namespaceharmony-rustfs (or your custom namespace)
  3. Creates credentials secret — stores the access/secret keys securely
  4. Deploys via Helm — installs the RustFS chart in standalone mode
  5. Configures Ingress — sets up routing at rustfs.local

Running it

cargo run -p example-rustfs

Verifying the deployment

# Check pods
kubectl get pods -n harmony-rustfs

# Check ingress
kubectl get ingress -n harmony-rustfs

# Access the S3 API
# Add rustfs.local to your /etc/hosts
echo "127.0.0.1 rustfs.local" | sudo tee -a /etc/hosts

# Use the AWS CLI or any S3 client
AWS_ACCESS_KEY_ID=rustfsadmin \
AWS_SECRET_ACCESS_KEY=rustfsadmin \
aws s3 ls --endpoint-url http://rustfs.local:9000

# Or via the web console
open http://rustfs.local:9001

Customizing the deployment

The RustFsConfig struct supports:

Field Default Description
release_name rustfs Helm release name
namespace harmony-rustfs Kubernetes namespace
storage_size 1Gi Data storage size
mode Standalone Deployment mode (standalone only for now)
access_key None S3 access key (default: rustfsadmin)
secret_key None S3 secret key (default: rustfsadmin)
ingress_class None Ingress class to use (default: nginx)

Example with custom credentials:

let rustfs = K8sRustFsScore {
    config: RustFsConfig {
        release_name: "my-rustfs".to_string(),
        namespace: "storage".to_string(),
        access_key: Some("myaccess".to_string()),
        secret_key: Some("mysecret".to_string()),
        ingress_class: Some("traefik".to_string()),
        ..Default::default()
    },
};

Architecture

The RustFS module follows the same pattern as PostgreSQL:

┌─────────────────────────────────────────────────────────────┐
│ K8sRustFsScore (user-facing)                               │
│  └── K8sRustFsInterpret                                   │
│       ├── ensure_namespace()                               │
│       ├── ensure_secret() → K8sResourceScore              │
│       └── HelmChartScore → HelmChartInterpret             │
│            └── Installs rustfs/rustfs chart               │
└─────────────────────────────────────────────────────────────┘

Future: Unified S3 Capability

This is the first step toward a unified S3 capability that will work with:

  • RustFS — local development (this example)
  • Ceph RGW — production S3 via Rook/Ceph
  • AWS S3 — cloud-native S3

The pattern will be:

// Future: unified S3 interface
trait S3Store: Send + Sync {
    async fn deploy_bucket(&self, config: &BucketConfig) -> Result<(), String>;
    async fn get_endpoint(&self) -> Result<S3Endpoint, String>;
}

See the Scores Catalog for related components.