151 lines
4.5 KiB
Markdown
151 lines
4.5 KiB
Markdown
# 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:
|
|
|
|
```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 namespace** — `harmony-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
|
|
|
|
```bash
|
|
cargo run -p example-rustfs
|
|
```
|
|
|
|
## Verifying the deployment
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```rust
|
|
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:
|
|
|
|
```rust
|
|
// 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](../catalogs/scores.md) for related components. |