AIDP ノートブックから AWS S3(`s3a://`)に対してデータの読み書きができるスキルです。 **使用する場合:** - ユーザーが S3、AWS S3 バケット、s3a について言及した場合 - AWS アクセスキーを持っている場合 **認証方法:** Hadoop S3A コネクタを経由して、アクセスキーとシークレットキー(秘密鍵)で認証します。 **その他の機能:** Spark 以外の管理操作(ファイル一覧表示、コピーなど)には boto3(AWS 操作用のプログラミングツール)も利用できます。
Read and write AWS S3 (`s3a://`) from an AIDP notebook. Use when the user mentions S3, AWS S3 bucket, s3a, or has AWS access keys. Auth is access key + secret key via the Hadoop S3A connector. boto3 is also available for non-Spark management operations (list, copy).
aidp-aws-s3 — S3A コネクタ経由の AWS S3AWS アクセスキーを使用して、AIDP Spark から s3a://<bucket>/<key> パスの読み書きを行います。
管理操作(list・copy・head)向けに boto3 パスも利用可能(オプション)。
aidp-object-storageaidp-azure-adlshadoop-aws と aws-java-sdk-bundle の両方をランタイムロードすることAIDP の tpcds クラスターには org.apache.hadoop.fs.s3a.S3AFileSystem がプリインストールされていません(2026-04-27 実環境確認済み)。
hadoop-aws-<ver>.jar(約 1 MB)と aws-java-sdk-bundle-<ver>.jar(約 280 MB)の両方をランタイムロードする必要があります。
hadoop-aws のバージョンはクラスターの Hadoop バージョンに厳密に合わせてください
(spark._jvm.org.apache.hadoop.util.VersionInfo.getVersion() で確認可能 — Spark 3.5.0 では通常 3.3.4)。
バージョン不一致が発生すると、org.apache.hadoop.fs.s3a 内部で NoSuchMethodError が発生します。
標準的なランタイムロード + DriverManager パターンに加え、S3A では Hadoop の Configuration に対して使用するクラスローダーを明示的に指定する必要があります。
Hadoop の FileSystem.get() は JVM のスレッドコンテキストローダーではなく Configuration.getClassLoader() を使用するためです。
import os, urllib.request
from py4j.java_gateway import java_import
# 1. クラスターの Hadoop バージョンを確認し、hadoop-aws jar を一致させる
HADOOP_VER = spark._jvm.org.apache.hadoop.util.VersionInfo.getVersion()
print("hadoop:", HADOOP_VER) # 例: 3.3.4
JARS = {
f"/tmp/hadoop-aws-{HADOOP_VER}.jar":
f"https://repo1.maven.org/maven2/org/apache/hadoop/hadoop-aws/{HADOOP_VER}/hadoop-aws-{HADOOP_VER}.jar",
"/tmp/aws-java-sdk-bundle-1.12.262.jar":
"https://repo1.maven.org/maven2/com/amazonaws/aws-java-sdk-bundle/1.12.262/aws-java-sdk-bundle-1.12.262.jar",
}
for path, url in JARS.items():
if not os.path.exists(path):
urllib.request.urlretrieve(url, path)
# 2. 両 jar を含む URLClassLoader を構築し、Hadoop Configuration に設定する
gw = spark._sc._gateway
URLArr = gw.new_array(spark._jvm.java.net.URL, len(JARS))
for i, p in enumerate(JARS):
URLArr[i] = spark._jvm.java.io.File(p).toURI().toURL()
sysCL = spark._jvm.java.lang.ClassLoader.getSystemClassLoader()
ucl = spark._jvm.java.net.URLClassLoader(URLArr, sysCL)
hconf = spark._jsc.hadoopConfiguration()
hconf.setClassLoader(ucl) # 重要 — Hadoop の FileSystem ルックアップはこちらを使用(スレッドコンテキストではない)
# 3. S3A 認証情報とエンドポイントを設定する
hconf.set("fs.s3a.access.key", os.environ["S3_ACCESS_KEY"])
hconf.set("fs.s3a.secret.key", os.environ["S3_SECRET_KEY"])
hconf.set("fs.s3a.endpoint", "s3.amazonaws.com") # または s3.<region>.amazonaws.com
hconf.set("fs.s3a.aws.credentials.provider",
"org.apache.hadoop.fs.s3a.SimpleAWSCredentialsProvider")
hconf.set("fs.s3a.impl", "org.apache.hadoop.fs.s3a.S3AFileSystem")
# 4. エグゼキューターへ jar を配布する(ドライバーのみの登録ではクラスター読み込みに不十分)
for p in JARS:
spark._jsc.addJar(p)
# 5. 読み込み — csv/json/parquet/delta に対応
df = spark.read.option("header", "true").csv(
f"s3a://{os.environ['S3_BUCKET']}/{os.environ['S3_FILE']}"
)
df.show()
2026-04-27 実環境検証済み: 本パターンにより s3a://test-data-sep3-2025/csv/sample.csv から 2 行を取得確認。
import boto3, os
s3 = boto3.client(
"s3",
aws_access_key_id = os.environ["S3_ACCESS_KEY"],
aws_secret_access_key = os.environ["S3_SECRET_KEY"],
region_name = os.environ.get("S3_REGION", "us-east-1"),
)
resp = s3.list_objects_v2(Bucket=os.environ["S3_BUCKET"], Prefix="")
for obj in resp.get("Contents", []):
print(obj["Key"])
s3a://(Hadoop ドライバー)を使用し、s3:// や s3n:// は使わないこと。
後者の 2 つは非推奨であり、クラスターに存在しない場合があります。
aws-java-sdk-bundle のバージョンずれに注意 —
hadoop-aws がビルドされた時点のバージョンに固定してください。
ラボ環境のクラスターではこの jar のインストールが必要なことが多く、
バージョン不一致の症状は list/read 時に org.apache.hadoop.fs.s3a 内部で NoSuchMethodError が発生することです。
ランタイムロード後は Configuration.setClassLoader が必須 —
Hadoop の FileSystem.get() は Configuration.getClassByName() を呼び出し、
JVM スレッドコンテキストではなく Configuration のクラスローダーを使用します。
hconf.setClassLoader(ucl) を設定しないと、jar を登録済みであっても
ClassNotFoundException: Class org.apache.hadoop.fs.s3a.S3AFileSystem not found が発生します。
シークレットは環境変数のみで管理すること。
ノートブックにキーをハードコードしないでください。.env / OCI Vault から取得してください。
リージョンについて —
デフォルト以外のリージョンでは boto3.client('s3', region_name=...) の指定が必要です。
Spark パスではバケットのリージョンが自動検出されますが、
us-east-1 以外で listing が失敗する場合は fs.s3a.endpoint=s3.<region>.amazonaws.com の設定が必要になることがあります。
boto3 は AIDP クラスターにプリインストールされていません。
PyPI ミラーも通常到達不能です。
管理操作(list・copy・head)はクラスターではなくローカルから実行してください。
エグレスコストとレイテンシ — AIDP からの S3 読み込みはクラウド間通信になります。 大規模な ETL の場合は、一度 OCI Object Storage にコピーしてからローカルで読み込むことを推奨します。
aidp-aws-s3 — AWS S3 via the S3A connectorRead or write s3a://<bucket>/<key> paths from AIDP Spark using AWS access keys. Optional boto3 path for management operations (list, copy, head).
aidp-object-storage.aidp-azure-adls.hadoop-aws and aws-java-sdk-bundleThe AIDP tpcds cluster does NOT have org.apache.hadoop.fs.s3a.S3AFileSystem pre-installed (verified live 2026-04-27). Both hadoop-aws-<ver>.jar (~1 MB) AND aws-java-sdk-bundle-<ver>.jar (~280 MB) must be runtime-loaded. Match hadoop-aws to the cluster's exact Hadoop version (spark._jvm.org.apache.hadoop.util.VersionInfo.getVersion() — typically 3.3.4 for Spark 3.5.0). Mismatch produces NoSuchMethodError deep in org.apache.hadoop.fs.s3a.
Beyond the standard runtime-load + DriverManager pattern, S3A also requires telling Hadoop's Configuration which classloader to use — Hadoop's FileSystem.get() uses Configuration.getClassLoader(), not the JVM thread context loader.
import os, urllib.request
from py4j.java_gateway import java_import
# 1. Confirm cluster's Hadoop version + match hadoop-aws jar
HADOOP_VER = spark._jvm.org.apache.hadoop.util.VersionInfo.getVersion()
print("hadoop:", HADOOP_VER) # e.g. 3.3.4
JARS = {
f"/tmp/hadoop-aws-{HADOOP_VER}.jar":
f"https://repo1.maven.org/maven2/org/apache/hadoop/hadoop-aws/{HADOOP_VER}/hadoop-aws-{HADOOP_VER}.jar",
"/tmp/aws-java-sdk-bundle-1.12.262.jar":
"https://repo1.maven.org/maven2/com/amazonaws/aws-java-sdk-bundle/1.12.262/aws-java-sdk-bundle-1.12.262.jar",
}
for path, url in JARS.items():
if not os.path.exists(path):
urllib.request.urlretrieve(url, path)
# 2. Build URLClassLoader covering BOTH jars + set on Hadoop Configuration
gw = spark._sc._gateway
URLArr = gw.new_array(spark._jvm.java.net.URL, len(JARS))
for i, p in enumerate(JARS):
URLArr[i] = spark._jvm.java.io.File(p).toURI().toURL()
sysCL = spark._jvm.java.lang.ClassLoader.getSystemClassLoader()
ucl = spark._jvm.java.net.URLClassLoader(URLArr, sysCL)
hconf = spark._jsc.hadoopConfiguration()
hconf.setClassLoader(ucl) # CRITICAL — Hadoop FileSystem lookup uses this, not the thread context
# 3. Configure S3A credentials + endpoint
hconf.set("fs.s3a.access.key", os.environ["S3_ACCESS_KEY"])
hconf.set("fs.s3a.secret.key", os.environ["S3_SECRET_KEY"])
hconf.set("fs.s3a.endpoint", "s3.amazonaws.com") # or s3.<region>.amazonaws.com
hconf.set("fs.s3a.aws.credentials.provider",
"org.apache.hadoop.fs.s3a.SimpleAWSCredentialsProvider")
hconf.set("fs.s3a.impl", "org.apache.hadoop.fs.s3a.S3AFileSystem")
# 4. Distribute the jars to executors (driver-only registration won't work for cluster reads)
for p in JARS:
spark._jsc.addJar(p)
# 5. Read — works for csv/json/parquet/delta
df = spark.read.option("header", "true").csv(
f"s3a://{os.environ['S3_BUCKET']}/{os.environ['S3_FILE']}"
)
df.show()
Live-validated 2026-04-27: 2 rows from s3a://test-data-sep3-2025/csv/sample.csv via this pattern.
import boto3, os
s3 = boto3.client(
"s3",
aws_access_key_id = os.environ["S3_ACCESS_KEY"],
aws_secret_access_key = os.environ["S3_SECRET_KEY"],
region_name = os.environ.get("S3_REGION", "us-east-1"),
)
resp = s3.list_objects_v2(Bucket=os.environ["S3_BUCKET"], Prefix="")
for obj in resp.get("Contents", []):
print(obj["Key"])
s3a:// (the Hadoop driver), not s3:// or s3n://. The latter two are deprecated and may not be present in the cluster.aws-java-sdk-bundle version drift — pin to the version hadoop-aws was built against. Lab clusters often need this jar installed; the symptom of mismatch is NoSuchMethodError deep in org.apache.hadoop.fs.s3a when listing/reading.Configuration.setClassLoader is required after runtime-load — Hadoop's FileSystem.get() calls Configuration.getClassByName() which uses the Configuration's classloader (not the JVM thread context). Without hconf.setClassLoader(ucl), you get ClassNotFoundException: Class org.apache.hadoop.fs.s3a.S3AFileSystem not found even though you just registered the jar..env/OCI Vault.boto3.client('s3', region_name=...) is required for non-default regions; for the Spark path the bucket region is auto-discovered, but you may need fs.s3a.endpoint=s3.<region>.amazonaws.com for non-us-east-1 if listings fail.boto3 is NOT pre-installed on AIDP cluster and PyPI mirror is typically unreachable. For management ops (list, copy, head), drive from local rather than cluster.原文・著作権は Anthropic および各プラグイン作者に帰属します。日本語訳は Claude API による自動翻訳です。