使用 AWS CLI 管理 Lambda
AWS Lambda 是 AWS 提供的一个无服务器(Serverless)计算服务。它允许你无需预置任何服务器即可运行代码,只需为实际消耗的计算时间付费。Lambda 会根据请求的数量自动扩展,处理来自各种事件源的请求,使你能够构建高效、可扩展的应用程序。
简单来说,Lambda 就是一个存储在云端的函数。
创建 IAM 角色
Lambda 函数需要由 IAM 角色来执行。如果你还没有 IAM 角色,可以通过下面的方法来创建一个新的 IAM 角色。
-
创建信任策略文件:
新建一个信任策略文件,并在文件中声明 Lambda 服务可以承担此角色的权限:
vim trust-policy.json
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
-
使用信任策略创建角色:
aws iam create-role \ --role-name 'LambdaBasicExecutionRole' \ --assume-role-policy-document 'file://trust-policy.json'
-
附加权限策略:
将
AWSLambdaBasicExecutionRole
权限策略附加到该角色,以便 Lambda 函数能够写入 CloudWatch 日志。aws iam attach-role-policy \ --role-name 'LambdaBasicExecutionRole' \ --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
-
查询角色 ARN:
export ROLE_ARN=$( aws iam get-role \ --role-name 'LambdaBasicExecutionRole' \ --query Role.Arn \ --output text )
创建 Lambda 函数
上传 Lambda
现在我们创建一个示例函数,当这个函数被调用时,返回一条欢迎语句。
-
编辑代码:
vim lambda_function.py
import json import logging import cowsay logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(event, context): first_name = event['first_name'] last_name = event['last_name'] speech = f"Hello, {first_name} {last_name}!" cowsay.cow(speech) logger.info(f"CloudWatch logs group: {context.log_group_name}") data = {"speech": speech} return json.dumps(data)
Lambda 函数被调用时,调用参数会被传入
event
对象。 -
打包代码:
zip function.zip lambda_function.py
-
上传 Lambda 函数:
aws lambda create-function \ --function-name 'my-function' \ --zip-file 'fileb://function.zip' \ --handler 'lambda_function.lambda_handler' \ --runtime 'python3.12' \ --role $ROLE_ARN \ --query '{FunctionArn:FunctionArn,FunctionName:FunctionName,Handler:Handler,LoggingConfig:LoggingConfig}'
--handler
参数的形式为主文件名.主函数名
--role
参数填写你要用来执行 Lambda 函数的 IAM 角色的 ARN。
上传 Layer
我们的代码里使用了第三方库 cowsay
,因此要将库打包上传到 Layer。
-
创建虚拟环境:
python -m venv my_env
-
安装依赖:
my_env/bin/pip install cowsay
- 对于一些不是纯 Python 的依赖(如 numpy),你需要在安装时指定平台和 Python 版本。参见使用原生库创建 .zip 部署包 | AWS Lambda
-
打包依赖:
mkdir python cp -r my_env/lib python zip -r python.zip python
-
上传 Layer:
-
通过 Lambda API 上传:
aws lambda publish-layer-version \ --layer-name 'my-layer' \ --zip-file 'fileb://python.zip' \ --description 'Layer with cowsay' \ --compatible-runtimes 'python3.12' \ --compatible-architectures 'x86_64' \ --query '{LayerVersionArn:LayerVersionArn,Version:Version}'
-
如果依赖包超过 50 MB 需要通过 S3 上传:
aws s3 cp python.zip s3://my-bucket/python.zip aws lambda publish-layer-version \ --layer-name 'my-layer' \ --content 'S3Bucket=my-bucket,S3Key=python.zip' \ --description 'Layer with cowsay' \ --compatible-runtimes 'python3.12' \ --compatible-architectures 'x86_64' \ --query '{LayerVersionArn:LayerVersionArn,Version:Version}'
-
-
查询 Layer 版本 ARN:
export LAYER_VERSION_ARN=$( aws lambda list-layer-versions \ --layer-name 'my-layer' \ --query 'LayerVersions[0].LayerVersionArn' \ --output text )
-
将 Layer 添加到 Lambda 函数:
aws lambda update-function-configuration \ --function-name 'my-function' \ --layers $LAYER_VERSION_ARN \ --query '{FunctionArn:FunctionArn,FunctionName:FunctionName,Handler:Handler,Layers:{Arn:Layers[*].Arn},LoggingConfig:LoggingConfig}'
参见:
- 创建第一个 Lambda 函数 | AWS Lambda
- 使用 Python Lambda 函数的层 | AWS Lambda
- 将 .zip 文件归档用于 Python Lambda 函数 | AWS Lambda
调用 Lambda 函数
手动触发
aws lambda invoke \
--function-name 'my-function' \
--cli-binary-format raw-in-base64-out \
--payload '{ "first_name": "John", "last_name": "Connor" }' \
response.json
$ cat response.json
"{\"speech\": \"Hello, John Connor!\"}"
定时触发
Amazon EventBridge 是一项无服务器事件总线服务,可从应用程序、AWS 服务和 SaaS 应用程序中收集和路由事件,以便实现自动化工作流和系统集成。
-
创建 EventBridge 规则:
aws events put-rule \ --name 'my-rule' \ --schedule-expression 'cron(50 13 * * ? *)'
- 这将创建一个每天 UTC 13:50 自动触发的规则。
- 可以通过
date -u +'%H:%M'
命令查看当前 UTC 时间。
-
保存规则 ARN:
export RULE_ARN=$( aws events describe-rule \ --name 'my-rule' \ --query Arn \ --output text )
-
授权规则调用 Lambda 函数:
默认情况下,AWS 服务之间的交互是受限的,因此我们要授权 EventBridge 规则调用 Lambda 函数:
aws lambda add-permission \ --function-name 'my-function' \ --statement-id EventBridgeInvoke \ --action 'lambda:InvokeFunction' \ --principal events.amazonaws.com \ --source-arn $RULE_ARN
-
保存 Lambda 函数 ARN:
export LAMBDA_ARN=$( aws lambda get-function \ --function-name 'my-function' \ --query Configuration.FunctionArn \ --output text )
-
为规则添加目标:
添加 Lambda 函数为目标,当规则触发时,事件将自动被发送到目标。
aws events put-targets \ --rule 'my-rule' \ --targets "Id=1,Arn=$LAMBDA_ARN"
查看日志
Amazon CloudWatch 是一项全面的监控和管理服务,用于跟踪和分析 AWS 云资源和应用程序的性能和日志,以增强可见性和自动化管理能力。
-
查询日志流:
日志流是根据时间顺序创建的,每次函数执行通常会创建一个新的日志流。
export LOG_STREAM_NAME=$( aws logs describe-log-streams \ --log-group-name '/aws/lambda/my-function' \ --order-by LastEventTime \ --descending \ --limit 1 \ --query 'logStreams[0].logStreamName' \ --output text )
-
获取日志流的日志事件:
aws logs get-log-events \ --log-group-name '/aws/lambda/my-function' \ --log-stream-name $LOG_STREAM_NAME \ --query 'events[*].message' \ --output text
INIT_START Runtime Version: python:3.12.v38 Runtime Version ARN: arn:aws:lambda:ap-east-1::runtime:7515e00d6763496e7a147ffa395ef5b0f0c1ffd6064130abb5ecde5a6d630e86 START RequestId: 12f2ce5e-028c-4303-a440-2050c47d029a Version: $LATEST ___________________ | Hello, John Connor! | =================== \ \ ^__^ (oo)\_______ (__)\ )\/\ ||----w | || || [INFO] 2025-01-08T10:24:16.077Z 12f2ce5e-028c-4303-a440-2050c47d029a CloudWatch logs group: /aws/lambda/my-function END RequestId: 12f2ce5e-028c-4303-a440-2050c47d029a REPORT RequestId: 12f2ce5e-028c-4303-a440-2050c47d029a Duration: 2.27 ms Billed Duration: 3 ms Memory Size: 128 MB Max Memory Used: 32 MB Init Duration: 85.47 ms
可以看到函数的标准输出都被保存到了日志事件里。
日志也可以在 AWS 控制台 CloudWatch 服务中查看。
删除 Lambda 函数
删除 Lambda
-
查询所有 Lambda 函数:
aws lambda list-functions --query 'Functions[*].{FunctionArn:FunctionArn,FunctionName:FunctionName,Handler:Handler,Layers:{Arn:Layers[*].Arn},LoggingConfig:LoggingConfig}'
-
删除 Lambda 函数:
aws lambda delete-function --function-name 'my-function'
删除 Layer
-
查询所有 Layer 版本:
aws lambda list-layer-versions \ --layer-name 'my-layer' \ --query 'LayerVersions[*].Version'
-
删除 Layer 版本:
aws lambda delete-layer-version \ --layer-name 'my-layer' \ --version-number 1