diff --git a/content/de/developer/integration/big-data/duckdb.md b/content/de/developer/integration/big-data/duckdb.md new file mode 100644 index 00000000..6db3de41 --- /dev/null +++ b/content/de/developer/integration/big-data/duckdb.md @@ -0,0 +1,244 @@ +--- +title: "DuckDB" +description: "Abfragen und Schreiben von Parquet-Dateien im RustFS-Objektspeicher mit DuckDB und dessen httpfs-Erweiterung, bereitgestellt mit Docker Compose." +--- + +Diese Anleitung betreibt **DuckDB** mit **RustFS** als S3-kompatiblem Speicher. Sie starten beide Dienste mit Docker Compose, konfigurieren DuckDBs `httpfs`-Erweiterung für den RustFS-Endpunkt, schreiben Abfrageergebnisse als Parquet in den Bucket, lesen sie zurück und prüfen die Objekte in RustFS. Der Ablauf wurde mit dem Image `duckdb/duckdb:latest` (v1.5.5) und `rustfs/rustfs-x86-musl:v2.3.1` verifiziert. + +Sie benötigen Docker mit dem Compose-Plugin. Dieses Setup ist für lokale Integrationstests gedacht, nicht für den Produktivbetrieb. + +## Architektur + +```mermaid +flowchart LR + DuckDB["DuckDB CLI"] -->|"S3 GET (httpfs)"| RustFS["RustFS :9000"] + DuckDB -->|"S3 PUT (httpfs)"| RustFS + Init["init-bucket job"] -->|"create my-bucket"| RustFS +``` + +DuckDB liest und schreibt Objekte über die [`httpfs`-Erweiterung](https://duckdb.org/docs/stable/extensions/httpfs/overview), die die S3-API implementiert. Ein S3-Secret enthält den RustFS-Endpunkt, die Anmeldeinformationen, Path-Style-Adressierung und die Plain-HTTP-Einstellung; anschließend lassen sich Parquet-Dateien über `s3://my-bucket/...`-Pfade wie lokale Dateien laden und schreiben. + +## 1. Projektdateien anlegen + +Erstellen Sie ein Arbeitsverzeichnis: + +```bash +mkdir rustfs-duckdb +cd rustfs-duckdb +``` + +Erstellen Sie eine Umgebungsdatei und ersetzen Sie beide Platzhalter für die Anmeldeinformationen: + +```ini title=".env" +RUSTFS_ACCESS_KEY= +RUSTFS_SECRET_KEY= +``` + +Verwenden Sie dedizierte Anmeldeinformationen für den Bucket. Committen Sie `.env` nicht in die Versionsverwaltung. + +Erstellen Sie die Compose-Datei: + +```yaml title="compose.yaml" +services: + rustfs: + image: rustfs/rustfs-x86-musl:v2.3.1 + environment: + RUSTFS_ACCESS_KEY: ${RUSTFS_ACCESS_KEY} + RUSTFS_SECRET_KEY: ${RUSTFS_SECRET_KEY} + RUSTFS_VOLUMES: /data + RUSTFS_ADDRESS: ":9000" + RUSTFS_CONSOLE_ADDRESS: ":9001" + RUSTFS_CONSOLE_ENABLE: "true" + volumes: + - rustfs-data:/data + ports: + - "9000:9000" + - "9001:9001" + healthcheck: + test: ["CMD", "curl", "-sf", "http://127.0.0.1:9000/health"] + interval: 10s + timeout: 5s + retries: 6 + start_period: 10s + networks: + - warehouse + + create-bucket: + image: rustfs/rc:latest + depends_on: + rustfs: + condition: service_healthy + environment: + RUSTFS_ACCESS_KEY: ${RUSTFS_ACCESS_KEY} + RUSTFS_SECRET_KEY: ${RUSTFS_SECRET_KEY} + entrypoint: + - /bin/sh + - -c + - | + until /usr/bin/rc alias set rustfs http://rustfs:9000 "$${RUSTFS_ACCESS_KEY}" "$${RUSTFS_SECRET_KEY}"; do + echo "Waiting for RustFS..." + sleep 2 + done + /usr/bin/rc ls rustfs/my-bucket >/dev/null 2>&1 || /usr/bin/rc mb rustfs/my-bucket + networks: + - warehouse + + duckdb: + image: duckdb/duckdb:latest + entrypoint: ["/duckdb"] + depends_on: + create-bucket: + condition: service_completed_successfully + networks: + - warehouse + +networks: + warehouse: + +volumes: + rustfs-data: +``` + +Das [`rc`-Image](https://github.com/rustfs/cli) stellt den offiziellen RustFS-Kommandozeilenclient bereit. Der Initialisierer prüft vor dem Anlegen, ob `my-bucket` bereits existiert, sodass wiederholte Starts keine bestehenden Daten löschen. Das Image `duckdb/duckdb` enthält nur die Binärdatei `/duckdb` und keine Shell, daher setzt der Dienst `entrypoint: ["/duckdb"]`. + +## 2. Bereitstellung starten + +Prüfen Sie die Compose-Datei, bevor Sie Container starten: + +```bash +docker compose config +``` + +Starten Sie die Dienste und warten Sie, bis die Bucket-Initialisierung abgeschlossen ist: + +```bash +docker compose up -d +docker compose ps -a +``` + +Der Dienst `create-bucket` sollte mit dem Exit-Code `0` enden. Die RustFS-Konsole erreichen Sie jederzeit unter `http://localhost:9001/rustfs/console/`. + +## 3. Das S3-Secret in DuckDB konfigurieren + +Starten Sie eine interaktive DuckDB-Sitzung: + +```bash +docker compose run --rm duckdb +``` + +Installieren Sie die Erweiterung und registrieren Sie den RustFS-Endpunkt: + +```sql +INSTALL httpfs; +LOAD httpfs; + +CREATE SECRET rustfs ( + TYPE S3, + KEY_ID '', + SECRET '', + ENDPOINT 'rustfs:9000', + USE_SSL FALSE, + URL_STYLE 'path' +); +``` + +Der Endpunkt wird als `host:port` ohne Schema angegeben. `USE_SSL FALSE` wählt Plain HTTP innerhalb des Compose-Netzwerks, und `URL_STYLE 'path'` wählt Path-Style-Adressierung, die RustFS erwartet. Secrets gelten nur für die aktuelle Sitzung — erstellen Sie das Secret bei jeder neuen Sitzung erneut. + +## 4. Abfrageergebnisse nach RustFS schreiben + +Schreiben Sie eine kleine Tabelle als Parquet in den Bucket: + +```sql +COPY + (SELECT i AS id, 'rustfs-duckdb-demo' AS source FROM range(1000) t(i)) + TO 's3://my-bucket/duckdb-demo/events.parquet' + (FORMAT PARQUET); +``` + +```text +┌─────────┐ +│ Success │ +│ boolean │ +├─────────┤ +│ true │ +└─────────┘ +``` + +## 5. Parquet aus RustFS zurücklesen + +Abfragen Sie das soeben geschriebene Objekt wie eine lokale Datei: + +```sql +SELECT count(*) AS rows, min(id) AS min_id, max(id) AS max_id +FROM read_parquet('s3://my-bucket/duckdb-demo/events.parquet'); +``` + +```text +┌───────┬────────┬────────┐ +│ rows │ min_id │ max_id │ +│ int64 │ int64 │ int64 │ +├───────┼────────┼────────┤ +│ 1000 │ 0 │ 999 │ +└───────┴────────┴────────┘ +``` + +Jedes Parquet-Objekt unter dem Bucket lässt sich auf diese Weise abfragen, einschließlich Dateien, die von anderen Systemen wie OpenObserve, Spark oder Iceberg geschrieben wurden. + +## 6. Objekte in RustFS prüfen + +Listen Sie das Präfix über das Bucket-Initialisierungs-Image auf: + +```bash +docker compose run --rm --entrypoint /bin/sh create-bucket -c \ + '/usr/bin/rc alias set rustfs http://rustfs:9000 "$RUSTFS_ACCESS_KEY" "$RUSTFS_SECRET_KEY" >/dev/null && /usr/bin/rc ls rustfs/my-bucket/duckdb-demo --recursive' +``` + +```text +[2026-09-20 06:52:45] 5.32 KiB duckdb-demo/events.parquet +``` + +Sie können das Präfix `duckdb-demo` auch in der RustFS-Konsole anzeigen: + +![Das Präfix duckdb-demo in der RustFS-Konsole](./images/rustfs-duckdb-objects.png) + +## 7. Stack stoppen oder zurücksetzen + +Stoppen Sie die Container und behalten Sie das RustFS-Datenvolumen: + +```bash +docker compose down +``` + +Um die lokalen Objekte zu löschen und mit einem leeren RustFS-Volumen zu beginnen, fügen Sie ausdrücklich `--volumes` hinzu: + +```bash +docker compose down --volumes +``` + +## Fehlerbehebung + +### DuckDB erreicht RustFS nicht + +Innerhalb des Compose-Netzwerks lautet der Endpunkt `rustfs:9000`. Für einen DuckDB-Prozess auf dem Host verwenden Sie `localhost:9000` und publizieren Port `9000` wie in der Compose-Datei gezeigt. + +### SSL- oder Verbindungsfehler mit einem Plain-HTTP-Endpunkt + +`ENDPOINT` nimmt kein Schema an. Läuft RustFS ohne TLS, muss `USE_SSL FALSE` im Secret gesetzt sein; andernfalls versucht `httpfs` HTTPS und schlägt mit einem Verbindungs- oder Zertifikatsfehler fehl. + +### AccessDenied-Antworten + +Prüfen Sie, ob die Anmeldeinformationen im Secret mit den RustFS-Anmeldeinformationen übereinstimmen und ob die Bucket-Initialisierung erfolgreich abgeschlossen wurde: + +```bash +docker compose logs create-bucket +``` + +### Virtual-Host-Style-Anfragen + +`URL_STYLE 'path'` ist für den Container-Netzwerk-Endpunkt erforderlich. Virtual-Host-Style-Anfragen erfordern eine RustFS-Domänenkonfiguration (`RUSTFS_SERVER_DOMAINS`) und passende DNS-Einträge und sind für dieses Setup nicht notwendig. + +## Nächste Schritte + +- Lesen Sie die [S3-Kompatibilitätshinweise](/administration/protocols/s3), bevor Sie weitere S3-Operationen verwenden. +- Erstellen Sie dedizierte Produktions-Anmeldeinformationen mit dem [Access Key Management](/security-compliance/iam/access-token). +- Folgen Sie der [DuckDB-httpfs-Dokumentation](https://duckdb.org/docs/stable/extensions/httpfs/overview) für erweiterte Optionen wie Regions-Overrides und Verbindungslimits. diff --git a/content/de/developer/integration/big-data/images/rustfs-duckdb-objects.png b/content/de/developer/integration/big-data/images/rustfs-duckdb-objects.png new file mode 100644 index 00000000..0ced40f4 Binary files /dev/null and b/content/de/developer/integration/big-data/images/rustfs-duckdb-objects.png differ diff --git a/content/de/developer/integration/big-data/index.md b/content/de/developer/integration/big-data/index.md index 89f9fe9f..f27292d1 100644 --- a/content/de/developer/integration/big-data/index.md +++ b/content/de/developer/integration/big-data/index.md @@ -8,6 +8,8 @@ Use **RustFS** as the object storage layer for big data systems that support an ## Systems - [Iceberg](./iceberg.md) +- [PyIceberg](./pyiceberg.md) - [Milvus](./milvus.md) +- [DuckDB](./duckdb.md) Keep application data in a dedicated bucket and prefix, and use credentials scoped to the required bucket operations. \ No newline at end of file diff --git a/content/de/developer/integration/big-data/meta.json b/content/de/developer/integration/big-data/meta.json index 2286437c..0627a4f9 100644 --- a/content/de/developer/integration/big-data/meta.json +++ b/content/de/developer/integration/big-data/meta.json @@ -3,6 +3,7 @@ "pages": [ "iceberg", "pyiceberg", - "milvus" + "milvus", + "duckdb" ] -} \ No newline at end of file +} diff --git a/content/en/developer/integration/big-data/duckdb.md b/content/en/developer/integration/big-data/duckdb.md new file mode 100644 index 00000000..d9673bfd --- /dev/null +++ b/content/en/developer/integration/big-data/duckdb.md @@ -0,0 +1,244 @@ +--- +title: "DuckDB" +description: "Query and write Parquet files stored in RustFS object storage with DuckDB and its httpfs extension, deployed with Docker Compose." +--- + +This guide runs **DuckDB** against **RustFS** as its S3-compatible storage. You will start both services with Docker Compose, configure DuckDB's `httpfs` extension for the RustFS endpoint, write query results to the bucket as Parquet, read them back, and verify the objects in RustFS. The workflow was verified with the `duckdb/duckdb:latest` image (v1.5.5) and `rustfs/rustfs-x86-musl:v2.3.1`. + +You need Docker with the Compose plugin. This deployment is intended for local integration testing, not production. + +## Architecture + +```mermaid +flowchart LR + DuckDB["DuckDB CLI"] -->|"S3 GET (httpfs)"| RustFS["RustFS :9000"] + DuckDB -->|"S3 PUT (httpfs)"| RustFS + Init["init-bucket job"] -->|"create my-bucket"| RustFS +``` + +DuckDB reads and writes objects through its [`httpfs` extension](https://duckdb.org/docs/stable/extensions/httpfs/overview), which implements the S3 API. An S3 secret carries the RustFS endpoint, credentials, path-style addressing, and the plain-HTTP setting; Parquet files then load from and write to `s3://my-bucket/...` paths like local files. + +## 1. Create the project files + +Create a working directory: + +```bash +mkdir rustfs-duckdb +cd rustfs-duckdb +``` + +Create an environment file and replace both credential placeholders: + +```ini title=".env" +RUSTFS_ACCESS_KEY= +RUSTFS_SECRET_KEY= +``` + +Use dedicated credentials for the bucket. Do not commit `.env` to source control. + +Create the Compose file: + +```yaml title="compose.yaml" +services: + rustfs: + image: rustfs/rustfs-x86-musl:v2.3.1 + environment: + RUSTFS_ACCESS_KEY: ${RUSTFS_ACCESS_KEY} + RUSTFS_SECRET_KEY: ${RUSTFS_SECRET_KEY} + RUSTFS_VOLUMES: /data + RUSTFS_ADDRESS: ":9000" + RUSTFS_CONSOLE_ADDRESS: ":9001" + RUSTFS_CONSOLE_ENABLE: "true" + volumes: + - rustfs-data:/data + ports: + - "9000:9000" + - "9001:9001" + healthcheck: + test: ["CMD", "curl", "-sf", "http://127.0.0.1:9000/health"] + interval: 10s + timeout: 5s + retries: 6 + start_period: 10s + networks: + - warehouse + + create-bucket: + image: rustfs/rc:latest + depends_on: + rustfs: + condition: service_healthy + environment: + RUSTFS_ACCESS_KEY: ${RUSTFS_ACCESS_KEY} + RUSTFS_SECRET_KEY: ${RUSTFS_SECRET_KEY} + entrypoint: + - /bin/sh + - -c + - | + until /usr/bin/rc alias set rustfs http://rustfs:9000 "$${RUSTFS_ACCESS_KEY}" "$${RUSTFS_SECRET_KEY}"; do + echo "Waiting for RustFS..." + sleep 2 + done + /usr/bin/rc ls rustfs/my-bucket >/dev/null 2>&1 || /usr/bin/rc mb rustfs/my-bucket + networks: + - warehouse + + duckdb: + image: duckdb/duckdb:latest + entrypoint: ["/duckdb"] + depends_on: + create-bucket: + condition: service_completed_successfully + networks: + - warehouse + +networks: + warehouse: + +volumes: + rustfs-data: +``` + +The [`rc` image](https://github.com/rustfs/cli) provides the official RustFS command-line client. The initializer checks for `my-bucket` before creating it, so repeated starts do not delete existing data. The `duckdb/duckdb` image contains only the `/duckdb` binary and no shell, so the service sets `entrypoint: ["/duckdb"]`. + +## 2. Start the deployment + +Resolve the Compose file before starting containers: + +```bash +docker compose config +``` + +Start the services and wait for the bucket initializer to finish: + +```bash +docker compose up -d +docker compose ps -a +``` + +The `create-bucket` service should show an exit code of `0`. Open the RustFS Console at `http://localhost:9001/rustfs/console/` to inspect the bucket at any time. + +## 3. Configure the S3 secret in DuckDB + +Start an interactive DuckDB session: + +```bash +docker compose run --rm duckdb +``` + +Install the extension and register the RustFS endpoint: + +```sql +INSTALL httpfs; +LOAD httpfs; + +CREATE SECRET rustfs ( + TYPE S3, + KEY_ID '', + SECRET '', + ENDPOINT 'rustfs:9000', + USE_SSL FALSE, + URL_STYLE 'path' +); +``` + +The endpoint is given as `host:port` without a scheme. `USE_SSL FALSE` selects plain HTTP inside the Compose network, and `URL_STYLE 'path'` selects path-style addressing, which is what RustFS expects. Secrets live for the current session — re-create the secret each time you start a new session. + +## 4. Write query results to RustFS + +Write a small table as Parquet into the bucket: + +```sql +COPY + (SELECT i AS id, 'rustfs-duckdb-demo' AS source FROM range(1000) t(i)) + TO 's3://my-bucket/duckdb-demo/events.parquet' + (FORMAT PARQUET); +``` + +```text +┌─────────┐ +│ Success │ +│ boolean │ +├─────────┤ +│ true │ +└─────────┘ +``` + +## 5. Read Parquet back from RustFS + +Query the object you just wrote as if it were a local file: + +```sql +SELECT count(*) AS rows, min(id) AS min_id, max(id) AS max_id +FROM read_parquet('s3://my-bucket/duckdb-demo/events.parquet'); +``` + +```text +┌───────┬────────┬────────┐ +│ rows │ min_id │ max_id │ +│ int64 │ int64 │ int64 │ +├───────┼────────┼────────┤ +│ 1000 │ 0 │ 999 │ +└───────┴────────┴────────┘ +``` + +Any Parquet object under the bucket can be queried this way, including files written by other systems such as OpenObserve, Spark, or Iceberg. + +## 6. Verify objects in RustFS + +List the prefix through the bucket-initializer image: + +```bash +docker compose run --rm --entrypoint /bin/sh create-bucket -c \ + '/usr/bin/rc alias set rustfs http://rustfs:9000 "$RUSTFS_ACCESS_KEY" "$RUSTFS_SECRET_KEY" >/dev/null && /usr/bin/rc ls rustfs/my-bucket/duckdb-demo --recursive' +``` + +```text +[2026-09-20 06:52:45] 5.32 KiB duckdb-demo/events.parquet +``` + +You can also inspect the `duckdb-demo` prefix in the RustFS Console: + +![The duckdb-demo prefix in the RustFS Console](./images/rustfs-duckdb-objects.png) + +## 7. Stop or reset the stack + +Stop the containers while keeping the RustFS data volume: + +```bash +docker compose down +``` + +To delete the local objects and start from an empty RustFS volume, explicitly include `--volumes`: + +```bash +docker compose down --volumes +``` + +## Troubleshooting + +### DuckDB cannot reach RustFS + +Inside the Compose network the endpoint is `rustfs:9000`. From a DuckDB process running on the host, use `localhost:9000` instead and publish port `9000` as shown in the Compose file. + +### SSL or connection errors with a plain-HTTP endpoint + +`ENDPOINT` takes no scheme. If RustFS runs without TLS, `USE_SSL FALSE` must be set in the secret; otherwise `httpfs` attempts HTTPS and fails with a connection or certificate error. + +### AccessDenied responses + +Check that the credentials in the secret match the RustFS credentials, and that the bucket initializer completed successfully: + +```bash +docker compose logs create-bucket +``` + +### Virtual-host style requests + +`URL_STYLE 'path'` is required for the container-network endpoint. Virtual-host style requests need a RustFS domain configuration (`RUSTFS_SERVER_DOMAINS`) and matching DNS records, and are not needed for this setup. + +## Next steps + +- Review [S3 compatibility notes](/administration/protocols/s3) before adopting additional S3 operations. +- Create dedicated production credentials with [Access Key Management](/security-compliance/iam/access-token). +- Follow the [DuckDB httpfs documentation](https://duckdb.org/docs/stable/extensions/httpfs/overview) for advanced options such as region overrides and connection limits. diff --git a/content/en/developer/integration/big-data/images/rustfs-duckdb-objects.png b/content/en/developer/integration/big-data/images/rustfs-duckdb-objects.png new file mode 100644 index 00000000..0ced40f4 Binary files /dev/null and b/content/en/developer/integration/big-data/images/rustfs-duckdb-objects.png differ diff --git a/content/en/developer/integration/big-data/index.md b/content/en/developer/integration/big-data/index.md index 89f9fe9f..f27292d1 100644 --- a/content/en/developer/integration/big-data/index.md +++ b/content/en/developer/integration/big-data/index.md @@ -8,6 +8,8 @@ Use **RustFS** as the object storage layer for big data systems that support an ## Systems - [Iceberg](./iceberg.md) +- [PyIceberg](./pyiceberg.md) - [Milvus](./milvus.md) +- [DuckDB](./duckdb.md) Keep application data in a dedicated bucket and prefix, and use credentials scoped to the required bucket operations. \ No newline at end of file diff --git a/content/en/developer/integration/big-data/meta.json b/content/en/developer/integration/big-data/meta.json index 2286437c..0627a4f9 100644 --- a/content/en/developer/integration/big-data/meta.json +++ b/content/en/developer/integration/big-data/meta.json @@ -3,6 +3,7 @@ "pages": [ "iceberg", "pyiceberg", - "milvus" + "milvus", + "duckdb" ] -} \ No newline at end of file +} diff --git a/content/fr/developer/integration/big-data/duckdb.md b/content/fr/developer/integration/big-data/duckdb.md new file mode 100644 index 00000000..ba5a31dd --- /dev/null +++ b/content/fr/developer/integration/big-data/duckdb.md @@ -0,0 +1,244 @@ +--- +title: "DuckDB" +description: "Interrogez et écrivez des fichiers Parquet stockés dans le stockage objet RustFS avec DuckDB et son extension httpfs, déployés avec Docker Compose." +--- + +Ce guide exécute **DuckDB** avec **RustFS** comme stockage compatible S3. Vous allez démarrer les deux services avec Docker Compose, configurer l'extension `httpfs` de DuckDB pour le point de terminaison RustFS, écrire des résultats de requête dans le bucket au format Parquet, les relire, puis vérifier les objets dans RustFS. Le flux a été validé avec l'image `duckdb/duckdb:latest` (v1.5.5) et `rustfs/rustfs-x86-musl:v2.3.1`. + +Vous avez besoin de Docker avec le plugin Compose. Ce déploiement est destiné aux tests d'intégration locaux, pas à la production. + +## Architecture + +```mermaid +flowchart LR + DuckDB["DuckDB CLI"] -->|"S3 GET (httpfs)"| RustFS["RustFS :9000"] + DuckDB -->|"S3 PUT (httpfs)"| RustFS + Init["init-bucket job"] -->|"create my-bucket"| RustFS +``` + +DuckDB lit et écrit les objets via son [extension `httpfs`](https://duckdb.org/docs/stable/extensions/httpfs/overview), qui implémente l'API S3. Un secret S3 contient le point de terminaison RustFS, les identifiants, l'adressage path-style et le réglage HTTP simple ; les fichiers Parquet se chargent alors depuis et vers des chemins `s3://my-bucket/...` comme des fichiers locaux. + +## 1. Créer les fichiers du projet + +Créez un répertoire de travail : + +```bash +mkdir rustfs-duckdb +cd rustfs-duckdb +``` + +Créez un fichier d'environnement et remplacez les deux espaces réservés d'identifiants : + +```ini title=".env" +RUSTFS_ACCESS_KEY= +RUSTFS_SECRET_KEY= +``` + +Utilisez des identifiants dédiés pour le bucket. Ne commettez pas `.env` dans le contrôle de version. + +Créez le fichier Compose : + +```yaml title="compose.yaml" +services: + rustfs: + image: rustfs/rustfs-x86-musl:v2.3.1 + environment: + RUSTFS_ACCESS_KEY: ${RUSTFS_ACCESS_KEY} + RUSTFS_SECRET_KEY: ${RUSTFS_SECRET_KEY} + RUSTFS_VOLUMES: /data + RUSTFS_ADDRESS: ":9000" + RUSTFS_CONSOLE_ADDRESS: ":9001" + RUSTFS_CONSOLE_ENABLE: "true" + volumes: + - rustfs-data:/data + ports: + - "9000:9000" + - "9001:9001" + healthcheck: + test: ["CMD", "curl", "-sf", "http://127.0.0.1:9000/health"] + interval: 10s + timeout: 5s + retries: 6 + start_period: 10s + networks: + - warehouse + + create-bucket: + image: rustfs/rc:latest + depends_on: + rustfs: + condition: service_healthy + environment: + RUSTFS_ACCESS_KEY: ${RUSTFS_ACCESS_KEY} + RUSTFS_SECRET_KEY: ${RUSTFS_SECRET_KEY} + entrypoint: + - /bin/sh + - -c + - | + until /usr/bin/rc alias set rustfs http://rustfs:9000 "$${RUSTFS_ACCESS_KEY}" "$${RUSTFS_SECRET_KEY}"; do + echo "Waiting for RustFS..." + sleep 2 + done + /usr/bin/rc ls rustfs/my-bucket >/dev/null 2>&1 || /usr/bin/rc mb rustfs/my-bucket + networks: + - warehouse + + duckdb: + image: duckdb/duckdb:latest + entrypoint: ["/duckdb"] + depends_on: + create-bucket: + condition: service_completed_successfully + networks: + - warehouse + +networks: + warehouse: + +volumes: + rustfs-data: +``` + +L'[image `rc`](https://github.com/rustfs/cli) fournit le client en ligne de commande officiel de RustFS. L'initialiseur vérifie l'existence de `my-bucket` avant de le créer, afin que des redémarrages répétés ne suppriment pas les données existantes. L'image `duckdb/duckdb` ne contient que le binaire `/duckdb`, sans shell ; le service définit donc `entrypoint: ["/duckdb"]`. + +## 2. Démarrer le déploiement + +Vérifiez le fichier Compose avant de démarrer les conteneurs : + +```bash +docker compose config +``` + +Démarrez les services et attendez la fin de l'initialisation du bucket : + +```bash +docker compose up -d +docker compose ps -a +``` + +Le service `create-bucket` doit afficher un code de sortie `0`. La console RustFS est disponible à l'adresse `http://localhost:9001/rustfs/console/` pour inspecter le bucket à tout moment. + +## 3. Configurer le secret S3 dans DuckDB + +Démarrez une session DuckDB interactive : + +```bash +docker compose run --rm duckdb +``` + +Installez l'extension et enregistrez le point de terminaison RustFS : + +```sql +INSTALL httpfs; +LOAD httpfs; + +CREATE SECRET rustfs ( + TYPE S3, + KEY_ID '', + SECRET '', + ENDPOINT 'rustfs:9000', + USE_SSL FALSE, + URL_STYLE 'path' +); +``` + +Le point de terminaison est donné sous la forme `host:port` sans schéma. `USE_SSL FALSE` sélectionne HTTP simple à l'intérieur du réseau Compose, et `URL_STYLE 'path'` sélectionne l'adressage path-style, attendu par RustFS. Les secrets ne vivent que le temps de la session — recréez le secret à chaque nouvelle session. + +## 4. Écrire des résultats de requête dans RustFS + +Écrivez une petite table au format Parquet dans le bucket : + +```sql +COPY + (SELECT i AS id, 'rustfs-duckdb-demo' AS source FROM range(1000) t(i)) + TO 's3://my-bucket/duckdb-demo/events.parquet' + (FORMAT PARQUET); +``` + +```text +┌─────────┐ +│ Success │ +│ boolean │ +├─────────┤ +│ true │ +└─────────┘ +``` + +## 5. Relire le Parquet depuis RustFS + +Interrogez l'objet que vous venez d'écrire comme s'il s'agissait d'un fichier local : + +```sql +SELECT count(*) AS rows, min(id) AS min_id, max(id) AS max_id +FROM read_parquet('s3://my-bucket/duckdb-demo/events.parquet'); +``` + +```text +┌───────┬────────┬────────┐ +│ rows │ min_id │ max_id │ +│ int64 │ int64 │ int64 │ +├───────┼────────┼────────┤ +│ 1000 │ 0 │ 999 │ +└───────┴────────┴────────┘ +``` + +Tout objet Parquet du bucket peut être interrogé de cette manière, y compris les fichiers écrits par d'autres systèmes comme OpenObserve, Spark ou Iceberg. + +## 6. Vérifier les objets dans RustFS + +Listez le préfixe via l'image d'initialisation du bucket : + +```bash +docker compose run --rm --entrypoint /bin/sh create-bucket -c \ + '/usr/bin/rc alias set rustfs http://rustfs:9000 "$RUSTFS_ACCESS_KEY" "$RUSTFS_SECRET_KEY" >/dev/null && /usr/bin/rc ls rustfs/my-bucket/duckdb-demo --recursive' +``` + +```text +[2026-09-20 06:52:45] 5.32 KiB duckdb-demo/events.parquet +``` + +Vous pouvez également inspecter le préfixe `duckdb-demo` dans la console RustFS : + +![Le préfixe duckdb-demo dans la console RustFS](./images/rustfs-duckdb-objects.png) + +## 7. Arrêter ou réinitialiser la pile + +Arrêtez les conteneurs en conservant le volume de données RustFS : + +```bash +docker compose down +``` + +Pour supprimer les objets locaux et repartir d'un volume RustFS vide, ajoutez explicitement `--volumes` : + +```bash +docker compose down --volumes +``` + +## Dépannage + +### DuckDB n'atteint pas RustFS + +À l'intérieur du réseau Compose, le point de terminaison est `rustfs:9000`. Pour un processus DuckDB exécuté sur l'hôte, utilisez `localhost:9000` et publiez le port `9000` comme dans le fichier Compose. + +### Erreurs SSL ou de connexion avec un point de terminaison HTTP simple + +`ENDPOINT` ne prend pas de schéma. Si RustFS fonctionne sans TLS, `USE_SSL FALSE` doit être défini dans le secret ; sinon `httpfs` tente HTTPS et échoue avec une erreur de connexion ou de certificat. + +### Réponses AccessDenied + +Vérifiez que les identifiants du secret correspondent aux identifiants RustFS et que l'initialisation du bucket s'est terminée avec succès : + +```bash +docker compose logs create-bucket +``` + +### Requêtes virtual-host style + +`URL_STYLE 'path'` est requis pour le point de terminaison du réseau de conteneurs. Les requêtes virtual-host nécessitent une configuration de domaine RustFS (`RUSTFS_SERVER_DOMAINS`) et des enregistrements DNS correspondants, et ne sont pas nécessaires ici. + +## Prochaines étapes + +- Consultez les [notes de compatibilité S3](/administration/protocols/s3) avant d'adopter d'autres opérations S3. +- Créez des identifiants de production dédiés avec la [gestion des clés d'accès](/security-compliance/iam/access-token). +- Suivez la [documentation httpfs de DuckDB](https://duckdb.org/docs/stable/extensions/httpfs/overview) pour les options avancées telles que les remplacements de région et les limites de connexion. diff --git a/content/fr/developer/integration/big-data/images/rustfs-duckdb-objects.png b/content/fr/developer/integration/big-data/images/rustfs-duckdb-objects.png new file mode 100644 index 00000000..0ced40f4 Binary files /dev/null and b/content/fr/developer/integration/big-data/images/rustfs-duckdb-objects.png differ diff --git a/content/fr/developer/integration/big-data/index.md b/content/fr/developer/integration/big-data/index.md index 89f9fe9f..f27292d1 100644 --- a/content/fr/developer/integration/big-data/index.md +++ b/content/fr/developer/integration/big-data/index.md @@ -8,6 +8,8 @@ Use **RustFS** as the object storage layer for big data systems that support an ## Systems - [Iceberg](./iceberg.md) +- [PyIceberg](./pyiceberg.md) - [Milvus](./milvus.md) +- [DuckDB](./duckdb.md) Keep application data in a dedicated bucket and prefix, and use credentials scoped to the required bucket operations. \ No newline at end of file diff --git a/content/fr/developer/integration/big-data/meta.json b/content/fr/developer/integration/big-data/meta.json index 2286437c..0627a4f9 100644 --- a/content/fr/developer/integration/big-data/meta.json +++ b/content/fr/developer/integration/big-data/meta.json @@ -3,6 +3,7 @@ "pages": [ "iceberg", "pyiceberg", - "milvus" + "milvus", + "duckdb" ] -} \ No newline at end of file +} diff --git a/content/ja/developer/integration/big-data/duckdb.md b/content/ja/developer/integration/big-data/duckdb.md new file mode 100644 index 00000000..a67a93dd --- /dev/null +++ b/content/ja/developer/integration/big-data/duckdb.md @@ -0,0 +1,244 @@ +--- +title: "DuckDB" +description: "DuckDB と httpfs 拡張機能を使って RustFS オブジェクトストレージ内の Parquet ファイルを照会・書き込みします。Docker Compose でデプロイします。" +--- + +このガイドでは、S3 互換ストレージとして **RustFS** を組み合わせて **DuckDB** を実行します。Docker Compose で両サービスを起動し、DuckDB の `httpfs` 拡張機能を RustFS エンドポイント向けに設定し、クエリ結果を Parquet としてバケットに書き込み、読み戻して、RustFS 内のオブジェクトを確認します。この流れは `duckdb/duckdb:latest` イメージ(v1.5.5)と `rustfs/rustfs-x86-musl:v2.3.1` で検証済みです。 + +Docker と Compose プラグインが必要です。このデプロイはローカルでの統合テストを目的としており、本番環境向けではありません。 + +## アーキテクチャ + +```mermaid +flowchart LR + DuckDB["DuckDB CLI"] -->|"S3 GET (httpfs)"| RustFS["RustFS :9000"] + DuckDB -->|"S3 PUT (httpfs)"| RustFS + Init["init-bucket job"] -->|"create my-bucket"| RustFS +``` + +DuckDB は S3 API を実装する [`httpfs` 拡張機能](https://duckdb.org/docs/stable/extensions/httpfs/overview)を通じてオブジェクトの読み書きを行います。S3 シークレットに RustFS エンドポイント、認証情報、パススタイルのアドレス指定、平文 HTTP の設定を保持させると、Parquet ファイルを `s3://my-bucket/...` のパスでローカルファイルと同じようにロード・書き込みできます。 + +## 1. プロジェクトファイルを作成する + +作業ディレクトリを作成します。 + +```bash +mkdir rustfs-duckdb +cd rustfs-duckdb +``` + +環境変数ファイルを作成し、2 つの認証情報プレースホルダーを置き換えます。 + +```ini title=".env" +RUSTFS_ACCESS_KEY= +RUSTFS_SECRET_KEY= +``` + +バケットには専用の認証情報を使用してください。`.env` をバージョン管理にコミットしないでください。 + +Compose ファイルを作成します。 + +```yaml title="compose.yaml" +services: + rustfs: + image: rustfs/rustfs-x86-musl:v2.3.1 + environment: + RUSTFS_ACCESS_KEY: ${RUSTFS_ACCESS_KEY} + RUSTFS_SECRET_KEY: ${RUSTFS_SECRET_KEY} + RUSTFS_VOLUMES: /data + RUSTFS_ADDRESS: ":9000" + RUSTFS_CONSOLE_ADDRESS: ":9001" + RUSTFS_CONSOLE_ENABLE: "true" + volumes: + - rustfs-data:/data + ports: + - "9000:9000" + - "9001:9001" + healthcheck: + test: ["CMD", "curl", "-sf", "http://127.0.0.1:9000/health"] + interval: 10s + timeout: 5s + retries: 6 + start_period: 10s + networks: + - warehouse + + create-bucket: + image: rustfs/rc:latest + depends_on: + rustfs: + condition: service_healthy + environment: + RUSTFS_ACCESS_KEY: ${RUSTFS_ACCESS_KEY} + RUSTFS_SECRET_KEY: ${RUSTFS_SECRET_KEY} + entrypoint: + - /bin/sh + - -c + - | + until /usr/bin/rc alias set rustfs http://rustfs:9000 "$${RUSTFS_ACCESS_KEY}" "$${RUSTFS_SECRET_KEY}"; do + echo "Waiting for RustFS..." + sleep 2 + done + /usr/bin/rc ls rustfs/my-bucket >/dev/null 2>&1 || /usr/bin/rc mb rustfs/my-bucket + networks: + - warehouse + + duckdb: + image: duckdb/duckdb:latest + entrypoint: ["/duckdb"] + depends_on: + create-bucket: + condition: service_completed_successfully + networks: + - warehouse + +networks: + warehouse: + +volumes: + rustfs-data: +``` + +[`rc` イメージ](https://github.com/rustfs/cli)は RustFS の公式コマンドラインクライアントを提供します。初期化ジョブは作成前に `my-bucket` の存在を確認するため、繰り返し起動しても既存のデータは削除されません。`duckdb/duckdb` イメージには `/duckdb` バイナリのみが含まれシェルはないため、サービスには `entrypoint: ["/duckdb"]` を設定しています。 + +## 2. デプロイを起動する + +コンテナを起動する前に Compose ファイルを検証します。 + +```bash +docker compose config +``` + +サービスを起動し、バケット初期化の完了を待ちます。 + +```bash +docker compose up -d +docker compose ps -a +``` + +`create-bucket` サービスは終了コード `0` で終了するはずです。RustFS コンソールは `http://localhost:9001/rustfs/console/` からいつでもバケットを確認できます。 + +## 3. DuckDB で S3 シークレットを設定する + +対話的な DuckDB セッションを開始します。 + +```bash +docker compose run --rm duckdb +``` + +拡張機能をインストールし、RustFS エンドポイントを登録します。 + +```sql +INSTALL httpfs; +LOAD httpfs; + +CREATE SECRET rustfs ( + TYPE S3, + KEY_ID '', + SECRET '', + ENDPOINT 'rustfs:9000', + USE_SSL FALSE, + URL_STYLE 'path' +); +``` + +エンドポイントはスキーマなしの `host:port` 形式で指定します。`USE_SSL FALSE` は Compose ネットワーク内での平文 HTTP を選択し、`URL_STYLE 'path'` は RustFS が期待するパススタイルのアドレス指定を選択します。シークレットは現在のセッションでのみ有効です。新しいセッションを開始するたびに再作成してください。 + +## 4. クエリ結果を RustFS に書き込む + +小さなテーブルを Parquet としてバケットに書き込みます。 + +```sql +COPY + (SELECT i AS id, 'rustfs-duckdb-demo' AS source FROM range(1000) t(i)) + TO 's3://my-bucket/duckdb-demo/events.parquet' + (FORMAT PARQUET); +``` + +```text +┌─────────┐ +│ Success │ +│ boolean │ +├─────────┤ +│ true │ +└─────────┘ +``` + +## 5. RustFS から Parquet を読み戻す + +書き込んだばかりのオブジェクトをローカルファイルと同じように照会します。 + +```sql +SELECT count(*) AS rows, min(id) AS min_id, max(id) AS max_id +FROM read_parquet('s3://my-bucket/duckdb-demo/events.parquet'); +``` + +```text +┌───────┬────────┬────────┐ +│ rows │ min_id │ max_id │ +│ int64 │ int64 │ int64 │ +├───────┼────────┼────────┤ +│ 1000 │ 0 │ 999 │ +└───────┴────────┴────────┘ +``` + +バケット配下の任意の Parquet オブジェクトをこの方法で照会できます。OpenObserve、Spark、Iceberg など他のシステムが書き込んだファイルも対象です。 + +## 6. RustFS 内のオブジェクトを確認する + +バケット初期化イメージを使ってプレフィックスを一覧表示します。 + +```bash +docker compose run --rm --entrypoint /bin/sh create-bucket -c \ + '/usr/bin/rc alias set rustfs http://rustfs:9000 "$RUSTFS_ACCESS_KEY" "$RUSTFS_SECRET_KEY" >/dev/null && /usr/bin/rc ls rustfs/my-bucket/duckdb-demo --recursive' +``` + +```text +[2026-09-20 06:52:45] 5.32 KiB duckdb-demo/events.parquet +``` + +RustFS コンソールで `duckdb-demo` プレフィックスを確認することもできます。 + +![RustFS コンソールの duckdb-demo プレフィックス](./images/rustfs-duckdb-objects.png) + +## 7. スタックを停止・リセットする + +RustFS データボリュームを保持したままコンテナを停止します。 + +```bash +docker compose down +``` + +ローカルのオブジェクトを削除して空の RustFS ボリュームからやり直す場合は、明示的に `--volumes` を付けます。 + +```bash +docker compose down --volumes +``` + +## トラブルシューティング + +### DuckDB から RustFS に接続できない + +Compose ネットワーク内のエンドポイントは `rustfs:9000` です。ホスト上で実行する DuckDB プロセスからは `localhost:9000` を使用し、Compose ファイルのとおりにポート `9000` を公開してください。 + +### 平文 HTTP エンドポイントでの SSL エラーや接続エラー + +`ENDPOINT` にスキーマは指定しません。RustFS が TLS なしで動作している場合は、シークレットに `USE_SSL FALSE` を設定する必要があります。設定しないと `httpfs` が HTTPS を試みて接続エラーや証明書エラーになります。 + +### AccessDenied レスポンス + +シークレットの認証情報が RustFS の認証情報と一致しているか、バケット初期化が正常に完了しているかを確認してください。 + +```bash +docker compose logs create-bucket +``` + +### バーチャルホストスタイルのリクエスト + +コンテナネットワークのエンドポイントには `URL_STYLE 'path'` が必要です。バーチャルホストスタイルのリクエストには RustFS のドメイン設定(`RUSTFS_SERVER_DOMAINS`)と対応する DNS レコードが必要で、この構成では不要です。 + +## 次のステップ + +- 追加の S3 オペレーションを採用する前に、[S3 互換性ノート](/administration/protocols/s3)を確認してください。 +- [アクセスキー管理](/security-compliance/iam/access-token)で本番用の専用認証情報を作成してください。 +- [DuckDB httpfs ドキュメント](https://duckdb.org/docs/stable/extensions/httpfs/overview)で、リージョン上書きや接続数制限などの高度なオプションを確認してください。 diff --git a/content/ja/developer/integration/big-data/images/rustfs-duckdb-objects.png b/content/ja/developer/integration/big-data/images/rustfs-duckdb-objects.png new file mode 100644 index 00000000..0ced40f4 Binary files /dev/null and b/content/ja/developer/integration/big-data/images/rustfs-duckdb-objects.png differ diff --git a/content/ja/developer/integration/big-data/index.md b/content/ja/developer/integration/big-data/index.md index 89f9fe9f..f27292d1 100644 --- a/content/ja/developer/integration/big-data/index.md +++ b/content/ja/developer/integration/big-data/index.md @@ -8,6 +8,8 @@ Use **RustFS** as the object storage layer for big data systems that support an ## Systems - [Iceberg](./iceberg.md) +- [PyIceberg](./pyiceberg.md) - [Milvus](./milvus.md) +- [DuckDB](./duckdb.md) Keep application data in a dedicated bucket and prefix, and use credentials scoped to the required bucket operations. \ No newline at end of file diff --git a/content/ja/developer/integration/big-data/meta.json b/content/ja/developer/integration/big-data/meta.json index f7051d79..b7c937d7 100644 --- a/content/ja/developer/integration/big-data/meta.json +++ b/content/ja/developer/integration/big-data/meta.json @@ -3,6 +3,7 @@ "pages": [ "iceberg", "pyiceberg", - "milvus" + "milvus", + "duckdb" ] -} \ No newline at end of file +} diff --git a/content/zh/developer/integration/big-data/duckdb.md b/content/zh/developer/integration/big-data/duckdb.md new file mode 100644 index 00000000..aeec9c40 --- /dev/null +++ b/content/zh/developer/integration/big-data/duckdb.md @@ -0,0 +1,244 @@ +--- +title: "DuckDB" +description: "使用 DuckDB 及其 httpfs 扩展查询和写入 RustFS 对象存储中的 Parquet 文件,通过 Docker Compose 部署。" +--- + +本指南将 **DuckDB** 与 **RustFS** 作为其 S3 兼容存储结合使用。你将使用 Docker Compose 启动两个服务,配置 DuckDB 的 `httpfs` 扩展以对接 RustFS 端点,将查询结果以 Parquet 格式写入桶中并读回,最后在 RustFS 中验证这些对象。整个流程使用 `duckdb/duckdb:latest` 镜像(v1.5.5)和 `rustfs/rustfs-x86-musl:v2.3.1` 验证通过。 + +你需要安装带有 Compose 插件的 Docker。本部署用于本地集成测试,不适用于生产环境。 + +## 架构 + +```mermaid +flowchart LR + DuckDB["DuckDB CLI"] -->|"S3 GET (httpfs)"| RustFS["RustFS :9000"] + DuckDB -->|"S3 PUT (httpfs)"| RustFS + Init["init-bucket job"] -->|"create my-bucket"| RustFS +``` + +DuckDB 通过 [`httpfs` 扩展](https://duckdb.org/docs/stable/extensions/httpfs/overview)读写对象,该扩展实现了 S3 API。S3 secret 中配置 RustFS 端点、凭证、path-style 寻址和纯 HTTP 设置;此后即可像访问本地文件一样,通过 `s3://my-bucket/...` 路径加载和写入 Parquet 文件。 + +## 1. 创建项目文件 + +创建工作目录: + +```bash +mkdir rustfs-duckdb +cd rustfs-duckdb +``` + +创建环境变量文件,并替换两个凭证占位符: + +```ini title=".env" +RUSTFS_ACCESS_KEY= +RUSTFS_SECRET_KEY= +``` + +请为桶使用专用的凭证,不要将 `.env` 提交到版本控制。 + +创建 Compose 文件: + +```yaml title="compose.yaml" +services: + rustfs: + image: rustfs/rustfs-x86-musl:v2.3.1 + environment: + RUSTFS_ACCESS_KEY: ${RUSTFS_ACCESS_KEY} + RUSTFS_SECRET_KEY: ${RUSTFS_SECRET_KEY} + RUSTFS_VOLUMES: /data + RUSTFS_ADDRESS: ":9000" + RUSTFS_CONSOLE_ADDRESS: ":9001" + RUSTFS_CONSOLE_ENABLE: "true" + volumes: + - rustfs-data:/data + ports: + - "9000:9000" + - "9001:9001" + healthcheck: + test: ["CMD", "curl", "-sf", "http://127.0.0.1:9000/health"] + interval: 10s + timeout: 5s + retries: 6 + start_period: 10s + networks: + - warehouse + + create-bucket: + image: rustfs/rc:latest + depends_on: + rustfs: + condition: service_healthy + environment: + RUSTFS_ACCESS_KEY: ${RUSTFS_ACCESS_KEY} + RUSTFS_SECRET_KEY: ${RUSTFS_SECRET_KEY} + entrypoint: + - /bin/sh + - -c + - | + until /usr/bin/rc alias set rustfs http://rustfs:9000 "$${RUSTFS_ACCESS_KEY}" "$${RUSTFS_SECRET_KEY}"; do + echo "Waiting for RustFS..." + sleep 2 + done + /usr/bin/rc ls rustfs/my-bucket >/dev/null 2>&1 || /usr/bin/rc mb rustfs/my-bucket + networks: + - warehouse + + duckdb: + image: duckdb/duckdb:latest + entrypoint: ["/duckdb"] + depends_on: + create-bucket: + condition: service_completed_successfully + networks: + - warehouse + +networks: + warehouse: + +volumes: + rustfs-data: +``` + +[`rc` 镜像](https://github.com/rustfs/cli)提供 RustFS 官方命令行客户端。初始化任务在创建前会先检查 `my-bucket` 是否存在,因此重复启动不会删除已有数据。`duckdb/duckdb` 镜像内只包含 `/duckdb` 二进制文件、没有 shell,因此该服务设置了 `entrypoint: ["/duckdb"]`。 + +## 2. 启动部署 + +启动容器前先解析 Compose 文件: + +```bash +docker compose config +``` + +启动服务并等待桶初始化任务完成: + +```bash +docker compose up -d +docker compose ps -a +``` + +`create-bucket` 服务的退出码应为 `0`。随时可以打开 `http://localhost:9001/rustfs/console/` 的 RustFS 控制台查看桶内容。 + +## 3. 在 DuckDB 中配置 S3 secret + +启动交互式 DuckDB 会话: + +```bash +docker compose run --rm duckdb +``` + +安装扩展并注册 RustFS 端点: + +```sql +INSTALL httpfs; +LOAD httpfs; + +CREATE SECRET rustfs ( + TYPE S3, + KEY_ID '', + SECRET '', + ENDPOINT 'rustfs:9000', + USE_SSL FALSE, + URL_STYLE 'path' +); +``` + +端点使用不带协议的 `host:port` 形式。`USE_SSL FALSE` 表示在 Compose 网络内使用纯 HTTP;`URL_STYLE 'path'` 选择 path-style 寻址,这正是 RustFS 所期望的。secret 只在当前会话有效——每次启动新会话时都需要重新创建。 + +## 4. 将查询结果写入 RustFS + +把一张小表以 Parquet 格式写入桶中: + +```sql +COPY + (SELECT i AS id, 'rustfs-duckdb-demo' AS source FROM range(1000) t(i)) + TO 's3://my-bucket/duckdb-demo/events.parquet' + (FORMAT PARQUET); +``` + +```text +┌─────────┐ +│ Success │ +│ boolean │ +├─────────┤ +│ true │ +└─────────┘ +``` + +## 5. 从 RustFS 读回 Parquet + +像查询本地文件一样查询刚写入的对象: + +```sql +SELECT count(*) AS rows, min(id) AS min_id, max(id) AS max_id +FROM read_parquet('s3://my-bucket/duckdb-demo/events.parquet'); +``` + +```text +┌───────┬────────┬────────┐ +│ rows │ min_id │ max_id │ +│ int64 │ int64 │ int64 │ +├───────┼────────┼────────┤ +│ 1000 │ 0 │ 999 │ +└───────┴────────┴────────┘ +``` + +桶中任何 Parquet 对象都可以这样查询,包括 OpenObserve、Spark 或 Iceberg 等其他系统写入的文件。 + +## 6. 在 RustFS 中验证对象 + +通过桶初始化镜像列出该前缀下的对象: + +```bash +docker compose run --rm --entrypoint /bin/sh create-bucket -c \ + '/usr/bin/rc alias set rustfs http://rustfs:9000 "$RUSTFS_ACCESS_KEY" "$RUSTFS_SECRET_KEY" >/dev/null && /usr/bin/rc ls rustfs/my-bucket/duckdb-demo --recursive' +``` + +```text +[2026-09-20 06:52:45] 5.32 KiB duckdb-demo/events.parquet +``` + +你也可以在 RustFS 控制台中查看 `duckdb-demo` 前缀: + +![RustFS 控制台中的 duckdb-demo 前缀](./images/rustfs-duckdb-objects.png) + +## 7. 停止或重置环境 + +停止容器并保留 RustFS 数据卷: + +```bash +docker compose down +``` + +如需删除本地对象并从空的 RustFS 数据卷开始,请显式加上 `--volumes`: + +```bash +docker compose down --volumes +``` + +## 故障排除 + +### DuckDB 无法连接 RustFS + +在 Compose 网络内端点是 `rustfs:9000`。如果 DuckDB 进程运行在宿主机上,请改用 `localhost:9000`,并按 Compose 文件中的配置发布 `9000` 端口。 + +### 纯 HTTP 端点出现 SSL 或连接错误 + +`ENDPOINT` 不带协议。如果 RustFS 未启用 TLS,secret 中必须设置 `USE_SSL FALSE`,否则 `httpfs` 会尝试 HTTPS 并报连接或证书错误。 + +### 返回 AccessDenied 响应 + +检查 secret 中的凭证是否与 RustFS 凭证一致,并确认桶初始化任务已成功完成: + +```bash +docker compose logs create-bucket +``` + +### Virtual-host 风格的请求 + +容器网络端点需要 `URL_STYLE 'path'`。Virtual-host 风格的请求需要 RustFS 域名配置(`RUSTFS_SERVER_DOMAINS`)和对应的 DNS 记录,本方案不需要。 + +## 后续步骤 + +- 在采用其他 S3 操作前,请查看 [S3 兼容性说明](/administration/protocols/s3)。 +- 通过[访问密钥管理](/security-compliance/iam/access-token)创建专用的生产凭证。 +- 阅读 [DuckDB httpfs 文档](https://duckdb.org/docs/stable/extensions/httpfs/overview)了解区域覆盖、连接数限制等高级选项。 diff --git a/content/zh/developer/integration/big-data/images/rustfs-duckdb-objects.png b/content/zh/developer/integration/big-data/images/rustfs-duckdb-objects.png new file mode 100644 index 00000000..fa65c53a Binary files /dev/null and b/content/zh/developer/integration/big-data/images/rustfs-duckdb-objects.png differ diff --git a/content/zh/developer/integration/big-data/index.md b/content/zh/developer/integration/big-data/index.md index 68e6949c..09e32d35 100644 --- a/content/zh/developer/integration/big-data/index.md +++ b/content/zh/developer/integration/big-data/index.md @@ -8,6 +8,8 @@ description: "通过 S3 兼容的对象存储接口将大数据系统连接到 R ## 系统 - [Iceberg](./iceberg.md) +- [PyIceberg](./pyiceberg.md) - [Milvus](./milvus.md) +- [DuckDB](./duckdb.md) 将应用程序数据保存在专用存储桶和前缀中,并使用作用域限定为所需存储桶操作的凭证。 \ No newline at end of file diff --git a/content/zh/developer/integration/big-data/meta.json b/content/zh/developer/integration/big-data/meta.json index 6baa4460..676e2b4c 100644 --- a/content/zh/developer/integration/big-data/meta.json +++ b/content/zh/developer/integration/big-data/meta.json @@ -3,6 +3,7 @@ "pages": [ "iceberg", "pyiceberg", - "milvus" + "milvus", + "duckdb" ] -} \ No newline at end of file +}