从AWS Lambda触发AWS EMR流程时超时

时间:2018-04-30 01:41:45

标签: javascript amazon-web-services aws-lambda aws-sdk amazon-emr

我正在尝试在JavaScript中运行AWS lambda应用程序,但我无法使其正常工作。 我没有任何关于JS配置和触发的麻烦(我成功运行了一个hello world应用程序),但是我遇到了aws-sdk库的问题。说实话,我不知道这是一个与网络配置或IAM配置有关的问题,但我很确定这不是一个脚本问题,因为我可以在我的计算机本地运行它没有任何问题。 我遇到的主要问题是,当lambda app调用AWS EMR API时,会出现超时错误。这就像lambda无法与EMR沟通。

在这里,您可以看到emr客户端(console.log(emr_client)):

  emr: Service {
    config: 
     Config {
       credentials: 
        EnvironmentCredentials {
          expired: false,
          expireTime: null,
          accessKeyId: 'XXXXXXXXXXXXXXXX',
          sessionToken: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
          envPrefix: 'AWS' },
       credentialProvider: CredentialProviderChain { providers: [Array] },
       region: 'us-west-2',
       logger: null,
       apiVersions: {},
       apiVersion: '2009-03-31',
       endpoint: 'elasticmapreduce.us-west-2.amazonaws.com',
       httpOptions: { timeout: 120000 },
       maxRetries: undefined,
       maxRedirects: 10,
       paramValidation: true,
       sslEnabled: true,
       s3ForcePathStyle: false,
       s3BucketEndpoint: false,
       s3DisableBodySigning: true,
       computeChecksums: true,
       convertResponseTypes: true,
       correctClockSkew: false,
       customUserAgent: null,
       dynamoDbCrc32: true,
       systemClockOffset: 0,
       signatureVersion: 'v4',
       signatureCache: true,
       retryDelayOptions: {},
       useAccelerateEndpoint: false,
       accesKeyId: 'XXXXXXXXXXXXXXXX' },
    isGlobalEndpoint: false,
    endpoint: 
     Endpoint {
       protocol: 'https:',
       host: 'elasticmapreduce.us-west-2.amazonaws.com',
       port: 443,
       hostname: 'elasticmapreduce.us-west-2.amazonaws.com',
       pathname: '/',
       path: '/',
       href: 'https://elasticmapreduce.us-west-2.amazonaws.com/' },
    _clientId: 1 
    }

一些AWS配置信息:

  1. 我创建了一个我的EMR集群所在的VPC,位于us-west-2区域,我在那里触发lambda函数(因为我可以确认安慰process.env.AWS_REGION)。

  2. 我设置了一个先前在同一个VPC中创建的子网。 EMR集群位于其中,Lambda函数可以访问它。

  3. 我在同一个VPC中设置了一个安全组,允许所有的入口/出口(所有端口来自和到0.0.0.0/0)以查看我是否有配置问题。

  4. 我设置了一个执行角色,该角色附加了以下策略并将其与我的lambda函数相关联:

  5.   

    AWSLambdaFullAccess

         

    AmazonElasticMapReduceFullAccess

         

    AWSLambdaExecute

         

    AWSLambdaVPCAccessExecutionRole

         

    AWSLambdaRole

         

    AWSLambdaENIManagementAccess

    最后,我的代码:

    const AWS = require('aws-sdk');
    
    exports.handler = (event, context, callback) => {
      const emr = new AWS.EMR({
        apiVersion:'2009-03-31',
        region: process.env.AWS_REGION,
        accessKeyId: process.env.AWS_ACCESS_KEY_ID,
        secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
      });
    
      const flowSteps = {
        JobFlowId: process.env['JOB_FLOW_ID'],
        Steps: [{
          Name: "my_beautiful_step",
          ActionOnFailure: "CANCEL_AND_WAIT",
          HadoopJarStep: {
            Jar: "command-runner.jar",
            Args: [
              "spark-submit",
              "--master"," yarn",
              ...
              ...
              ...
            ]
          }
        }]
      };
    
      emr.addJobFlowSteps(flowSteps, (err, data) => {
        if (err) {
          console.log('ERROR', err, err.stack);
        } else {
          console.log('NO ERROR', data);
        }
      });
    
    };
    

    修改 我尝试与s3(获取存储桶位置)进行通信,以测试问题是否仅适用于EMR,但功能也是时间。

1 个答案:

答案 0 :(得分:0)

好吧,我解决了我的问题。基本上,如果您没有互联网访问权限,则无法在VPC内调用AWS API端点,因为大多数aws服务都有公共URL,例如<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>。当您控制EMR客户端对象时,您可以清楚地看到这一点(这也适用于我验证的其他客户端对象,例如S3)

https://elasticmapreduce.us-west-2.amazonaws.com

无论如何,AWS在vpcs VPC Endpoints中提供了一些本地端点,因此您可以访问VPC内的那些服务端点,而无需访问Internet。在另一种情况下,您必须设置NAT网关+互联网网关(〜每月30美元)才能访问其他服务,例如EMR。