

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# Amazon EMR on EC2 的 Lake Formation 完整資料表存取
<a name="lake-formation-unfiltered-ec2-access"></a>

透過 Amazon EMR 7.8.0 版及更高版本，您可以利用 AWS Lake Formation 搭配 Glue Data Catalog，其中任務執行期角色具有完整的資料表許可，而不受精細存取控制的限制。此功能可讓您從 Amazon EMR on EC2 Spark 批次和互動式任務讀取和寫入受 Lake Formation 保護的資料表。請參閱下列各節，進一步了解 Lake Formation 以及如何搭配 Amazon EMR on EC2 使用。

## 使用 Lake Formation 搭配完整資料表存取
<a name="lake-formation-unfiltered-ec2-full-access"></a>

您可以從 Amazon EMR on EC2 Spark 任務或互動式工作階段存取 AWS Lake Formation 保護的 Glue Data 目錄資料表，其中任務的執行期角色具有完整資料表存取權。您不需要在 Amazon EMR on EC2 應用程式上啟用 AWS Lake Formation。當 Spark 任務設定為完整資料表存取 (FTA) 時， AWS Lake Formation 登入資料會用於讀取/寫入 AWS Lake Formation 註冊資料表的 S3 資料，而任務的執行時間角色登入資料則會用於讀取/寫入未向 AWS Lake Formation 註冊的資料表。

**重要**  
請勿為精細存取控制啟用 AWS Lake Formation。任務無法同時在相同的 EMR 叢集或應用程式上執行完整資料表存取 (FTA) 和精細存取控制 (FGAC)。

### 步驟 1：在 Lake Formation 中啟用完整資料表存取
<a name="lake-formation-unfiltered-ec2-full-table-access"></a>

若要使用完整資料表存取 (FTA) 模式，您必須允許第三方查詢引擎存取資料，而不需要 AWS Lake Formation 中的 IAM 工作階段標籤驗證。若要啟用，請遵循[整合應用程式進行完整資料表存取](https://docs.aws.amazon.com/lake-formation/latest/dg/full-table-credential-vending.html)中的步驟。

**注意**  
 存取跨帳戶資料表時，必須在生產者和消費者帳戶中啟用完整資料表存取。同樣地，存取跨區域資料表時，必須在生產者和消費者區域啟用此設定。

### 步驟 2：設定任務執行時期角色的 IAM 許可
<a name="lake-formation-unfiltered-ec2-iam-permissions"></a>

對於基礎資料的讀取或寫入存取權，除了 Lake Formation 許可之外，任務執行期角色還需要 IAM `lakeformation:GetDataAccess` 許可。有了此許可，Lake Formation 就會授與要求存取資料所需的臨時憑證。

以下範例政策說明如何提供 IAM 許可，以存取 Amazon S3 中的指令碼、將日誌上傳至 S3、 AWS Glue API 許可，以及存取 Lake Formation 的許可。

#### 步驟 2.1 設定 Lake Formation 許可
<a name="lake-formation-unfiltered-ec2-permission-model"></a>
+ 從 S3 讀取資料的 Spark 任務需要 Lake Formation SELECT 許可。
+ 在 S3 中寫入/刪除資料的 Spark 任務需要 Lake Formation ALL (SUPER) 許可。
+ 與 Glue Data Catalog 互動的 Spark 任務需要適當的 DESCRIBE、ALTER、DROP 許可。

如需詳細資訊，請參閱[授予 Data Catalog 資源的許可](https://docs.aws.amazon.com/lake-formation/latest/dg/granting-catalog-permissions.html)。

### 步驟 3：使用 Lake Formation 初始化完整資料表存取的 Spark 工作階段
<a name="lake-formation-unfiltered-ec2-spark-session"></a>

#### 先決條件
<a name="lake-formation-unfiltered-ec2-spark-session-prereq"></a>

AWS Glue Data Catalog 必須設定為中繼存放區，才能存取 Lake Formation 資料表。

設定下列設定，將 Glue 目錄設定為中繼存放區：

```
--conf spark.sql.catalogImplementation=hive
--conf spark.hive.metastore.client.factory.class=com.amazonaws.glue.catalog.metastore.AWSGlueDataCatalogHiveClientFactory
```

如需在 EC2 上啟用 Amazon EMR Data Catalog 的詳細資訊，請參閱 [ EC2 上 Amazon EMR 的中繼存放區組態](metastore-config.html)。

若要存取向 AWS Lake Formation 註冊的資料表，需要在 Spark 初始化期間設定下列組態，以將 Spark 設定為使用 AWS Lake Formation 憑證。

------
#### [ Hive ]

```
‐‐conf spark.hadoop.fs.s3.credentialsResolverClass=com.amazonaws.glue.accesscontrol.AWSLakeFormationCredentialResolver
--conf spark.hadoop.fs.s3.useDirectoryHeaderAsFolderObject=true 
--conf spark.hadoop.fs.s3.folderObject.autoAction.disabled=true
--conf spark.sql.catalog.skipLocationValidationOnCreateTable.enabled=true
--conf spark.sql.catalog.createDirectoryAfterTable.enabled=true
--conf spark.sql.catalog.dropDirectoryBeforeTable.enabled=true
```

------
#### [ Iceberg ]

```
--conf spark.sql.catalog.spark_catalog=org.apache.iceberg.spark.SparkSessionCatalog
--conf spark.sql.catalog.spark_catalog.warehouse={{S3_DATA_LOCATION}}
--conf spark.sql.catalog.spark_catalog.client.region={{REGION}}
--conf spark.sql.catalog.spark_catalog.type=glue
--conf spark.sql.catalog.spark_catalog.glue.account-id={{ACCOUNT_ID}}
--conf spark.sql.catalog.spark_catalog.glue.lakeformation-enabled=true
--conf spark.sql.catalog.dropDirectoryBeforeTable.enabled=true
```

------
#### [ Delta Lake ]

```
‐‐conf spark.hadoop.fs.s3.credentialsResolverClass=com.amazonaws.glue.accesscontrol.AWSLakeFormationCredentialResolver
--conf spark.hadoop.fs.s3.useDirectoryHeaderAsFolderObject=true 
--conf spark.hadoop.fs.s3.folderObject.autoAction.disabled=true
--conf spark.sql.catalog.skipLocationValidationOnCreateTable.enabled=true
--conf spark.sql.catalog.createDirectoryAfterTable.enabled=true
--conf spark.sql.catalog.dropDirectoryBeforeTable.enabled=true
```

------
#### [ Hudi ]

```
‐‐conf spark.hadoop.fs.s3.credentialsResolverClass=com.amazonaws.glue.accesscontrol.AWSLakeFormationCredentialResolver
--conf spark.hadoop.fs.s3.useDirectoryHeaderAsFolderObject=true 
--conf spark.hadoop.fs.s3.folderObject.autoAction.disabled=true
--conf spark.sql.catalog.skipLocationValidationOnCreateTable.enabled=true
--conf spark.sql.catalog.createDirectoryAfterTable.enabled=true
--conf spark.sql.catalog.dropDirectoryBeforeTable.enabled=true
--conf spark.jars=/usr/lib/hudi/hudi-spark-bundle.jar
--conf spark.sql.extensions=org.apache.spark.sql.hudi.HoodieSparkSessionExtension
--conf spark.sql.catalog.spark_catalog=org.apache.spark.sql.hudi.catalog.HoodieCatalog
--conf spark.serializer=org.apache.spark.serializer.KryoSerializer
```

------
+ `spark.hadoop.fs.s3.credentialsResolverClass=com.amazonaws.glue.accesscontrol.AWSLakeFormationCredentialResolver`：設定 EMR Filesystem (EMRFS) 或 EMR S3A 以使用 AWS Lake Formation 註冊資料表的 Lake Formation S3 登入資料。如果未註冊資料表，請使用任務的執行時期角色憑證。
+ `spark.hadoop.fs.s3.useDirectoryHeaderAsFolderObject=true` 和 `spark.hadoop.fs.s3.folderObject.autoAction.disabled=true`：將 EMRFS 設定為在建立 S3 資料夾時使用內容類型標頭 application/x-directory，而非 $folder$ 尾碼。這是讀取 Lake Formation 資料表時的必要項目，因為 Lake Formation 登入資料不允許使用 $folder$ 尾碼讀取資料表資料夾。
+ `spark.sql.catalog.skipLocationValidationOnCreateTable.enabled=true`：將 Spark 設定為在建立之前略過驗證資料表位置的空白。這對於 Lake Formation 註冊的資料表是必要的，因為 Lake Formation 憑證只有在 Glue Data Catalog 資料表建立後才能使用。如果沒有此組態，任務的執行時期角色憑證將驗證空白資料表位置。
+ `spark.sql.catalog.createDirectoryAfterTable.enabled=true`：將 Spark 設定為在 Hive 中繼存放區中建立資料表之後建立 Amazon S3 資料夾。Lake Formation 註冊的資料表需要此項目，因為建立 S3 資料夾的 Lake Formation 憑證只有在 Glue Data Catalog 資料表建立後才能使用。
+ `spark.sql.catalog.dropDirectoryBeforeTable.enabled=true`：設定 Spark 在 Hive 中繼存放區中刪除資料表之前捨棄 S3 資料夾。這對於 Lake Formation 註冊的資料表是必要的，因為從 Glue Data Catalog 刪除資料表後，無法使用 Lake Formation 登入資料來捨棄 S3 資料夾。
+ `spark.sql.catalog.<catalog>.glue.lakeformation-enabled=true`：設定 Iceberg 目錄以使用 AWS Lake Formation 註冊資料表的 Lake Formation S3 登入資料。如果未註冊資料表，請使用預設環境憑證。

#### 在 SageMaker Unified Studio 中設定完整資料表存取模式
<a name="lake-formation-unfiltered-ec2-full-table"></a>

若要從 JupyterLab 筆記本中的互動式 Spark 工作階段存取 Lake Formation 註冊的資料表，請使用相容性許可模式。使用 %%configure 魔術命令來設定 Spark 組態。根據資料表類型選擇組態：

------
#### [ For Hive tables ]

```
%%configure -f
{
    "conf": {
        "spark.hadoop.fs.s3.credentialsResolverClass": "com.amazonaws.glue.accesscontrol.AWSLakeFormationCredentialResolver",
        "spark.hadoop.fs.s3.useDirectoryHeaderAsFolderObject": true,
        "spark.hadoop.fs.s3.folderObject.autoAction.disabled": true,
        "spark.sql.catalog.skipLocationValidationOnCreateTable.enabled": true,
        "spark.sql.catalog.createDirectoryAfterTable.enabled": true,
        "spark.sql.catalog.dropDirectoryBeforeTable.enabled": true
    }
}
```

------
#### [ For Iceberg tables ]

```
%%configure -f
{
    "conf": {
        "spark.sql.catalog.spark_catalog": "org.apache.iceberg.spark.SparkSessionCatalog",
        "spark.sql.catalog.spark_catalog.warehouse": "{{S3_DATA_LOCATION}}",
        "spark.sql.catalog.spark_catalog.client.region": "{{REGION}}",
        "spark.sql.catalog.spark_catalog.type": "glue",
        "spark.sql.catalog.spark_catalog.glue.account-id": "{{ACCOUNT_ID}}",
        "spark.sql.catalog.spark_catalog.glue.lakeformation-enabled": "true",
        "spark.sql.catalog.dropDirectoryBeforeTable.enabled": "true", 
    }
}
```

------
#### [ For Delta Lake tables ]

```
%%configure -f
{
    "conf": {
        "spark.hadoop.fs.s3.credentialsResolverClass": "com.amazonaws.glue.accesscontrol.AWSLakeFormationCredentialResolver",
        "spark.hadoop.fs.s3.useDirectoryHeaderAsFolderObject": true,
        "spark.hadoop.fs.s3.folderObject.autoAction.disabled": true,
        "spark.sql.catalog.skipLocationValidationOnCreateTable.enabled": true,
        "spark.sql.catalog.createDirectoryAfterTable.enabled": true,
        "spark.sql.catalog.dropDirectoryBeforeTable.enabled": true
    }
}
```

------
#### [ For Hudi tables ]

```
%%configure -f
{
    "conf": {
        "spark.hadoop.fs.s3.credentialsResolverClass": "com.amazonaws.glue.accesscontrol.AWSLakeFormationCredentialResolver",
        "spark.hadoop.fs.s3.useDirectoryHeaderAsFolderObject": true,
        "spark.hadoop.fs.s3.folderObject.autoAction.disabled": true,
        "spark.sql.catalog.skipLocationValidationOnCreateTable.enabled": true,
        "spark.sql.catalog.createDirectoryAfterTable.enabled": true,
        "spark.sql.catalog.dropDirectoryBeforeTable.enabled": true,
        "spark.jars": "/usr/lib/hudi/hudi-spark-bundle.jar",
        "spark.sql.extensions": "org.apache.spark.sql.hudi.HoodieSparkSessionExtension",
        "spark.sql.catalog.spark_catalog": "org.apache.spark.sql.hudi.catalog.HoodieCatalog",
        "spark.serializer": "org.apache.spark.serializer.KryoSerializer"
    }
}
```

------

取代預留位置：
+ `S3_DATA_LOCATION`：您的 S3 儲存貯體路徑
+ `REGION`： AWS region （例如 us-east-1)
+ `ACCOUNT_ID`： AWS 您的帳戶 ID

**注意**  
必須先設定這些組態，才能在筆記本中執行任何 Spark 操作。

#### 受支援的 操作
<a name="lake-formation-unfiltered-ec2-supported-operations"></a>

這些操作將使用 AWS Lake Formation 登入資料來存取資料表資料。
+ CREATE TABLE
+ ALTER TABLE
+ INSERT INTO
+ INSERT OVERWRITE
+ UPDATE
+ 合併為
+ DELETE FROM
+ ANALYZE TABLE
+ REPAIR TABLE
+ DROP TABLE
+ Spark 資料來源查詢
+ Spark 資料來源寫入

**注意**  
上面未列出的操作將繼續使用 IAM 許可來存取資料表資料。

#### 考量事項
<a name="considerations"></a>
+ 如果 Hive 資料表是使用未啟用完整資料表存取的任務建立，而且未插入任何記錄，則具有完整資料表存取的任務後續讀取或寫入將會失敗。這是因為沒有完整資料表存取權的 EMR Spark `$folder$` 會將尾碼新增至資料表資料夾名稱。若要解決此問題，您可以：
  + 從未啟用 FTA 的任務中將至少一列插入資料表。
  + 將未啟用 FTA 的任務設定為不要在 S3 `$folder$` 的資料夾名稱中使用尾碼。這可以透過設定 Spark 組態 `spark.hadoop.fs.s3.useDirectoryHeaderAsFolderObject=true` 來實現。
  + `s3://path/to/table/table_name` 使用 S3 主控台或 AWS S3 CLI 在資料表位置建立 AWS S3 資料夾。
+ 從 Amazon EMR 7.8.0 版開始的 EMR 檔案系統 (EMRFS) 和從 Amazon EMR 7.10.0 版開始的 S3A 檔案系統支援完整資料表存取。
+ Hive、Iceberg、Delta 和 Hudi 資料表支援完整資料表存取。
+ **Hudi FTA Write Support 考量事項：**
  + Hudi FTA 寫入要求在任務執行期間使用HoodieCredentialedHadoopStorage 進行憑證販賣。在執行 Hudi 任務時設定下列組態： `hoodie.storage.class=org.apache.spark.sql.hudi.storage.HoodieCredentialedHadoopStorage`
  + Hudi 的完整資料表存取 (FTA) 寫入支援從 Amazon EMR 7.12 版開始提供。
  + Hudi FTA 寫入支援目前僅適用於預設 Hudi 組態。自訂或非預設 Hudi 設定可能未完全支援，並可能導致非預期的行為。
  + 在 FTA 寫入模式下，目前不支援叢集 Hudi Merge-On-Read (MOR) 資料表。
+ 使用 Lake Formation 精細存取控制 (FGAC) 規則或 Glue Data Catalog 檢視參考資料表的任務將會失敗。若要查詢具有 FGAC 規則或 Glue Data Catalog View 的資料表，您必須使用 FGAC 模式。您可以按照 AWS 文件中概述的步驟啟用 FGAC 模式：[在 EC2 上使用 Amazon EMR 搭配 AWS Lake Formation 進行精細存取控制](emr-serverless-lf-enable.html)。
+ 完整資料表存取不支援 Spark 串流。
+ 將 Spark DataFrame 寫入 Lake Formation 資料表時，Hive 和 Iceberg 資料表僅支援 APPEND 模式： `df.write.mode("append").saveAsTable({{table_name}})`
+ 建立外部資料表需要 IAM 許可。
+ 由於 Lake Formation 會暫時快取 Spark 任務中的登入資料，因此目前正在執行的 Spark 批次任務或互動式工作階段可能不會反映許可變更。
+ 您必須使用使用者定義的角色，而不是角色的服務連結角色：[Lake Formation 要求](https://docs.aws.amazon.com/lake-formation/latest/dg/registration-role.html)。

#### Hudi FTA 寫入支援 - 支援的操作
<a name="hudi-fta-supported-operations"></a>

下表顯示完整資料表存取模式下 Hudi Copy-On-Write(COW) Merge-On-Read(MOR) 資料表支援的寫入操作：


**Hudi FTA 支援的寫入操作**  

| 資料表類型 | 作業 | SQL 寫入命令 | 狀態 | 
| --- | --- | --- | --- | 
| COW | INSERT | INSERT INTO TABLE | 支援 | 
| COW | INSERT | INSERT IN TO TABLE - PARTITION （靜態、動態） | 支援 | 
| COW | INSERT | INSERT OVERWRITE | 支援 | 
| COW | INSERT | INSERT OVERWRITE - PARTITION （靜態、動態） | 支援 | 
| UPDATE | UPDATE | UPDATE TABLE | 支援 | 
| COW | UPDATE | 更新資料表 - 變更分割區 | 不支援 | 
| DELETE | DELETE | DELETE FROM TABLE | 支援 | 
| ALTER | ALTER | ALTER TABLE - 重新命名為 | 不支援 | 
| COW | ALTER | ALTER TABLE - 設定 TBLPROPERTIES | 支援 | 
| COW | ALTER | ALTER TABLE - 取消設定 TBLPROPERTIES | 支援 | 
| COW | ALTER | ALTER 資料表 - ALTER 資料欄 | 支援 | 
| COW | ALTER | ALTER TABLE - 新增資料欄 | 支援 | 
| COW | ALTER | ALTER TABLE - 新增分割區 | 支援 | 
| COW | ALTER | ALTER TABLE - 捨棄分割區 | 支援 | 
| COW | ALTER | ALTER TABLE - 復原分割區 | 支援 | 
| COW | ALTER | 修復資料表同步分割區 | 支援 | 
| DROP | DROP | DROP TABLE | 支援 | 
| COW | DROP | DROP TABLE - PURGE | 支援 | 
| CREATE | CREATE | CREATE TABLE - 受管 | 支援 | 
| COW | CREATE | 建立資料表 - 分割區依據 | 支援 | 
| COW | CREATE | 如果不存在，則建立資料表 | 支援 | 
| COW | CREATE | CREATE TABLE LIKE | 支援 | 
| COW | CREATE | CREATE TABLE AS SELECT | 支援 | 
| CREATE | CREATE | 使用 LOCATION 建立資料表 - 外部資料表 | 不支援 | 
| DATAFRAME(INSERT) | DATAFRAME(INSERT) | saveAsTable.Overwrite | 支援 | 
| COW | DATAFRAME(INSERT) | saveAsTable.Append | 不支援 | 
| COW | DATAFRAME(INSERT) | saveAsTable.Ignore | 支援 | 
| COW | DATAFRAME(INSERT) | saveAsTable.ErrorIfExists | 支援 | 
| COW | DATAFRAME(INSERT) | saveAsTable - 外部資料表 （路徑） | 不支援 | 
| COW | DATAFRAME(INSERT) | save(path) - DF v1 | 不支援 | 
| MOR | INSERT | INSERT INTO TABLE | 支援 | 
| MOR | INSERT | INSERT IN TO TABLE - PARTITION （靜態、動態） | 支援 | 
| MOR | INSERT | INSERT OVERWRITE | 支援 | 
| MOR | INSERT | INSERT OVERWRITE - PARTITION （靜態、動態） | 支援 | 
| UPDATE | UPDATE | UPDATE TABLE | 支援 | 
| MOR | UPDATE | 更新資料表 - 變更分割區 | 不支援 | 
| DELETE | DELETE | DELETE FROM TABLE | 支援 | 
| ALTER | ALTER | ALTER TABLE - 重新命名為 | 不支援 | 
| MOR | ALTER | ALTER TABLE - 設定 TBLPROPERTIES | 支援 | 
| MOR | ALTER | ALTER TABLE - 取消設定 TBLPROPERTIES | 支援 | 
| MOR | ALTER | ALTER 資料表 - ALTER 資料欄 | 支援 | 
| MOR | ALTER | ALTER TABLE - 新增資料欄 | 支援 | 
| MOR | ALTER | ALTER TABLE - 新增分割區 | 支援 | 
| MOR | ALTER | ALTER TABLE - 捨棄分割區 | 支援 | 
| MOR | ALTER | ALTER TABLE - 復原分割區 | 支援 | 
| MOR | ALTER | 修復資料表同步分割區 | 支援 | 
| DROP | DROP | DROP TABLE | 支援 | 
| MOR | DROP | DROP TABLE - PURGE | 支援 | 
| CREATE | CREATE | CREATE TABLE - 受管 | 支援 | 
| MOR | CREATE | 建立資料表 - 分割區依據 | 支援 | 
| MOR | CREATE | 如果不存在，則建立資料表 | 支援 | 
| MOR | CREATE | CREATE TABLE LIKE | 支援 | 
| MOR | CREATE | CREATE TABLE AS SELECT | 支援 | 
| CREATE | CREATE | 使用 LOCATION 建立資料表 - 外部資料表 | 不支援 | 
| DATAFRAME(UPSERT) | DATAFRAME(UPSERT) | saveAsTable.Overwrite | 支援 | 
| MOR | DATAFRAME(UPSERT) | saveAsTable.Append | 不支援 | 
| MOR | DATAFRAME(UPSERT) | saveAsTable.Ignore | 支援 | 
| MOR | DATAFRAME(UPSERT) | saveAsTable.ErrorIfExists | 支援 | 
| MOR | DATAFRAME(UPSERT) | saveAsTable - 外部資料表 （路徑） | 不支援 | 
| MOR | DATAFRAME(UPSERT) | save(path) - DF v1 | 不支援 | 
| DATAFRAME（刪除） | DATAFRAME（刪除） | saveAsTable.Append | 不支援 | 
| MOR | DATAFRAME（刪除） | saveAsTable - 外部資料表 （路徑） | 不支援 | 
| MOR | DATAFRAME（刪除） | save(path) - DF v1 | 不支援 | 
| DATAFRAME(BULK\_INSERT) | DATAFRAME(BULK\_INSERT) | saveAsTable.Overwrite | 支援 | 
| MOR | DATAFRAME(BULK\_INSERT) | saveAsTable.Append | 不支援 | 
| MOR | DATAFRAME(BULK\_INSERT) | saveAsTable.Ignore | 支援 | 
| MOR | DATAFRAME(BULK\_INSERT) | saveAsTable.ErrorIfExists | 支援 | 
| MOR | DATAFRAME(BULK\_INSERT) | saveAsTable - 外部資料表 （路徑） | 不支援 | 
| MOR | DATAFRAME(BULK\_INSERT) | save(path) - DF v1 | 不支援 | 