Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions content/de/developer/integration/ai/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ Nutzen Sie **RustFS** als Objektspeicher-Layer für KI- und Machine-Learning-Pla
## Plattformen

- [Ray](./ray.md)
- [vLLM](./vllm.md)

Speichern Sie Trainingsdaten und Checkpoints in dedizierten Buckets und beschränken Sie die Anmeldeinformationen auf die erforderlichen Bucket-Operationen.
3 changes: 2 additions & 1 deletion content/de/developer/integration/ai/meta.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"title": "AI",
"pages": [
"ray"
"ray",
"vllm"
]
}
154 changes: 154 additions & 0 deletions content/de/developer/integration/ai/vllm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
---
title: "vLLM"
description: "Serve LLM inference with vLLM loading model weights stored in RustFS."
---

This guide connects [vLLM](https://github.com/vllm-project/vllm) — the high-throughput LLM inference engine — to **RustFS** as its model-weight store. You will upload a model into a RustFS bucket, expose the bucket to the vLLM host through an rclone mount, and serve the model with the OpenAI-compatible API. The workflow was verified with `vllm/vllm-openai-cpu` (vLLM 0.30.0) serving `facebook/opt-125m` from a RustFS bucket backed by `rustfs/rustfs-x86-musl:v2.3.1`, on a CPU-only host.

You need Docker and an rclone binary on the host that runs vLLM. This deployment is intended for local integration testing, not production.

## Architecture

```mermaid
flowchart LR
Upload["rclone copy"] -->|"weights"| RustFS["RustFS :9000"]
RustFS -->|"rclone mount"| Mount["/mnt/vllm-models"]
Mount -->|"weight load"| vLLM["vLLM :8000"]
Client["OpenAI SDK / curl"] -->|"completions"| vLLM
```

The bucket is the single copy of the model. Hosts that serve the model mount the bucket read-only, so every node pulls weights from RustFS and no local model store exists to drift.

:::note[Why an rclone mount]

vLLM 0.30 loads `s3://` model paths through the RunAI model streamer, whose ranged reads currently fail against custom S3 endpoints such as RustFS (the loader errors with `File access error` on any non-zero offset). Mounting the bucket as a filesystem is the verified way to keep the weights in RustFS while vLLM reads them as local files.

:::

## 1. Upload the model to RustFS

Create the bucket and copy model weights into it, replacing all connection placeholders:

```ini title="rclone.conf"
[rustfs]
type = s3
provider = Other
access_key_id = <your-access-key>
secret_access_key = <your-secret-key>
endpoint = http://<your-rustfs-endpoint>:9000
region = us-east-1
```

```bash
rc mb rustfs/vllm-models
rclone copy ./opt-125m rustfs:vllm-models/opt-125m --transfers 4
```

Any Hugging Face layout works — `config.json`, the tokenizer files, and the weight files (`model.safetensors` or `pytorch_model.bin`). Keep one model per prefix so several models can share the bucket.

## 2. Mount the bucket on the vLLM host

On the machine that runs vLLM, mount the bucket read-only for clients with `--allow-other`:

```bash
mkdir -p /mnt/vllm-models
rclone mount rustfs:vllm-models /mnt/vllm-models \
--allow-other --daemon
ls /mnt/vllm-models/opt-125m/
```

```text
config.json merges.txt model.safetensors tokenizer.json vocab.json
```

## 3. Run vLLM

Start the CPU image against the mounted weights:

```bash
docker run -d --name vllm -p 8000:8000 --shm-size=2g \
-v /mnt/vllm-models:/models:ro \
vllm/vllm-openai-cpu:latest \
--model /models/opt-125m --served-model-name opt-125m \
--dtype float32 --max-model-len 256 --gpu-memory-utilization 0.15
```

vLLM reads the weights through the mount — the container stays stateless and the model lives in RustFS. Wait for the server to come up:

```bash
curl -s http://localhost:8000/v1/models | head -c 200
```

```text
{"object":"list","data":[{"id":"opt-125m","object":"model","created":...,"root":"/models/opt-125m",...}]}
```

`--gpu-memory-utilization` controls the fraction of RAM reserved for the KV cache on the CPU backend; lower it on small hosts. `--dtype float32` matches what the CPU attention kernels support for this model.

## 4. Run inference

Send an OpenAI-compatible completion request:

```bash
curl -s http://localhost:8000/v1/completions \
-H "Content-Type: application/json" \
-d '{"model": "opt-125m", "prompt": "RustFS is", "max_tokens": 12, "temperature": 0}'
```

```json
{"id":"cmpl-...","object":"text_completion","model":"opt-125m",
"choices":[{"index":0,"text":" a great tool for building your own server. It's a",
"finish_reason":"length",...}]}
```

The request is standard OpenAI schema, so the Python client works unchanged:

```python
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="EMPTY")
print(client.completions.create(
model="opt-125m", prompt="RustFS is", max_tokens=12, temperature=0,
).choices[0].text)
```

![vLLM model weights stored in the RustFS Console](./images/rustfs-vllm-models.png)

## 5. Stop or reset

To tear down the demo while keeping the bucket objects:

```bash
docker rm -f vllm
fusermount -u /mnt/vllm-models
```

To delete the stored model:

```bash
rclone purge rustfs:vllm-models
```

## Troubleshooting

### `Cannot find any model weights with /models/...`

The mount had a stale directory cache or the weight files never made it to the bucket. Re-run `rclone copy` and confirm the files through the mount with `ls` before starting vLLM. A short `--dir-cache-time` (for example `10s`) helps while you iterate.

### `Unsupported CPU attention configuration: head_dim=...`

vLLM's CPU kernels support a fixed set of head dimensions. Tiny test models such as `hf-internal-testing/tiny-random-*` use exotic shapes that fail at request time — use a real small model such as `facebook/opt-125m`.

### `Insufficient space in /dev/shm`

vLLM's CPU engine exchanges tensors through shared memory. Run the container with `--shm-size=2g` (or `--ipc=host`).

### Server exits with `Available memory on node 0 ... is less than desired CPU memory utilization`

The default KV-cache reservation is 90% of system RAM. Lower it with `--gpu-memory-utilization 0.15` (the flag applies to the CPU backend as a memory fraction despite its name).

## Next steps

- Review [S3 compatibility notes](/administration/protocols/s3) before adopting additional serving setups.
- Create dedicated production credentials with [Access Key Management](/security-compliance/iam/access-token).
- Follow the [vLLM documentation](https://docs.vllm.ai/en/latest/serving/openai_compatible_server.html) for chat templates, tensor parallelism, and quantized weights on top of the same bucket-backed model store.
170 changes: 170 additions & 0 deletions content/de/developer/integration/big-data/airflow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
---
title: "Airflow"
description: "Move data between Airflow DAGs and RustFS with the Amazon S3 provider."
---

This guide connects [Apache Airflow](https://github.com/apache/airflow) — the workflow orchestration platform — to **RustFS** through the Amazon S3 provider's hooks, operators, and sensors. You will register a custom-endpoint connection, run a DAG that writes an object to a RustFS bucket, waits for a key with `S3KeySensor`, and reads the object back with `S3Hook`. The workflow was verified with `apache/airflow:3.3.2` (standalone, SequentialExecutor) and the `apache-airflow-providers-amazon` provider against `rustfs/rustfs-x86-musl:v2.3.1`.

You need Docker, or an existing Airflow installation. This deployment is intended for local integration testing, not production.

## Architecture

```mermaid
flowchart LR
Scheduler["Airflow scheduler"] -->|"tasks"| Hook["S3Hook / operators"]
Hook -->|"S3 API"| RustFS["RustFS :9000"]
Sensor["S3KeySensor"] -->|"poll key"| RustFS
```

Every S3 interaction inside a DAG goes through the provider's S3 client, pointed at RustFS by the connection's `endpoint_url`. Operators, sensors, and hooks share the same connection object.

## 1. Run Airflow

Start a standalone instance with examples disabled, and create the demo bucket:

```bash
docker run -d --name airflow --network oo-rustfs_default -p 8080:8080 \
-e AIRFLOW__CORE__LOAD_EXAMPLES=False \
-v "$PWD/dags":/opt/airflow/dags \
apache/airflow:3.3.2 standalone

rc mb rustfs/airflow-demo
```

The image ships with all providers preinstalled, including `apache-airflow-providers-amazon`.

## 2. Register the RustFS connection

The S3 provider reads its endpoint from the connection's extra field. Replace all connection placeholders:

```bash
docker exec airflow airflow connections add rustfs \
--conn-type aws \
--conn-extra '{"endpoint_url": "http://<your-rustfs-endpoint>:9000", "region_name": "us-east-1", "aws_access_key_id": "<your-access-key>", "aws_secret_access_key": "<your-secret-key>"}'
```

The keys `aws_access_key_id` and `aws_secret_access_key` inside `--conn-extra` supply credentials; `endpoint_url` redirects the boto3 client from AWS to RustFS.

## 3. Write the DAG

The DAG writes an object with an operator, waits for the key with a sensor, and reads it back with the hook:

```python title="rustfs_demo.py"
import datetime

from airflow.providers.amazon.aws.hooks.s3 import S3Hook
from airflow.providers.amazon.aws.operators.s3 import S3CreateObjectOperator
from airflow.providers.amazon.aws.sensors.s3 import S3KeySensor
from airflow.sdk import dag, task

@dag(
schedule=None,
start_date=datetime.datetime(2026, 1, 1),
catchup=False,
tags=["rustfs"],
)
def rustfs_demo():
create = S3CreateObjectOperator(
task_id="write_object",
s3_bucket="airflow-demo",
s3_key="dags/airflow-put.txt",
data="written by airflow to rustfs",
aws_conn_id="rustfs",
replace=True,
)

wait = S3KeySensor(
task_id="wait_for_object",
bucket_key="dags/airflow-put.txt",
bucket_name="airflow-demo",
aws_conn_id="rustfs",
timeout=120,
poke_interval=10,
mode="reschedule",
)

@task
def read_object():
hook = S3Hook(aws_conn_id="rustfs")
body = hook.read_key(key="dags/airflow-put.txt", bucket_name="airflow-demo")
print("read back:", body)
assert body == "written by airflow to rustfs"

create >> [wait, read_object()]

rustfs_demo()
```

Note the import paths: `S3CreateObjectOperator` lives in the `operators` module while `S3KeySensor` lives in the `sensors` module — importing both from one place fails.

## 4. Unpause and trigger

New DAGs start paused, and a trigger fired while paused stays queued forever. Unpause first, then trigger:

```bash
docker exec airflow airflow dags unpause rustfs_demo
docker exec airflow airflow dags trigger rustfs_demo
```

Watch the run finish:

```bash
docker exec airflow airflow dags list-runs rustfs_demo | head -3
```

```text
dag_id run_id state
rustfs_demo manual__2026-09-29T13:15:57.332688+00:00 success
```

All three tasks succeed: `write_object`, `wait_for_object`, and `read_object`.

## 5. Verify objects in RustFS

List the bucket prefix:

```bash
rc ls rustfs/airflow-demo/ -r
rc cat rustfs/airflow-demo/dags/airflow-put.txt
```

```text
[2026-09-29 13:16:01] 28 B dags/airflow-put.txt
written by airflow to rustfs
```

![Airflow object stored in the RustFS Console](./images/rustfs-airflow-object.png)

## 6. Stop or reset

To tear down the demo while keeping the bucket objects:

```bash
docker rm -f airflow
```

To delete the stored data:

```bash
rc rm rustfs/airflow-demo/ --recursive --force
```

## Troubleshooting

### Dag runs stay `queued` after triggering

The DAG is paused. New DAGs are paused by default in Airflow 3, and runs triggered in that state never execute. Run `airflow dags unpause rustfs_demo`; queued runs then start on their own.

### `cannot import name 'S3KeySensor' from 'airflow.providers.amazon.aws.operators.s3'`

The sensor lives in a separate module: `from airflow.providers.amazon.aws.sensors.s3 import S3KeySensor`.

### Tasks fail with connection errors

The `endpoint_url` must be reachable from the Airflow container — use the Docker network hostname for RustFS, not `localhost`. Airflow 3 serves its health endpoint under `/api/v2/monitor/health` if you need to check component status.

## Next steps

- Review [S3 compatibility notes](/administration/protocols/s3) before adopting additional provider hooks.
- Create dedicated production credentials with [Access Key Management](/security-compliance/iam/access-token).
- Follow the [Amazon provider documentation](https://airflow.apache.org/docs/apache-airflow-providers-amazon/stable/index.html) for transfer operators such as `S3ToLocalFilesystemOperator` and `LocalFilesystemToS3Operator`.
Loading
Loading