关于亚马逊网络服务:如何在一段时间后自动终止 AWS EMR 集群

How to terminate AWS EMR Cluster automatically after some time

我目前手头的任务是在设定的时间段(基于某些指标)后终止长期运行的 EMR 集群。 Google Dataproc 在称为"集群计划删除"的东西中具有此功能,此处列出:https://cloud.google.com/dataproc/docs/concepts/configuring-clusters/scheduled-deletion

这在 EMR 原生上是可能的吗?也许使用 Cloudwatch 指标?或者我是否可以编写一个长时间运行的 jar,它将位于 EMR 主节点上,只轮询Yarn以获取一些空闲时间指标,然后在设定的时间段后关闭集群?

编辑:更多说明。我想要一些功能,其中集群基于空闲时间终止一些 x 时间。例如如果集群已经启动了一段时间,但作业已经运行了 1 个小时,并且集群只是坐在那里无所事事,那么我希望能够终止集群。


请记住您在问题中提供的说明,可能有 3 种可能的方法来做到这一点。

1) 使用 EMR 集群的 AWS CloudWatch 指标 isIdle。此指标跟踪集群是否处于活动状态,但当前未运行任务。您可以设置在集群空闲一段时间(例如三十分钟)时触发警报。
参考:https://docs.aws.amazon.com/emr/latest/ManagementGuide/UsingEMR_ViewingMetrics.html

2) 使用 AWS CloudWatch 事件/规则和 AWS Lambda 函数检查空闲 EMR 集群。您可以在 AWS 控制台级别实现可见性,并且可以轻松启用和禁用它。推荐

3) 其他一些基于 Shell 的自定义解决方案,该解决方案针对 EMR 集群主节点上的 CRON 作业运行,但您将在 AWS 控制台级别失去其可见性,并且您可能还需要 SSH 访问。

使用第二种方法的解决方案:推荐

考虑到这一点,我开发了一个小框架来使用上面提到的第二个解决方案来实现这一点。此框架是一个基于 AWS 的解决方案,它使用 AWS CloudWatch 和 AWS Lambda 使用 Python 脚本,该脚本使用 Boto3 来终止已空闲一段时间的 AWS EMR 集群。

您指定最大空闲时间阈值,AWS CloudWatch 事件/规则会触发一个 AWS Lambda 函数,该函数会查询所有处于 WAITING 状态的 AWS EMR 集群,并将当前时间与 AWS EMR 集群的就绪时间进行比较,以防万一到目前为止没有添加 EMR 步骤或将当前时间与 AWS EMR 集群的最后一步的结束时间进行比较。如果阈值已被破坏,AWS EMR 将在启用终止保护后终止。如果不是,它将跳过该 AWS EMR 集群。

AWS CloudWatch 事件/规则将决定 AWS Lambda 函数检查空闲 AWS EMR 集群的频率。

您可以随时禁用 AWS CloudWatch 事件/规则,只需单击一下即可禁用此框架,而无需删除其 AWS CloudFormation 堆栈。

AWS Lambda 函数使用 Python 3.7 作为其运行时环境。

您可以在此处从 GitHub 获取代码并使用它:https://github.com/abdullahkhawer/auto-terminate-idle-emr

我们将非常感谢对此解决方案的任何贡献、改进和建议。 :)


最简单的方法将用于 Amazon CloudWatch 的 Amazon EMR 指标和维度。有一个 isIdle 布尔值"表示集群不再执行工作"。

您可以创建一个 CloudWatch 警报,说明它是否为真超过 x 分钟,然后触发警报。这将向 Amazon SNS 发送一条消息,该消息可以触发 Lambda 函数来关闭集群。

组件:

  • 亚马逊 CloudWatch 警报
  • 亚马逊 SNS 队列
  • AWS Lambda 函数

更新:这显然不合适(请参阅下面的评论)。

另一种方法是:

  • 使用 Amazon CloudWatch Events 每隔 x 秒安排一次 Lambda 函数
  • Lambda 函数查找具有特定标签的任何集群,该标签指示要等待多长时间才能关闭(例如 40 分钟)。如果标签不存在,则集群保持不变。
  • Lambda 函数查询集群状态(不知何故——可能通过 Hadoop API 调用),然后:

    • 如果集群空闲且没有 Idle Since 标签,则添加一个带有当前时间戳的 Idle since 标签
    • 如果集群空闲并且自 Idle since 标签中的时间戳超过 x 分钟,则终止集群。
    • 如果集群不是空闲的,请移除 Idle since 标签(如果存在)


我不得不做一个类似的实现,仅仅考虑集群经过的时间并不能解决我们的问题。

所以我们想出了一个使用 Hadoop API 的方法,你可以在这里找到它们

1
https://hadoop.apache.org/docs/current/hadoop-yarn/hadoop-yarn-site/ResourceManagerRest.html#Cluster_Scheduler_API

这就是我们所做的,

  • 要求启动集群的用户添加一个标签,如 "AutoShutDown":"True:BufferMinutes",这里 "AutoShutDown" 是键,"True:BufferMinutes" 是值标签的

  • 这里的 BufferMinutes 是以分钟为单位的时间(30、60 等)

  • 创建一个 Lambda 以访问所有使用步骤 1 配置的集群的 hadoop api(如果用户不添加标签,则集群保持不变)并获取最后完成的作业的结束时间(仅当所有作业已完成/终止),如果任何作业仍在运行,则什么也不做并退出。

  • 现在

    datetime_difference = (current_time - lastFinished)
    如果(日期时间差 > 请求时间)
    {
    终止集群
    }

  • 创建一个云监视触发器并将作为目标创建的 lambda 添加到其中,安排触发器按要求运行。

  • 注意:Lambda 是用 python 编写的,因此使用了 boto3,客户端将是 "emr",就像上面的解决方案中提到的 abdullahkhawer 一样。

    此实现为用户提供了选择的灵活性,并减轻了开发操作的大量负担。