我正在尝试在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配置信息:
我创建了一个我的EMR集群所在的VPC,位于us-west-2区域,我在那里触发lambda函数(因为我可以确认安慰process.env.AWS_REGION
)。
我设置了一个先前在同一个VPC中创建的子网。 EMR集群位于其中,Lambda函数可以访问它。
我在同一个VPC中设置了一个安全组,允许所有的入口/出口(所有端口来自和到0.0.0.0/0)以查看我是否有配置问题。
我设置了一个执行角色,该角色附加了以下策略并将其与我的lambda函数相关联:
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,但功能也是时间。
答案 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。