Тайм-аут при запуске шага потока AWS EMR от AWS Lambda - PullRequest
0 голосов
/ 30 апреля 2018

Я пытаюсь запустить лямбда-приложение AWS на JavaScript, но не могу заставить его работать должным образом. У меня нет проблем с настройкой и запуском JS (я успешно запустил приложение hello world), но у меня проблемы с библиотекой aws-sdk. Честно говоря, я не знаю, является ли это проблемой, связанной с конфигурацией сети или конфигурацией IAM, но я почти уверен, что это не проблема сценариев, потому что я могу запустить ее без каких-либо проблем локально на моем компьютере. Основная проблема у меня заключается в том, что когда лямбда-приложение вызывает API AWS EMR, возникает ошибка тайм-аута. Как будто лямбда не может общаться с 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. Я создал VPC, где находится мой кластер EMR, расположенный в регионе us-west-2, и я запускаю там лямбда-функцию (как я могу подтвердить, утешительно process.env.AWS_REGION).

  2. Я создал подсеть, которая ранее была создана в этом же VPC. Кластер EMR находится внутри него, и функция Lambda имеет к нему доступ.

  3. Я установил группу безопасности в этом же VPC со всеми разрешенными входами / выходами (все порты от и до 0.0.0.0/0), чтобы посмотреть, не возникла ли у меня там проблема конфигурации.

  4. Я установил роль выполнения, к которой были прикреплены следующие политики, и связал ее с моей лямбда-функцией:

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);
    }
  });

};

EDIT: Я попытался связаться с s3 (получить местоположение корзины) только для того, чтобы проверить, была ли проблема только в EMR, но также в тайм-аутах функции.

1 Ответ

0 голосов
/ 03 мая 2018

Ну, я решил свою проблему. По сути, вы не можете вызывать конечные точки API AWS внутри VPC, если у вас нет доступа к Интернету, поскольку большинство служб aws имеют общедоступный URL-адрес, например, https://elasticmapreduce.us-west-2.amazonaws.com. Вы можете ясно видеть это, когда утешаете клиентский объект EMR (и это относится также к другим клиентским объектам, таким как S3, как я проверял)

Service {
  config: 
   Config {
     ...
     ...
     region: 'us-west-2',
     logger: null,
     apiVersions: {},
     apiVersion: null,
     endpoint: 'elasticmapreduce.us-west-2.amazonaws.com',
     httpOptions: { timeout: 120000 },
     maxRetries: undefined,
   },
  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/' 
    },
  ...
}

В любом случае, AWS предоставляет некоторые локальные конечные точки внутри vpcs Конечные точки VPC , поэтому вы можете получить доступ к этим конечным точкам служб внутри VPC без доступа к Интернету. В другом случае вам необходимо установить NAT-шлюз + интернет-шлюз (~ 30 $ в месяц) для доступа к другим службам, таким как EMR.

...