

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Menanggapi peristiwa kapasitas instans Amazon EMR cluster yang tidak mencukupi
<a name="emr-events-response-insuff-capacity"></a>

## Ikhtisar
<a name="emr-events-response-insuff-capacity-overview"></a>

Cluster EMR Amazon mengembalikan kode peristiwa `EC2 provisioning - Insufficient Instance Capacity` ketika Availability Zone yang dipilih tidak memiliki kapasitas yang cukup untuk memenuhi permintaan awal atau pengubahan ukuran klaster Anda. Peristiwa akan muncul secara berkala dengan grup instans dan armada instans jika EMR Amazon berulang kali menemukan pengecualian kapasitas yang tidak mencukupi dan tidak dapat memenuhi permintaan penyediaan Anda untuk operasi pengaktifan klaster atau pengubahan ukuran klaster.

Halaman ini menjelaskan cara terbaik Anda merespons jenis peristiwa ini saat terjadi untuk klaster EMR Anda.

## Respons yang disarankan untuk acara kapasitas yang tidak mencukupi
<a name="emr-events-response-insuff-capacity-rec"></a>

Kami menyarankan Anda menanggapi peristiwa kapasitas yang tidak memadai dengan salah satu cara berikut:
+ Tunggu kapasitas untuk pulih. Kapasitas sering bergeser, sehingga pengecualian kapasitas yang tidak mencukupi dapat pulih dengan sendirinya. Cluster Anda akan mulai atau selesai mengubah ukuran segera setelah kapasitas Amazon EC2 tersedia.
+ Atau, Anda dapat menghentikan klaster, memodifikasi konfigurasi tipe instans, dan membuat klaster baru dengan permintaan konfigurasi klaster yang diperbarui. Untuk informasi selengkapnya, lihat [Fleksibilitas Availability Zone untuk klaster EMR Amazon](emr-flexibility.md).

Anda juga dapat mengatur aturan atau respons otomatis terhadap peristiwa kapasitas yang tidak mencukupi, seperti yang dijelaskan di bagian berikutnya.

## Pemulihan otomatis dari peristiwa kapasitas yang tidak mencukupi
<a name="emr-events-response-insuff-capacity-ex"></a>

Anda dapat membangun otomatisasi dalam menanggapi peristiwa EMR Amazon seperti yang memiliki kode acara. `EC2 provisioning - Insufficient Instance Capacity` Misalnya, AWS Lambda fungsi berikut mengakhiri klaster EMR dengan grup instans yang menggunakan instance On-Demand, dan kemudian membuat klaster EMR baru dengan grup instans yang berisi tipe instans yang berbeda dari permintaan asli.

Kondisi berikut memicu proses otomatis terjadi:
+ Peristiwa kapasitas yang tidak mencukupi telah dipancarkan untuk node primer atau inti selama lebih dari 20 menit.
+ Cluster tidak dalam keadaan **SIAP** atau **MENUNGGU**. Untuk informasi lebih lanjut tentang status klaster EMR, lihat. [Memahami siklus hidup klaster](emr-overview.md#emr-overview-cluster-lifecycle)

**catatan**  
Ketika Anda membangun proses otomatis untuk pengecualian kapasitas yang tidak mencukupi, Anda harus mempertimbangkan bahwa peristiwa kapasitas yang tidak mencukupi dapat dipulihkan. Kapasitas sering bergeser dan cluster Anda akan melanjutkan pengubahan ukuran atau mulai beroperasi segera setelah kapasitas Amazon EC2 tersedia.

**Example berfungsi untuk menanggapi peristiwa kapasitas yang tidak mencukupi**  

```
// Lambda code with Python 3.10 and handler is lambda_function.lambda_handler
// Note: related IAM role requires permission to use Amazon EMR

import json
import boto3
import datetime
from datetime import timezone

INSUFFICIENT_CAPACITY_EXCEPTION_DETAIL_TYPE = "EMR Instance Group Provisioning"
INSUFFICIENT_CAPACITY_EXCEPTION_EVENT_CODE = (
    "EC2 provisioning - Insufficient Instance Capacity"
)
ALLOWED_INSTANCE_TYPES_TO_USE = [
    "m5.xlarge",
    "c5.xlarge",
    "m5.4xlarge",
    "m5.2xlarge",
    "t3.xlarge",
]
CLUSTER_START_ACCEPTABLE_STATES = ["WAITING", "RUNNING"]
CLUSTER_START_SLA = 20

CLIENT = boto3.client("emr", region_name="us-east-1")

# checks if the incoming event is 'EMR Instance Fleet Provisioning' with eventCode 'EC2 provisioning - Insufficient Instance Capacity'
def is_insufficient_capacity_event(event):
    if not event["detail"]:
        return False
    else:
        return (
            event["detail-type"] == INSUFFICIENT_CAPACITY_EXCEPTION_DETAIL_TYPE
            and event["detail"]["eventCode"]
            == INSUFFICIENT_CAPACITY_EXCEPTION_EVENT_CODE
        )


# checks if the cluster is eligible for termination
def is_cluster_eligible_for_termination(event, describeClusterResponse):
    # instanceGroupType could be CORE, MASTER OR TASK
    instanceGroupType = event["detail"]["instanceGroupType"]
    clusterCreationTime = describeClusterResponse["Cluster"]["Status"]["Timeline"][
        "CreationDateTime"
    ]
    clusterState = describeClusterResponse["Cluster"]["Status"]["State"]

    now = datetime.datetime.now()
    now = now.replace(tzinfo=timezone.utc)
    isClusterStartSlaBreached = clusterCreationTime < now - datetime.timedelta(
        minutes=CLUSTER_START_SLA
    )

    # Check if instance group receiving Insufficient capacity exception is CORE or PRIMARY (MASTER),
    # and it's been more than 20 minutes since cluster was created but the cluster state and the cluster state is not updated to RUNNING or WAITING
    if (
        (instanceGroupType == "CORE" or instanceGroupType == "MASTER")
        and isClusterStartSlaBreached
        and clusterState not in CLUSTER_START_ACCEPTABLE_STATES
    ):
        return True
    else:
        return False


# Choose item from the list except the exempt value
def choice_excluding(exempt):
    for i in ALLOWED_INSTANCE_TYPES_TO_USE:
        if i != exempt:
            return i


# Create a new cluster by choosing different InstanceType.
def create_cluster(event):
    # instanceGroupType cloud be CORE, MASTER OR TASK
    instanceGroupType = event["detail"]["instanceGroupType"]

    # Following two lines assumes that the customer that created the cluster already knows which instance types they use in original request
    instanceTypesFromOriginalRequestMaster = "m5.xlarge"
    instanceTypesFromOriginalRequestCore = "m5.xlarge"

    # Select new instance types to include in the new createCluster request
    instanceTypeForMaster = (
        instanceTypesFromOriginalRequestMaster
        if instanceGroupType != "MASTER"
        else choice_excluding(instanceTypesFromOriginalRequestMaster)
    )
    instanceTypeForCore = (
        instanceTypesFromOriginalRequestCore
        if instanceGroupType != "CORE"
        else choice_excluding(instanceTypesFromOriginalRequestCore)
    )

    print("Starting to create cluster...")
    instances = {
        "InstanceGroups": [
            {
                "InstanceRole": "MASTER",
                "InstanceCount": 1,
                "InstanceType": instanceTypeForMaster,
                "Market": "ON_DEMAND",
                "Name": "Master",
            },
            {
                "InstanceRole": "CORE",
                "InstanceCount": 1,
                "InstanceType": instanceTypeForCore,
                "Market": "ON_DEMAND",
                "Name": "Core",
            },
        ]
    }
    response = CLIENT.run_job_flow(
        Name="Test Cluster",
        Instances=instances,
        VisibleToAllUsers=True,
        JobFlowRole="EMR_EC2_DefaultRole",
        ServiceRole="EMR_DefaultRole",
        ReleaseLabel="emr-6.10.0",
    )

    return response["JobFlowId"]


# Terminated the cluster using clusterId received in an event
def terminate_cluster(event):
    print("Trying to terminate cluster, clusterId: " + event["detail"]["clusterId"])
    response = CLIENT.terminate_job_flows(JobFlowIds=[event["detail"]["clusterId"]])
    print(f"Terminate cluster response: {response}")


def describe_cluster(event):
    response = CLIENT.describe_cluster(ClusterId=event["detail"]["clusterId"])
    return response


def lambda_handler(event, context):
    if is_insufficient_capacity_event(event):
        print(
            "Received insufficient capacity event for instanceGroup, clusterId: "
            + event["detail"]["clusterId"]
        )

        describeClusterResponse = describe_cluster(event)

        shouldTerminateCluster = is_cluster_eligible_for_termination(
            event, describeClusterResponse
        )
        if shouldTerminateCluster:
            terminate_cluster(event)

            clusterId = create_cluster(event)
            print("Created a new cluster, clusterId: " + clusterId)
        else:
            print(
                "Cluster is not eligible for termination, clusterId: "
                + event["detail"]["clusterId"]
            )

    else:
        print("Received event is not insufficient capacity event, skipping")
```