[GCP] Spark Hadoop Access with Requester Pays
在生醫領域有很多開放資料都是存在 Google Cloud Platform (GCP),有時候要避免大量複製檔案,我們會想要直接使用 gs:// 開頭的開放資料當作 Spark Table 的後端路徑,與 AWS 與 Azure 不同的是 GCP Dataproc 提供了一個使用者付費的方式,顧名思義就是資料的傳輸費用是由使用者去支付的,本篇紀錄如何設定 Spark Cluster 的設定檔透過 Spark SQL 的方式直接使用公開的資料,減少複製檔案與儲存帶來的成本。
使用 gcs-connector 驅動 GoogleHadoopFileSystem
要讓 Spark Hadoop 能夠認得 gs:// 開頭的 URL,需要以下幾個要件:
- 放置相對應的 JAR 檔案:
https://mvnrepository.com/artifact/com.google.cloud.bigdataoss/gcs-connector/hadoop3-2.2.26 - 設定以下固定參數在 core-site.xml 或是 spark-defaults.conf 裡面:
<!-- Access of Google Cloud --> <property> <name>fs.gs.impl</name> <value>com.google.cloud.hadoop.fs.gcs.GoogleHadoopFileSystem</value> <description>The FileSystem for gs: (GCS) uris.</description> </property> <property> <name>fs.AbstractFileSystem.gs.impl</name> <value>com.google.cloud.hadoop.fs.gcs.GoogleHadoopFS</value> <description>The AbstractFileSystem for gs: uris.</description> </property>
- 設定 Authentication 的方法:
一般比較簡單的方法是利用 SERVICE_ACCOUNT_JSON_KEYFILE,不過也可以使用其他的方式,在 Requester Pays 的情境下,一定要有認證才能夠使用,畢竟要知道要向誰去收費。
其他 SPARK Configuration 設定可以參考,本篇使用的是 USER_CREDENTIALS
https://github.com/GoogleCloudDataproc/hadoop-connectors/blob/master/gcs/CONFIGURATION.md
設定完 Authentication 之後開始透過 Spark 去取得資料會一直回報類似以下的錯誤訊息:
03:23:26.701 WARN FileStreamSink - Assume no metadata directory. Error while looking for metadata directory in the path: gs://open-targets-data-releases/25.03/output/drug_molecule.
java.io.IOException: Error accessing gs://open-targets-data-releases/25.03/output/drug_molecule. reason=400 Bad Request
GET https://storage.googleapis.com/storage/v1/b/open-targets-data-releases/o/25.03%2Foutput%2Fdrug_molecule?fields=bucket,name,timeCreated,updated,generation,metageneration,size,contentType,contentEncoding,md5Hash,crc32c,metadata
{
"code" : 400,
"errors" : [ {
"domain" : "global",
"message" : "Bucket is a requester pays bucket but no user project provided.",
"reason" : "required"
} ],
"message" : "Bucket is a requester pays bucket but no user project provided."
}
嘗試把以上的錯誤訊息貼給 LLM 會發現他會一直建議你要檢查 `fs.gs.auth.project.id` 是不是有設定正確?但是即便確定有設定下去還是一直報錯。
解決方法:
嘗試查找其他的資料之後,找到 Hail Project 的 Forum,針對這個問題,他裡面建議要另外再加以下三個 Spark Configurations 就可以解決:
spark.hadoop.fs.gs.requester.pays.mode CUSTOM
spark.hadoop.fs.gs.requester.pays.buckets open-targets-data-releases
spark.hadoop.fs.gs.requester.pays.project.id <Your-Google-Project-ID>
完整可以用的 Spark Configurations:
原本使用 SERVICE_ACCOUNT_JSON_KEYFILE 的認證方式,但是因為不想要固定給一個 Json 檔案在環境中,想要比較彈性的使用 Spark Configuration 的方式提供,所以後來嘗試去使用 USER_CREDENTIALS 的認證方式,以下參數提供參考:
spark.hadoop.fs.gs.project.id <Your-Google-Project-ID>
spark.hadoop.fs.gs.auth.type USER_CREDENTIALS
spark.hadoop.fs.gs.auth.client.id <USER_CLIENT_ID>
spark.hadoop.fs.gs.auth.client.secret <USER_CLIENT_SECRET>
spark.hadoop.fs.gs.auth.refresh.token <USER_REFRESH_TOKEN>
spark.hadoop.fs.gs.requester.pays.mode CUSTOM
spark.hadoop.fs.gs.requester.pays.buckets open-targets-data-releases
spark.hadoop.fs.gs.requester.pays.project.id <Your-Google-Project-ID>