From d8927369587778d9c6b8ba248a292f1dba1c66f1 Mon Sep 17 00:00:00 2001 From: gatewayJ <835269233@qq.com> Date: Wed, 9 Sep 2026 10:07:18 +0800 Subject: [PATCH] docs: add S3 Tables and PyIceberg guides --- content/de/administration/data/meta.json | 1 + content/de/administration/data/s3-tables.md | 156 +++++++++++++++ content/de/administration/index.md | 1 + .../developer/integration/big-data/iceberg.md | 2 + .../developer/integration/big-data/meta.json | 1 + .../integration/big-data/pyiceberg.md | 178 ++++++++++++++++++ content/en/administration/data/meta.json | 1 + content/en/administration/data/s3-tables.md | 156 +++++++++++++++ content/en/administration/index.md | 1 + .../developer/integration/big-data/iceberg.md | 2 + .../developer/integration/big-data/meta.json | 1 + .../integration/big-data/pyiceberg.md | 178 ++++++++++++++++++ content/fr/administration/data/meta.json | 1 + content/fr/administration/data/s3-tables.md | 156 +++++++++++++++ content/fr/administration/index.md | 1 + .../developer/integration/big-data/iceberg.md | 2 + .../developer/integration/big-data/meta.json | 1 + .../integration/big-data/pyiceberg.md | 178 ++++++++++++++++++ content/ja/administration/data/meta.json | 1 + content/ja/administration/data/s3-tables.md | 156 +++++++++++++++ content/ja/administration/index.md | 1 + .../developer/integration/big-data/iceberg.md | 2 + .../developer/integration/big-data/meta.json | 1 + .../integration/big-data/pyiceberg.md | 178 ++++++++++++++++++ content/zh/administration/data/meta.json | 1 + content/zh/administration/data/s3-tables.md | 156 +++++++++++++++ content/zh/administration/index.md | 1 + .../developer/integration/big-data/iceberg.md | 2 + .../developer/integration/big-data/meta.json | 1 + .../integration/big-data/pyiceberg.md | 178 ++++++++++++++++++ 30 files changed, 1695 insertions(+) create mode 100644 content/de/administration/data/s3-tables.md create mode 100644 content/de/developer/integration/big-data/pyiceberg.md create mode 100644 content/en/administration/data/s3-tables.md create mode 100644 content/en/developer/integration/big-data/pyiceberg.md create mode 100644 content/fr/administration/data/s3-tables.md create mode 100644 content/fr/developer/integration/big-data/pyiceberg.md create mode 100644 content/ja/administration/data/s3-tables.md create mode 100644 content/ja/developer/integration/big-data/pyiceberg.md create mode 100644 content/zh/administration/data/s3-tables.md create mode 100644 content/zh/developer/integration/big-data/pyiceberg.md diff --git a/content/de/administration/data/meta.json b/content/de/administration/data/meta.json index e72a1121..68247d52 100644 --- a/content/de/administration/data/meta.json +++ b/content/de/administration/data/meta.json @@ -3,6 +3,7 @@ "pages": [ "object", "bucket", + "s3-tables", "tiered-storage", "lifecycle-management" ] diff --git a/content/de/administration/data/s3-tables.md b/content/de/administration/data/s3-tables.md new file mode 100644 index 00000000..b1b16878 --- /dev/null +++ b/content/de/administration/data/s3-tables.md @@ -0,0 +1,156 @@ +--- +title: "S3 Tables" +description: "Aktivieren Sie einen RustFS-Tabellen-Bucket und verbinden Sie Iceberg-Clients mit dem integrierten REST-Katalog." +--- + +RustFS S3 Tables verwaltet **Apache Iceberg**-Tabellen über einen integrierten REST-Katalog. Tabellendaten, Manifeste und Iceberg-Metadaten bleiben als S3-Objekte in RustFS gespeichert. Diese Anleitung zeigt, wie Sie einen eigenen Tabellen-Bucket aktivieren, Clients verbinden und Berechtigungen sowie Wartungsgrenzen berücksichtigen. + +:::note[Vorschaustatus und Versionsumfang] + +S3 Tables ist eine Vorschaufunktion; die Client-Kompatibilität beschränkt sich auf die unten aufgeführten Abläufe. Diese Seite bezieht sich auf den RustFS-Commit [`7e0c6711`](https://github.com/rustfs/rustfs/commit/7e0c67111b97703d47e23719b0264a739c8acea8), geprüft am 8. September 2026. Prüfen Sie die [Supportmatrix](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/docs/architecture/s3-tables-support-matrix.md) und Ihre Version, bevor Sie weitere Katalogoperationen oder Clients einsetzen. + +::: + +## Funktionsweise + +Ein Iceberg-Client nutzt den REST-Katalog, um Tabellen zu finden und Metadatenänderungen festzuschreiben. Tabellendateien liest und schreibt er über die S3-API. RustFS stellt beide Schnittstellen am S3-API-Port bereit. + +```mermaid +flowchart TB + Client["Iceberg client"] -->|Catalog requests| Catalog["RustFS Iceberg REST catalog"] + Client -->|Read and write files| S3["RustFS S3 API"] + Catalog -->|Validate referenced objects| S3 +``` + +| Ressource | Zweck | +| --- | --- | +| Tabellen-Bucket | Ein vorhandener S3-Bucket, der für den Katalog aktiviert wurde; sein Name ist der `warehouse`-Wert des Clients. | +| Namespace | Eine logische Gruppe von Tabellen innerhalb dieses Warehouse. | +| Tabelle | Ein Iceberg-Schema, Snapshots und ein vom Katalog verwalteter aktueller Metadatenpfad. | + +Das Aktivieren eines Tabellen-Buckets registriert vorhandene Parquet-Dateien nicht automatisch als Iceberg-Tabellen. Erstellen oder registrieren Sie Tabellen über einen Iceberg-Client. Ohne Angabe von `location` weist RustFS einen Speicherort zu; ein benutzerdefinierter Speicherort muss im selben Bucket liegen. Clients sollten den zurückgegebenen Speicherort verwenden. + +Das standardmäßige Katalog-Backend `object` speichert den Katalogzustand dauerhaft im RustFS-Objektspeicher. Ein Tabellen-Commit prüft seine Ausgangsmetadaten und referenzierten Objekte, bevor der Zeiger auf die aktuellen Metadaten bedingt aktualisiert wird. Bei einem Schreibkonflikt muss der Client die Tabelle neu laden und den Konflikt auflösen. Eine Transaktion umfasst genau eine Tabelle. + +## Voraussetzungen + +- Starten Sie eine RustFS-Bereitstellung mit den oben beschriebenen S3-Tables-Endpunkten. Siehe [Installation](/installation). +- Installieren Sie die [AWS CLI](/developer/examples/aws-cli) und `curl` ab Version 7.76 mit Unterstützung für `--aws-sigv4` und `--fail-with-body`. +- Erstellen Sie für diese Anleitung einen eigenen neuen Bucket. Das Beispiel verwendet `my-bucket`. +- Verwenden Sie ein vorhandenes Administratorkonto mit Zugriff auf Katalogoperationen und S3-Objekte. Die integrierte Richtlinie `consoleAdmin` deckt diese Anleitung ab; konfigurieren Sie enger begrenzte Richtlinien für Anwendungen. + +Die Beispiele verwenden `http://localhost:9000`. Ersetzen Sie dies durch Ihren Server-Endpunkt und verwenden Sie außerhalb lokaler Tests [TLS](/integration/tls-configured) mit aktivierter Zertifikatsprüfung. + +:::warning[Lebenszyklusverhalten von Tabellen-Buckets] + +Tabellen-Buckets sind von der normalen Ablaufverarbeitung der Bucket-Lebenszyklusregeln ausgenommen. Wenn Sie diesen Modus für einen vorhandenen Bucket aktivieren, ändert sich die Anwendung seiner Ablaufregeln. Verwenden Sie Katalogwartungsfunktionen, die Iceberg-Referenzen berücksichtigen, um Snapshots ablaufen zu lassen und Tabellendateien zu bereinigen. + +::: + +## 1. Bucket erstellen + +Legen Sie Endpunkt und Zugangsdaten für die Beispiel-Clients fest: + +```bash +export RUSTFS_ENDPOINT="http://localhost:9000" +export AWS_ACCESS_KEY_ID="" +export AWS_SECRET_ACCESS_KEY="" +export AWS_DEFAULT_REGION="us-east-1" +``` + +Erstellen Sie den eigenen Bucket: + +```bash +aws --endpoint-url "$RUSTFS_ENDPOINT" s3api create-bucket --bucket my-bucket +``` + +Diese Beispiele verwenden einen Zugriffsschlüssel und einen geheimen Zugriffsschlüssel ohne temporäres Sitzungstoken. Behalten Sie dieselbe Shell-Umgebung für die folgenden Anfragen und die PyIceberg-Anleitung bei. + +## 2. Tabellen-Bucket aktivieren + +Senden Sie eine mit SigV4 signierte Anfrage mit leerem Body an den Tabellen-Bucket-Endpunkt: + +```bash +curl --fail-with-body --silent --show-error \ + --aws-sigv4 "aws:amz:us-east-1:s3" \ + --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \ + --header "x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" \ + --request PUT "$RUSTFS_ENDPOINT/iceberg/v1/buckets/my-bucket" +``` + +Lesen Sie den Zustand mit denselben Zugangsdaten zurück: + +```bash +curl --fail-with-body --silent --show-error \ + --aws-sigv4 "aws:amz:us-east-1:s3" \ + --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \ + --header "x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" \ + "$RUSTFS_ENDPOINT/iceberg/v1/buckets/my-bucket" +``` + +Beide Anfragen liefern bei Erfolg HTTP `200`. Prüfen Sie, ob die Antwort diese Werte enthält: + +```json +{ + "table-bucket": "my-bucket", + "enabled": true, + "catalog-type": "iceberg-rest", + "warehouse": "my-bucket", + "catalog-entry-present": true +} +``` + +Dies ist ein Antwortauszug. Der zurückgegebene `catalog-uri` ist eine Bucket-spezifische Route; verwenden Sie für die Konfiguration eines Iceberg-REST-Clients den Basis-URI aus dem nächsten Abschnitt. + +## 3. Iceberg-Client verbinden + +Verwenden Sie für den RustFS-Beispielendpunkt folgende Einstellungen: + +| Einstellung | Wert | +| --- | --- | +| REST-Katalog-URI | `http://localhost:9000/iceberg` | +| Warehouse und Präfix | `my-bucket` | +| REST-Authentifizierung | AWS Signature Version 4, Signaturdienst `s3` | +| Region | `us-east-1` | +| S3-Dateiendpunkt | `http://localhost:9000` mit pfadbasierter Adressierung | + +Der Client ergänzt den Katalog-URI um `/v1`. Das Warehouse ist ein Bucket-Name, kein S3-URI oder AWS S3 Tables ARN. Konfigurieren Sie sowohl die REST-Anfragesignierung als auch den S3-Dateizugriff, auch wenn beide dasselbe Konto verwenden. + +Wenn Sie bereits einen separaten Iceberg-REST-Katalog betreiben, beschreibt die [Apache-Iceberg-Integration](/developer/integration/big-data/iceberg) die Bereitstellung mit einem externen Katalog. + +## Berechtigungen und Zugangsdaten + +Zum Aktivieren eines Tabellen-Buckets ist `admin:SetTableBucket` erforderlich, zum Prüfen des Zustands `admin:GetTableBucket`. Die Katalogerkennung verwendet `admin:GetTableCatalog`. Namespace- und Tabellenoperationen besitzen eigene RustFS-Admin-Aktionen, darunter `admin:SetTableNamespace`, `admin:CreateTable`, `admin:GetTableMetadata` und `admin:CommitTable`. + +Für das Lesen und Schreiben von Tabellendateien sind zusätzlich normale S3-Berechtigungen erforderlich. RustFS prüft Tabellenberechtigungen für Objektpfade im Warehouse: Lesen erfordert die entsprechende Autorisierung für `admin:GetTableMetadata`, Schreiben für `admin:SetTableMetadata`. Eine Berechtigung für Katalog-Commits allein erlaubt nicht die vorausgehenden S3-Dateischreibvorgänge. Konfigurieren Sie [IAM-Richtlinien](/security-compliance/iam/policies) für beide Schnittstellen. + +Die Ausgabe von Zugangsdaten durch den Katalog ist standardmäßig deaktiviert. Bei aktivierter Funktion muss ein kompatibler Client `X-Iceberg-Access-Delegation: vended-credentials` aushandeln, und der Aufrufer benötigt die Berechtigung, Tabellenzugangsdaten anzufordern. Der erste Katalogzugriff erfordert weiterhin eine autorisierte Identität. Die verlinkte PyIceberg-Anleitung verwendet ausdrücklich konfigurierte Zugangsdaten. + +## Wartung und Schutz vor Datenverlust + +Das Löschen von Metadaten und die Hintergrundwartung sind standardmäßig deaktiviert. RustFS stellt explizite Operationen für Planung, Scheduler-Läufe und Worker-Läufe bereit; ein integrierter periodischer Wartungs-Scheduler wird nicht ausgeführt. Prüfen Sie einen Wartungsplan und die darin beibehaltenen Referenzen, bevor Sie Löschvorgänge aktivieren. + +Beim Löschen einer Tabelle wird ihr Katalogeintrag entfernt, während die zugrunde liegenden Objekte erhalten bleiben. Führen Sie erforderliche Tabellenwartungen vor dem Entfernen aus dem Katalog durch; danach können Wartungsoperationen die Tabelle nicht mehr finden. Die Bereinigung verbliebener Objekte erfordert einen separaten Plan, der alle verbleibenden Referenzen berücksichtigt. Löschen Sie keine S3-Pfade rekursiv, auf die Snapshots oder andere Metadaten noch verweisen könnten. + +Behalten Sie für diese Anleitung das Standard-Katalog-Backend bei. Der Wechsel einer vorhandenen Bereitstellung zu `durable-strong` erfordert das [Verfahren zur Katalogumstellung](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/docs/operations/s3-tables-cutover-runbook.md), einschließlich Migrationsvorprüfung und koordinierter Sperrung der schreibenden Clients. + +## Client-Kompatibilität und Grenzen + +Das Quellcode-Repository pflegt folgenden Validierungsumfang: + +| Client | Validierungsumfang | +| --- | --- | +| PyIceberg | Automatisierte Prüfungen für Erstellen, Anhängen, erneutes Laden, Scannen und Katalogoperationen. | +| DuckDB Iceberg 1.5.5 | Automatisierte Prüfungen eines generischen REST-Katalogs für Lesen, Schreiben und Schemaänderungen an einzelnen Tabellen. | +| Spark | Eine optional aktivierbare Live-Testumgebung; prüfen Sie die konkret eingesetzten Spark- und Iceberg-Versionen. | +| Trino | Ein manueller Lesetest; Schreibkompatibilität wird nicht zugesichert. | + +Die Iceberg-Formate v1 und v2 werden unterstützt; v2 ist der Standard. Gestuftes Erstellen von Tabellen, Datenbereinigung beim Löschen und Iceberg-Format v3 werden nicht unterstützt. + +RustFS S3 Tables bietet weder eine SQL-Ausführungsengine noch atomare Transaktionen über mehrere Tabellen oder unabhängige regionsübergreifende Active-Active-Schreibzugriffe. Eine vollständige Kompatibilität mit der AWS-S3-Tables-Steuerungsebene wird nicht zugesichert. Prüfen Sie die [Supportmatrix](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/docs/architecture/s3-tables-support-matrix.md), bevor Sie eine andere Engine oder ein anbieterspezifisches Profil verwenden. + +## Nächste Schritte + +- Führen Sie die [PyIceberg-Anleitung](/developer/integration/big-data/pyiceberg) aus. +- Prüfen Sie die [IAM-Richtlinien](/security-compliance/iam/policies), bevor Sie Anwendungen Zugriff gewähren. +- Validieren Sie weitere Client-Versionen mit den [Client-Konformitätsprüfungen](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/scripts/table-catalog/README.md) des Repositorys. diff --git a/content/de/administration/index.md b/content/de/administration/index.md index 2c059b42..51cf0a7a 100644 --- a/content/de/administration/index.md +++ b/content/de/administration/index.md @@ -9,6 +9,7 @@ Use this section to manage RustFS through the Console, administer buckets and ob - [Console](./console/index.md) covers browser-based administration and sign-in methods. - [Data Management](./data/object/object-lock.md) covers buckets, objects, lifecycle behavior, and data protection features. +- [S3 Tables](/administration/data/s3-tables) behandelt Tabellen-Buckets und den integrierten Iceberg-REST-Katalog. - [Protocol Support](./protocols/s3.md) covers S3, WebDAV, FTPS, and SFTP access. - [CORS Configuration](./cors/index.md) covers cross-origin access to RustFS services. - [Virtual-Host Access](/integration/virtual) covers domain-based S3 addressing. diff --git a/content/de/developer/integration/big-data/iceberg.md b/content/de/developer/integration/big-data/iceberg.md index 9511170c..10bc4a5f 100644 --- a/content/de/developer/integration/big-data/iceberg.md +++ b/content/de/developer/integration/big-data/iceberg.md @@ -5,6 +5,8 @@ description: "Run Apache Iceberg with Spark, a REST catalog, and RustFS object s This guide runs **Apache Iceberg** with Spark, an Iceberg REST catalog, and **RustFS** as the S3-compatible warehouse. You will create an Iceberg table, write rows, query them, and verify that the table files are stored in RustFS. +Für den in RustFS integrierten REST-Katalog folgen Sie der [Einrichtung von S3 Tables](/administration/data/s3-tables) und der [PyIceberg-Anleitung](/developer/integration/big-data/pyiceberg). Die folgende Bereitstellung verwendet einen separaten Katalogdienst. + You need Docker with the Compose plugin and enough local resources to run four containers. This deployment is intended for local integration testing, not production. :::note[Upstream status] diff --git a/content/de/developer/integration/big-data/meta.json b/content/de/developer/integration/big-data/meta.json index c3f673eb..2286437c 100644 --- a/content/de/developer/integration/big-data/meta.json +++ b/content/de/developer/integration/big-data/meta.json @@ -2,6 +2,7 @@ "title": "Big Data", "pages": [ "iceberg", + "pyiceberg", "milvus" ] } \ No newline at end of file diff --git a/content/de/developer/integration/big-data/pyiceberg.md b/content/de/developer/integration/big-data/pyiceberg.md new file mode 100644 index 00000000..5ccd6a36 --- /dev/null +++ b/content/de/developer/integration/big-data/pyiceberg.md @@ -0,0 +1,178 @@ +--- +title: "PyIceberg" +description: "Erstellen, schreiben und lesen Sie mit PyIceberg eine Iceberg-Tabelle über den REST-Katalog von RustFS S3 Tables." +--- + +Mit **PyIceberg** erstellen Sie einen Namespace und eine Tabelle im RustFS-S3-Tables-Katalog, hängen zwei Zeilen an und prüfen die Daten nach erneutem Laden der Tabelle. Diese Anleitung verwendet PyIceberg `0.10.0`, Python `3.12` und ausdrücklich konfigurierte Zugangsdaten. + +## Voraussetzungen + +- Schließen Sie die [Einrichtung von S3 Tables](/administration/data/s3-tables) ab: Erstellen und aktivieren Sie `my-bucket` und erfüllen Sie die Anforderungen an Konto und TLS. +- Behalten Sie `RUSTFS_ENDPOINT`, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` und `AWS_DEFAULT_REGION` wie dort beschrieben bei. + +## 1. Client installieren + +Erstellen Sie ein Verzeichnis und eine isolierte Python-Umgebung: + +```bash +mkdir rustfs-s3-tables +cd rustfs-s3-tables +python3.12 -m venv .venv +source .venv/bin/activate +python -m pip install 'pyiceberg[pyarrow]==0.10.0' boto3 +``` + +## 2. Katalogverbindung konfigurieren + +Speichern Sie das folgende Verbindungsmodul. Es signiert sowohl die erste Anfrage zur Katalogerkennung als auch nachfolgende REST-Anfragen mit demselben S3-SigV4-Verhalten wie das [validierte Client-Beispiel](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/scripts/table-catalog/pyiceberg_smoke.py) von RustFS. + +```python title="rustfs_catalog.py" +import hashlib +import os + +from botocore.auth import S3SigV4Auth +from botocore.awsrequest import AWSRequest +from botocore.credentials import Credentials +from pyiceberg.catalog.rest import RestCatalog +from requests.adapters import HTTPAdapter + +endpoint = os.environ["RUSTFS_ENDPOINT"].rstrip("/") +region = os.environ["AWS_DEFAULT_REGION"] +access_key = os.environ["AWS_ACCESS_KEY_ID"] +secret_key = os.environ["AWS_SECRET_ACCESS_KEY"] +credentials = Credentials(access_key, secret_key) + + +class RustFSSigV4Adapter(HTTPAdapter): + def add_headers(self, request, **kwargs): + body = request.body or b"" + if isinstance(body, str): + body = body.encode("utf-8") + request.headers["x-amz-content-sha256"] = hashlib.sha256(body).hexdigest() + request.headers.pop("connection", None) + signed = AWSRequest( + method=request.method, + url=request.url, + data=body, + headers=dict(request.headers), + ) + S3SigV4Auth(credentials, "s3", region).add_auth(signed) + request.headers.update(signed.headers) + + +class RustFSRestCatalog(RestCatalog): + def _init_sigv4(self, session): + session.mount(self.uri, RustFSSigV4Adapter()) + + +catalog = RustFSRestCatalog( + "rustfs", + **{ + "uri": f"{endpoint}/iceberg", + "warehouse": "my-bucket", + "prefix": "my-bucket", + "rest.sigv4-enabled": "true", + "rest.signing-name": "s3", + "rest.signing-region": region, + "py-io-impl": "pyiceberg.io.pyarrow.PyArrowFileIO", + "s3.endpoint": endpoint, + "s3.access-key-id": access_key, + "s3.secret-access-key": secret_key, + "s3.region": region, + "s3.force-virtual-addressing": "false", + }, +) +``` + +`s3.force-virtual-addressing=false` wählt für diesen benutzerdefinierten Endpunkt die pfadbasierte Adressierung in der PyArrow-Dateiimplementierung von PyIceberg. + +:::note[Client-Version] + +Der Adapter überschreibt den PyIceberg-Hook `_init_sigv4`, damit die Katalogerkennung bereits vor Abschluss des Konstruktors signiert wird. Behalten Sie bei Verwendung dieses Moduls die festgelegte PyIceberg-Version bei und führen Sie vor einem Versionswechsel die gesamte Anleitung erneut aus. + +::: + +## 3. Tabelle erstellen und lesen + +Das Beispiel erstellt den Namespace `analytics` und die Tabelle `events` und stoppt, wenn eine der Ressourcen bereits vorhanden ist. Jedes Namespace-Segment und jeder Tabellenname muss aus 1–64 ASCII-Zeichen bestehen: Kleinbuchstaben, Ziffern, `_` oder `-`, mit einem Buchstaben oder einer Ziffer an beiden Enden. Der vollständige Namespace darf einschließlich der Punkte höchstens 512 Zeichen lang sein. + +Für andere Namen ändern Sie `identifier` in `example.py` sowie die Namen in den nachfolgenden Prüf- und Entfernungsbefehlen. + +Speichern Sie das folgende Programm im selben Verzeichnis: + +```python title="example.py" +import json + +import pyarrow as pa + +from rustfs_catalog import catalog + +identifier = ("analytics", "events") +schema = pa.schema( + [ + pa.field("id", pa.int64(), nullable=False), + pa.field("payload", pa.string(), nullable=False), + ] +) +expected = [{"id": 1, "payload": "alpha"}, {"id": 2, "payload": "beta"}] + +catalog.create_namespace(identifier[0]) +catalog.create_table(identifier, schema=schema) +table = catalog.load_table(identifier) +table.append(pa.Table.from_pylist(expected, schema=schema)) + +loaded = catalog.load_table(identifier) +actual = sorted(loaded.scan().to_arrow().to_pylist(), key=lambda row: row["id"]) +assert actual == expected, f"Unexpected table contents: {actual}" +print("rows:", json.dumps(actual)) +print("metadata:", loaded.metadata_location) +``` + +Führen Sie es aus: + +```bash +python example.py +``` + +Die Ausgabe enthält die beiden vollständigen Zeilen und den S3-URI des aktuellen Metadatenobjekts: + +```text +rows: [{"id": 1, "payload": "alpha"}, {"id": 2, "payload": "beta"}] +metadata: s3://my-bucket/ +``` + +Der erzeugte Objektschlüssel für die Metadaten variiert. Eine erfolgreiche Prüfung bedeutet, dass die Tabelle aus dem Katalog neu geladen und ihre Datendateien über S3 gelesen wurden. Das Erstellen der Tabelle allein prüft keines dieser Ergebnisse. + +## 4. Beispiel prüfen oder aus dem Katalog entfernen + +Listen Sie die Tabelle in einem neuen Python-Prozess mit demselben Verbindungsmodul auf: + +```bash +python - <<'PY' +from rustfs_catalog import catalog + +print(catalog.list_tables("analytics")) +PY +``` + +Das Ergebnis sollte `("analytics", "events")` enthalten. + +:::note[Nur Katalogeinträge entfernen] + +Die folgenden Befehle entfernen den Tabelleneintrag dieser Anleitung und den anschließend leeren Namespace. Bucket und zugrunde liegende Objekte bleiben erhalten. Planen Sie eine eventuelle Datenbereinigung vorab: Nach `drop_table` kann die Tabellenwartung die Tabelle nicht mehr finden. Siehe [Wartung und Schutz vor Datenverlust](/administration/data/s3-tables). + +::: + +```bash +python - <<'PY' +from rustfs_catalog import catalog + +catalog.drop_table(("analytics", "events")) +catalog.drop_namespace("analytics") +PY +``` + +## Nächste Schritte + +- Nutzen Sie die [PyIceberg-API-Dokumentation](https://py.iceberg.apache.org/api/) für Client-Operationen und gleichen Sie jede Operation mit dem RustFS-Supportumfang ab. +- Verwenden Sie die [Integration mit externem Iceberg-Katalog](/developer/integration/big-data/iceberg), wenn Sie einen separaten Katalogdienst betreiben. diff --git a/content/en/administration/data/meta.json b/content/en/administration/data/meta.json index 5668022a..e9471592 100644 --- a/content/en/administration/data/meta.json +++ b/content/en/administration/data/meta.json @@ -3,6 +3,7 @@ "pages": [ "object", "bucket", + "s3-tables", "tiered-storage", "lifecycle-management" ] diff --git a/content/en/administration/data/s3-tables.md b/content/en/administration/data/s3-tables.md new file mode 100644 index 00000000..47d1403f --- /dev/null +++ b/content/en/administration/data/s3-tables.md @@ -0,0 +1,156 @@ +--- +title: "S3 Tables" +description: "Enable a RustFS table bucket and connect Iceberg clients to the built-in REST catalog." +--- + +RustFS S3 Tables manages **Apache Iceberg** tables through a built-in REST catalog. Table data, manifests, and Iceberg metadata remain S3 objects in RustFS. This guide enables a dedicated table bucket and explains client connections, permissions, and maintenance boundaries. + +:::note[Preview and version scope] + +S3 Tables is a preview feature; client compatibility is limited to the workflows listed below. This page follows RustFS commit [`7e0c6711`](https://github.com/rustfs/rustfs/commit/7e0c67111b97703d47e23719b0264a739c8acea8), reviewed on September 8, 2026. Check the [support matrix](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/docs/architecture/s3-tables-support-matrix.md) and your release before adopting additional catalog operations or clients. + +::: + +## How it works + +An Iceberg client uses the REST catalog to discover tables and commit metadata changes. It uses the S3 API to read and write table files. Both interfaces are served by RustFS on the S3 API port. + +```mermaid +flowchart TB + Client["Iceberg client"] -->|Catalog requests| Catalog["RustFS Iceberg REST catalog"] + Client -->|Read and write files| S3["RustFS S3 API"] + Catalog -->|Validate referenced objects| S3 +``` + +| Resource | Purpose | +| --- | --- | +| Table bucket | An existing S3 bucket enabled for catalog use; its name is the client `warehouse`. | +| Namespace | A logical group of tables within that warehouse. | +| Table | An Iceberg schema, snapshots, and a current metadata location maintained by the catalog. | + +Enabling a table bucket does not register existing Parquet files as Iceberg tables. Create or register tables through an Iceberg client. If no `location` is supplied, RustFS assigns one; a custom location must be in the same bucket. Clients should use the returned location. + +The default `object` catalog backing persists catalog state in RustFS object storage. A table commit validates its base metadata and referenced objects before conditionally updating the current metadata pointer. A conflicting writer must reload the table and resolve the conflict. The transaction boundary is one table. + +## Before you begin + +- Start a RustFS deployment with the S3 Tables endpoints described above. See [Installation](/installation). +- Install the [AWS CLI](/developer/examples/aws-cli) and `curl` 7.76 or later, which supports `--aws-sigv4` and `--fail-with-body`. +- Use a new, dedicated bucket for this walkthrough. The example uses `my-bucket`. +- Use an existing administrative account with access to both catalog operations and S3 objects. The built-in `consoleAdmin` policy covers this walkthrough; configure narrower policies for applications. + +The examples use `http://localhost:9000`. Replace it with your server endpoint, and use [TLS](/integration/tls-configured) with certificate verification enabled outside a local test environment. + +:::warning[Table bucket lifecycle behavior] + +Table buckets are excluded from ordinary bucket lifecycle expiration. Enabling this mode on an existing bucket changes how its expiration rules are applied. Use catalog maintenance that understands Iceberg references to expire snapshots and clean up table files. + +::: + +## 1. Create a bucket + +Set the endpoint and access credentials for the example clients: + +```bash +export RUSTFS_ENDPOINT="http://localhost:9000" +export AWS_ACCESS_KEY_ID="" +export AWS_SECRET_ACCESS_KEY="" +export AWS_DEFAULT_REGION="us-east-1" +``` + +Create the dedicated bucket: + +```bash +aws --endpoint-url "$RUSTFS_ENDPOINT" s3api create-bucket --bucket my-bucket +``` + +These examples use an access key and secret key, without a temporary session token. Keep the same shell environment for the following requests and the PyIceberg guide. + +## 2. Enable the table bucket + +Send an empty, SigV4-signed request to the table bucket endpoint: + +```bash +curl --fail-with-body --silent --show-error \ + --aws-sigv4 "aws:amz:us-east-1:s3" \ + --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \ + --header "x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" \ + --request PUT "$RUSTFS_ENDPOINT/iceberg/v1/buckets/my-bucket" +``` + +Read the state back with the same credentials: + +```bash +curl --fail-with-body --silent --show-error \ + --aws-sigv4 "aws:amz:us-east-1:s3" \ + --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \ + --header "x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" \ + "$RUSTFS_ENDPOINT/iceberg/v1/buckets/my-bucket" +``` + +Both requests return HTTP `200` on success. Confirm that the response includes these values: + +```json +{ + "table-bucket": "my-bucket", + "enabled": true, + "catalog-type": "iceberg-rest", + "warehouse": "my-bucket", + "catalog-entry-present": true +} +``` + +This is a response excerpt. The returned `catalog-uri` is a bucket-specific route; use the client base URI in the next section when configuring an Iceberg REST client. + +## 3. Connect an Iceberg client + +Use these settings for the canonical RustFS endpoint: + +| Setting | Value | +| --- | --- | +| REST catalog URI | `http://localhost:9000/iceberg` | +| Warehouse and prefix | `my-bucket` | +| REST authentication | AWS Signature Version 4, signing name `s3` | +| Region | `us-east-1` | +| S3 file endpoint | `http://localhost:9000` with path-style addressing | + +The client adds `/v1` to the catalog URI. The warehouse is a bucket name, not an S3 URI or an AWS S3 Tables ARN. Configure both REST request signing and S3 file access, even when they use the same account. + +If you already operate a separate Iceberg REST catalog, use the [Apache Iceberg integration](/developer/integration/big-data/iceberg) for the external-catalog deployment pattern. + +## Permissions and credentials + +Table bucket enablement requires `admin:SetTableBucket`; inspecting it requires `admin:GetTableBucket`. Catalog discovery uses `admin:GetTableCatalog`. Namespace and table operations have their own RustFS admin actions, including `admin:SetTableNamespace`, `admin:CreateTable`, `admin:GetTableMetadata`, and `admin:CommitTable`. + +Table file reads and writes also require ordinary S3 permissions. RustFS checks table permissions on warehouse object paths: reads require the corresponding `admin:GetTableMetadata` authorization, and writes require `admin:SetTableMetadata`. A catalog commit grant alone does not authorize the S3 file writes that precede it. Configure [IAM policies](/security-compliance/iam/policies) for both interfaces. + +Catalog credential vending is disabled by default. When enabled, a compatible client must negotiate `X-Iceberg-Access-Delegation: vended-credentials`, and the caller must have permission to request table credentials. Initial catalog setup still requires an authorized principal. The linked PyIceberg walkthrough uses explicitly configured credentials. + +## Maintenance and data protection + +Metadata deletion and background maintenance are disabled by default. RustFS exposes explicit planning, scheduler-run, and worker-run operations; it does not run a built-in periodic maintenance scheduler. Review a maintenance plan and its retained references before enabling deletion. + +Dropping a table removes its catalog entry while retaining its underlying objects. Complete any required table maintenance before unregistering the table; afterward, maintenance operations can no longer find it. Cleanup of retained objects needs a separate plan that accounts for all remaining references. Do not recursively delete S3 paths that snapshots or other metadata may still reference. + +Keep the default catalog backing for this walkthrough. Switching an existing deployment to `durable-strong` requires the [catalog cutover procedure](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/docs/operations/s3-tables-cutover-runbook.md), including migration preflight and coordinated writer fencing. + +## Client compatibility and limits + +The source repository maintains the following validation scope: + +| Client | Validation scope | +| --- | --- | +| PyIceberg | Automated create, append, reload, scan, and catalog operation checks. | +| DuckDB Iceberg 1.5.5 | Automated generic REST catalog checks for single-table reads, writes, and schema changes. | +| Spark | An opt-in live harness; validate the exact Spark and Iceberg versions you deploy. | +| Trino | A manual read-only probe; write compatibility is not claimed. | + +Iceberg format v1 and v2 are supported, with v2 as the default. Staged table creation, purge-on-drop, and Iceberg format v3 are unsupported. + +RustFS S3 Tables does not provide a SQL execution engine, multi-table atomic transactions, or independent active-active writes across regions. It does not claim full AWS S3 Tables control-plane compatibility. Consult the [support matrix](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/docs/architecture/s3-tables-support-matrix.md) before using another engine or vendor profile. + +## Next steps + +- Run the [PyIceberg walkthrough](/developer/integration/big-data/pyiceberg). +- Review [IAM policies](/security-compliance/iam/policies) before granting application access. +- Use the repository's [client conformance checks](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/scripts/table-catalog/README.md) to validate additional client versions. diff --git a/content/en/administration/index.md b/content/en/administration/index.md index 2c059b42..d2f55515 100644 --- a/content/en/administration/index.md +++ b/content/en/administration/index.md @@ -9,6 +9,7 @@ Use this section to manage RustFS through the Console, administer buckets and ob - [Console](./console/index.md) covers browser-based administration and sign-in methods. - [Data Management](./data/object/object-lock.md) covers buckets, objects, lifecycle behavior, and data protection features. +- [S3 Tables](/administration/data/s3-tables) covers table buckets and the built-in Iceberg REST catalog. - [Protocol Support](./protocols/s3.md) covers S3, WebDAV, FTPS, and SFTP access. - [CORS Configuration](./cors/index.md) covers cross-origin access to RustFS services. - [Virtual-Host Access](/integration/virtual) covers domain-based S3 addressing. diff --git a/content/en/developer/integration/big-data/iceberg.md b/content/en/developer/integration/big-data/iceberg.md index 9511170c..fbb4a255 100644 --- a/content/en/developer/integration/big-data/iceberg.md +++ b/content/en/developer/integration/big-data/iceberg.md @@ -5,6 +5,8 @@ description: "Run Apache Iceberg with Spark, a REST catalog, and RustFS object s This guide runs **Apache Iceberg** with Spark, an Iceberg REST catalog, and **RustFS** as the S3-compatible warehouse. You will create an Iceberg table, write rows, query them, and verify that the table files are stored in RustFS. +To use the REST catalog built into RustFS, follow [S3 Tables setup](/administration/data/s3-tables) and the [PyIceberg guide](/developer/integration/big-data/pyiceberg). The deployment below runs a separate catalog service. + You need Docker with the Compose plugin and enough local resources to run four containers. This deployment is intended for local integration testing, not production. :::note[Upstream status] diff --git a/content/en/developer/integration/big-data/meta.json b/content/en/developer/integration/big-data/meta.json index c3f673eb..2286437c 100644 --- a/content/en/developer/integration/big-data/meta.json +++ b/content/en/developer/integration/big-data/meta.json @@ -2,6 +2,7 @@ "title": "Big Data", "pages": [ "iceberg", + "pyiceberg", "milvus" ] } \ No newline at end of file diff --git a/content/en/developer/integration/big-data/pyiceberg.md b/content/en/developer/integration/big-data/pyiceberg.md new file mode 100644 index 00000000..76862a02 --- /dev/null +++ b/content/en/developer/integration/big-data/pyiceberg.md @@ -0,0 +1,178 @@ +--- +title: "PyIceberg" +description: "Create, write, and read an Iceberg table through the RustFS S3 Tables REST catalog with PyIceberg." +--- + +Use **PyIceberg** to create a namespace and table in the RustFS S3 Tables catalog, append two rows, and verify the data after reloading the table. This walkthrough uses PyIceberg `0.10.0` and Python `3.12` with explicitly configured access credentials. + +## Before you begin + +- Complete [S3 Tables setup](/administration/data/s3-tables), including creating and enabling `my-bucket` and meeting the account and TLS requirements. +- Keep `RUSTFS_ENDPOINT`, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_DEFAULT_REGION` set as in that guide. + +## 1. Install the client + +Create a directory and an isolated Python environment: + +```bash +mkdir rustfs-s3-tables +cd rustfs-s3-tables +python3.12 -m venv .venv +source .venv/bin/activate +python -m pip install 'pyiceberg[pyarrow]==0.10.0' boto3 +``` + +## 2. Configure the catalog connection + +Save the following connection module. It signs both the initial catalog discovery request and subsequent REST requests using the S3 SigV4 signing behavior used by RustFS's [verified client example](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/scripts/table-catalog/pyiceberg_smoke.py). + +```python title="rustfs_catalog.py" +import hashlib +import os + +from botocore.auth import S3SigV4Auth +from botocore.awsrequest import AWSRequest +from botocore.credentials import Credentials +from pyiceberg.catalog.rest import RestCatalog +from requests.adapters import HTTPAdapter + +endpoint = os.environ["RUSTFS_ENDPOINT"].rstrip("/") +region = os.environ["AWS_DEFAULT_REGION"] +access_key = os.environ["AWS_ACCESS_KEY_ID"] +secret_key = os.environ["AWS_SECRET_ACCESS_KEY"] +credentials = Credentials(access_key, secret_key) + + +class RustFSSigV4Adapter(HTTPAdapter): + def add_headers(self, request, **kwargs): + body = request.body or b"" + if isinstance(body, str): + body = body.encode("utf-8") + request.headers["x-amz-content-sha256"] = hashlib.sha256(body).hexdigest() + request.headers.pop("connection", None) + signed = AWSRequest( + method=request.method, + url=request.url, + data=body, + headers=dict(request.headers), + ) + S3SigV4Auth(credentials, "s3", region).add_auth(signed) + request.headers.update(signed.headers) + + +class RustFSRestCatalog(RestCatalog): + def _init_sigv4(self, session): + session.mount(self.uri, RustFSSigV4Adapter()) + + +catalog = RustFSRestCatalog( + "rustfs", + **{ + "uri": f"{endpoint}/iceberg", + "warehouse": "my-bucket", + "prefix": "my-bucket", + "rest.sigv4-enabled": "true", + "rest.signing-name": "s3", + "rest.signing-region": region, + "py-io-impl": "pyiceberg.io.pyarrow.PyArrowFileIO", + "s3.endpoint": endpoint, + "s3.access-key-id": access_key, + "s3.secret-access-key": secret_key, + "s3.region": region, + "s3.force-virtual-addressing": "false", + }, +) +``` + +`s3.force-virtual-addressing=false` selects path-style access for this custom endpoint in PyIceberg's PyArrow file implementation. + +:::note[Client version] + +The adapter overrides PyIceberg's `_init_sigv4` hook so that discovery is signed before the catalog constructor finishes. Keep the pinned PyIceberg version when using this module, and rerun the full walkthrough before changing it. + +::: + +## 3. Create and read a table + +The example creates namespace `analytics` and table `events` and stops if either already exists. Each namespace segment and table name must contain 1–64 ASCII characters: lowercase letters, digits, `_`, or `-`, with a letter or digit at each end. The full namespace, including dots, is limited to 512 characters. + +For other names, update `identifier` in `example.py` and the inspection and removal commands below. + +Save the following program in the same directory: + +```python title="example.py" +import json + +import pyarrow as pa + +from rustfs_catalog import catalog + +identifier = ("analytics", "events") +schema = pa.schema( + [ + pa.field("id", pa.int64(), nullable=False), + pa.field("payload", pa.string(), nullable=False), + ] +) +expected = [{"id": 1, "payload": "alpha"}, {"id": 2, "payload": "beta"}] + +catalog.create_namespace(identifier[0]) +catalog.create_table(identifier, schema=schema) +table = catalog.load_table(identifier) +table.append(pa.Table.from_pylist(expected, schema=schema)) + +loaded = catalog.load_table(identifier) +actual = sorted(loaded.scan().to_arrow().to_pylist(), key=lambda row: row["id"]) +assert actual == expected, f"Unexpected table contents: {actual}" +print("rows:", json.dumps(actual)) +print("metadata:", loaded.metadata_location) +``` + +Run it: + +```bash +python example.py +``` + +The output includes the two complete rows and the current metadata object's S3 URI: + +```text +rows: [{"id": 1, "payload": "alpha"}, {"id": 2, "payload": "beta"}] +metadata: s3://my-bucket/ +``` + +The generated metadata object key varies. Successful verification means the table was reloaded from the catalog and its data files were read through S3; table creation alone does not verify either result. + +## 4. Inspect or unregister the example + +List the table from a new Python process using the same connection module: + +```bash +python - <<'PY' +from rustfs_catalog import catalog + +print(catalog.list_tables("analytics")) +PY +``` + +The result should contain `("analytics", "events")`. + +:::note[Catalog entries only] + +The following commands remove this tutorial’s table entry and its now-empty namespace. The bucket and underlying objects remain. Plan any data cleanup before proceeding: after `drop_table`, table maintenance can no longer find the table. See [maintenance and data protection](/administration/data/s3-tables). + +::: + +```bash +python - <<'PY' +from rustfs_catalog import catalog + +catalog.drop_table(("analytics", "events")) +catalog.drop_namespace("analytics") +PY +``` + +## Next steps + +- Follow the [PyIceberg API documentation](https://py.iceberg.apache.org/api/) for client operations, checking each operation against RustFS's supported scope. +- Use the [external Iceberg catalog integration](/developer/integration/big-data/iceberg) if you manage a separate catalog service. diff --git a/content/fr/administration/data/meta.json b/content/fr/administration/data/meta.json index c6c3e886..ed3da348 100644 --- a/content/fr/administration/data/meta.json +++ b/content/fr/administration/data/meta.json @@ -3,6 +3,7 @@ "pages": [ "object", "bucket", + "s3-tables", "tiered-storage", "lifecycle-management" ] diff --git a/content/fr/administration/data/s3-tables.md b/content/fr/administration/data/s3-tables.md new file mode 100644 index 00000000..b0fdc2a1 --- /dev/null +++ b/content/fr/administration/data/s3-tables.md @@ -0,0 +1,156 @@ +--- +title: "S3 Tables" +description: "Activez un compartiment de tables RustFS et connectez des clients Iceberg au catalogue REST intégré." +--- + +RustFS S3 Tables gère les tables **Apache Iceberg** au moyen d’un catalogue REST intégré. Les données des tables, les manifestes et les métadonnées Iceberg restent stockés sous forme d’objets S3 dans RustFS. Ce guide explique comment activer un compartiment de tables dédié, connecter les clients et prendre en compte les autorisations et les limites de maintenance. + +:::note[Préversion et versions concernées] + +S3 Tables est une fonctionnalité en préversion ; la compatibilité des clients se limite aux workflows indiqués ci-dessous. Cette page s’appuie sur le commit RustFS [`7e0c6711`](https://github.com/rustfs/rustfs/commit/7e0c67111b97703d47e23719b0264a739c8acea8), vérifié le 8 septembre 2026. Consultez la [matrice de prise en charge](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/docs/architecture/s3-tables-support-matrix.md) et votre version avant d’utiliser d’autres opérations de catalogue ou clients. + +::: + +## Fonctionnement + +Un client Iceberg utilise le catalogue REST pour découvrir les tables et valider les modifications de métadonnées. Il utilise l’API S3 pour lire et écrire les fichiers des tables. RustFS expose les deux interfaces sur le port de l’API S3. + +```mermaid +flowchart TB + Client["Iceberg client"] -->|Catalog requests| Catalog["RustFS Iceberg REST catalog"] + Client -->|Read and write files| S3["RustFS S3 API"] + Catalog -->|Validate referenced objects| S3 +``` + +| Ressource | Rôle | +| --- | --- | +| Compartiment de tables | Un compartiment S3 existant activé pour le catalogue ; son nom correspond au paramètre `warehouse` du client. | +| Espace de noms | Un groupe logique de tables au sein de cet entrepôt. | +| Table | Un schéma Iceberg, des instantanés et un emplacement courant des métadonnées géré par le catalogue. | + +L’activation d’un compartiment de tables n’enregistre pas automatiquement les fichiers Parquet existants comme tables Iceberg. Créez ou enregistrez les tables avec un client Iceberg. Sans `location` explicite, RustFS attribue un emplacement de stockage ; un emplacement personnalisé doit se trouver dans le même compartiment. Les clients devraient utiliser l’emplacement renvoyé. + +Le backend de catalogue par défaut, `object`, conserve durablement l’état du catalogue dans le stockage objet RustFS. Un commit de table vérifie les métadonnées de départ et les objets référencés avant de mettre à jour, sous condition, le pointeur vers les métadonnées courantes. En cas de conflit d’écriture, le client doit recharger la table et résoudre le conflit. La transaction porte sur une seule table. + +## Prérequis + +- Démarrez un déploiement RustFS disposant des points de terminaison S3 Tables décrits ci-dessus. Consultez [Installation](/installation). +- Installez l’[AWS CLI](/developer/examples/aws-cli) et `curl` 7.76 ou une version ultérieure, avec prise en charge de `--aws-sigv4` et `--fail-with-body`. +- Créez un compartiment dédié à ce tutoriel. L’exemple utilise `my-bucket`. +- Utilisez un compte d’administration existant autorisé à effectuer les opérations de catalogue et à accéder aux objets S3. La politique intégrée `consoleAdmin` couvre ce tutoriel ; configurez des politiques plus restreintes pour les applications. + +Les exemples utilisent `http://localhost:9000`. Remplacez cette adresse par le point de terminaison de votre serveur et utilisez [TLS](/integration/tls-configured) avec vérification des certificats en dehors d’un environnement de test local. + +:::warning[Cycle de vie des compartiments de tables] + +Les compartiments de tables sont exclus du traitement d’expiration habituel du cycle de vie des compartiments. Activer ce mode sur un compartiment existant modifie l’application de ses règles d’expiration. Utilisez une maintenance de catalogue qui tient compte des références Iceberg pour faire expirer les instantanés et nettoyer les fichiers des tables. + +::: + +## 1. Créer un compartiment + +Définissez le point de terminaison et les informations d’identification des clients d’exemple : + +```bash +export RUSTFS_ENDPOINT="http://localhost:9000" +export AWS_ACCESS_KEY_ID="" +export AWS_SECRET_ACCESS_KEY="" +export AWS_DEFAULT_REGION="us-east-1" +``` + +Créez le compartiment dédié : + +```bash +aws --endpoint-url "$RUSTFS_ENDPOINT" s3api create-bucket --bucket my-bucket +``` + +Ces exemples utilisent une clé d’accès et une clé d’accès secrète, sans jeton de session temporaire. Conservez le même environnement shell pour les requêtes suivantes et le guide PyIceberg. + +## 2. Activer le compartiment de tables + +Envoyez une requête au corps vide, signée avec SigV4, au point de terminaison du compartiment de tables : + +```bash +curl --fail-with-body --silent --show-error \ + --aws-sigv4 "aws:amz:us-east-1:s3" \ + --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \ + --header "x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" \ + --request PUT "$RUSTFS_ENDPOINT/iceberg/v1/buckets/my-bucket" +``` + +Relisez son état avec les mêmes informations d’identification : + +```bash +curl --fail-with-body --silent --show-error \ + --aws-sigv4 "aws:amz:us-east-1:s3" \ + --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \ + --header "x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" \ + "$RUSTFS_ENDPOINT/iceberg/v1/buckets/my-bucket" +``` + +Les deux requêtes renvoient HTTP `200` en cas de réussite. Vérifiez que la réponse contient les valeurs suivantes : + +```json +{ + "table-bucket": "my-bucket", + "enabled": true, + "catalog-type": "iceberg-rest", + "warehouse": "my-bucket", + "catalog-entry-present": true +} +``` + +Il s’agit d’un extrait de réponse. La valeur `catalog-uri` renvoyée est une route propre au compartiment ; utilisez l’URI de base de la section suivante pour configurer un client REST Iceberg. + +## 3. Connecter un client Iceberg + +Utilisez les paramètres suivants pour le point de terminaison RustFS de l’exemple : + +| Paramètre | Valeur | +| --- | --- | +| URI du catalogue REST | `http://localhost:9000/iceberg` | +| Entrepôt et préfixe | `my-bucket` | +| Authentification REST | AWS Signature Version 4, nom du service de signature `s3` | +| Région | `us-east-1` | +| Point de terminaison des fichiers S3 | `http://localhost:9000` avec adressage de type chemin | + +Le client ajoute `/v1` à l’URI du catalogue. L’entrepôt est un nom de compartiment, et non un URI S3 ou un ARN AWS S3 Tables. Configurez la signature des requêtes REST et l’accès aux fichiers S3, même si les deux utilisent le même compte. + +Si vous exploitez déjà un catalogue REST Iceberg séparé, consultez l’[intégration Apache Iceberg](/developer/integration/big-data/iceberg) pour le modèle de déploiement avec catalogue externe. + +## Autorisations et informations d’identification + +L’activation d’un compartiment de tables nécessite `admin:SetTableBucket` ; la consultation de son état nécessite `admin:GetTableBucket`. La découverte du catalogue utilise `admin:GetTableCatalog`. Les opérations sur les espaces de noms et les tables possèdent leurs propres actions d’administration RustFS, notamment `admin:SetTableNamespace`, `admin:CreateTable`, `admin:GetTableMetadata` et `admin:CommitTable`. + +La lecture et l’écriture des fichiers de tables nécessitent aussi les autorisations S3 ordinaires. RustFS vérifie les autorisations de table sur les chemins des objets de l’entrepôt : les lectures nécessitent l’autorisation `admin:GetTableMetadata` correspondante, et les écritures `admin:SetTableMetadata`. Une autorisation de commit de catalogue ne suffit pas à autoriser les écritures de fichiers S3 qui le précèdent. Configurez les [politiques IAM](/security-compliance/iam/policies) pour les deux interfaces. + +La fourniture d’informations d’identification par le catalogue est désactivée par défaut. Lorsqu’elle est activée, un client compatible doit négocier `X-Iceberg-Access-Delegation: vended-credentials`, et l’appelant doit être autorisé à demander des informations d’identification de table. L’accès initial au catalogue nécessite toujours une identité autorisée. Le tutoriel PyIceberg associé utilise des informations d’identification configurées explicitement. + +## Maintenance et protection des données + +La suppression des métadonnées et la maintenance en arrière-plan sont désactivées par défaut. RustFS expose des opérations explicites de planification, d’exécution de l’ordonnanceur et d’exécution des workers ; il n’exécute pas d’ordonnanceur intégré de maintenance périodique. Examinez le plan de maintenance et les références qu’il conserve avant d’activer la suppression. + +Supprimer une table retire son entrée du catalogue tout en conservant les objets sous-jacents. Effectuez les opérations de maintenance nécessaires avant de retirer la table du catalogue ; ensuite, elles ne pourront plus la trouver. Le nettoyage des objets conservés exige un plan distinct tenant compte de toutes les références restantes. Ne supprimez pas récursivement des chemins S3 que des instantanés ou d’autres métadonnées pourraient encore référencer. + +Conservez le backend de catalogue par défaut pour ce tutoriel. Le passage d’un déploiement existant à `durable-strong` nécessite la [procédure de bascule du catalogue](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/docs/operations/s3-tables-cutover-runbook.md), notamment les vérifications préalables à la migration et le blocage coordonné des clients en écriture. + +## Compatibilité des clients et limites + +Le dépôt source maintient le périmètre de validation suivant : + +| Client | Périmètre de validation | +| --- | --- | +| PyIceberg | Vérifications automatisées de création, d’ajout, de rechargement, de lecture des lignes et d’opérations de catalogue. | +| DuckDB Iceberg 1.5.5 | Vérifications automatisées du catalogue REST générique pour la lecture, l’écriture et les modifications de schéma sur une seule table. | +| Spark | Un banc de test sur service actif, à activer explicitement ; validez les versions exactes de Spark et d’Iceberg que vous déployez. | +| Trino | Un test manuel en lecture seule ; la compatibilité en écriture n’est pas revendiquée. | + +Les formats Iceberg v1 et v2 sont pris en charge, avec v2 par défaut. La création de tables en mode différé, la purge lors de la suppression et le format Iceberg v3 ne sont pas pris en charge. + +RustFS S3 Tables ne fournit ni moteur d’exécution SQL, ni transactions atomiques sur plusieurs tables, ni écritures actives-actives indépendantes entre régions. Il ne revendique pas une compatibilité complète avec le plan de contrôle AWS S3 Tables. Consultez la [matrice de prise en charge](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/docs/architecture/s3-tables-support-matrix.md) avant d’utiliser un autre moteur ou un profil propre à un fournisseur. + +## Étapes suivantes + +- Exécutez le [tutoriel PyIceberg](/developer/integration/big-data/pyiceberg). +- Consultez les [politiques IAM](/security-compliance/iam/policies) avant d’autoriser les applications. +- Validez d’autres versions de clients avec les [vérifications de conformité des clients](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/scripts/table-catalog/README.md) du dépôt. diff --git a/content/fr/administration/index.md b/content/fr/administration/index.md index 2c059b42..83121bd2 100644 --- a/content/fr/administration/index.md +++ b/content/fr/administration/index.md @@ -9,6 +9,7 @@ Use this section to manage RustFS through the Console, administer buckets and ob - [Console](./console/index.md) covers browser-based administration and sign-in methods. - [Data Management](./data/object/object-lock.md) covers buckets, objects, lifecycle behavior, and data protection features. +- [S3 Tables](/administration/data/s3-tables) présente les compartiments de tables et le catalogue REST Iceberg intégré. - [Protocol Support](./protocols/s3.md) covers S3, WebDAV, FTPS, and SFTP access. - [CORS Configuration](./cors/index.md) covers cross-origin access to RustFS services. - [Virtual-Host Access](/integration/virtual) covers domain-based S3 addressing. diff --git a/content/fr/developer/integration/big-data/iceberg.md b/content/fr/developer/integration/big-data/iceberg.md index 9511170c..0b0ad517 100644 --- a/content/fr/developer/integration/big-data/iceberg.md +++ b/content/fr/developer/integration/big-data/iceberg.md @@ -5,6 +5,8 @@ description: "Run Apache Iceberg with Spark, a REST catalog, and RustFS object s This guide runs **Apache Iceberg** with Spark, an Iceberg REST catalog, and **RustFS** as the S3-compatible warehouse. You will create an Iceberg table, write rows, query them, and verify that the table files are stored in RustFS. +Pour utiliser le catalogue REST intégré à RustFS, suivez la [configuration de S3 Tables](/administration/data/s3-tables) et le [guide PyIceberg](/developer/integration/big-data/pyiceberg). Le déploiement ci-dessous exécute un service de catalogue séparé. + You need Docker with the Compose plugin and enough local resources to run four containers. This deployment is intended for local integration testing, not production. :::note[Upstream status] diff --git a/content/fr/developer/integration/big-data/meta.json b/content/fr/developer/integration/big-data/meta.json index c3f673eb..2286437c 100644 --- a/content/fr/developer/integration/big-data/meta.json +++ b/content/fr/developer/integration/big-data/meta.json @@ -2,6 +2,7 @@ "title": "Big Data", "pages": [ "iceberg", + "pyiceberg", "milvus" ] } \ No newline at end of file diff --git a/content/fr/developer/integration/big-data/pyiceberg.md b/content/fr/developer/integration/big-data/pyiceberg.md new file mode 100644 index 00000000..d597ee96 --- /dev/null +++ b/content/fr/developer/integration/big-data/pyiceberg.md @@ -0,0 +1,178 @@ +--- +title: "PyIceberg" +description: "Créez, écrivez et lisez une table Iceberg avec PyIceberg via le catalogue REST de RustFS S3 Tables." +--- + +Utilisez **PyIceberg** pour créer un espace de noms et une table dans le catalogue RustFS S3 Tables, ajouter deux lignes et vérifier les données après avoir rechargé la table. Ce tutoriel utilise PyIceberg `0.10.0` et Python `3.12`, avec des informations d’identification configurées explicitement. + +## Prérequis + +- Terminez la [configuration de S3 Tables](/administration/data/s3-tables) : créez et activez `my-bucket` et respectez les exigences relatives au compte et à TLS. +- Conservez les variables `RUSTFS_ENDPOINT`, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` et `AWS_DEFAULT_REGION` définies dans ce guide. + +## 1. Installer le client + +Créez un répertoire et un environnement Python isolé : + +```bash +mkdir rustfs-s3-tables +cd rustfs-s3-tables +python3.12 -m venv .venv +source .venv/bin/activate +python -m pip install 'pyiceberg[pyarrow]==0.10.0' boto3 +``` + +## 2. Configurer la connexion au catalogue + +Enregistrez le module de connexion suivant. Il signe la requête initiale de découverte du catalogue et les requêtes REST suivantes avec le même comportement S3 SigV4 que l’[exemple client validé](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/scripts/table-catalog/pyiceberg_smoke.py) de RustFS. + +```python title="rustfs_catalog.py" +import hashlib +import os + +from botocore.auth import S3SigV4Auth +from botocore.awsrequest import AWSRequest +from botocore.credentials import Credentials +from pyiceberg.catalog.rest import RestCatalog +from requests.adapters import HTTPAdapter + +endpoint = os.environ["RUSTFS_ENDPOINT"].rstrip("/") +region = os.environ["AWS_DEFAULT_REGION"] +access_key = os.environ["AWS_ACCESS_KEY_ID"] +secret_key = os.environ["AWS_SECRET_ACCESS_KEY"] +credentials = Credentials(access_key, secret_key) + + +class RustFSSigV4Adapter(HTTPAdapter): + def add_headers(self, request, **kwargs): + body = request.body or b"" + if isinstance(body, str): + body = body.encode("utf-8") + request.headers["x-amz-content-sha256"] = hashlib.sha256(body).hexdigest() + request.headers.pop("connection", None) + signed = AWSRequest( + method=request.method, + url=request.url, + data=body, + headers=dict(request.headers), + ) + S3SigV4Auth(credentials, "s3", region).add_auth(signed) + request.headers.update(signed.headers) + + +class RustFSRestCatalog(RestCatalog): + def _init_sigv4(self, session): + session.mount(self.uri, RustFSSigV4Adapter()) + + +catalog = RustFSRestCatalog( + "rustfs", + **{ + "uri": f"{endpoint}/iceberg", + "warehouse": "my-bucket", + "prefix": "my-bucket", + "rest.sigv4-enabled": "true", + "rest.signing-name": "s3", + "rest.signing-region": region, + "py-io-impl": "pyiceberg.io.pyarrow.PyArrowFileIO", + "s3.endpoint": endpoint, + "s3.access-key-id": access_key, + "s3.secret-access-key": secret_key, + "s3.region": region, + "s3.force-virtual-addressing": "false", + }, +) +``` + +`s3.force-virtual-addressing=false` sélectionne l’adressage de type chemin pour ce point de terminaison personnalisé dans l’implémentation de fichiers PyArrow de PyIceberg. + +:::note[Version du client] + +L’adaptateur redéfinit le hook `_init_sigv4` de PyIceberg afin que la découverte soit signée avant la fin du constructeur du catalogue. Conservez la version PyIceberg fixée pour ce module et réexécutez tout le tutoriel avant d’en changer. + +::: + +## 3. Créer et lire une table + +L’exemple crée l’espace de noms `analytics` et la table `events` et s’arrête si l’une de ces ressources existe déjà. Chaque segment d’espace de noms et chaque nom de table doit comporter 1–64 caractères ASCII : lettres minuscules, chiffres, `_` ou `-`, avec une lettre ou un chiffre à chaque extrémité. L’espace de noms complet est limité à 512 caractères, points compris. + +Pour utiliser d’autres noms, modifiez `identifier` dans `example.py` ainsi que les noms dans les commandes d’inspection et de suppression ci-dessous. + +Enregistrez le programme suivant dans le même répertoire : + +```python title="example.py" +import json + +import pyarrow as pa + +from rustfs_catalog import catalog + +identifier = ("analytics", "events") +schema = pa.schema( + [ + pa.field("id", pa.int64(), nullable=False), + pa.field("payload", pa.string(), nullable=False), + ] +) +expected = [{"id": 1, "payload": "alpha"}, {"id": 2, "payload": "beta"}] + +catalog.create_namespace(identifier[0]) +catalog.create_table(identifier, schema=schema) +table = catalog.load_table(identifier) +table.append(pa.Table.from_pylist(expected, schema=schema)) + +loaded = catalog.load_table(identifier) +actual = sorted(loaded.scan().to_arrow().to_pylist(), key=lambda row: row["id"]) +assert actual == expected, f"Unexpected table contents: {actual}" +print("rows:", json.dumps(actual)) +print("metadata:", loaded.metadata_location) +``` + +Exécutez-le : + +```bash +python example.py +``` + +La sortie contient les deux lignes complètes et l’URI S3 de l’objet de métadonnées courant : + +```text +rows: [{"id": 1, "payload": "alpha"}, {"id": 2, "payload": "beta"}] +metadata: s3://my-bucket/ +``` + +La clé générée pour l’objet de métadonnées varie. Une vérification réussie signifie que la table a été rechargée depuis le catalogue et que ses fichiers de données ont été lus via S3. La seule création de la table ne vérifie aucun de ces deux résultats. + +## 4. Inspecter l’exemple ou le retirer du catalogue + +Listez la table dans un nouveau processus Python avec le même module de connexion : + +```bash +python - <<'PY' +from rustfs_catalog import catalog + +print(catalog.list_tables("analytics")) +PY +``` + +Le résultat devrait contenir `("analytics", "events")`. + +:::note[Suppression des entrées du catalogue uniquement] + +Les commandes suivantes retirent l’entrée de table de ce tutoriel et son espace de noms devenu vide. Le compartiment et les objets sous-jacents sont conservés. Planifiez tout nettoyage de données avant de continuer : après `drop_table`, la maintenance ne peut plus trouver la table. Consultez la [maintenance et la protection des données](/administration/data/s3-tables). + +::: + +```bash +python - <<'PY' +from rustfs_catalog import catalog + +catalog.drop_table(("analytics", "events")) +catalog.drop_namespace("analytics") +PY +``` + +## Étapes suivantes + +- Suivez la [documentation de l’API PyIceberg](https://py.iceberg.apache.org/api/) pour les opérations client, en vérifiant chacune par rapport au périmètre pris en charge par RustFS. +- Utilisez l’[intégration avec un catalogue Iceberg externe](/developer/integration/big-data/iceberg) si vous gérez un service de catalogue séparé. diff --git a/content/ja/administration/data/meta.json b/content/ja/administration/data/meta.json index e044492d..2f891006 100644 --- a/content/ja/administration/data/meta.json +++ b/content/ja/administration/data/meta.json @@ -3,6 +3,7 @@ "pages": [ "object", "bucket", + "s3-tables", "tiered-storage", "lifecycle-management" ] diff --git a/content/ja/administration/data/s3-tables.md b/content/ja/administration/data/s3-tables.md new file mode 100644 index 00000000..b3d89f7a --- /dev/null +++ b/content/ja/administration/data/s3-tables.md @@ -0,0 +1,156 @@ +--- +title: "S3 Tables" +description: "RustFS のテーブルバケットを有効にし、Iceberg クライアントを組み込み REST カタログに接続します。" +--- + +RustFS S3 Tables は、組み込み REST カタログを通じて **Apache Iceberg** テーブルを管理します。テーブルデータ、マニフェスト、Iceberg メタデータは、RustFS 内の S3 オブジェクトとして保存されます。このガイドでは、専用テーブルバケットの有効化、クライアント接続、権限、メンテナンスの制限を説明します。 + +:::note[プレビューの状態と対象バージョン] + +S3 Tables はプレビュー機能です。クライアントの互換性は、以下に示すワークフローに限られます。このページは RustFS コミット [`7e0c6711`](https://github.com/rustfs/rustfs/commit/7e0c67111b97703d47e23719b0264a739c8acea8) に基づき、2026 年 9 月 8 日に確認しました。別のカタログ操作やクライアントを使用する前に、[サポートマトリクス](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/docs/architecture/s3-tables-support-matrix.md)とデプロイ済みのバージョンを確認してください。 + +::: + +## 仕組み + +Iceberg クライアントは REST カタログを使用してテーブルを検出し、メタデータの変更をコミットします。テーブルファイルの読み書きには S3 API を使用します。どちらのインターフェイスも、RustFS の S3 API ポートで提供されます。 + +```mermaid +flowchart TB + Client["Iceberg client"] -->|Catalog requests| Catalog["RustFS Iceberg REST catalog"] + Client -->|Read and write files| S3["RustFS S3 API"] + Catalog -->|Validate referenced objects| S3 +``` + +| リソース | 用途 | +| --- | --- | +| テーブルバケット | カタログ用に有効化した既存の S3 バケットです。バケット名がクライアントの `warehouse` になります。 | +| 名前空間 | 同じウェアハウス内でテーブルをまとめる論理的なグループです。 | +| テーブル | Iceberg スキーマ、スナップショット、カタログが管理する現在のメタデータの場所です。 | + +テーブルバケットを有効にしても、既存の Parquet ファイルが自動的に Iceberg テーブルとして登録されるわけではありません。Iceberg クライアントでテーブルを作成または登録します。`location` を指定しない場合は RustFS が保存先を割り当てます。指定する場合は同じバケット内に置く必要があります。クライアントは返された保存先を使用してください。 + +デフォルトの `object` カタログバックエンドは、カタログの状態を RustFS オブジェクトストレージに永続化します。テーブルのコミットでは、基準となるメタデータと参照先オブジェクトを検証してから、現在のメタデータを指すポインターを条件付きで更新します。書き込みが競合した場合、クライアントはテーブルを再読み込みして競合を解決する必要があります。トランザクションの範囲は単一テーブルです。 + +## 前提条件 + +- 上記の S3 Tables エンドポイントを備えた RustFS を起動します。[インストール](/installation)を参照してください。 +- [AWS CLI](/developer/examples/aws-cli) と、`--aws-sigv4` および `--fail-with-body` をサポートする `curl` 7.76 以降をインストールします。 +- このチュートリアル専用の新しいバケットを用意します。例では `my-bucket` を使用します。 +- カタログ操作と S3 オブジェクトの両方にアクセスできる既存の管理者アカウントを使用します。組み込みの `consoleAdmin` ポリシーは、このチュートリアルの操作をカバーします。アプリケーションには、範囲を絞ったポリシーを設定してください。 + +例では `http://localhost:9000` を使用します。サーバーのエンドポイントに置き換え、ローカルテスト環境以外では証明書の検証を有効にした [TLS](/integration/tls-configured) を使用してください。 + +:::warning[テーブルバケットのライフサイクル動作] + +テーブルバケットは、通常のバケットライフサイクルの有効期限処理から除外されます。既存のバケットでこのモードを有効にすると、有効期限ルールの適用方法が変わります。スナップショットの期限切れ処理やテーブルファイルのクリーンアップには、Iceberg の参照関係を認識するカタログメンテナンスを使用してください。 + +::: + +## 1. バケットを作成する + +サンプルクライアントのエンドポイントと認証情報を設定します。 + +```bash +export RUSTFS_ENDPOINT="http://localhost:9000" +export AWS_ACCESS_KEY_ID="" +export AWS_SECRET_ACCESS_KEY="" +export AWS_DEFAULT_REGION="us-east-1" +``` + +専用バケットを作成します。 + +```bash +aws --endpoint-url "$RUSTFS_ENDPOINT" s3api create-bucket --bucket my-bucket +``` + +これらの例はアクセスキーとシークレットアクセスキーを使用し、一時セッショントークンは使用しません。以降のリクエストと PyIceberg ガイドでも、同じシェル環境を使用します。 + +## 2. テーブルバケットを有効にする + +テーブルバケットのエンドポイントに、本文が空の SigV4 署名付きリクエストを送信します。 + +```bash +curl --fail-with-body --silent --show-error \ + --aws-sigv4 "aws:amz:us-east-1:s3" \ + --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \ + --header "x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" \ + --request PUT "$RUSTFS_ENDPOINT/iceberg/v1/buckets/my-bucket" +``` + +同じ認証情報で状態を読み取ります。 + +```bash +curl --fail-with-body --silent --show-error \ + --aws-sigv4 "aws:amz:us-east-1:s3" \ + --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \ + --header "x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" \ + "$RUSTFS_ENDPOINT/iceberg/v1/buckets/my-bucket" +``` + +どちらのリクエストも、成功すると HTTP `200` を返します。レスポンスに次の値が含まれていることを確認します。 + +```json +{ + "table-bucket": "my-bucket", + "enabled": true, + "catalog-type": "iceberg-rest", + "warehouse": "my-bucket", + "catalog-entry-present": true +} +``` + +これはレスポンスの抜粋です。返される `catalog-uri` はバケット固有のルートです。Iceberg REST クライアントの設定には、次のセクションに示すクライアント用のベース URI を使用します。 + +## 3. Iceberg クライアントを接続する + +例の RustFS エンドポイントには、次の設定を使用します。 + +| 設定 | 値 | +| --- | --- | +| REST カタログ URI | `http://localhost:9000/iceberg` | +| ウェアハウスとプレフィックス | `my-bucket` | +| REST 認証 | AWS Signature Version 4、署名サービス名は `s3` | +| リージョン | `us-east-1` | +| S3 ファイルエンドポイント | `http://localhost:9000` を使用し、パス形式でアドレス指定 | + +クライアントはカタログ URI に `/v1` を追加します。ウェアハウスには S3 URI や AWS S3 Tables ARN ではなく、バケット名を指定します。同じアカウントを使用する場合でも、REST リクエストの署名と S3 ファイルアクセスの両方を設定します。 + +別の Iceberg REST カタログをすでに運用している場合は、[Apache Iceberg 連携](/developer/integration/big-data/iceberg)の外部カタログを使用する構成を参照してください。 + +## 権限と認証情報 + +テーブルバケットの有効化には `admin:SetTableBucket`、状態の確認には `admin:GetTableBucket` が必要です。カタログの検出には `admin:GetTableCatalog` を使用します。名前空間とテーブルの操作には、それぞれ `admin:SetTableNamespace`、`admin:CreateTable`、`admin:GetTableMetadata`、`admin:CommitTable` などの RustFS 管理アクションがあります。 + +テーブルファイルの読み書きには、通常の S3 権限も必要です。RustFS はウェアハウス内のオブジェクトパスに対してテーブル権限を確認します。読み取りには対応する `admin:GetTableMetadata` の認可、書き込みには `admin:SetTableMetadata` の認可が必要です。カタログのコミット権限だけでは、その前に行う S3 ファイルの書き込みは許可されません。両方のインターフェイスに対して [IAM ポリシー](/security-compliance/iam/policies)を設定してください。 + +カタログによる認証情報の払い出しは、デフォルトで無効です。有効にした場合、対応クライアントは `X-Iceberg-Access-Delegation: vended-credentials` を使用してネゴシエーションを行い、呼び出し元にはテーブル認証情報を要求する権限が必要です。カタログへの初回接続にも、認可済みの主体が必要です。リンク先の PyIceberg チュートリアルでは、明示的に設定した認証情報を使用します。 + +## メンテナンスとデータ保護 + +メタデータの削除とバックグラウンドメンテナンスは、デフォルトで無効です。RustFS は計画の作成、スケジューラーの実行、ワーカーの実行を明示的な操作として提供します。組み込みの定期メンテナンススケジューラーはありません。削除を有効にする前に、メンテナンス計画と保持される参照を確認してください。 + +テーブルを削除すると、カタログのエントリは削除されますが、基になるオブジェクトは残ります。必要なテーブルメンテナンスは登録解除前に実施します。登録解除後は、メンテナンス操作でテーブルを見つけられなくなります。残ったオブジェクトのクリーンアップには、残存するすべての参照を考慮した別の計画が必要です。スナップショットやほかのメタデータが参照している可能性のある S3 パスを再帰的に削除しないでください。 + +このチュートリアルでは、デフォルトのカタログバックエンドを使用します。既存のデプロイを `durable-strong` に切り替えるには、移行前の検査と書き込み元の協調的な遮断を含む[カタログ切り替え手順](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/docs/operations/s3-tables-cutover-runbook.md)が必要です。 + +## クライアントの互換性と制限 + +ソースリポジトリで維持されている検証範囲は次のとおりです。 + +| クライアント | 検証範囲 | +| --- | --- | +| PyIceberg | 作成、追加、再読み込み、スキャン、カタログ操作の自動検証。 | +| DuckDB Iceberg 1.5.5 | 汎用 REST カタログを使用した、単一テーブルの読み書きとスキーマ変更の自動検証。 | +| Spark | 明示的に有効化する実環境テストハーネス。デプロイする Spark と Iceberg の正確なバージョンで検証してください。 | +| Trino | 手動の読み取り専用テスト。書き込みの互換性は保証していません。 | + +Iceberg フォーマット v1 と v2 をサポートし、デフォルトは v2 です。ステージングによるテーブル作成、テーブル削除時のデータ消去、Iceberg フォーマット v3 はサポートしていません。 + +RustFS S3 Tables は、SQL 実行エンジン、複数テーブルにまたがるアトミックトランザクション、リージョン間で独立したアクティブ・アクティブ書き込みを提供しません。AWS S3 Tables のコントロールプレーンとの完全な互換性も表明していません。別のエンジンやベンダー固有のプロファイルを使用する前に、[サポートマトリクス](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/docs/architecture/s3-tables-support-matrix.md)を確認してください。 + +## 次のステップ + +- [PyIceberg チュートリアル](/developer/integration/big-data/pyiceberg)を実行します。 +- アプリケーションへのアクセスを許可する前に、[IAM ポリシー](/security-compliance/iam/policies)を確認します。 +- リポジトリの[クライアント適合性チェック](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/scripts/table-catalog/README.md)を使用して、ほかのクライアントバージョンを検証します。 diff --git a/content/ja/administration/index.md b/content/ja/administration/index.md index 2c059b42..470ccd6d 100644 --- a/content/ja/administration/index.md +++ b/content/ja/administration/index.md @@ -9,6 +9,7 @@ Use this section to manage RustFS through the Console, administer buckets and ob - [Console](./console/index.md) covers browser-based administration and sign-in methods. - [Data Management](./data/object/object-lock.md) covers buckets, objects, lifecycle behavior, and data protection features. +- [S3 Tables](/administration/data/s3-tables)では、テーブルバケットと組み込み Iceberg REST カタログを説明します。 - [Protocol Support](./protocols/s3.md) covers S3, WebDAV, FTPS, and SFTP access. - [CORS Configuration](./cors/index.md) covers cross-origin access to RustFS services. - [Virtual-Host Access](/integration/virtual) covers domain-based S3 addressing. diff --git a/content/ja/developer/integration/big-data/iceberg.md b/content/ja/developer/integration/big-data/iceberg.md index 9511170c..f5521688 100644 --- a/content/ja/developer/integration/big-data/iceberg.md +++ b/content/ja/developer/integration/big-data/iceberg.md @@ -5,6 +5,8 @@ description: "Run Apache Iceberg with Spark, a REST catalog, and RustFS object s This guide runs **Apache Iceberg** with Spark, an Iceberg REST catalog, and **RustFS** as the S3-compatible warehouse. You will create an Iceberg table, write rows, query them, and verify that the table files are stored in RustFS. +RustFS の組み込み REST カタログを使用する場合は、[S3 Tables の設定](/administration/data/s3-tables)と [PyIceberg ガイド](/developer/integration/big-data/pyiceberg)を参照してください。以下の構成では、別のカタログサービスを起動します。 + You need Docker with the Compose plugin and enough local resources to run four containers. This deployment is intended for local integration testing, not production. :::note[Upstream status] diff --git a/content/ja/developer/integration/big-data/meta.json b/content/ja/developer/integration/big-data/meta.json index 91cde7a2..f7051d79 100644 --- a/content/ja/developer/integration/big-data/meta.json +++ b/content/ja/developer/integration/big-data/meta.json @@ -2,6 +2,7 @@ "title": "ビッグデータ", "pages": [ "iceberg", + "pyiceberg", "milvus" ] } \ No newline at end of file diff --git a/content/ja/developer/integration/big-data/pyiceberg.md b/content/ja/developer/integration/big-data/pyiceberg.md new file mode 100644 index 00000000..3ad1103a --- /dev/null +++ b/content/ja/developer/integration/big-data/pyiceberg.md @@ -0,0 +1,178 @@ +--- +title: "PyIceberg" +description: "PyIceberg を使用して、RustFS S3 Tables の REST カタログ経由で Iceberg テーブルを作成し、読み書きします。" +--- + +**PyIceberg** を使用して RustFS S3 Tables カタログに名前空間とテーブルを作成し、2 行を追加してから、テーブルの再読み込み後にデータを検証します。このチュートリアルでは、PyIceberg `0.10.0`、Python `3.12`、明示的に設定したアクセス認証情報を使用します。 + +## 前提条件 + +- [S3 Tables の設定](/administration/data/s3-tables)を完了し、`my-bucket` を作成して有効にします。アカウントと TLS の要件も満たしてください。 +- そのガイドで設定した `RUSTFS_ENDPOINT`、`AWS_ACCESS_KEY_ID`、`AWS_SECRET_ACCESS_KEY`、`AWS_DEFAULT_REGION` を維持します。 + +## 1. クライアントをインストールする + +ディレクトリと分離された Python 環境を作成します。 + +```bash +mkdir rustfs-s3-tables +cd rustfs-s3-tables +python3.12 -m venv .venv +source .venv/bin/activate +python -m pip install 'pyiceberg[pyarrow]==0.10.0' boto3 +``` + +## 2. カタログ接続を設定する + +次の接続モジュールを保存します。RustFS の[検証済みクライアント例](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/scripts/table-catalog/pyiceberg_smoke.py)と同じ S3 SigV4 の署名方式を使用し、初回のカタログ検出リクエストと後続の REST リクエストの両方に署名します。 + +```python title="rustfs_catalog.py" +import hashlib +import os + +from botocore.auth import S3SigV4Auth +from botocore.awsrequest import AWSRequest +from botocore.credentials import Credentials +from pyiceberg.catalog.rest import RestCatalog +from requests.adapters import HTTPAdapter + +endpoint = os.environ["RUSTFS_ENDPOINT"].rstrip("/") +region = os.environ["AWS_DEFAULT_REGION"] +access_key = os.environ["AWS_ACCESS_KEY_ID"] +secret_key = os.environ["AWS_SECRET_ACCESS_KEY"] +credentials = Credentials(access_key, secret_key) + + +class RustFSSigV4Adapter(HTTPAdapter): + def add_headers(self, request, **kwargs): + body = request.body or b"" + if isinstance(body, str): + body = body.encode("utf-8") + request.headers["x-amz-content-sha256"] = hashlib.sha256(body).hexdigest() + request.headers.pop("connection", None) + signed = AWSRequest( + method=request.method, + url=request.url, + data=body, + headers=dict(request.headers), + ) + S3SigV4Auth(credentials, "s3", region).add_auth(signed) + request.headers.update(signed.headers) + + +class RustFSRestCatalog(RestCatalog): + def _init_sigv4(self, session): + session.mount(self.uri, RustFSSigV4Adapter()) + + +catalog = RustFSRestCatalog( + "rustfs", + **{ + "uri": f"{endpoint}/iceberg", + "warehouse": "my-bucket", + "prefix": "my-bucket", + "rest.sigv4-enabled": "true", + "rest.signing-name": "s3", + "rest.signing-region": region, + "py-io-impl": "pyiceberg.io.pyarrow.PyArrowFileIO", + "s3.endpoint": endpoint, + "s3.access-key-id": access_key, + "s3.secret-access-key": secret_key, + "s3.region": region, + "s3.force-virtual-addressing": "false", + }, +) +``` + +`s3.force-virtual-addressing=false` は、このカスタムエンドポイントに対して PyIceberg の PyArrow ファイル実装でパス形式のアドレス指定を選択します。 + +:::note[クライアントのバージョン] + +アダプターは PyIceberg の `_init_sigv4` フックをオーバーライドし、カタログのコンストラクターが完了する前の検出リクエストにも署名します。このモジュールでは指定された PyIceberg バージョンを維持し、変更する前にチュートリアル全体を再実行してください。 + +::: + +## 3. テーブルを作成して読み取る + +サンプルは名前空間 `analytics` とテーブル `events` を作成し、どちらかがすでに存在すると停止します。名前空間の各セグメントとテーブル名は 1–64 文字の ASCII 文字列とし、小文字の英字、数字、`_`、`-` のみを使用できます。先頭と末尾は英字または数字にする必要があります。名前空間全体は、ドットを含めて 512 文字以内です。 + +別の名前を使う場合は、`example.py` 内の `identifier` と、以下の確認および削除コマンド内の名前を変更します。 + +次のプログラムを同じディレクトリに保存します。 + +```python title="example.py" +import json + +import pyarrow as pa + +from rustfs_catalog import catalog + +identifier = ("analytics", "events") +schema = pa.schema( + [ + pa.field("id", pa.int64(), nullable=False), + pa.field("payload", pa.string(), nullable=False), + ] +) +expected = [{"id": 1, "payload": "alpha"}, {"id": 2, "payload": "beta"}] + +catalog.create_namespace(identifier[0]) +catalog.create_table(identifier, schema=schema) +table = catalog.load_table(identifier) +table.append(pa.Table.from_pylist(expected, schema=schema)) + +loaded = catalog.load_table(identifier) +actual = sorted(loaded.scan().to_arrow().to_pylist(), key=lambda row: row["id"]) +assert actual == expected, f"Unexpected table contents: {actual}" +print("rows:", json.dumps(actual)) +print("metadata:", loaded.metadata_location) +``` + +実行します。 + +```bash +python example.py +``` + +出力には、2 行分の完全なデータと現在のメタデータオブジェクトの S3 URI が含まれます。 + +```text +rows: [{"id": 1, "payload": "alpha"}, {"id": 2, "payload": "beta"}] +metadata: s3://my-bucket/ +``` + +生成されるメタデータのオブジェクトキーは実行ごとに異なります。検証の成功は、カタログからテーブルを再読み込みし、S3 経由でデータファイルを読み取れたことを意味します。テーブルの作成に成功しただけでは、この 2 点は検証できません。 + +## 4. サンプルを確認または登録解除する + +同じ接続モジュールを使用し、新しい Python プロセスからテーブルを一覧表示します。 + +```bash +python - <<'PY' +from rustfs_catalog import catalog + +print(catalog.list_tables("analytics")) +PY +``` + +結果には `("analytics", "events")` が含まれているはずです。 + +:::note[カタログエントリのみを削除] + +以下のコマンドは、このチュートリアルのテーブルエントリと、削除後に空になる名前空間を削除します。バケットと基になるオブジェクトは残ります。データのクリーンアップが必要な場合は、実行前に計画してください。`drop_table` の後は、テーブルメンテナンスでテーブルを見つけられなくなります。[メンテナンスとデータ保護](/administration/data/s3-tables)を参照してください。 + +::: + +```bash +python - <<'PY' +from rustfs_catalog import catalog + +catalog.drop_table(("analytics", "events")) +catalog.drop_namespace("analytics") +PY +``` + +## 次のステップ + +- クライアント操作は [PyIceberg API ドキュメント](https://py.iceberg.apache.org/api/)を参照し、各操作が RustFS のサポート範囲に含まれるか確認します。 +- 別のカタログサービスを管理している場合は、[外部 Iceberg カタログとの連携](/developer/integration/big-data/iceberg)を使用します。 diff --git a/content/zh/administration/data/meta.json b/content/zh/administration/data/meta.json index 43019cad..bbe3858c 100644 --- a/content/zh/administration/data/meta.json +++ b/content/zh/administration/data/meta.json @@ -3,6 +3,7 @@ "pages": [ "object", "bucket", + "s3-tables", "tiered-storage", "lifecycle-management" ] diff --git a/content/zh/administration/data/s3-tables.md b/content/zh/administration/data/s3-tables.md new file mode 100644 index 00000000..2099892d --- /dev/null +++ b/content/zh/administration/data/s3-tables.md @@ -0,0 +1,156 @@ +--- +title: "S3 Tables" +description: "启用 RustFS 表存储桶,并将 Iceberg 客户端连接到内置 REST 目录。" +--- + +RustFS S3 Tables 通过内置 REST 目录管理 **Apache Iceberg** 表。表数据、清单和 Iceberg 元数据均以 S3 对象的形式存储在 RustFS 中。本指南介绍如何启用专用表存储桶,以及客户端连接、权限和维护方面的要求与限制。 + +:::note[预览状态与版本范围] + +S3 Tables 目前为预览功能,客户端兼容性限于下文列出的工作流。本页依据 RustFS 提交 [`7e0c6711`](https://github.com/rustfs/rustfs/commit/7e0c67111b97703d47e23719b0264a739c8acea8) 编写,核对日期为 2026 年 9 月 8 日。使用其他目录操作或客户端前,请对照[支持矩阵](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/docs/architecture/s3-tables-support-matrix.md)确认当前部署版本的支持情况。 + +::: + +## 工作原理 + +Iceberg 客户端通过 REST 目录发现表并提交元数据变更,通过 S3 API 读写表文件。这两个接口都由 RustFS 在 S3 API 端口上提供。 + +```mermaid +flowchart TB + Client["Iceberg client"] -->|Catalog requests| Catalog["RustFS Iceberg REST catalog"] + Client -->|Read and write files| S3["RustFS S3 API"] + Catalog -->|Validate referenced objects| S3 +``` + +| 资源 | 用途 | +| --- | --- | +| 表存储桶 | 已启用目录功能的现有 S3 存储桶;桶名作为客户端的 `warehouse`。 | +| 命名空间 | 同一仓库内用于组织表的逻辑分组。 | +| 表 | 由目录维护的 Iceberg schema、快照和当前元数据位置。 | + +启用表存储桶不会自动将现有 Parquet 文件注册为 Iceberg 表。请通过 Iceberg 客户端创建或注册表。未指定 `location` 时,RustFS 会分配存储位置;自定义位置必须位于同一存储桶内。客户端应使用返回的位置。 + +默认的 `object` 目录后端将目录状态持久化到 RustFS 对象存储。提交表变更时,会先校验其基准元数据和引用的对象,再有条件地更新当前元数据指针。发生写入冲突时,客户端必须重新加载表并处理冲突。事务范围限于单表。 + +## 开始之前 + +- 启动提供上述 S3 Tables 端点的 RustFS 部署。请参阅[安装](/installation)。 +- 安装 [AWS CLI](/developer/examples/aws-cli),以及支持 `--aws-sigv4` 和 `--fail-with-body` 的 `curl` 7.76 或更高版本。 +- 为本教程新建一个专用存储桶,示例使用 `my-bucket`。 +- 使用已有的管理账户,确保它同时具有目录操作和 S3 对象访问权限。内置的 `consoleAdmin` 策略覆盖本教程所需操作;应用程序应配置范围更小的策略。 + +示例使用 `http://localhost:9000` 作为端点。请替换为服务器端点,并在本地测试环境以外使用 [TLS](/integration/tls-configured),保持证书校验开启。 + +:::warning[表存储桶的生命周期行为] + +普通存储桶生命周期过期处理会跳过表存储桶。在现有存储桶上启用此模式,会改变其过期规则的执行方式。执行快照过期处理和清理表文件时,应使用能够识别 Iceberg 引用关系的目录维护操作。 + +::: + +## 1. 创建存储桶 + +设置示例客户端的端点和访问凭证: + +```bash +export RUSTFS_ENDPOINT="http://localhost:9000" +export AWS_ACCESS_KEY_ID="" +export AWS_SECRET_ACCESS_KEY="" +export AWS_DEFAULT_REGION="us-east-1" +``` + +创建专用存储桶: + +```bash +aws --endpoint-url "$RUSTFS_ENDPOINT" s3api create-bucket --bucket my-bucket +``` + +这些示例使用访问密钥和秘密密钥,不使用临时会话令牌。后续请求及 PyIceberg 指南均使用同一组 shell 环境变量。 + +## 2. 启用表存储桶 + +向表存储桶端点发送请求体为空的 SigV4 签名请求: + +```bash +curl --fail-with-body --silent --show-error \ + --aws-sigv4 "aws:amz:us-east-1:s3" \ + --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \ + --header "x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" \ + --request PUT "$RUSTFS_ENDPOINT/iceberg/v1/buckets/my-bucket" +``` + +使用相同凭证读取状态: + +```bash +curl --fail-with-body --silent --show-error \ + --aws-sigv4 "aws:amz:us-east-1:s3" \ + --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \ + --header "x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" \ + "$RUSTFS_ENDPOINT/iceberg/v1/buckets/my-bucket" +``` + +两个请求成功时均返回 HTTP `200`。确认响应包含以下值: + +```json +{ + "table-bucket": "my-bucket", + "enabled": true, + "catalog-type": "iceberg-rest", + "warehouse": "my-bucket", + "catalog-entry-present": true +} +``` + +以上仅为响应节选。返回的 `catalog-uri` 是特定存储桶的路由;配置 Iceberg REST 客户端时,请使用下一节中的客户端基础 URI。 + +## 3. 连接 Iceberg 客户端 + +使用以下设置连接示例 RustFS 端点: + +| 设置 | 值 | +| --- | --- | +| REST 目录 URI | `http://localhost:9000/iceberg` | +| 仓库与前缀 | `my-bucket` | +| REST 身份验证 | AWS Signature Version 4,签名服务名为 `s3` | +| 区域 | `us-east-1` | +| S3 文件端点 | `http://localhost:9000` 配合路径式寻址 | + +客户端会在目录 URI 后添加 `/v1`。仓库值是存储桶名称,不是 S3 URI 或 AWS S3 Tables ARN。即使使用同一账户,也必须分别配置 REST 请求签名和 S3 文件访问。 + +如果已经运行独立的 Iceberg REST 目录,请参阅 [Apache Iceberg 集成](/developer/integration/big-data/iceberg)中的外部目录部署方式。 + +## 权限与凭证 + +启用表存储桶需要 `admin:SetTableBucket`,查询状态需要 `admin:GetTableBucket`。目录发现使用 `admin:GetTableCatalog`。命名空间和表操作分别对应 RustFS 管理操作权限,包括 `admin:SetTableNamespace`、`admin:CreateTable`、`admin:GetTableMetadata` 和 `admin:CommitTable`。 + +读写表文件还需要普通 S3 权限。RustFS 会对仓库对象路径检查表权限:读取需要相应的 `admin:GetTableMetadata` 授权,写入需要 `admin:SetTableMetadata`。仅授予目录提交权限,不会授权提交前的 S3 文件写入。请为两个接口配置 [IAM 策略](/security-compliance/iam/policies)。 + +目录凭证分发默认关闭。启用后,兼容客户端必须通过 `X-Iceberg-Access-Delegation: vended-credentials` 协商,调用方也必须具有请求表凭证的权限。初始目录连接仍然需要已获授权的身份。本文链接的 PyIceberg 教程使用显式配置的凭证。 + +## 维护与数据保护 + +元数据删除和后台维护默认关闭。RustFS 提供显式的维护规划、调度器运行和工作器运行操作,没有内置的定期维护调度器。启用删除前,请审查维护计划及其中保留的引用。 + +删除表会移除目录条目,但保留底层对象。请在注销表之前完成所需的表维护;注销后,维护操作将无法找到该表。清理遗留对象需要另行制定方案,并核实所有剩余引用。不要递归删除仍可能被快照或其他元数据引用的 S3 路径。 + +本教程保留默认目录后端。将现有部署切换到 `durable-strong` 时,必须遵循[目录切换流程](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/docs/operations/s3-tables-cutover-runbook.md),包括迁移预检和协调隔离写入方。 + +## 客户端兼容性与限制 + +源码仓库维护的验证范围如下: + +| 客户端 | 验证范围 | +| --- | --- | +| PyIceberg | 自动化验证创建、追加、重新加载、扫描及目录操作。 | +| DuckDB Iceberg 1.5.5 | 自动化验证通用 REST 目录下的单表读写和 schema 变更。 | +| Spark | 提供按需启用的在线测试框架;请验证实际部署的 Spark 和 Iceberg 版本组合。 | +| Trino | 仅提供手动只读探测,不声明写入兼容性。 | + +支持 Iceberg 格式 v1 和 v2,默认使用 v2。不支持暂存式建表、删表时清除数据和 Iceberg 格式 v3。 + +RustFS S3 Tables 不提供 SQL 执行引擎、多表原子事务或跨区域独立双活写入,也不声明完整兼容 AWS S3 Tables 控制面。使用其他引擎或厂商专用配置前,请查阅[支持矩阵](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/docs/architecture/s3-tables-support-matrix.md)。 + +## 后续步骤 + +- 运行 [PyIceberg 教程](/developer/integration/big-data/pyiceberg)。 +- 授予应用程序访问权限前,查阅 [IAM 策略](/security-compliance/iam/policies)。 +- 使用仓库中的[客户端一致性检查](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/scripts/table-catalog/README.md)验证其他客户端版本。 diff --git a/content/zh/administration/index.md b/content/zh/administration/index.md index 63faab2e..8f949bc0 100644 --- a/content/zh/administration/index.md +++ b/content/zh/administration/index.md @@ -9,6 +9,7 @@ description: "管理 RustFS 数据、访问协议和基于浏览器的管理功 - [控制台](./console/index.md)介绍基于浏览器的管理和登录方式。 - [数据管理](./data/object/object-lock.md)介绍存储桶、对象、生命周期行为和数据保护功能。 +- [S3 Tables](/administration/data/s3-tables)介绍表存储桶和内置 Iceberg REST 目录。 - [协议支持](./protocols/s3.md)介绍 S3、WebDAV、FTPS 和 SFTP 访问。 - [CORS 配置](./cors/index.md)介绍 RustFS 服务的跨源访问。 - [虚拟主机访问](/integration/virtual)介绍基于域名的 S3 寻址。 diff --git a/content/zh/developer/integration/big-data/iceberg.md b/content/zh/developer/integration/big-data/iceberg.md index 521af853..85b0302f 100644 --- a/content/zh/developer/integration/big-data/iceberg.md +++ b/content/zh/developer/integration/big-data/iceberg.md @@ -5,6 +5,8 @@ description: "使用 Docker Compose 运行 Apache Iceberg、Spark、REST catalog 本指南将运行 **Apache Iceberg**、Spark、Iceberg REST catalog,并将 **RustFS** 用作兼容 S3 的仓库。你将创建一个 Iceberg 表、写入并查询数据行,然后验证表文件是否存储在 RustFS 中。 +如需使用 RustFS 内置 REST 目录,请参阅 [S3 Tables 配置](/administration/data/s3-tables)和 [PyIceberg 指南](/developer/integration/big-data/pyiceberg)。下文的部署方式会运行独立的目录服务。 + 你需要安装带 Compose 插件的 Docker,并具备足够的本地资源来运行四个容器。此部署仅用于本地集成测试,不适用于生产环境。 :::note[上游状态] diff --git a/content/zh/developer/integration/big-data/meta.json b/content/zh/developer/integration/big-data/meta.json index 21662d96..6baa4460 100644 --- a/content/zh/developer/integration/big-data/meta.json +++ b/content/zh/developer/integration/big-data/meta.json @@ -2,6 +2,7 @@ "title": "大数据", "pages": [ "iceberg", + "pyiceberg", "milvus" ] } \ No newline at end of file diff --git a/content/zh/developer/integration/big-data/pyiceberg.md b/content/zh/developer/integration/big-data/pyiceberg.md new file mode 100644 index 00000000..bf219885 --- /dev/null +++ b/content/zh/developer/integration/big-data/pyiceberg.md @@ -0,0 +1,178 @@ +--- +title: "PyIceberg" +description: "使用 PyIceberg 通过 RustFS S3 Tables REST 目录创建、写入和读取 Iceberg 表。" +--- + +使用 **PyIceberg** 在 RustFS S3 Tables 目录中创建命名空间和表,追加两行数据,并在重新加载表后验证内容。本教程使用 PyIceberg `0.10.0`、Python `3.12` 和显式配置的访问凭证。 + +## 开始之前 + +- 完成 [S3 Tables 配置](/administration/data/s3-tables),创建并启用 `my-bucket`,并满足其中的账户和 TLS 要求。 +- 按该指南保留 `RUSTFS_ENDPOINT`、`AWS_ACCESS_KEY_ID`、`AWS_SECRET_ACCESS_KEY` 和 `AWS_DEFAULT_REGION` 环境变量。 + +## 1. 安装客户端 + +创建工作目录和隔离的 Python 环境: + +```bash +mkdir rustfs-s3-tables +cd rustfs-s3-tables +python3.12 -m venv .venv +source .venv/bin/activate +python -m pip install 'pyiceberg[pyarrow]==0.10.0' boto3 +``` + +## 2. 配置目录连接 + +保存以下连接模块。它采用 RustFS [已验证客户端示例](https://github.com/rustfs/rustfs/blob/7e0c67111b97703d47e23719b0264a739c8acea8/scripts/table-catalog/pyiceberg_smoke.py)中的 S3 SigV4 签名方式,同时签署初始目录发现请求和后续 REST 请求。 + +```python title="rustfs_catalog.py" +import hashlib +import os + +from botocore.auth import S3SigV4Auth +from botocore.awsrequest import AWSRequest +from botocore.credentials import Credentials +from pyiceberg.catalog.rest import RestCatalog +from requests.adapters import HTTPAdapter + +endpoint = os.environ["RUSTFS_ENDPOINT"].rstrip("/") +region = os.environ["AWS_DEFAULT_REGION"] +access_key = os.environ["AWS_ACCESS_KEY_ID"] +secret_key = os.environ["AWS_SECRET_ACCESS_KEY"] +credentials = Credentials(access_key, secret_key) + + +class RustFSSigV4Adapter(HTTPAdapter): + def add_headers(self, request, **kwargs): + body = request.body or b"" + if isinstance(body, str): + body = body.encode("utf-8") + request.headers["x-amz-content-sha256"] = hashlib.sha256(body).hexdigest() + request.headers.pop("connection", None) + signed = AWSRequest( + method=request.method, + url=request.url, + data=body, + headers=dict(request.headers), + ) + S3SigV4Auth(credentials, "s3", region).add_auth(signed) + request.headers.update(signed.headers) + + +class RustFSRestCatalog(RestCatalog): + def _init_sigv4(self, session): + session.mount(self.uri, RustFSSigV4Adapter()) + + +catalog = RustFSRestCatalog( + "rustfs", + **{ + "uri": f"{endpoint}/iceberg", + "warehouse": "my-bucket", + "prefix": "my-bucket", + "rest.sigv4-enabled": "true", + "rest.signing-name": "s3", + "rest.signing-region": region, + "py-io-impl": "pyiceberg.io.pyarrow.PyArrowFileIO", + "s3.endpoint": endpoint, + "s3.access-key-id": access_key, + "s3.secret-access-key": secret_key, + "s3.region": region, + "s3.force-virtual-addressing": "false", + }, +) +``` + +`s3.force-virtual-addressing=false` 会让 PyIceberg 的 PyArrow 文件实现使用路径式寻址。 + +:::note[客户端版本] + +适配器覆盖 PyIceberg 的 `_init_sigv4` 钩子,使目录构造完成前发出的发现请求也带有签名。使用此模块时请保留固定的 PyIceberg 版本,升级前重新运行完整教程。 + +::: + +## 3. 创建并读取表 + +示例创建命名空间 `analytics` 和表 `events`,任一资源已存在时都会停止。命名空间的每一段和表名均须为 1–64 个 ASCII 字符,仅允许小写字母、数字、`_`、`-`,且首尾必须是字母或数字。命名空间总长(含点号)不超过 512 个字符。 + +使用其他名称时,请修改 `example.py` 中的 `identifier`,并同步修改下方查看和移除命令中的名称。 + +将以下程序保存到同一目录: + +```python title="example.py" +import json + +import pyarrow as pa + +from rustfs_catalog import catalog + +identifier = ("analytics", "events") +schema = pa.schema( + [ + pa.field("id", pa.int64(), nullable=False), + pa.field("payload", pa.string(), nullable=False), + ] +) +expected = [{"id": 1, "payload": "alpha"}, {"id": 2, "payload": "beta"}] + +catalog.create_namespace(identifier[0]) +catalog.create_table(identifier, schema=schema) +table = catalog.load_table(identifier) +table.append(pa.Table.from_pylist(expected, schema=schema)) + +loaded = catalog.load_table(identifier) +actual = sorted(loaded.scan().to_arrow().to_pylist(), key=lambda row: row["id"]) +assert actual == expected, f"Unexpected table contents: {actual}" +print("rows:", json.dumps(actual)) +print("metadata:", loaded.metadata_location) +``` + +运行程序: + +```bash +python example.py +``` + +输出包含两行完整数据,以及当前元数据对象的 S3 URI: + +```text +rows: [{"id": 1, "payload": "alpha"}, {"id": 2, "payload": "beta"}] +metadata: s3://my-bucket/ +``` + +生成的元数据对象键会有所不同。验证成功意味着程序已从目录重新加载表,并通过 S3 读取数据文件;仅创建表成功无法验证这两个结果。 + +## 4. 查看或注销示例 + +使用同一连接模块,在新的 Python 进程中列出表: + +```bash +python - <<'PY' +from rustfs_catalog import catalog + +print(catalog.list_tables("analytics")) +PY +``` + +结果应包含 `("analytics", "events")`。 + +:::note[仅移除目录条目] + +以下命令移除本教程的表条目及其随后为空的命名空间,保留存储桶和底层对象。如需清理数据,请先规划:执行 `drop_table` 后,表维护将无法找到该表。请参阅[维护与数据保护](/administration/data/s3-tables)。 + +::: + +```bash +python - <<'PY' +from rustfs_catalog import catalog + +catalog.drop_table(("analytics", "events")) +catalog.drop_namespace("analytics") +PY +``` + +## 后续步骤 + +- 参考 [PyIceberg API 文档](https://py.iceberg.apache.org/api/)使用客户端操作,并逐项确认是否在 RustFS 支持范围内。 +- 如果自行管理独立目录服务,请使用[外部 Iceberg 目录集成](/developer/integration/big-data/iceberg)。