使用 AWS CLI 管理 Lambda

AWS Lambda 是 AWS 提供的一个无服务器(Serverless)计算服务。它允许你无需预置任何服务器即可运行代码,只需为实际消耗的计算时间付费。Lambda 会根据请求的数量自动扩展,处理来自各种事件源的请求,使你能够构建高效、可扩展的应用程序。

简单来说,Lambda 就是一个存储在云端的函数。

创建 IAM 角色

Lambda 函数需要由 IAM 角色来执行。如果你还没有 IAM 角色,可以通过下面的方法来创建一个新的 IAM 角色。

  1. 创建信任策略文件:

    新建一个信任策略文件,并在文件中声明 Lambda 服务可以承担此角色的权限:

    vim trust-policy.json
    
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "Service": "lambda.amazonaws.com"
          },
          "Action": "sts:AssumeRole"
        }
      ]
    }
    
  2. 使用信任策略创建角色:

    aws iam create-role \
        --role-name 'LambdaBasicExecutionRole' \
        --assume-role-policy-document 'file://trust-policy.json'
    
  3. 附加权限策略:

    AWSLambdaBasicExecutionRole 权限策略附加到该角色,以便 Lambda 函数能够写入 CloudWatch 日志。

    aws iam attach-role-policy \
        --role-name 'LambdaBasicExecutionRole' \
        --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
    
  4. 查询角色 ARN:

    export ROLE_ARN=$(
    aws iam get-role \
        --role-name 'LambdaBasicExecutionRole' \
        --query Role.Arn \
        --output text
    )
    

创建 Lambda 函数

上传 Lambda

现在我们创建一个示例函数,当这个函数被调用时,返回一条欢迎语句。

  1. 编辑代码:

    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 对象。

  2. 打包代码:

    zip function.zip lambda_function.py
    
  3. 上传 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。

  1. 创建虚拟环境:

    python -m venv my_env
    
  2. 安装依赖:

    my_env/bin/pip install cowsay
    
  3. 打包依赖:

    mkdir python
    cp -r my_env/lib python
    zip -r python.zip python
    
  4. 上传 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}'
      
  5. 查询 Layer 版本 ARN:

    export LAYER_VERSION_ARN=$(
    aws lambda list-layer-versions \
        --layer-name 'my-layer' \
        --query 'LayerVersions[0].LayerVersionArn' \
        --output text
    )
    
  6. 将 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 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 应用程序中收集和路由事件,以便实现自动化工作流和系统集成。

  1. 创建 EventBridge 规则:

    aws events put-rule \
        --name 'my-rule' \
        --schedule-expression 'cron(50 13 * * ? *)'
    
    • 这将创建一个每天 UTC 13:50 自动触发的规则。
    • 可以通过 date -u +'%H:%M' 命令查看当前 UTC 时间。
  2. 保存规则 ARN:

    export RULE_ARN=$(
    aws events describe-rule \
        --name 'my-rule' \
        --query Arn \
        --output text
    )
    
  3. 授权规则调用 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
    
  4. 保存 Lambda 函数 ARN:

    export LAMBDA_ARN=$(
    aws lambda get-function \
        --function-name 'my-function' \
        --query Configuration.FunctionArn \
        --output text
    )
    
  5. 为规则添加目标:

    添加 Lambda 函数为目标,当规则触发时,事件将自动被发送到目标。

    aws events put-targets \
        --rule 'my-rule' \
        --targets "Id=1,Arn=$LAMBDA_ARN"
    

查看日志

Amazon CloudWatch 是一项全面的监控和管理服务,用于跟踪和分析 AWS 云资源和应用程序的性能和日志,以增强可见性和自动化管理能力。

  1. 查询日志流:

    日志流是根据时间顺序创建的,每次函数执行通常会创建一个新的日志流。

    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
    )
    
  2. 获取日志流的日志事件:

    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

  1. 查询所有 Layer 版本:

    aws lambda list-layer-versions \
        --layer-name 'my-layer' \
        --query 'LayerVersions[*].Version'
    
  2. 删除 Layer 版本:

    aws lambda delete-layer-version \
        --layer-name 'my-layer' \
        --version-number 1
    
posted @ 2024-12-13 12:20  Undefined443  阅读(10)  评论(0编辑  收藏  举报