为了后人,我接受了 John Rotenstein 的出色建议,并使用 VPC 向导让事情顺利进行。事实证明,关键细节与 NAT 网关的构造有关。
如果您希望您的 Lambda 函数能够访问 AWS 开发工具包和您的 VPC 资源,您至少需要两个子网(一个用于公共资源,一个用于私有资源)。以下是您需要执行的 VPC 命令,这些命令与 VPC 向导所发生的类似:
创建一个新的 VPC,或将这些环境变量设置为您现有的变量
export REGION=us-west-2 #or whatever region you want
export VPC_ID=`aws ec2 create-vpc --cidr-block 10.1.0.0/16 \
--query Vpc.VpcId --output text`
为您的公共资源创建一个互联网网关
export IGW_ID=`aws ec2 create-internet-gateway \
--query InternetGateway.InternetGatewayId --output text`
aws ec2 attach-internet-gateway --internet-gateway-id $IGW_ID --vpc-id $VPC_ID
使用上述 IGW 为您的公共子网创建路由表
export ROUTE_TABLE_ID_PUBLIC=`aws ec2 describe-route-tables \
--filter Name=vpc-id,Values=$VPC_ID --query RouteTables[0].RouteTableId --output text`
export SUBNET_ID_PUBLIC=`aws ec2 create-subnet --vpc-id $VPC_ID \
--cidr-block 10.1.0.0/24 --availability-zone ${REGION}a \
--query Subnet.SubnetId --output text`
aws ec2 associate-route-table --subnet-id $SUBNET_ID_PUBLIC \
--route-table-id $ROUTE_TABLE_ID_PUBLIC
aws ec2 create-route --route-table-id $ROUTE_TABLE_ID_PUBLIC \
--gateway-id $IGW_ID --destination-cidr-block 0.0.0.0/0
为 NAT 网关创建 IP 分配,用于私有子网
export IP_ALLOCATION_ID=`aws ec2 allocate-address --domain vpc \
--query AllocationId --output text`
export ROUTE_TABLE_ID_PRIVATE=`aws ec2 create-route-table --vpc-id $VPC_ID \
--query RouteTable.RouteTableId --output text`
export SUBNET_ID_PRIVATE=`aws ec2 create-subnet --vpc-id $VPC_ID \
--cidr-block 10.1.1.0/24 --availability-zone ${REGION}b \
--query Subnet.SubnetId --output text`
aws ec2 associate-route-table --subnet-id $SUBNET_ID_PRIVATE \
--route-table-id $ROUTE_TABLE_ID_PRIVATE
export NAT_GW_ID=`aws ec2 create-nat-gateway --subnet-id $SUBNET_ID_PUBLIC \
--allocation-id $IP_ALLOCATION_ID --query NatGateway.NatGatewayId --output text`
在这里稍等片刻 - NAT 网关需要一些时间才能准备好并可用于进一步的命令。
关键细节(我无法在 AWS 文档中找到)在上面的最后一条命令中 - NAT 网关 必须 使用 PUBLIC 创建子网,即使它与 PRIVATE 路由表相关联:
使用 NAT 网关创建私有路由表
aws ec2 create-route --route-table-id $ROUTE_TABLE_ID_PRIVATE \
--gateway-id $NAT_GW_ID --destination-cidr-block 0.0.0.0/0
创建安全组等......
export SECURITY_GROUP_ID=`aws ec2 create-security-group --vpc-id $VPC_ID \
--group-name mygroup --description "My SG" \
--query GroupId --output text`
aws ec2 authorize-security-group-ingress --group-id $SECURITY_GROUP_ID \
--protocol tcp --port 22 --cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress --group-id $SECURITY_GROUP_ID \
--cidr 10.1.0.0/16 --protocol all
此时,您应该能够创建与私有子网关联的 Lambda 函数,这些函数可以访问 VPC 中的资源,还可以调用 Internet(AWS SDK 使用所必需的)。这是一个执行此操作的示例 Lambda 函数:
创建在您的 VPC 中执行 Lambda 函数所需的 IAM 角色
aws iam create-instance-profile --instance-profile-name testRole
testRole_trust_policy.json:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
export TEST_ROLE_ARN=`aws iam create-role --role-name testRole \
--assume-role-policy-document file://testRole_trust_policy.json \
--query Role.Arn --output text`
testRole_policy.json:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"lambda:*",
"ec2:CreateNetworkInterface",
"ec2:DescribeNetworkInterfaces",
"ec2:DeleteNetworkInterface"
],
"Resource": [
"*"
]
}
]
}
aws iam put-role-policy --role-name testRole \
--policy-name testRole --policy-document file://testRole_policy.json
aws iam add-role-to-instance-profile \
--instance-profile-name testRole \
--role-name testRole
使用此 IAM 角色创建 Lambda 函数
contents of lambda.zip:
- test.js:
exports.handler = (event, context, callback) => {
AWS = require('aws-sdk'),
lambda = new AWS.Lambda({"apiVersion": '2015-03-31'});
lambda.listFunctions(callback);
};
aws lambda create-function --function-name testWithVPC \
--runtime nodejs6.10 --role $TEST_ROLE_ARN \
--handler test.handler --timeout 10 \
--zip-file fileb://lambda.zip \
--vpc-config SubnetIds=$SUBNET_ID_PRIVATE,SecurityGroupIds=$SECURITY_GROUP_ID
执行并查看结果:
aws lambda invoke --function-name testWithVPC with.txt
with.txt:
{"NextMarker":null,"Functions":[{"FunctionName":"testWithVPC","FunctionArn": ....]}
这足以演示功能。我基于此模式构建的项目可在此处获得,以获得更强大的示例:https://github.com/jakefeasel/sqlfiddle3