

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

# 管理虚拟集群
<a name="virtual-cluster"></a>

虚拟集群是 Amazon EMR 注册的 Kubernetes 命名空间。您可以创建、描述、列出和删除虚拟集群。它们不会消耗您系统中的任何额外资源。一个虚拟集群映射到一个 Kubernetes 命名空间。鉴于这种关系，您可以按照对 Kubernetes 命名空间进行建模的方式对虚拟集群进行建模，来满足您的需求。请参阅 [Kubernetes 概念概览](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/)文档中可能的使用案例。

要在 Amazon EKS 集群上使用 Kubernetes 命名空间注册 Amazon EMR，您需要 EKS 集群的名称以及为运行您的工作负载而设置的命名空间。Amazon EMR 中的这些注册集群称为虚拟集群，因为它们不管理物理计算或存储，而是指向计划工作负载的 Kubernetes 命名空间。

**注意**  
在创建虚拟集群之前，您必须首先完成[设置 Amazon EMR on EKS](setting-up.md)中的步骤 1-8。

**Topics**
+ [创建虚拟集群](#create-virtul-cluster)
+ [列出虚拟集群](#list-virtual-cluster)
+ [描述虚拟集群](#describe-virtual-cluster)
+ [删除虚拟集群](#delete-virtual-cluster)
+ [虚拟集群状态](#virtual-cluster-states)
+ [虚拟集群的并发作业限制](#virtual-cluster-job-concurrency-limits)

## 创建虚拟集群
<a name="create-virtul-cluster"></a>

运行以下命令，通过使用 EKS 集群上的命名空间注册 Amazon EMR 来创建虚拟集群。{{virtual\_cluster\_name}}替换为您为虚拟集群提供的名称。{{eks\_cluster\_name}}替换为 EKS 集群的名称。将{{namespace\_name}}替换为您要注册 Amazon EMR 的命名空间。

```
aws emr-containers create-virtual-cluster \
--name {{virtual_cluster_name}} \
--container-provider '{
    "id": "{{eks_cluster_name}}",
    "type": "EKS",
    "info": {
        "eksInfo": {
            "namespace": "{{namespace_name}}"
        }
    }
}'
```

或者，您可以创建包含虚拟集群所需参数的 JSON 文件，如以下示例所示。

```
{
    "name": "{{virtual_cluster_name}}", 
    "containerProvider": {
        "type": "EKS", 
        "id": "{{eks_cluster_name}}", 
        "info": {
            "eksInfo": {
                "namespace": "{{namespace_name}}"
            }
        }
    }
}
```

然后使用 JSON 文件路径运行以下 `create-virtual-cluster` 命令。

```
aws emr-containers create-virtual-cluster \
--cli-input-json {{file://./create-virtual-cluster-request.json}}
```

**注意**  
要验证虚拟集群是否成功创建，请通过运行 `list-virtual-clusters` 命令或转到 Amazon EMR 控制台中的 **Virtual clusters (虚拟集群)** 页面，以查看虚拟集群状态。

## 列出虚拟集群
<a name="list-virtual-cluster"></a>

运行以下命令来查看虚拟集群的状态。

```
aws emr-containers list-virtual-clusters
```

## 描述虚拟集群
<a name="describe-virtual-cluster"></a>

运行以下命令以获取有关虚拟集群的详细信息，例如命名空间、状态和注册日期。{{123456}}替换为您的虚拟集群 ID。

```
aws emr-containers describe-virtual-cluster --id {{123456}}
```

## 删除虚拟集群
<a name="delete-virtual-cluster"></a>

运行以下命令来删除虚拟集群。{{123456}}替换为您的虚拟集群 ID。

```
aws emr-containers delete-virtual-cluster --id {{123456}}
```

## 虚拟集群状态
<a name="virtual-cluster-states"></a>

下表描述了虚拟集群的四种可能状态。


| `State` | 说明 | 
| --- | --- | 
| `RUNNING` | 虚拟集群处于 RUNNING 状态。 | 
| `TERMINATING` | 正在请求终止虚拟集群。 | 
| `TERMINATED` | 已完成请求的终止。 | 
| `ARRESTED` | 由于权限不足，请求的终止失败。 | 

## 虚拟集群的并发作业限制
<a name="virtual-cluster-job-concurrency-limits"></a>

您可以在 EKS 虚拟集群上的 Amazon EMR 上配置并行任务限制，以控制有多少任务同时运行，有多少任务可以在队列中等待。您可以单独设置并发限制 (`maxConcurrentJobRuns`) 和队列深度 (`maxInQueueJobRuns`)，因此可以对正在运行的作业运行和/或排队作业运行设置上限。当您设置这些限制时，`StartJobRun`API 会在虚拟集群级别提供背压。作业超出运行限制，在队列中等待`PENDING`处于`SUBMITTED`或状态，而不是立即启动，一旦队列已满，就会`StartJobRun`拒绝进一步的提交。例如，如果您将虚拟集群设置为允许 500 次并发作业运行和 100 次排队作业，则第 101 次排队提交将被拒绝，并且您可以在同一 EKS 集群上的其他虚拟集群之间重新平衡该工作负载或增加容量。当你没有设置并发限制且队列深度持续增长，从而使任务运行在开始之前更长时间地`PENDING`处于`SUBMITTED`或状态时，这可能表明底层 EKS 集群的计算资源不足，无法足够快地调度新 Pod。在这种情况下，将工作负载路由到另一个集群或增加容量。

并行任务限制在 Kubernetes 调度器和 Kubernetes 网站上的该[ResourceQuota](https://kubernetes.io/docs/concepts/policy/resource-quotas/)功能前面添加了一个控制层。由于它们是在创建任何 Pod 之前强制执行的，因此多余的负载会在 API 排队或拒绝，这样在任务到达底层集群之前就保护了底层集群。`StartJobRun`Kubernetes 仍然强制执行下方的实际CPU和内存上限。

### 并行任务限制的主要优点
<a name="virtual-cluster-job-concurrency-benefits"></a>
+ **防止邻居噪声过载 **-限制每个虚拟集群正在运行和排队的作业运行次数，这样单个虚拟集群就无法独占共享 EKS 集群并导致其他虚拟集群的噪声邻居调度失败。
+ **启用流量整形 **-当虚拟集群的队列已满时，立即返回拒绝，因此您可以将提交重定向到其他虚拟集群，而不必让单个虚拟集群不堪重负。
+ **提供可见性 ** — 每 5 分钟发出`AWS/EMRContainers`命名空间中每个虚拟集群`JobsRunning`的活跃和队列中任务运行次数的`JobsInQueue` CloudWatch 指标，从而为您的调度提供运行状况信号。

### 并发任务限制入门
<a name="virtual-cluster-job-concurrency-getting-started"></a>

您可以使用虚拟群集上的`schedulerConfiguration`字段配置并发作业限制。此字段接受两个参数：

`maxConcurrentJobRuns`  
随时可以处于该`RUNNING`状态的最大作业运行次数。

`maxInQueueJobRuns`  
任何时候可以处于`PENDING`或`SUBMITTED`状态（队列深度）的最大作业运行次数。

#### AWS CLI
<a name="virtual-cluster-job-concurrency-cli"></a>

要在创建虚拟集群时设置限制，请在请求`schedulerConfiguration`中指定。

```
aws emr-containers create-virtual-cluster \
  --name {{my-virtual-cluster}} \
  --container-provider '{ ... }' \
  --scheduler-configuration '{
      "maxConcurrentJobRuns": 500,
      "maxInQueueJobRuns": 100
  }'
```

要更改现有虚拟集群的限制，请使用`update-virtual-cluster`命令。

```
aws emr-containers update-virtual-cluster \
  --id {{virtual-cluster-id}} \
  --scheduler-configuration '{
      "maxConcurrentJobRuns": 500,
      "maxInQueueJobRuns": 100
  }'
```

要删除虚拟集群的限制，请传递一个空值`schedulerConfiguration`。这会清除配置，因此不存在任何限制，虚拟集群将恢复默认（无限制）行为。请注意，在请求*`schedulerConfiguration`中*省略会使现有限制保持不变——您必须传递一个空对象才能清除这些限制。

```
aws emr-containers update-virtual-cluster \
  --id {{virtual-cluster-id}} \
  --scheduler-configuration '{}'
```

要查看当前限制和实时任务数，请使用`describe-virtual-cluster`命令。响应包括您的`schedulerConfiguration`和当前为`activeJobRunCount`和的`SchedulerStatus`对象`inQueueJobRunCount`。

**注意**  
当您向队列已满的虚拟集群提交作业运行时，`StartJobRun`返回`ValidationException`。

### 为最大值ConcurrentJobRuns 和最大值选择值 InQueueJobRuns
<a name="virtual-cluster-job-concurrency-choosing-values"></a>

正确的限制取决于三点：您的 Amazon EKS 集群一次可以运行多少工作、提交的突发性以及您希望虚拟集群在满时表现如何。使用以下指南选择起点，然后从实时计数器中对其进行优化。

#### 设置最大值ConcurrentJobRuns （运行插槽）
<a name="virtual-cluster-job-concurrency-running-slots"></a>

`maxConcurrentJobRuns`是一种基于任务粒度的护栏。这里的粗略估计可以保护底层 Amazon EKS 集群免受负载降级，并可以提高可用性。
+ **从容量除以每项任务的占地面积开始。**以每个任务的*请求量*（驱动程序、执行程序和内存开销）为基础，将大约 70-80% 的命名空间容量作为目标，为驱动程序开销、节点扩展和突发事件留出余地。
+ **限制每项任务的规模（T-shirt 大小）。**将每项任务绑定到几种规模`spark.dynamicAllocation.maxExecutors`并对其进行标准化——例如，小型（20 个执行者）、中型（100）和大型（大约 500 个）——因此，`maxConcurrentJobRuns`乘以上限可以预测地映射到容量，而不是为可变的平均值预留过度配置或配置不足。为了获得最简洁的数学运算，请将每个大小类路由到自己的虚拟集群。
+ **在实时计数器上收听。**从保守开始，在观察`activeJobRunCount``AWS/EMRContainers`命名空间中的`JobsRunning`指标时逐渐提高值。

#### 设置最大值InQueueJobRuns （队列深度）
<a name="virtual-cluster-job-concurrency-queue-depth"></a>

`maxInQueueJobRuns`控制虚拟集群在开始拒绝提交之前接受的待办事项大小。它是一种爆发吸收缓冲液。考虑以下因素。
+ **Burst 配置文件 ** — 调整队列大小以吸收预期会高于跑步速率的提交连发量。如果计划管道同时触发多个作业，则更深的队列可以防止虚假拒绝。根据预期的爆发大小而不是固定倍数来确定深度`maxConcurrentJobRuns`，并根据随后的排水时间限制对其进行验证。
+ **可接受的等待时间 ** — 排队的任务等待正在运行的空位腾出。排在满队列后面的任务大约等待队列深度除以完成吞吐量。例如，如果任务以每分钟 N 的速度完成且队列保存 Q，则尾部等待大约 Q 除以 N 分钟。将其保留在您的 SLA 范围内。因为如果没有空闲的空位，缓冲任务会在 30 分钟后失败，所以要保持足够`maxInQueueJobRuns`小的规模，以保持稳定的完成率，满队列在 30 分钟内就会耗尽。否则，排队的任务会超时。
+ **背压与缓冲相比 ** ——更深的队列可以平滑突发情况，但它会延迟您用于流量整形的队列满抑制并增加尾部延迟。较浅的队列会快速失效，这为客户端提供了可操作的早期信号，可以重试或路由到其他地方。根据您是喜欢缓冲负载还是减少负载并重定向来进行选择。
+ **客户端重试行为 **-队列已满时，`StartJobRun`返回。`ValidationException`确保您的提交者处理了此异常 — 使用退避功能重试，或将工作负载路由到另一个虚拟集群。设置深度，使拒绝仅在真正过载时发生，而不是在常规操作期间发生。

### 并发任务限制的注意事项
<a name="virtual-cluster-job-concurrency-considerations"></a>
+ 默认情况下不应用任何限制。除非您明确设置`schedulerConfiguration`，否则现有的虚拟集群和工作负载不会受到影响。
+ 由于计数器是在分布式系统中维护的，因此有时可以预期真实值会有很小的瞬态增量。内部和解可以纠正任何偏差。