AWS EMR实例组竞价实例扩展失败切换按需实例方法

时间:2023-02-06 16:06:15

 

背景

本文介绍如何解决EMR集群实例组模式下竞价实例请求失败后无法切换到按需实例问题,主要思路是通过CloudWatch+Lambda实现在EMR集群竞价实例请求失败情况下补充制定数量的按需实例到EMR集群。

目前较多公司使用EMR构建大数据平台,使用按需实例+竞价实例混合配置完成计算任务所需资源,可最大程度节省成本并满足平台高峰期计算能力的需求。但竞价实例有可能会出现容量不足无法正常请求的情况,如何在竞价实例请求失败的情况下补充按需实例到集群,是使用该架构用户需要注意的问题。

 

架构

主题逻辑为:通过自动化的脚本监控竞价实例组状态,如果指定时间内实例组处于扩展状态但添加的实例为0的情况下触发Lambda程序,由Lambda程序扩展按需实例并添加到集群中。

 

AWS EMR实例组竞价实例扩展失败切换按需实例方法

配置

1.   定时任务监控竞价实例组

前提:需配置相应的权限才可完成实例组状态的监控,建将程序配置到EMR Master节点来监控竞价实例组配置,可节省相应权限配置。

配置定时任务监控竞价实例组状态:

1.      运行crontab -e命令

2.      写入如下定时任务(可根据实际情况配置)

*/5 * * * * sh /backup/scripts/linkyoyo-emr-instance-group-status.sh

 

3.      编写定时任务脚本,脚本内容包括两个部分,定时任务脚本主体内容如下:

#!/bin/bash

Instance=$(hostname -I | awk '{print $1}') 

#通过脚本 获取该实例目前扩展状态

task=$(/usr/bin/python /backup/scripts/spot-task.py)

#实例组扩充状态指标上传

aws cloudwatch put-metric-data --namespace Mynamespace --metric-name Mymetricname --dimensions Instance=$Instance --unit Count --value $task

4.      编写python脚本定时任务脚本,python程序如下:

import os

import json

#获取对应EMR集群相关信息,并读取到tasks缓存变量

tasks = os.popen("aws emr describe-cluster --cluster-id j- xxxxxxxxx").read()

tasks=json.loads(tasks)

#设置标识位

flag=1

 

#循环读取集群中不同实例组的相关信息并进行判断

for i in range(4):

 

  #对集群信息中的实例组的id进行读取

  task_id=tasks["Cluster"]["InstanceGroups"][i]["Id"]

 

  #读取该实例组的状态信息

  task_status=tasks["Cluster"]["InstanceGroups"][i]["Status"]["State"]

 

  #读取该实例组的运行实例数量

  task_num=tasks["Cluster"]["InstanceGroups"][i]["RunningInstanceCount"]

 

  #判断是否为目标监控实例组,是则判断状态和数量,如果状态不为running且数量为0,则置标识位为0

  if task_id == "ig-xxxxxxxxx":

      if task_status != "RUNNING":

          if task_num == "0":

              flag=0

 

#输出标识位

print (flag)

 

定时任务配置注意事项:

--namespace  命名空间(必填)

--metric-name 监控项名称(必填)

--dimensions 区别信息,,可以设为实例ID或者其他可以用来区分机器的标识,例如:Instance=i-xxxxxxx

--value 数值,监控项对应数值

5. 以上程序配置完成后可在Amazon CloudWatch控制台查看到配置的指标信息,

 

 

2.   配置Lambda程序

配置用于扩展按需实例组的Lambda程序

首先创建Lambda程序所需的IAM Role,创建步骤如下:

1.       打开 Amazon IAM控制台:

2.       在导航窗格上选择Roles

3.       选择Create role

4.       Trusted entity type选择Amazon Web Services service

5.       Common use cases选择Lambda,点击下一步

6.       选择Create policy

7.       请确认创建的policy 包含ModifyInstanceGroups权限,权限配置可参考:

{

    "Version": "2012-10-17",

    "Statement": [

        {

            "Sid": "VisualEditor0",

            "Effect": "Allow",

            "Action": "elasticmapreduce:ModifyInstanceGroups",

            "Resource": "*"

        }

    ]

}

8.       在新IAM Role中选择新创建的policy,完成IAM Role创建。

 

 

然后创建Lambda并部署程序代码

1.       打开 Amazon Lambda控制台:

2.       在导航窗格上选择Functions

3.       选择Create function

4.       选择Author from scratch选项,填写Function name名称

5.       Runtime选择python3.9

6.       Change default execution role选择Use an existing role并在列表中选择上一步已经创建的IAM Role。

7.       完成Lambda的创建

8.       在新创建的Lambda程序的Code选项中部署如下Python代码:

 

import boto3

import datetime

 

# 获取当前时间

today = datetime.datetime.now().strftime("%H:%M:%S")

class Emrclient(object):

    def __init__(self):

        # 修改emr所在区域

        self.region_name = "us-east-1"

        self.client = boto3.client("emr", region_name=self.region_name)

 

    #  EMR修改实例组的节点数

    def modify_instance_groups(self, ClusterId, InstanceGroupId, InstanceCount):

        response = self.client.modify_instance_groups(

            ClusterId=ClusterId,

            InstanceGroups=[

                {

                    'InstanceGroupId': InstanceGroupId,

                    'InstanceCount': InstanceCount,

                },

            ]

        )

        return response

  

def lambda_handler(event, context):

    # 实例化

    emr = Emrclient()

    # 需传入EMR集群ID,实例组ID,自定义节点数量

    response = emr.modify_instance_groups('j-xxxxxxx', 'ig-xxxxxxx', 节点数量)

  

3.   配置CloudWatch告警

创建CloudWatch告警,在达到阈值的时候扩展按需实例组数量。CloudWatch配置步骤如下:

配置SNS通知

1.       打开 Amazon SNS控制台:

2.       在导航窗格上选择Topics

3.       点击Create topic

4.       在Type中选择Standard

5.       填写Name后选择Create topic

6.       在导航窗格上选择Subscriptions

7.       点击Create subscription

8.       在Topic ARN选择步骤三创建的Topic

9.       在Protocol选择Amazon Lambda

10.   在Endpoint中选择已配置的Lambda程序

11.   点击Create subscription完成SNS配置

 

Amazon SNS 与 Amazon Lambda 结合使用:

​https://docs.amazonaws.cn/lambda/latest/dg/with-sns.html​

 

创建CloudWatch告警

1.       打开 Amazon CloudWatch控制台:

2.       在导航窗格上选择Functions

3.       选择In alarm

4.       点击Create alarm

5.       在Metric中选择定时任务程序输出的指标名称

6.       在Statistic选择Average,Period选择5minutes (可根据实际配置情况选择)

7.       Threshold type选择Static

8.       Whenever xxxx is中选择Lower<1,目前程序中1为正常状态0是异常状态。

9.       在Additional configuration中选择Datapoints to alarm的值,点击下一步。该值配置的是触法告警的次数,可根据实际情况配置,本文推荐配置6最大为6,这会在连续6个5分钟指标都处于告警的状态才会触发告警。

10.   配置Notification选项,选择已配置的SNS通知,点击下一步

11.   填写Alarm nameAlarm description后即可完成CloudWatch配置

 

更对cloudwatch alarm配置可查看:

​https://docs.amazonaws.cn/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html​