

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# EMR 文件系统 (EMRFS)
<a name="emr-fs"></a>

**注意**  
从 EMR 7.10.0 版本开始，S3A 文件系统已取代 EMRFS 成为默认 EMR S3 连接器。

EMR 文件系统（EMRFS）是 HDFS 的实现，所有 Amazon EMR 集群将其用于直接从 Amazon EMR 读取常规文件并将其写入 Amazon S3。EMRFS 使您能够方便地将持久性数据存储在 Amazon S3 中以便用于 Hadoop，同时它还提供了数据加密等功能。

数据加密可让您对由 EMRFS 写入 Amazon S3 的对象进行加密，并且还允许 EMRFS 处理 Amazon S3 中的加密对象。如果您使用的是 Amazon EMR 发行版 4.8.0 或更高版本，则可使用安全配置设置 Amazon S3 中 EMRFS 对象的加密以及其他加密设置。有关更多信息，请参阅[加密选项](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-data-encryption-options)。如果您使用的是 Amazon EMR 的早期发行版，则可以手动配置加密设置。有关更多信息，请参阅 [使用 EMRFS 属性指定 Amazon S3 加密](emr-emrfs-encryption.md)。

Amazon S3 在 AWS 区域为所有 GET、PUT 和 LIST 操作提供了强大的读写后编写一致性。这意味着您使用 EMRFS 编写的内容就是从 Amazon S3 中读取的内容，对性能没有影响。有关更多信息，请参阅 [Amazon S3 数据一致性模型](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html#ConsistencyModel)。

在使用 Amazon EMR 发行版 5.10.0 或更高版本时，可以根据集群用户、组或 EMRFS 数据在 Amazon S3 中的位置，使用不同的 IAM 角色来处理 EMRFS 对 Amazon S3 的请求。有关更多信息，请参阅[为处理 EMRFS 对 Amazon S3 的请求配置 IAM 角色](https://docs.aws.amazon.com//emr/latest/ManagementGuide/emr-emrfs-iam-roles)。

**警告**  
在为运行 Apache Spark 任务的 Amazon EMR 集群启用推测执行之前，请查看以下信息。  
EMRFS 包括 EMRFS S3 优化的提交器，该 OutputCommitter 实现针对使用 EMRFS 时将文件写入 Amazon S3 进行了优化。如果您对将数据写入 Amazon S3 的应用程序启用 Apache Spark 推测执行功能，并且不使用经 EMRFS S3 优化的提交程序，则可能会遇到 [SPARK-10063](https://issues.apache.org/jira/browse/SPARK-10063) 中描述的数据正确性问题。如果您使用的是低于 Amazon EMR 5.19 版本的 Amazon EMR 版本，或者正在使用 ORC 和 CSV 等格式将文件写入 Amazon S3，则会发生该情况。EMRFS S3 优化的提交者不支持这些格式。有关使用经 EMRFS S3 优化的提交程序的完整要求列表，请参阅[经 EMRFS S3 优化的提交程序的要求](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-spark-committer-reqs.html)。  
当经 EMRFS S3 优化的提交程序不受支持时（例如在写入以下内容时），通常使用 EMRFS 直接写入：  
Parquet 以外的输出格式（例如 ORC 或文本）。
使用 Spark RDD API 的 Hadoop 文件。
使用 Hive SerDe 的实木复合地板。请参阅 [Hive 元存储 Parquet 表转换](https://spark.apache.org/docs/latest/sql-data-sources-parquet.html#hive-metastore-parquet-table-conversion)。
以下情形不使用 EMRFS 直接写入  
启用经 EMRFS S3 优化的提交程序时 请查看[经 EMRFS S3 优化的提交程序的要求](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-spark-committer-reqs.html)。
在 partitionOverwriteMode 设置为动态的情况下写入动态分区时。
写入自定义分区位置（例如不符合 Hive 默认分区位置约定的位置）时。
使用 EMRFS 以外的文件系统（例如写入 HDFS 或使用 S3A 文件系统）时。
要确定您的应用程序是否在 Amazon EMR 5.14.0 或更高版本中使用了直接写入，请启用 Spark INFO 日志记录。如果 Spark 驱动程序日志或 Spark 执行程序容器日志中，存在包含文本“Direct Write: ENABLED”的日志行，则 Spark 应用程序会使用直接写入的方式进行写入。  
默认情况下，Amaz `OFF` EMRclusters on 开启了推测执行功能。如果以下两个条件都为真，我们强烈建议您不要启用推测执行：  
您正将数据写入 Amazon S3。
数据以 Apache Parque 以外的格式写入，或者以 Apache Parquet 格式写入但不使用经 EMRFS S3 优化的提交程序。
如果您启用 Spark 推测执行并使用 EMRFS 直接写入，将数据写入 Amazon S3，您可能会遇到间歇性数据丢失问题。将数据写入 HDFS，或使用经 EMRFS S3 优化的提交程序以 Parquet 格式写入数据时，Amazon EMR 不使用直接写入，也不会发生此问题。  
如果您需要以使用 EMRFS 直接写入的格式从 Spark 将数据写入 Amazon S3，并使用推测执行，我们建议您写入 HDFS，然后使用 S3DistCP 将输出文件传输到 Amazon S3。

**Topics**
+ [

# 一致视图
](emr-plan-consistent-view.md)
+ [

# 授予对 Amazon S3 中的 EMRFS 数据的访问权
](emr-plan-credentialsprovider.md)
+ [

# 管理默认终 AWS Security Token Service 端节点
](emr-emrfs-sts-endpoint.md)
+ [

# 使用 EMRFS 属性指定 Amazon S3 加密
](emr-emrfs-encryption.md)

# 一致视图
<a name="emr-plan-consistent-view"></a>

**警告**  
2023 年 6 月 1 日，EMRFS 一致视图将终止对未来 Amazon EMR 发行版的标准支持。EMRFS 一致视图将继续支持现有发行版。

随着 2020 年 12 月 1 日发布的 Amazon S3 强 read-after-write一致性版本，您不再需要在亚马逊 EMR 集群中使用 EMRFS 一致视图 (EMRFS CV)。EMRFS CV 是一项可选功能，它允许 Amazon EMR 集群检查 Amazon S3 对象的列表和 read-after-write一致性。当您创建集群并打开 EMRFS CV 时，Amazon EMR 会创建一个 Amazon DynamoDB 数据库来存储用于跟踪 S3 对象列表和一致性的对象元数据。 read-after-write现在，您可以关闭 EMRFS CV 并删除它使用的 DynamoDB 数据库，这样就不会产生额外费用。以下过程说明了如何检查、关闭 CV 功能以及删除该功能使用的 DynamoDB 数据库。<a name="enable-emr-fs-console"></a>

**检查您是否在使用 EMRFS CV 功能**

1. 导航到 **Configuration**（配置）选项卡。如果您的集群具有以下配置，它将使用 EMRFS CV。

   ```
   Classification=emrfs-site,Property=fs.s3.consistent,Value=true
   ```

1. 或者，也可以使用 [`describe-cluster`API AWS CLI](https://docs.aws.amazon.com/cli/latest/reference/emr/describe-cluster.html) 来描述您的集群。如果输出包含 `fs.s3.consistent: true`，则您的集群使用 EMRFS CV。

**在您的 Amazon EMR 集群上关闭 EMRFS CV**

要关闭 EMRFS CV 功能，请使用以下三个选项之一。在将这些选项应用到生产环境之前，应先在测试环境中测试它们。

1. 

**停止现有集群并启动没有 EMRFS CV 选项的新集群。**

   1. 在停止集群之前，请务必备份数据并通知用户。

   1. 要停止集群，请按照[终止集群](https://docs.aws.amazon.com/emr/latest/ManagementGuide/UsingEMR_TerminateJobFlow.html)中的说明操作。

   1. 如果您使用 Amazon EMR 控制台创建新集群，请导航到 **Advanced Options**（高级选项）。在 **Edit software settings**（编辑软件设置）部分中，取消选中该选项以打开 EMRFS CV。如果 **EMRFS consistent view**（EMRFS 一致视图）复选框可用，请保持其未选中。

   1. 如果您使用使用 AWS CLI [`create-cluster`API](https://docs.aws.amazon.com/cli/latest/reference/emr/create-cluster.html) 创建新集群，请不要使用该`--emrfs`选项，该选项会启用 EMRFS CV。

   1. 如果您使用 SDK 或 CloudFormation 创建新集群，请不要使用配置[一致视图](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emrfs-configure-consistent-view.html)中列出的任何配置。

1. 

**克隆集群并删除 EMRFS CV**

   1. 在 Amazon EMR 控制台中，选择使用 EMRFS CV 的集群。

   1. 在 **Cluster Details**（集群详细信息）页面顶部，选择 **Clone**（克隆）。

   1. 选择 **Previous**（上一步）并导航至 **Step 1: Software and Steps**（步骤 1：软件和步骤）。

   1. 在 **Edit software settings**（编辑软件设置）中，删除 EMRFS CV。在 **Edit configuration**（编辑配置）椎间盘每个。删除 `emrfs-site` 分类中的以下配置。如果您要从 S3 存储桶加载 JSON，则必须修改您的 S3 对象。

      ```
      [
      	{"classification":
      		"emrfs-site",
      		"properties": {
      			"fs.s3.consistent.retryPeriodSeconds":"10",
      			"fs.s3.consistent":"true",
      			"fs.s3.consistent.retryCount":"5",
      			"fs.s3.consistent.metadata.tableName":"EmrFSMetadata"
      		}
      	}
      ]
      ```

1. 

**从使用实例组的集群中删除 EMRFS CV**

   1. 使用以下命令检查是否有一个 EMR 集群使用与 EMRFS CV 关联的 DynamoDB 表，或者是否有多个集群共享该表。表名称在 `fs.s3.consistent.metadata.tableName` 中指定，如 [Configure consistent view](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emrfs-configure-consistent-view.html)（配置一致视图）中所述。EMRFS CV 使用的默认表名称为 `EmrFSMetadata`。

      ```
      aws emr describe-cluster --cluster-id j-XXXXX | grep fs.s3.consistent.metadata.tableName
      ```

   1. 如果您的集群未与其他集群共享您的 DynamoDB 数据库，请使用以下命令重新配置集群并停用 EMRFS CV。有关更多信息，请参阅[重新配置正在运行的集群中的实例组](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-configure-apps-running-cluster.html)。

      ```
      aws emr modify-instance-groups --cli-input-json file://disable-emrfs-1.json
      ```

      此命令打开要修改的文件。请使用以下配置修改此文件。

      ```
      {
      	"ClusterId": "j-xxxx",
      	"InstanceGroups": [
      		{
      			"InstanceGroupId": "ig-xxxx",
      			"Configurations": [
      				{
      					"Classification": "emrfs-site",
      					"Properties": {
      						"fs.s3.consistent": "false"
      					},
      					"Configurations": []
      				}
      			]
      		}
      	]
      }
      ```

   1. 如果您的集群与其他集群共享 DynamoDB 表，请在没有集群修改共享 S3 位置中的任何对象时关闭所有集群上的 EMRFS CV。

**删除与 EMRFS CV 关联的 Amazon DynamoDB 资源**

从 Amazon EMR 集群中删除 EMRFS CV 后，请删除与 EMRFS CV 关联的 DynamoDB 资源。在您执行此操作之前，您将继续承担与 EMRFS CV 相关的 DynamoDB 费用。

1. 检查您的 DynamoDB 表的 CloudWatch 指标，并确认该表未被任何集群使用。

1. 删除 DynamoDB 表。

   ```
   aws dynamodb delete-table --table-name <your-table-name>
   ```

**删除与 EMRFS CV 关联的 Amazon SQS 资源**

1. 如果您将集群配置为向 Amazon SQS 推送不一致通知，则可以删除所有 SQS 队列。

1. 查找 `fs.s3.consistent.notification.SQS.queueName` 中指定的 Amazon SQS 队列名称，如 [Configure consistent view](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emrfs-configure-consistent-view.html)（配置一致视图）中所述。默认队列名称格式为 `EMRFS-Inconsistency-<j-cluster ID>`。

   ```
   aws sqs list-queues | grep ‘EMRFS-Inconsistency’
   aws sqs delete-queue –queue-url <your-queue-url>
   ```

**停止使用 EMRFS CLI**
+ [EMRFS CLI](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emrfs-cli-reference.html) 管理 EMRFS CV 生成的元数据。随着对 EMRFS CV 的标准支持在 Amazon EMR 的未来版本中即将结束，对 EMRFS CLI 的支持也将结束。

**Topics**
+ [

# 启用一致视图
](enable-consistent-view.md)
+ [

# 了解 EMRFS 一致视图如何跟踪 Amazon S3 中的对象
](emrfs-files-tracked.md)
+ [

# 重试逻辑
](emrfs-retry-logic.md)
+ [

# EMRFS 一致视图元数据
](emrfs-metadata.md)
+ [

# 为 CloudWatch 和 Amazon SQS 配置一致性通知
](emrfs-configure-sqs-cw.md)
+ [

# 配置一致视图
](emrfs-configure-consistent-view.md)
+ [

# EMRFS CLI 命令参考
](emrfs-cli-reference.md)

# 启用一致视图
<a name="enable-consistent-view"></a>

您可以使用、或配置分类为 EMRFS 启用 Amazon S3 服务器端加密或一致视图。 AWS 管理控制台 AWS CLI`emrfs-site`<a name="enable-emr-fs-console"></a>

**使用控制台配置一致视图**

1. 导航到 Amazon EMR 新控制台，然后从侧面导航栏中选择**切换到旧控制台**。有关切换到旧控制台后预期情况的更多信息，请参阅 [Using the old console](https://docs.aws.amazon.com/emr/latest/ManagementGuide/whats-new-in-console.html#console-opt-in)。

1. 依次选择 **Create cluster (创建集群)**、**Go to advanced options (转到高级选项)**。

1. 选择 **Step 1: Software and Steps (步骤 1: 软件和步骤)** 和 **Step 2: Hardware (步骤 2: 硬件)** 的设置。

1. 对于 **Step 3: General Cluster Settings (步骤 3: 常规集群设置)**，在 **Additional Options (附加选项)** 下选择 **EMRFS consistent view (EMRFS 一致视图)**。

1. 对于 **EMRFS Metadata store (EMRFS 元数据存储)**，键入您的元数据存储的名称。默认值为 **EmrFSMetadata**。如果 Emr FSMetadata 表不存在，则会在 DynamoDB 中为您创建该表。
**注意**  
集群终止时，Amazon EMR 不会自动从 DynamoDB 中删除 EMRFS 元数据。

1. 对于 **Number of retries (重试次数)**，键入一个整数值。如果检测到不一致，EMRFS 会尝试进行此次数的 Amazon S3 调用。默认值为 **5**。

1. 对于 **Retry period (in seconds) (重试期间 (秒))**，键入一个整数值。这是 EMRFS 在重试尝试之间等待的时间量。默认值为 **10**。
**注意**  
后续重试会使用指数退避。

**要启动启用一致视图的集群，请使用 AWS CLI**

我们建议您安装当前版本的 AWS CLI。要下载最新版本，请参阅[https://aws.amazon.com/cli/](https://aws.amazon.com/cli/)。
+ 
**注意**  
为了便于读取，包含 Linux 行继续符（\$1）。它们可以通过 Linux 命令删除或使用。对于 Windows，请将它们删除或替换为脱字号（^）。

  ```
  1. aws emr create-cluster --instance-type m5.xlarge --instance-count 3 --emrfs Consistent=true \
  2. --release-label emr-7.12.0 --ec2-attributes KeyName=myKey
  ```

**要检查一致视图是否已启用，请使用 AWS 管理控制台**
+ 要在控制台中检查是否启用了一致视图，请导航到 **Cluster List (集群列表)**，然后选择您的集群名称以查看 **Cluster Details (集群详细信息)**。“EMRFS consistent view (EMRFS 一致视图)”字段的值为 `Enabled` (已启用) 或 `Disabled` (已禁用)。

**通过检查 `emrfs-site.xml` 文件查看是否启用了一致视图**
+ 您可以通过检查集群主节点上的 `emrfs-site.xml` 配置文件，来查看是否启用了一致性。如果 `fs.s3.consistent` 的布尔值设置为 `true`，则表示已为涉及 Amazon S3 的文件系统操作启用了一致视图。

# 了解 EMRFS 一致视图如何跟踪 Amazon S3 中的对象
<a name="emrfs-files-tracked"></a>

EMRFS 通过向 EMRFS 元数据添加有关 Amazon S3 中对象的信息，创建这些对象的一致视图。EMRFS 会在以下情况下向其元数据添加这些列表：
+  EMRFS 在 Amazon EMR 任务执行期间写入对象。
+  使用 EMRFS CLI 将对象与 EMRFS 元数据同步或导入到元数据。

EMRFS 读取的对象不会自动添加到元数据。当 EMRFS 删除对象时，一个具有已删除状态的列表仍保留在元数据中，直到使用 EMRFS CLI 清除该列表。要了解有关 CLI 的更多信息，请参阅[EMRFS CLI 命令参考](emrfs-cli-reference.md)。有关在 EMRFS 元数据中清除列表的更多信息，请参阅[EMRFS 一致视图元数据](emrfs-metadata.md)。

对于每个 Amazon S3 操作，EMRFS 都会在元数据中检查有关一致视图中的对象集的信息。如果 EMRFS 在其中一个操作执行过程中发现 Amazon S3 是不一致的，则会根据 `emrfs-site` 配置属性中定义的参数重试该操作。在 EMRFS 用尽重试次数后，它会引发 `ConsistencyException` 或记录异常并继续执行工作流程。有关重试逻辑的更多信息，请参阅[重试逻辑](emrfs-retry-logic.md)。您可以在日志中找到 `ConsistencyExceptions`，例如：
+  listStatus: No Amazon S3 object for metadata item `/S3_bucket/dir/object`
+  getFileStatus: 密钥存在`dir/file`于元数据中，但不存在于 Amazon S3 中

如果直接从 Amazon S3 中删除 EMRFS 一致视图跟踪的对象，则 EMRFS 会将该对象视为不一致，这是因为 Amazon S3 中显示它仍存在于元数据中。如果您的元数据与 EMRFS 在 Amazon S3 中跟踪的对象不同步，则可以使用 EMRFS CLI 的 **sync** 子命令重置元数据以使其反映 Amazon S3 的情况。要了解元数据与 Amazon S3 之间的差异，请使用 **diff**。最后，EMRFS 只有在元数据中引用的对象的一致视图；相同 Amazon S3 路径中可能存在未进行跟踪的其它对象。EMRFS 在列出 Amazon S3 路径中的对象时，将返回在元数据中进行跟踪的对象与该 Amazon S3 路径中的对象的超集。

# 重试逻辑
<a name="emrfs-retry-logic"></a>

EMRFS 将尝试针对其元数据中跟踪的对象验证列表一致性，并重试特定次数。默认值为 5。如果超过重试次数，则发起任务会返回错误，除非 `fs.s3.consistent.throwExceptionOnInconsistency` 设置为 `false` (此时仅将跟踪的对象记录为不一致)。EMRFS 默认使用指数退避重试策略，但您也可以将它设置为固定策略。用户还可能希望在重试特定一段时间之后继续任务的其余操作，而不是引发异常。可通过将 `fs.s3.consistent.throwExceptionOnInconsistency` 设置为 `false`，将 `fs.s3.consistent.retryPolicyType` 设置为 `fixed`，将 `fs.s3.consistent.retryPeriodSeconds` 设置为所需的值，来实现此目的。以下示例创建一个启用了一致性的集群，将记录不一致并设置 10 秒的固定重试间隔：

**Example 将重试期间设置为固定量**  

```
aws emr create-cluster --release-label emr-7.12.0 \
--instance-type m5.xlarge --instance-count 1 \
--emrfs Consistent=true,Args=[fs.s3.consistent.throwExceptionOnInconsistency=false, fs.s3.consistent.retryPolicyType=fixed,fs.s3.consistent.retryPeriodSeconds=10] --ec2-attributes KeyName=myKey
```

**注意**  
为了便于读取，包含 Linux 行继续符（\$1）。它们可以通过 Linux 命令删除或使用。对于 Windows，请将它们删除或替换为脱字号（^）。

有关更多信息，请参阅[一致视图](emr-plan-consistent-view.md)。

## 为 IMDS 的 EMRFS 配置获取区域调用
<a name="randomized-exponential-backoff-retry"></a>

EMRFS 依靠 IMDS（实例元数据服务）来获取实例区域和亚马逊 S3、DynamoDB 或终端节点。 AWS KMS 但是，IMDS 对可以处理的请求数量有限制，以及超过限制失败的请求。此 IMDS 限制可能会导致 EMRFS 初始化失败，查询或命令失败。您可以使用以下随机的指数回退重试机制和 emrfs-site.xml 中的回退区域配置属性来解决所有重试都失败的情况。

```
<property>
    <name>fs.s3.region.retryCount</name>
    <value>3</value>
    <description>
    Maximum retries that would be attempted to get AWS region.
    </description>
</property>
<property>
    <name>fs.s3.region.retryPeriodSeconds</name>
    <value>3</value>
    <description>
    Base sleep time in second for each get-region retry.
    </description>
</property>
<property>
    <name>fs.s3.region.fallback</name>
    <value>us-east-1</value>
    <description>
    Fallback to this region after maximum retries for getting AWS region have been reached.
    </description>
</property>
```

# EMRFS 一致视图元数据
<a name="emrfs-metadata"></a>

EMRFS 一致视图使用 DynamoDB 表跟踪 Amazon S3 中已与 EMRFS 同步或已由 EMRFS 创建的对象，从而跟踪一致性。元数据用于跟踪所有操作 (读取、写入、更新和复制)。其中不存储任何实际内容。此元数据用于验证从 Amazon S3 接收的对象或元数据是否与预期内容匹配。此确认使 EMRFS 能够检查 EMRFS 写入 Amazon S3 的新对象或与 EMRFS 同步的对象的列表 read-after-write一致性和一致性。多个集群可共享相同的元数据。

**如何向元数据添加条目**  
您可以使用 `sync` 或 `import` 子命令向元数据添加条目。`sync` 反映路径中 Amazon S3 对象的状态，而 `import` 用于向元数据添加新条目。有关更多信息，请参阅[EMRFS CLI 命令参考](emrfs-cli-reference.md)。

**如何检查元数据与 Amazon S3 中的对象之间的差异**  
要检查元数据与 Amazon S3 之间的差异，请使用 EMRFS CLI 的 `diff` 子命令。有关更多信息，请参阅[EMRFS CLI 命令参考](emrfs-cli-reference.md)。

**如何了解元数据操作是否受限制**  
EMRFS 针对元数据的读取和写入操作，分别设置了默认 500 和 100 个单位的吞吐量容量限制。大量对象或存储桶可能会导致操作超过此容量，此时 DynamoDB 会对它们进行限制。例如，如果您执行的操作超过这些容量限制，则应用程序可能会导致 EMRFS 引发 `ProvisionedThroughputExceededException`。施加节流时，EMRFS CLI 工具将尝试使用[指数回退](https://docs.aws.amazon.com/general/latest/gr/api-retries.html)重试对 DynamoDB 表进行写入操作，直到操作完成，或是达到将对象从 Amazon EMR 写入到 Amazon S3 的最大重试次数值。

您可以配置自己的吞吐容量限制。但是，对于读取和写入操作，DynamoDB 有严格的分区限制，分别为每秒 3000 个读取容量单位 RCUs WCUs () 和 1000 个写入容量单位 ()。为避免限制导致`sync`故障，我们建议您将读取操作的吞吐量限制在 3000 RCUs 以下，将写入操作的吞吐量限制在 1000 以下。 WCUs有关设置自定义吞吐容量限制的说明，请参阅 [配置一致视图](emrfs-configure-consistent-view.md)。

您还可以在 DynamoDB 控制台中查看 EMRFS 元数据的亚马逊 CloudWatch 指标，您可以在其中查看受限制的读取和写入请求数量。如果受限制的请求数不为零值，则增加为读取或写入操作分配的吞吐量容量可能会使应用程序受益。如果您发现操作长时间接近分配的最大读取或写入吞吐量容量，则这样做也可能会获得性能好处。

**重要 EMRFS 操作的吞吐量特征**  
读取和写入操作的默认值分别为 400 和 100 个吞吐量容量单位。您可以通过以下性能特征了解特定操作所需的吞吐量。这些测试是使用单节点 `m3.large` 集群执行的。所有操作都是单线程执行。特定应用程序特征会对性能造成很大影响，可能需要通过实验来优化文件系统操作。


| 操作  | 平均值 read-per-second  | 平均值 write-per-second  | 
| --- | --- | --- | 
| create（对象） | 26.79 |  6.70 | 
| delete（对象） | 10.79 |  10.79 | 
| delete（包含 1000 个对象的目录） | 21.79 | 338.40  | 
|  getFileStatus（对象） | 34.70 | 0  | 
| getFileStatus（目录） | 19.96 | 0 | 
| listStatus（包含 1 个对象的目录） | 43.31 | 0 | 
| listStatus（包含 10 个对象的目录） | 44.34 | 0 | 
| listStatus（包含 100 个对象的目录） | 84.44 | 0 | 
| listStatus（包含 1000 个对象的目录） | 308.81 | 0 | 
| listStatus（包含 10000 个对象的目录） | 416.05 | 0 | 
| listStatus（包含 100000 个对象的目录） | 823.56 | 0 | 
| listStatus（包含 1000000 个对象的目录） | 882.36 | 0 | 
| mkdir（持续 120 秒）  | 24.18 | 4.03 | 
| mkdir | 12.59 | 0 | 
| rename（对象） | 19.53 | 4.88 | 
| rename（包含 1000 个对象的目录） | 23.22 | 339.34 | 

**提交从元数据存储中清除旧数据的步骤**  
用户可能希望在基于 DynamoDB 的元数据中删除特定条目。这样可以帮助降低与表关联的存储成本。用户可以使用 EMRFS CLI `delete` 子命令，以手动或编程方式清除特定条目。但是，如果从元数据中删除条目，则 EMRFS 不再进行任何一致性检查。

可以通过向集群提交在 EMRFS CLI 中执行命令的最终步骤，以编程方式在任务完成之后进行清除。例如，键入以下命令可向集群提交删除两天之前的所有条目的步骤。

```
aws emr add-steps --cluster-id j-2AL4XXXXXX5T9 --steps Name="emrfsCLI",Jar="command-runner.jar",Args=["emrfs","delete","--time","2","--time-unit","days"]
{
    "StepIds": [
        "s-B12345678902"
    ]
}
```

使用返回的 StepId 值在日志中查看操作结果。

# 为 CloudWatch 和 Amazon SQS 配置一致性通知
<a name="emrfs-configure-sqs-cw"></a>

您可以在 EMRFS 中启用 CloudWatch 指标和 Amazon SQS 消息，以解决 Amazon S3 最终一致性问题。

**CloudWatch**  
启用 CloudWatch 指标后，由于 Amazon S3 的最终**一致性**，每次 `FileSystem` API 调用失败时，都会推送名为 “不一致” 的指标。

**查看 Amazon S3 最终一致性问题的 CloudWatch 指标**

要在 CloudWatch 控制台中查看**不一致**指标，请选择 EMRFS 指标，然后选择 **JobFlowId**/**指标**名称对。例如：`j-162XXXXXXM2CU ListStatus`、`j-162XXXXXXM2CU GetFileStatus` 等。

1. 打开 CloudWatch 控制台，网址为[https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/)。

1. 在 **Dashboard (控制面板)** 的 **Metrics (指标)** 部分中，选择 **EMRFS**。

1. 在 **Job Flow Metrics** 窗格中，选择一个或多个 **JobFlowId**/**指标名称**对。将在下面的窗口中显示指标的图形表示。

**Amazon SQS**  
启用 Amazon SQS 通知后，系统会在初始化 EMRFS 时创建一个名为 `EMRFS-Inconsistency-<jobFlowId>` 的 Amazon SQS 队列。当 `FileSystem` API 调用因 Amazon S3 最终一致性问题而失败时，系统会将 Amazon SQS 消息推送到该队列中。该消息包含诸如 API JobFlowId、不一致路径列表、堆栈跟踪等信息。可以使用 Amazon SQS 控制台或 EMRFS `read-sqs` 命令读取消息。

**管理针对 Amazon S3 最终一致性问题的 Amazon SQS 消息**

可使用 EMRFS CLI 读取针对 Amazon S3 最终一致性问题的 Amazon SQS 消息。要从 EMRFS Amazon SQS 队列读取消息，请键入 `read-sqs` 命令并为生成的输出文件在主节点的本地文件系统上指定输出位置。

还可以使用 `delete-sqs` 命令删除 EMRFS Amazon SQS 队列。

1. 要从 Amazon SQS 队列读取消息，请键入以下命令。*queuename*替换为您配置的 Amazon SQS 队列的名称，并*/path/filename*替换为输出文件的路径：

   ```
   emrfs read-sqs --queue-name queuename --output-file /path/filename
   ```

   例如，要从默认队列读取和输出 Amazon SQS 消息，请键入：

   ```
   emrfs read-sqs --queue-name EMRFS-Inconsistency-j-162XXXXXXM2CU --output-file /path/filename
   ```
**注意**  
还可以分别使用 `-q` 和 `-o` 快捷方式代替 `--queue-name` 和 `--output-file`。

1. 要删除 Amazon SQS 队列，请键入以下命令：

   ```
   emrfs delete-sqs --queue-name queuename
   ```

   例如，要删除默认队列，请键入：

   ```
   emrfs delete-sqs --queue-name EMRFS-Inconsistency-j-162XXXXXXM2CU
   ```
**注意**  
还可以使用 `-q` 快捷方式代替 `--queue-name`。

# 配置一致视图
<a name="emrfs-configure-consistent-view"></a>

您可以为一致视图配置其它设置，方法是使用 `emrfs-site` 属性的配置属性来提供这些设置。例如，您可以选择其它的默认 DynamoDB 吞吐量（方式是将以下参数提供给 CLI `--emrfs` 选项，使用 emrfs-site 配置分类（仅限 Amazon EMR 发行版 4.x 及更高版本））或引导操作来配置主节点上的 emrfs-site.xml 文件：

**Example 在集群启动时更改默认元数据读取和写入值**  

```
aws emr create-cluster --release-label emr-7.12.0 --instance-type m5.xlarge \
--emrfs Consistent=true,Args=[fs.s3.consistent.metadata.read.capacity=600,\
fs.s3.consistent.metadata.write.capacity=300] --ec2-attributes KeyName=myKey
```

或者，使用下面的配置文件并将其保存到本地或 Amazon S3 中：

```
[
    {
      "Classification": "emrfs-site",
      "Properties": {
        "fs.s3.consistent.metadata.read.capacity": "600",
        "fs.s3.consistent.metadata.write.capacity": "300"
      }
    }
 ]
```

按照下面的语法使用您创建的配置：

```
aws emr create-cluster --release-label emr-7.12.0 --applications Name=Hive \
--instance-type m5.xlarge --instance-count 2 --configurations file://./myConfig.json
```

**注意**  
为了便于读取，包含 Linux 行继续符（\$1）。它们可以通过 Linux 命令删除或使用。对于 Windows，请将它们删除或替换为脱字号（^）。

可以使用配置或 AWS CLI `--emrfs`参数设置以下选项。有关这些实参的信息，请参阅 [AWS CLI 命令参考](https://docs.aws.amazon.com/cli/latest/reference/)。


**一致视图的 `emrfs-site.xml` 属性**  

| 属性  | 默认 值 | 说明  | 
| --- | --- | --- | 
| fs.s3.consistent | false |  设置为 **true** 时，此属性会将 EMRFS 配置为使用 DynamoDB 提供一致性。  | 
| fs.s3.consistent.retryPolicyType | exponential | 此属性标识针对一致性问题进行重试时要使用的策略。选项包括：exponential、fixed 和 none。 | 
| fs.s3.consistent.retryPeriodSeconds | 1 | 此属性设置两次一致性重试尝试之间等待的时间长度。 | 
| fs.s3.consistent.retryCount | 10 | 此属性设置检测到不一致时的最大重试次数。 | 
| fs.s3.consistent.throwExceptionOnInconsistency | true | 此属性确定是引发还是记录一致性异常。设置为 true 时，会引发 ConsistencyException。 | 
| fs.s3.consistent.metadata.autoCreate | true | 设置为 true 时，此属性会启用元数据表的自动创建。 | 
| fs.s3.consistent.metadata.etag.verification.enabled | true | 对于 Amazon EMR 5.29.0，此属性已默认启用。启用后，EMRFS 将使用 S3 ETags 来验证正在读取的对象是否为最新的可用版本。此功能对于 S3 上的文件被覆盖，同时保留相同名称的 read-after-update用例非常有用。此 ETag 验证功能目前不适用于 S3 Select。 | 
| fs.s3.consistent.metadata.tableName | EmrFSMetadata | 此属性指定 DynamoDB 中元数据表的名称。 | 
| fs.s3.consistent.metadata.read.capacity | 500 | 此属性指定创建元数据表时要配置的 DynamoDB 读取容量。 | 
| fs.s3.consistent.metadata.write.capacity | 100 | 此属性指定创建元数据表时要配置的 DynamoDB 写入容量。 | 
| fs.s3.consistent.fastList | true | 设置为 true 时，此属性会使用多个线程列出目录（需要时）。必须启用一致性才能使用此属性。 | 
| fs.s3.consistent.fastList.prefetchMetadata | false | 设置为 true 时，此属性会为包含 20000 个以上的项目的目录启用元数据预取。 | 
| fs.s3.consistent.notification.CloudWatch | false | 如果设置为true，则会为因 Amazon S3 最终一致性问题而失败的 FileSystem API 调用启用 CloudWatch 指标。 | 
| fs.s3.consistent.notification.SQS | false | 设置为 true 时，向 Amazon SQS 队列推送最终一致性通知。 | 
| fs.s3.consistent.notification.SQS.queueName | EMRFS-Inconsistency-<jobFlowId> | 通过更改此属性可以为有关 Amazon S3 最终一致性问题的消息指定您自己的 SQS 队列名称。 | 
| fs.s3.consistent.notification.SQS.customMsg | none | 通过此属性可以指定有关 Amazon S3 最终一致性问题的 SQS 消息中包含的自定义信息。如果没有为此属性指定值，则消息中的对应字段为空。 | 
| fs.s3.consistent.dynamodb.endpoint | none | 此属性允许您为一致性视图元数据指定自定义 DynamoDB 终端节点。 | 
| fs.s3.useRequesterPaysHeader | false | 当设置为true，此属性允许在启用付款人选项请求的情况下向存储桶发出Amazon S3 请求。 | 

# EMRFS CLI 命令参考
<a name="emrfs-cli-reference"></a>

默认情况下，EMRFS CLI 安装在使用 Amazon EMR 发行版 3.2.1 或更高版本创建的所有集群主节点上。您可以使用 EMRFS CLI 管理一致视图的元数据。

**注意**  
只有 VT100 终端仿真才支持该**emrfs**命令。但是，它可能适用于其它终端仿真器模式。

## emrfs 顶级命令
<a name="emrfs-top-level"></a>

**emrfs** 顶级命令支持以下结构。

```
emrfs [describe-metadata | set-metadata-capacity | delete-metadata | create-metadata | \
list-metadata-stores | diff | delete | sync | import ] [options] [arguments]
```

指定 [选项]，根据需要使用或不使用下表中描述的 [参数]。有关特定于子命令 (`describe-metadata`、`set-metadata-capacity` 等) 的 [选项]，请参阅下面的每个子命令。


**emrfs 的 [选项]**  

| 选项  | 描述  | 必填  | 
| --- | --- | --- | 
|  `-a AWS_ACCESS_KEY_ID \| --access-key AWS_ACCESS_KEY_ID`  |  用于向 Amazon S3 写入对象以及在 DynamoDB 中创建或访问元数据存储的访问密钥。 AWS 默认情况下，设置*AWS\$1ACCESS\$1KEY\$1ID*为用于创建集群的访问密钥。  |  否  | 
|  `-s AWS_SECRET_ACCESS_KEY \| --secret-key AWS_SECRET_ACCESS_KEY`  |  与您用于向 Amazon S3 写入对象以及在 DynamoDB 中创建或访问元数据存储的访问 AWS 密钥关联的密钥。默认情况下，设置*AWS\$1SECRET\$1ACCESS\$1KEY*为与用于创建集群的访问密钥关联的密钥。  |  否  | 
|  `-v \| --verbose`  |  使输出为详细模式。  |  否  | 
|  `-h \| --help`  |  通过用法语句显示 `emrfs` 命令的帮助消息。  |  否  | 

## emrfs describe-metadata 子命令
<a name="emrfs-describe-metadata"></a>


**emrfs describe-metadata 的 [选项]**  

| 选项  | 描述  | 必填  | 
| --- | --- | --- | 
|  `-m METADATA_NAME \| --metadata-name METADATA_NAME`  |  *METADATA\$1NAME*是 DynamoDB 元数据表的名称。如果未提供*METADATA\$1NAME*参数，则默认值为`EmrFSMetadata`。  |  否  | 

**Example emrfs describe-metadata 示例**  <a name="emrfs-describe-metadata"></a>
以下示例描述默认元数据表。  

```
$ emrfs describe-metadata
EmrFSMetadata
  read-capacity: 400
  write-capacity: 100
  status: ACTIVE
  approximate-item-count (6 hour delay): 12
```

## emrfs set-metadata-capacity 子命令
<a name="emrfs-set-metadata-capacity"></a>


**emrfs 的 [选项] set-metadata-capacity**  

| 选项  | 描述  | 必填  | 
| --- | --- | --- | 
|  `-m METADATA_NAME \| --metadata-name METADATA_NAME`  |  *METADATA\$1NAME*是 DynamoDB 元数据表的名称。如果未提供*METADATA\$1NAME*参数，则默认值为`EmrFSMetadata`。  |  否  | 
|  `-r READ_CAPACITY \| --read-capacity READ_CAPACITY`  |  对元数据表请求的读取吞吐容量。如果未提供*READ\$1CAPACITY*参数，则默认值为`400`。  |  否  | 
|  `-w WRITE_CAPACITY \| --write-capacity WRITE_CAPACITY`  |  对元数据表请求的写入吞吐容量。如果未提供*WRITE\$1CAPACITY*参数，则默认值为`100`。  |  否  | 

**Example emrfs 示例 set-metadata-capacity**  
以下示例将名为 `600` 的元数据表的读取吞吐容量设置为 `150`，将写入容量设置为 `EmrMetadataAlt`。  

```
$ emrfs set-metadata-capacity --metadata-name EmrMetadataAlt  --read-capacity 600 --write-capacity 150
  read-capacity: 400
  write-capacity: 100
  status: UPDATING
  approximate-item-count (6 hour delay): 0
```

## emrfs delete-metadata 子命令
<a name="emrfs-delete-metadata"></a>


**emrfs delete-metadata 的 [选项]**  

| 选项  | 描述  | 必填  | 
| --- | --- | --- | 
|  `-m METADATA_NAME \| --metadata-name METADATA_NAME`  |  *METADATA\$1NAME*是 DynamoDB 元数据表的名称。如果未提供*METADATA\$1NAME*参数，则默认值为`EmrFSMetadata`。  |  否  | 

**Example emrfs delete-metadata 示例**  
以下示例删除默认元数据表。  

```
$ emrfs delete-metadata
```

## emrfs create-metadata 子命令
<a name="emrfs-create-metadata"></a>


**emrfs create-metadata 的 [选项]**  

| 选项  | 描述  | 必填  | 
| --- | --- | --- | 
|  `-m METADATA_NAME \| --metadata-name METADATA_NAME`  |  *METADATA\$1NAME*是 DynamoDB 元数据表的名称。如果未提供*METADATA\$1NAME*参数，则默认值为`EmrFSMetadata`。  |  否  | 
|  `-r READ_CAPACITY \| --read-capacity READ_CAPACITY`  |  对元数据表请求的读取吞吐容量。如果未提供*READ\$1CAPACITY*参数，则默认值为`400`。  |  否  | 
|  `-w WRITE_CAPACITY \| --write-capacity WRITE_CAPACITY`  |  对元数据表请求的写入吞吐容量。如果未提供*WRITE\$1CAPACITY*参数，则默认值为`100`。  |  否  | 

**Example emrfs create-metadata 示例**  
以下示例创建一个名为 `EmrFSMetadataAlt` 的元数据表。  

```
$ emrfs create-metadata -m EmrFSMetadataAlt
Creating metadata: EmrFSMetadataAlt
EmrFSMetadataAlt
  read-capacity: 400
  write-capacity: 100
  status: ACTIVE
  approximate-item-count (6 hour delay): 0
```

## emrfs list-metadata-stores 子命令
<a name="emrfs-list-metadata-stores"></a>

**emrfs list-metadata-stores** 子命令没有任何 [选项]。

**Example List-metadata-stores 示例**  
以下示例列出您的元数据表。  

```
$ emrfs list-metadata-stores
  EmrFSMetadata
```

## emrfs diff 子命令
<a name="emrfs-diff"></a>


**emrfs diff 的 [选项]**  

| 选项  | 描述  | 必填  | 
| --- | --- | --- | 
|  `-m METADATA_NAME \| --metadata-name METADATA_NAME`  |  *METADATA\$1NAME*是 DynamoDB 元数据表的名称。如果未提供*METADATA\$1NAME*参数，则默认值为`EmrFSMetadata`。  |  否  | 
|  *s3://s3Path*  |  与元数据表进行比较的 Amazon S3 存储桶的路径。存储桶以递归方式同步。  |  是  | 

**Example emrfs diff 示例**  
以下示例将默认元数据表与 Amazon S3 存储桶进行比较。  

```
$ emrfs diff s3://elasticmapreduce/samples/cloudfront
BOTH | MANIFEST ONLY | S3 ONLY
DIR elasticmapreduce/samples/cloudfront
DIR elasticmapreduce/samples/cloudfront/code/
DIR elasticmapreduce/samples/cloudfront/input/
DIR elasticmapreduce/samples/cloudfront/logprocessor.jar
DIR elasticmapreduce/samples/cloudfront/input/XABCD12345678.2009-05-05-14.WxYz1234
DIR elasticmapreduce/samples/cloudfront/input/XABCD12345678.2009-05-05-15.WxYz1234
DIR elasticmapreduce/samples/cloudfront/input/XABCD12345678.2009-05-05-16.WxYz1234
DIR elasticmapreduce/samples/cloudfront/input/XABCD12345678.2009-05-05-17.WxYz1234
DIR elasticmapreduce/samples/cloudfront/input/XABCD12345678.2009-05-05-18.WxYz1234
DIR elasticmapreduce/samples/cloudfront/input/XABCD12345678.2009-05-05-19.WxYz1234
DIR elasticmapreduce/samples/cloudfront/input/XABCD12345678.2009-05-05-20.WxYz1234
DIR elasticmapreduce/samples/cloudfront/code/cloudfront-loganalyzer.tgz
```

## emrfs delete 子命令
<a name="emrfs-delete"></a>


**emrfs delete 的 [选项]**  

|  选项  |  描述  |  必填  | 
| --- | --- | --- | 
|  `-m METADATA_NAME \| --metadata-name METADATA_NAME`  |  *METADATA\$1NAME*是 DynamoDB 元数据表的名称。如果未提供*METADATA\$1NAME*参数，则默认值为`EmrFSMetadata`。  |  否  | 
|  *s3://s3Path*  |  为实现一致视图而跟踪的 Amazon S3 存储桶的路径。存储桶以递归方式同步。  |  是  | 
| -t TIME \$1 --time TIME |  过期时间 (使用时间单位参数进行解释)。将删除指定存储桶中所有早于*TIME*参数的元数据条目。  |  | 
|  `-u UNIT \| --time-unit UNIT`  |  用于解释时间参数的度量值 (纳秒、微秒、毫秒、秒、分钟、小时或天)。如果未指定参数，则默认值为 `days`。  |  | 
|  `--read-consumption READ_CONSUMPTION`  |  请求用于 **delete** 操作的可用读取吞吐量。如果未指定*READ\$1CONSUMPTION*参数，则默认值为`400`。  |  否   | 
|  `--write-consumption WRITE_CONSUMPTION`  |  请求用于 **delete** 操作的可用写入吞吐量。如果未指定*WRITE\$1CONSUMPTION*参数，则默认值为`100`。  |  否  | 

**Example emrfs delete 示例**  
以下示例从一致视图的跟踪元数据中删除一个 Amazon S3 存储桶中的所有对象。  

```
$ emrfs delete s3://elasticmapreduce/samples/cloudfront
entries deleted: 11
```

## emrfs import 子命令
<a name="emrfs-import"></a>


**for emrfs import 的 [选项]**  

| 选项  | 描述  | 必填  | 
| --- | --- | --- | 
|  `-m METADATA_NAME \| --metadata-name METADATA_NAME`  |  *METADATA\$1NAME*是 DynamoDB 元数据表的名称。如果未提供*METADATA\$1NAME*参数，则默认值为`EmrFSMetadata`。  |  否  | 
|  *s3://s3Path*  |  为实现一致视图而跟踪的 Amazon S3 存储桶的路径。存储桶以递归方式同步。  |  是  | 
|  `--read-consumption READ_CONSUMPTION`  |  请求用于 **delete** 操作的可用读取吞吐量。如果未指定*READ\$1CONSUMPTION*参数，则默认值为`400`。  |  否  | 
|  `--write-consumption WRITE_CONSUMPTION`  |  请求用于 **delete** 操作的可用写入吞吐量。如果未指定*WRITE\$1CONSUMPTION*参数，则默认值为`100`。  |  否  | 

**Example emrfs import 示例**  
以下示例随一致视图的跟踪元数据导入一个 Amazon S3 存储桶中的所有对象。忽略所有未知键。  

```
$ emrfs import s3://elasticmapreduce/samples/cloudfront
```

## emrfs sync 子命令
<a name="emrfs-sync"></a>


**emrfs sync 的 [选项]**  

| 选项  | 描述  | 必填  | 
| --- | --- | --- | 
|  `-m METADATA_NAME \| --metadata-name METADATA_NAME`  |  *METADATA\$1NAME*是 DynamoDB 元数据表的名称。如果未提供*METADATA\$1NAME*参数，则默认值为`EmrFSMetadata`。  |  否  | 
|  *s3://s3Path*  |  为实现一致视图而跟踪的 Amazon S3 存储桶的路径。存储桶以递归方式同步。  |  是  | 
|  `--read-consumption READ_CONSUMPTION`  |  请求用于 **delete** 操作的可用读取吞吐量。如果未指定*READ\$1CONSUMPTION*参数，则默认值为`400`。  |  否  | 
|  `--write-consumption WRITE_CONSUMPTION`  |  请求用于 **delete** 操作的可用写入吞吐量。如果未指定*WRITE\$1CONSUMPTION*参数，则默认值为`100`。  |  否  | 

**Example emrfs sync 命令示例**  
以下示例随一致视图的跟踪元数据导入一个 Amazon S3 存储桶中的所有对象。删除所有未知键。  

```
$ emrfs sync s3://elasticmapreduce/samples/cloudfront
Synching samples/cloudfront                                       0 added | 0 updated | 0 removed | 0 unchanged
Synching samples/cloudfront/code/                                 1 added | 0 updated | 0 removed | 0 unchanged
Synching samples/cloudfront/                                      2 added | 0 updated | 0 removed | 0 unchanged
Synching samples/cloudfront/input/                                9 added | 0 updated | 0 removed | 0 unchanged
Done synching s3://elasticmapreduce/samples/cloudfront            9 added | 0 updated | 1 removed | 0 unchanged
creating 3 folder key(s)
folders written: 3
```

## emrfs read-sqs 子命令
<a name="emrfs-read-sqs"></a>


**emrfs read-sqs 的 [选项]**  

| 选项  | 描述  | 必填  | 
| --- | --- | --- | 
|  `-q QUEUE_NAME \| --queue-name QUEUE_NAME`  |  *QUEUE\$1NAME*是在中配置的 Amazon SQS 队列的名称。`emrfs-site.xml`默认值为 **EMRFS-Inconsistency-<jobFlowId>**。  |  是  | 
|  `-o OUTPUT_FILE \| --output-file OUTPUT_FILE`  |  *OUTPUT\$1FILE*是主节点本地文件系统上输出文件的路径。从队列读取的消息会写入此文件。  |  是  | 

## emrfs delete-sqs 子命令
<a name="emrfs-delete-sqs"></a>


**emrfs delete-sqs 的 [选项]**  

| 选项  | 描述  | 必填  | 
| --- | --- | --- | 
|  `-q QUEUE_NAME \| --queue-name QUEUE_NAME`  |  *QUEUE\$1NAME*是在中配置的 Amazon SQS 队列的名称。`emrfs-site.xml`默认值为 **EMRFS-Inconsistency-<jobFlowId>**。  |  是  | 

## 以步骤形式提交 EMRFS CLI 命令
<a name="emrfs-submit-steps-as-cli"></a>

以下示例说明如何在主节点上使用该`emrfs`实用程序，方法是利用 AWS CLI 或 API 和`command-runner.jar`，将`emrfs`命令作为一个步骤运行。该示例使用 适用于 Python (Boto3) 的 AWS SDK 向集群添加一个步骤，该步骤将 Amazon S3 存储桶中的对象添加到默认 EMRFS 元数据表中。

```
import boto3
from botocore.exceptions import ClientError


def add_emrfs_step(command, bucket_url, cluster_id, emr_client):
    """
    Add an EMRFS command as a job flow step to an existing cluster.

    :param command: The EMRFS command to run.
    :param bucket_url: The URL of a bucket that contains tracking metadata.
    :param cluster_id: The ID of the cluster to update.
    :param emr_client: The Boto3 Amazon EMR client object.
    :return: The ID of the added job flow step. Status can be tracked by calling
             the emr_client.describe_step() function.
    """
    job_flow_step = {
        "Name": "Example EMRFS Command Step",
        "ActionOnFailure": "CONTINUE",
        "HadoopJarStep": {
            "Jar": "command-runner.jar",
            "Args": ["/usr/bin/emrfs", command, bucket_url],
        },
    }

    try:
        response = emr_client.add_job_flow_steps(
            JobFlowId=cluster_id, Steps=[job_flow_step]
        )
        step_id = response["StepIds"][0]
        print(f"Added step {step_id} to cluster {cluster_id}.")
    except ClientError:
        print(f"Couldn't add a step to cluster {cluster_id}.")
        raise
    else:
        return step_id


def usage_demo():
    emr_client = boto3.client("emr")
    # Assumes the first waiting cluster has EMRFS enabled and has created metadata
    # with the default name of 'EmrFSMetadata'.
    cluster = emr_client.list_clusters(ClusterStates=["WAITING"])["Clusters"][0]
    add_emrfs_step(
        "sync", "s3://elasticmapreduce/samples/cloudfront", cluster["Id"], emr_client
    )


if __name__ == "__main__":
    usage_demo()
```

可以使用返回的 `step_id` 值检查日志以了解操作结果。

# 授予对 Amazon S3 中的 EMRFS 数据的访问权
<a name="emr-plan-credentialsprovider"></a>

默认情况下，EC2 的 EMR 角色确定访问 Amazon S3 中 EMRFS 数据的权限。无论是用户还是组通过 EMRFS 提出请求，附加到此角色的 IAM policy 都适用。默认值为 `EMR_EC2_DefaultRole`。有关更多信息，请参阅[集群 EC2 实例的服务角色（EC2 实例配置文件）](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-iam-role-for-ec2.html)。

从 Amazon EMR 发行版 5.10.0 开始，可以使用安全配置来指定 EMRFS 的 IAM 角色。这样可以为多用户集群自定义 EMRFS 对 Amazon S3 的请求的权限。您可以为不同用户和组指定不同的 IAM 角色，也可根据在 Amazon S3 中的前缀为不同的 Amazon S3 存储桶位置进行指定。当 EMRFS 向 Amazon S3 发出的请求与您指定的用户、组或位置匹配时，集群将使用您指定的相应角色，而不是 EC2 的 EMR 角色。有关更多信息，请参阅[为处理 EMRFS 对 Amazon S3 的请求配置 IAM 角色](https://docs.aws.amazon.com//emr/latest/ManagementGuide/emr-emrfs-iam-roles)。

或者，如果您的 Amazon EMR 解决方案的需求超出了 EMRFS 的 IAM 角色所能提供的权限，您也可以定义自定义凭证提供程序类，从而让您能够自定义对 Amazon S3 中的 EMRFS 数据的访问。

## 为 Amazon S3 中的 EMRFS 数据创建自定义凭证提供程序
<a name="emr-create-credentialsprovider"></a>

要创建自定义凭据提供程序，您需要实现[AWSCredentials提供程序](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/AWSCredentialsProvider.html)和 Hadoop [可配置](https://hadoop.apache.org/docs/stable/api/org/apache/hadoop/conf/Configurable.html)类。

有关此方法的详细说明，请参阅 AWS 大[数据博客中的使用 EMRFS 安全分析来自其他 AWS 账户](https://aws.amazon.com/blogs/big-data/securely-analyze-data-from-another-aws-account-with-emrfs)的数据。博客文章包含一个教程，指导您完成从创建 IAM 角色到启动集群的整个过程end-to-end。其中还提供了实施自定义凭证提供程序类的 Java 代码示例。

基本步骤如下所示：

**指定自定义凭证提供程序**

1. 创建编译为 JAR 文件的自定义凭证提供程序类。

1. 将脚本作为引导操作运行，从而将自定义凭证提供程序 JAR 文件复制到集群主节点的 `/usr/share/aws/emr/emrfs/auxlib` 位置。有关引导操作的更多信息，请参阅[（可选）创建引导操作以安装其它软件](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-plan-bootstrap.html)。

1. 自定义 `emrfs-site` 分类，以指定在 JAR 文件中实施的类。有关指定要自定义应用程序的配置对象的更多信息，请参阅《Amazon EMR 版本指南》**中的[配置应用程序](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-configure-apps.html)。

   以下示例演示了启动包含常见配置参数的 Hive 集群的 `create-cluster` 命令，并包括：
   + 运行脚本 `copy_jar_file.sh` 的引导操作，该脚本已保存到 Amazon S3 中的 `amzn-s3-demo-bucket`。
   + 将 JAR 文件中定义的自定义凭证提供程序指定为 `emrfs-site` 的 `MyCustomCredentialsProvider` 分类
**注意**  
为了便于读取，包含 Linux 行继续符（\$1）。它们可以通过 Linux 命令删除或使用。对于 Windows，请将它们删除或替换为脱字号（^）。

   ```
   aws emr create-cluster --applications Name=Hive \
   --bootstrap-actions '[{"Path":"s3://amzn-s3-demo-bucket/copy_jar_file.sh","Name":"Custom action"}]' \
   --ec2-attributes '{"KeyName":"MyKeyPair","InstanceProfile":"EMR_EC2_DefaultRole",\
   "SubnetId":"subnet-xxxxxxxx","EmrManagedSlaveSecurityGroup":"sg-xxxxxxxx",\
   "EmrManagedMasterSecurityGroup":"sg-xxxxxxxx"}' \
   --service-role EMR_DefaultRole_V2 --enable-debugging --release-label emr-7.12.0 \
   --log-uri 's3n://amzn-s3-demo-bucket/' --name 'test-awscredentialsprovider-emrfs' \
   --instance-type=m5.xlarge --instance-count 3  \
   --configurations '[{"Classification":"emrfs-site",\
   "Properties":{"fs.s3.customAWSCredentialsProvider":"MyAWSCredentialsProviderWithUri"},\
   "Configurations":[]}]'
   ```

# 管理默认终 AWS Security Token Service 端节点
<a name="emr-emrfs-sts-endpoint"></a>

EMRFS 使用 AWS Security Token Service (STS) 检索临时安全证书以访问您的 AWS 资源。早期的 Amazon EMR 发行版本将所有 AWS STS 请求发送到位于的单个全球终端节点。`https://sts.amazonaws.com`亚马逊 EMR 发布版本 5.31.0 和 6.1.0 及更高版本改为向区域终端节点发出请求。 AWS STS 这可以降低延迟并提高会话令牌的有效性。有关 AWS STS 终端节点的更多信息，请参阅《*AWS Identity and Access Management 用户指南》*中的在[AWS 区域中管理 AWS STS](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html)。

使用 Amazon EMR 发行版 5.31.0 和 6.1.0 及更高版本时，您可以覆盖默认的 AWS STS 终端节点。为此，您必须更改 `emrfs-site` 配置中的 `fs.s3.sts.endpoint` 属性。

以下 AWS CLI 示例将 EMRFS 使用的默认 AWS STS 终端节点设置为全局终端节点。

```
aws emr create-cluster --release-label <emr-5.33.0> --instance-type m5.xlarge \
--emrfs Args=[fs.s3.sts.endpoint=https://sts.amazonaws.com]
```

**注意**  
为了便于读取，包含 Linux 行继续符（\$1）。它们可以通过 Linux 命令删除或使用。对于 Windows，请将它们删除或替换为脱字号（^）。

或者，您也可以使用以下示例创建 JSON 配置文件，并使用 `emr create-cluster` 的 `--configurations` 实参指定它。有关使用 `--configurations,` 的更多信息，请参阅 [*AWS CLI 命令参考*。](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/emr/create-cluster.html)

```
[
  {
    "classification": "emrfs-site",
    "properties": {
      "fs.s3.sts.endpoint": "https://sts.amazonaws.com"
    }
  }
]
```

# 使用 EMRFS 属性指定 Amazon S3 加密
<a name="emr-emrfs-encryption"></a>

**重要**  
从 Amazon EMR 发行版 4.8.0 开始，您可以使用安全配置以更轻松的方式应用安全设置，并获得更多选项。建议您使用安全配置。有关更多信息，请参阅[配置数据加密](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-create-security-configuration.html#emr-security-configuration-encryption)。此部分中所述的控制台说明适用于 4.8.0 之前的版本。如果您使用在 AWS CLI 集群配置和后续版本的安全配置中配置 Amazon S3 加密，则安全配置将覆盖集群配置。

创建集群时，您可以使用控制台或通过或 EMR SDK 使用`emrfs-site`分类属性为 Amazon S3 中的 EMRFS 数据指定服务器端加密 (SSE) 或客户端加密 (CSE)。 AWS CLI Amazon S3 SSE 和 CSE 是互斥的；您可以任选其一，但不能同时选择两者。

有关 AWS CLI 说明，请参阅下面与您的加密类型对应的部分。

**要指定 EMRFS 加密选项，请使用 AWS 管理控制台**

1. 导航到 Amazon EMR 新控制台，然后从侧面导航栏中选择**切换到旧控制台**。有关切换到旧控制台后预期情况的更多信息，请参阅 [Using the old console](https://docs.aws.amazon.com/emr/latest/ManagementGuide/whats-new-in-console.html#console-opt-in)。

1. 依次选择 **Create cluster (创建集群)**、**Go to advanced options (转到高级选项)**。

1. 选择 **Release (版本)** 4.7.2 或更早版本。

1. 为 **Software and Steps (软件和步骤)** 选择适用于您的应用程序的其它选项，然后选择 **Next (下一步)**。

1. 在 **Hardware (硬件)** 和 **General Cluster Settings (常规集群设置)** 窗格中选择适用于您的应用程序的设置。

1. 在 **Security (安全)** 窗格上的 **Authentication and encryption (身份验证和加密)** 下，选择要使用的 **S3 Encryption (with EMRFS)** 选项。
**注意**  
在使用 Amazon EMR 发行版 4.4 或更早版本时，**S3 server-side encryption with KMS Key Management (利用 KMS Key Management 进行 S3 服务器端加密)**（SSE-KMS）不可用。
   + 如果您选择一个使用 **AWS Key Management** 的选项，请选择一个 **AWS KMS Key ID**。有关更多信息，请参阅[用 AWS KMS keys 于 EMRFS 加密](#emr-emrfs-awskms)。
   + 如果您选择 **S3 client-side encryption with custom materials provider (利用自定义材料提供程序进行 S3 客户端加密)**，请提供 **Class name (类名称)** 和 **JAR location (AR 位置)**。有关更多信息，请参阅[Amazon S3 客户端加密](emr-emrfs-encryption-cse.md)。

1. 选择适用于您的应用程序的其它选项，然后选择 **Create Cluster (创建集群)**。

## 用 AWS KMS keys 于 EMRFS 加密
<a name="emr-emrfs-awskms"></a>

 AWS KMS 加密密钥必须与您的 Amazon EMR 集群实例和与 EMRFS 一起使用的 Amazon S3 存储桶所在的区域创建。如果指定的密钥没有位于用于配置集群的账户中，则必须使用它的 ARN 指定密钥。

Amazon EC2 实例配置文件的角色必须具有使用您指定的 KMS 密钥的权限。Amazon EMR 中实例配置文件的默认角色是 `EMR_EC2_DefaultRole`。如果您对实例配置文件使用不同的角色，或者对 Amazon S3 的 EMRFS 请求使用 IAM 角色，请确保根据需要将每个角色添加为密钥用户。这会为该角色授予使用该 KMS 密钥的权限。有关更多信息，请参阅*《AWS Key Management Service 开发人员指南》*和[为向 Amazon S3 发出的 EMRFS 请求配置 IAM 角色](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-emrfs-iam-roles.html)中的[使用密钥策略](https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html#key-policy-default-allow-users)。

您可以使用将您的实例配置文件或 EC2 实例配置文件 AWS 管理控制台 添加到指定 KMS 密钥的密钥用户列表中，也可以使用 AWS CLI 或 AWS 软件开发工具包来附加相应的密钥策略。

请注意 Amazon EMR 仅支持[对称 KMS 密钥](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#symmetric-cmks)。不能使用[非对称 KMS 密钥](https://docs.aws.amazon.com/kms/latest/developerguide/symmetric-asymmetric.html#asymmetric-cmks)加密 Amazon EMR 集群中的静态数据。要获取确定 KMS 密钥是对称还是非对称的帮助，请参阅[识别对称密钥和非对称密钥](https://docs.aws.amazon.com/kms/latest/developerguide/find-symm-asymm.html)。

以下步骤介绍了如何使用 AWS 管理控制台将 Amazon EMR 实例配置文件 `EMR_EC2_DefaultRole` 作为*密钥用户*添加。它假定您已创建一个 KMS 密钥。要创建新的 KMS 密钥，请参阅*《AWS Key Management Service 开发人员指南》*中的[创建密钥](https://docs.aws.amazon.com/kms/latest/developerguide/create-keys.html)。

**将 Amazon EMR 的 EC2 实例配置文件添加到加密密钥用户列表中**

1. 登录 AWS 管理控制台 并在 [https://console.aws.amazon.com/km](https://console.aws.amazon.com/kms) s 处打开 AWS Key Management Service (AWS KMS) 控制台。

1. 要更改 AWS 区域，请使用页面右上角的区域选择器。

1. 选择要修改的 KMS 密钥的别名。

1. 在密钥详细信息页面的 **Key Users (密钥用户)** 下，选择 **Add (添加)**。

1. 在 **Add key users (添加密钥用户)** 对话框中，选择适当的角色。默认角色的名称为 `EMR_EC2_DefaultRole`。

1. 选择**添加**。

## Amazon S3 服务器端加密
<a name="emr-emrfs-encryption-sse"></a>

默认情况下，所有 Amazon S3 存储桶都配置了加密，所有上传到 S3 存储桶的新对象都会自动静态加密，Amazon S3 在向磁盘写入数据时会在对象级别对数据进行加密，并在访问数据时对其进行解密。有关 SSE 的更多信息，请参阅*《Amazon Simple Storage Service 用户指南》*中的[使用服务器端加密保护数据](https://docs.aws.amazon.com/AmazonS3/latest/userguide/serv-side-encryption.html)。

在 Amazon EMR 中指定 SSE 时，可以在两个不同的密钥管理系统之间进行选择：
+ **SSE-S3**：Amazon S3 为您管理密钥。
+ **SSE-KMS** — 您可以使用 AWS KMS key 来设置适用于 Amazon EMR 的策略。有关 Amazon EMR 密钥要求的更多信息，请参阅[AWS KMS keys 用于](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-encryption-enable.html#emr-awskms-keys)加密。

客户提供密钥的 SSE（SSE-C）不能用于 Amazon EMR。

**要创建启用了 SSE-S3 的集群，请使用 AWS CLI**
+ 键入以下命令：

  ```
  aws emr create-cluster --release-label emr-4.7.2 or earlier \
  --instance-count 3 --instance-type m5.xlarge --emrfs Encryption=ServerSide
  ```

你也可以通过设置 fs.s3 来启用 SSE-S3。 enableServerSide属性中的`emrfs-site`加密属性为 true。请参阅下面的 SSE-KMS 示例并忽略密钥 ID 的属性。

**要创建启用了 SSE-KMS 的集群，请使用 AWS CLI**
**注意**  
SSE-KMS 仅在 Amazon EMR 发行版 4.5.0 及更高版本中可用。
+ 键入以下 AWS CLI 命令创建带有 SSE-KMS 的集群，其中*keyID*是 AWS KMS key，例如：*a4567b8-9900-12ab-1234-123a45678901*

  ```
  aws emr create-cluster --release-label emr-4.7.2 or earlier --instance-count 3 \
  --instance-type m5.xlarge --use-default-roles \
  --emrfs Encryption=ServerSide,Args=[fs.s3.serverSideEncryption.kms.keyId=keyId]
  ```

  **或者**

  使用`emrfs-site`分类键入以下 AWS CLI 命令，并提供包含内容的配置 JSON 文件，如下例`myConfig.json`所示：

  ```
  aws emr create-cluster --release-label emr-4.7.2 or earlier --instance-count 3 --instance-type m5.xlarge --applications Name=Hadoop --configurations file://myConfig.json --use-default-roles
  ```

  **myConfig.json** 的示例内容：

  ```
  [
    {
      "Classification":"emrfs-site",
      "Properties": {
         "fs.s3.enableServerSideEncryption": "true",
         "fs.s3.serverSideEncryption.kms.keyId":"a4567b8-9900-12ab-1234-123a45678901"
      }
    }
  ]
  ```

### SSE-S3 和 SSE-KMS 的配置属性
<a name="emr-emrfs-encryption-site-sse-properties"></a>

可使用 `emrfs-site` 配置分类来配置这些属性。SSE-KMS 仅在 Amazon EMR 发行版 4.5.0 及更高版本中可用。


| 属性  | 默认 值 | 说明  | 
| --- | --- | --- | 
| fs.s3.enableServerSideEncryption | false |  设置为 **true** 时，使用服务器端加密对 Amazon S3 中存储的对象进行加密。如果未指定密钥，则使用 SSE-S3。  | 
| fs.s3.serverSideEncryption.kms.keyId | n/a |  指定密 AWS KMS 钥 ID 或 ARN。如果未指定密钥，则使用 SSE-KMS。  | 

# Amazon S3 客户端加密
<a name="emr-emrfs-encryption-cse"></a>

对于 Amazon S3 客户端加密，Amazon S3 加密和解密过程在您的 EMR 集群上的 EMRFS 客户端中进行。在对象上载到 Amazon S3 之前对其进行加密，并在下载后对其进行解密。您指定的提供程序会提供客户端使用的加密密钥。客户端可以使用 AWS KMS 提供的密钥（CSE-KMS）或提供客户端根密钥（CSE-C）的自定义 Java 类。CSE-KMS 和 CSE-C 之间的加密细节略有不同，具体取决于指定的提供程序以及正在解密或加密对象的元数据。有关这些区别的更多信息，请参阅*《Amazon Simple Storage Service 用户指南》*中的[使用客户端加密保护数据](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingClientSideEncryption.html)。

**注意**  
Amazon S3 CSE 仅确保与 Amazon S3 交换的 EMRFS 数据已加密；不确保集群实例卷上的所有数据都已加密。此外，由于 Hue 不使用 EMRFS，因此 Hue S3 文件浏览器写入 Amazon S3 的对象没有加密。

**要在 Amazon S3 中为 EMRFS 数据指定 CSE-KMS，请使用 AWS CLI**
+ 键入以下命令并替换为要*MyKMSKeyID*使用的 KMS 密钥的密钥 ID 或 ARN：

  ```
  aws emr create-cluster --release-label emr-4.7.2 or earlier
  --emrfs Encryption=ClientSide,ProviderType=KMS,KMSKeyId=MyKMSKeyId
  ```

## 创建自定义密钥提供程序
<a name="emr-emrfs-create-cse-key"></a>

根据您在创建自定义密钥提供程序时使用的加密类型，应用程序还必须实现不同的 EncryptionMaterialsProvider 接口。这两个接口在适用于 Java 的 AWS SDK 版本 1.11.0 及更高版本中都可用。
+ 要实现亚马逊 S3 加密，请使用 [com.amazonaws.services.s3.model。 EncryptionMaterialsProvider 接口](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/model/EncryptionMaterialsProvider.html)。
+ 要实现本地磁盘加密，请使用 [com.amazonaws.services.elasticmapreduce.spi.security。 EncryptionMaterialsProvider 接口](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/elasticmapreduce/spi/security/EncryptionMaterialsProvider.html)。

您可以使用任何策略为实施提供加密材料。例如，您可以选择提供静态加密材料，也可以选择与更复杂的密钥管理系统集成。

如果您使用的是 Amazon S3 加密，则必须**AES/GCM/NoPadding**对自定义加密材料使用加密算法。

如果您使用的是本地磁盘加密，则用于自定义加密材料的加密算法因 EMR 发行版而异。对于亚马逊 EMR 7.0.0 及更低版本，您必须使用。**AES/GCM/NoPadding**对于 Amazon EMR 7.1.0 及更高版本，您必须使用 **AES**。

该 EncryptionMaterialsProvider 类通过加密上下文获取加密材料。Amazon EMR 在运行时填充加密上下文信息，以帮助调用者确定要返回的正确加密材料。

**Example 示例：通过 EMRFS 使用自定义密钥提供程序对 Amazon S3 进行加密**  
当 Amazon EMR 从EncryptionMaterialsProvider 类中提取加密材料以执行加密时，EMRFS 可以选择在材料描述参数中填充两个字段：对象的 Amazon S3 URI 和 JobFlowId 集群的 URI，该类可以选择性地使用这两个字段来有选择地返回加密材料。EncryptionMaterialsProvider   
例如，提供程序可能会为不同的 Amazon S3 URI 前缀返回不同的密钥。它是最终与 Amazon S3 对象一起存储的返回加密材料的描述，而不是 EMRFS 生成并传递给提供程序的 materialsDescription 值。解密 Amazon S3 对象时，加密材料描述会传递给该EncryptionMaterialsProvider 类，这样它就可以有选择地返回匹配的密钥来解密该对象。  
下面提供了一个 EncryptionMaterialsProvider 参考实现。另一个自定义提供程序可从中获得 GitHub。[EMRFSRSAEncryptionMaterialsProvider](https://github.com/awslabs/emr-sample-apps/tree/master/emrfs-plugins/EMRFSRSAEncryptionMaterialsProvider)  

```
import com.amazonaws.services.s3.model.EncryptionMaterials;
import com.amazonaws.services.s3.model.EncryptionMaterialsProvider;
import com.amazonaws.services.s3.model.KMSEncryptionMaterials;
import org.apache.hadoop.conf.Configurable;
import org.apache.hadoop.conf.Configuration;

import java.util.Map;

/**
 * Provides KMSEncryptionMaterials according to Configuration
 */
public class MyEncryptionMaterialsProviders implements EncryptionMaterialsProvider, Configurable{
  private Configuration conf;
  private String kmsKeyId;
  private EncryptionMaterials encryptionMaterials;

  private void init() {
    this.kmsKeyId = conf.get("my.kms.key.id");
    this.encryptionMaterials = new KMSEncryptionMaterials(kmsKeyId);
  }

  @Override
  public void setConf(Configuration conf) {
    this.conf = conf;
    init();
  }

  @Override
  public Configuration getConf() {
    return this.conf;
  }

  @Override
  public void refresh() {

  }

  @Override
  public EncryptionMaterials getEncryptionMaterials(Map<String, String> materialsDescription) {
    return this.encryptionMaterials;
  }

  @Override
  public EncryptionMaterials getEncryptionMaterials() {
    return this.encryptionMaterials;
  }
}
```

## 使用指定定制材料提供商 AWS CLI
<a name="emr-emrfs-encryption-cse-custom-cli"></a>

要使用 AWS CLI，请将 `Encryption`、`ProviderType`、`CustomProviderClass` 和 `CustomProviderLocation` 参数传递给 `emrfs` 选项。

```
aws emr create-cluster --instance-type m5.xlarge --release-label emr-4.7.2 or earlier --emrfs Encryption=ClientSide,ProviderType=Custom,CustomProviderLocation=s3://amzn-s3-demo-bucket/myfolder/provider.jar,CustomProviderClass=classname
```

将 `Encryption` 设置为 `ClientSide` 会启用客户端加密，`CustomProviderClass` 是您的 `EncryptionMaterialsProvider` 对象的名称，而 `CustomProviderLocation` 是本地或 Amazon S3 位置，Amazon EMR 从此位置将 `CustomProviderClass` 复制到集群中的每个节点并放置在类路径中。

## 使用 SDK 指定自定义材料提供程序
<a name="emr-emrfs-encryption-cse-custom-sdk"></a>

要使用 SDK，您可以将属性 `fs.s3.cse.encryptionMaterialsProvider.uri` 设置为将存储在 Amazon S3 中的自定义 `EncryptionMaterialsProvider` 类下载到集群中的每个节点。您在 `emrfs-site.xml` 文件中配置此设置，同时启用 CSE 并提供自定义提供程序的正确位置。

例如，在 适用于 Java 的 AWS SDK 使用中 RunJobFlowRequest，您的代码可能如下所示：

```
<snip>
		Map<String,String> emrfsProperties = new HashMap<String,String>();
	    	emrfsProperties.put("fs.s3.cse.encryptionMaterialsProvider.uri","s3://amzn-s3-demo-bucket/MyCustomEncryptionMaterialsProvider.jar");
	    	emrfsProperties.put("fs.s3.cse.enabled","true");
	    	emrfsProperties.put("fs.s3.consistent","true");
		    emrfsProperties.put("fs.s3.cse.encryptionMaterialsProvider","full.class.name.of.EncryptionMaterialsProvider");

		Configuration myEmrfsConfig = new Configuration()
	    	.withClassification("emrfs-site")
	    	.withProperties(emrfsProperties);

		RunJobFlowRequest request = new RunJobFlowRequest()
			.withName("Custom EncryptionMaterialsProvider")
			.withReleaseLabel("emr-7.12.0")
			.withApplications(myApp)
			.withConfigurations(myEmrfsConfig)
			.withServiceRole("EMR_DefaultRole_V2")
			.withJobFlowRole("EMR_EC2_DefaultRole")
			.withLogUri("s3://myLogUri/")
			.withInstances(new JobFlowInstancesConfig()
				.withEc2KeyName("myEc2Key")
				.withInstanceCount(2)
				.withKeepJobFlowAliveWhenNoSteps(true)
				.withMasterInstanceType("m5.xlarge")
				.withSlaveInstanceType("m5.xlarge")
			);						
					
		RunJobFlowResult result = emr.runJobFlow(request);
</snip>
```

## 带参数的自定义 EncryptionMaterialsProvider
<a name="emr-emrfs-encryption-custommaterials"></a>

您可能需要将参数直接传递给提供程序。要执行此操作，您可以将 `emrfs-site` 配置分类与定义为属性的自定义参数结合使用。下面显示了一个示例配置，该示例配置将另存为 `myConfig.json` 文件：

```
[
    {
      "Classification": "emrfs-site",
      "Properties": {
        "myProvider.arg1":"value1",
	    "myProvider.arg2":"value2"
      }
    }
 ]
```

使用中的`create-cluster`命令 AWS CLI，您可以使用`--configurations`选项来指定文件，如下所示：

```
aws emr create-cluster --release-label emr-7.12.0 --instance-type m5.xlarge --instance-count 2 --configurations file://myConfig.json --emrfs Encryption=ClientSide,CustomProviderLocation=s3://amzn-s3-demo-bucket/myfolder/myprovider.jar,CustomProviderClass=classname
```

## 配置 EMRFS S3EC V2 支持
<a name="emr-emrfs-encryption-cse-s3v2"></a>

S3 Java SDK 版本（1.11.837 及更高版本）支持带有各种安全增强功能的加密客户端版本 2（S3EC V2）。有关更多信息，请参阅 S3 博客文章 [Updates to the Amazon S3 encryption client](https://aws.amazon.com/blogs/developer/updates-to-the-amazon-s3-encryption-client/)。另请参阅《 适用于 Java 的 AWS SDK 开发人员指南》[中的 Amazon S3 加密客户端迁移](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/s3-encryption-migration.html)。

为保持向后兼容性，加密客户端 V1 在 SDK 中仍可用。默认情况下，启用 CSE 后，EMRFS 将使用 S3EC V1 加密和解密 S3 对象。

在发行版早于 emr-5.31.0（emr-5.30.1 及更早版本、emr-6.1.0 及更早版本）的 EMR 集群上，使用 S3EC V2 加密的 S3 对象无法通过 EMRFS 来解密。

**Example 将 EMRFS 配置为使用 S3EC V2**  
要将 EMRFS 配置为使用 S3EC V2，请添加以下配置：  

```
{
  "Classification": "emrfs-site",
  "Properties": {
    "fs.s3.cse.encryptionV2.enabled": "true"
  }
}
```

## Amazon S3 客户端加密的 `emrfs-site.xml` 属性
<a name="emr-emrfs-cse-config"></a>


| 属性  | 默认 值 | 说明  | 
| --- | --- | --- | 
| fs.s3.cse.enabled | false |  设置为 **true** 时，使用客户端加密对 Amazon S3 中存储的 EMRFS 对象进行加密。  | 
| fs.s3.cse.encryptionV2.enabled | false |  设置为 `true` 时，EMRFS 使用 S3 加密客户端版本 2 来加密和解密 S3 上的对象。在 EMR 版本 5.31.0 及更高版本中提供。  | 
| fs.s3.cse.encryptionMaterialsProvider.uri | N/A | 在使用自定义加密材料时适用。带 EncryptionMaterialsProvider 的 JAR 所在的 Amazon S3 URI。如果您提供此 URI，Amazon EMR 将此 JAR 自动下载到集群中的所有节点。 | 
| fs.s3.cse.encryptionMaterialsProvider | N/A |  用于客户端加密的 `EncryptionMaterialsProvider` 类路径。在使用 CSE-KMS 时，请指定 `com.amazon.ws.emr.hadoop.fs.cse.KMSEncryptionMaterialsProvider`。  | 
| fs.s3.cse.materialsDescription.enabled | false |  如果设置为`true`，则使用加密对象的 Amazon S3 URI 填充加密对象的 MaterialsDescription 和。 JobFlowId在使用自定义加密材料时设置为 `true`。  | 
| fs.s3.cse.kms.keyId | N/A |  在使用 CSE-KMS 时适用。用于加密的 KMS 密钥的值 KeyId、ARN 或别名。  | 
| fs.s3.cse.cryptoStorageMode | ObjectMetadata  |  Amazon S3 存储模式。默认情况下，加密信息的描述存储在对象元数据中。也可以将描述存储在指令文件中。有效值为 ObjectMetadata 和InstructionFile。有关更多信息，请参阅使用[适用于 Java 的 AWS SDK 和 Amazon S3 进行客户端数据加密](https://aws.amazon.com/articles/client-side-data-encryption-with-the-aws-sdk-for-java-and-amazon-s3/)。  | 