the5fire

关注Python、Django、Vim、Linux、Web开发、团队管理和互联网--Life is short, we need Python.


通过github actions部署aws lambda记录 - s3部署、ECR部署 以及固定出口IP

作者:the5fire | 标签:             | 发布:2024-06-26 5:17 p.m. | 阅读量: 554, 489

背景

一个每天只需要运行一次的策略(每天只需要去交易所拿一次行情数据,计算完成后输出结果),放到EC2里跑有点浪费资源,不如部署到aws lambda中。

本篇内容主要记录在使用lambda时遇到的依赖资源过大的问题。

下面主要分两部分来记录,

第一部分:lambda使用

关于lambda应该不用详细介绍,直接看这里即可:lambda文档

lambda的使用比较简单,创建时有三种方式,前两种(从头开始创建和使用蓝图)可以直接在aws面板上编辑代码,或者上传代码压缩包(zip)来部署,第三种是基于容器来部署。

根据项目不同情况,有三种部署方式:

1. 没有外部依赖的代码,比如:

import json


def lambda_handler(event, context):
    return {
        'statusCode': 200,
        'body': json.dumps({'content': 'hi the5fire'})
    }

可以直接在面板编辑并更新项目。

2. 有外部依赖的情况,比如:

import json

import requests


def lambda_handler(event, context):
    r = requests.get('https://api.github.com/user', auth=('user', 'pass'))

    return {
        'statusCode': 200,
        'body': json.dumps({'content': f'hi the5fire, code:{r.status_code}'})
    }

这种情况需要处理外部依赖,有两个方案:

方案一:在部署项目时需要把依赖打包一起部署。打包命令如下 :

pip install -r requirements.txt --target .
zip -r lambda_function.zip . -x '*.git*'

之后把zip包在aws lambda管理面板上传即可。

方案二:可以通过layer的方式处理

即在lambda管理面包上找到【层】的菜单,进去创建一个新的层,把依赖单独打包上传到该层,最后关联到你的lambda函数下面即可。

这两个方案都有一个限制就是你的整个项目+依赖包的大小不能超过250M,如果超了,那就看第三种方式。

3. 使用容器部署的方式,也就是ECR

简单来说就是把你的代码放进容器里,镜像打包注册到aws的ecr,然后lambda直接运行容器.

在项目中增加一个Dockerfile:

FROM public.ecr.aws/lambda/python:3.12

# Copy requirements.txt
COPY .  ${LAMBDA_TASK_ROOT}

# Install the specified packages
RUN pip install -r requirements.txt

# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
CMD [ "lambda_function.lambda_handler" ]

项目结构如下:

.
|-- .github/workflows/deploy.yml
|-- Dockerfile
|-- README.md
|-- lambda_function.py
|-- requirements.txt
|-- strategy.py

部署的话需要使用docker和aws cli工具,参考这里:https://docs.aws.amazon.com/zh_cn/lambda/latest/dg/python-image.html,我自己的使用方式也会放到下面github action workflow配置中。

第二部分:github action配置

使用github action部署lambda之前,需要先去aws的IAM管理后台创建访问KEY,然后配置到github 的action/secrets中。

对于使用zip部署的方式也分两种情况,压缩包小于10M可以直接在上传,大于10M、小于250M的需要通过s3来上传。

所以这部分的action配置也分两种。

  1. 直接上传zip文件的方式:
# .github/workflows/deploy.yml
name: Deploy Lambda Function

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout
      uses: actions/checkout@v4

    - name: Set up Python 3.12
      uses: actions/setup-python@v2
      with:
        python-version: 3.12

    - name: Install & zip
      run: |
        pip install --upgrade pip
        pip install -r ./requirements.txt
        zip -r lambda_function.zip . -x '*.git*'

    - name: Deploy to AWS Lambda
      env:
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        AWS_DEFAULT_REGION: ${{ secrets.AWS_REGION }}

      run: |
        # Assuming you have an IAM role ARN for your Lambda function
        aws lambda update-function-code \
          --function-name helloworld \
          --zip-file fileb://lambda_function.zip
  1. 通过 s3 上传zip包并部署:

这里需要先到aws s3上创建桶

name: Deploy Lambda Function

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout
      uses: actions/checkout@v4

    - name: Set up Python 3.12
      uses: actions/setup-python@v2
      with:
        python-version: 3.12

    - name: Install & zip
      run: |
        pip install --upgrade pip
        pip install -r ./requirements.txt --target .
        zip -r lambda_function.zip . -x '*.git*'

    - name: Deploy to AWS Lambda
      env:
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        AWS_DEFAULT_REGION: ${{ secrets.AWS_REGION }}

      run: |
        # Assuming you have an IAM role ARN for your Lambda function
        aws s3 cp ./lambda_function.zip s3://${{ secrets.BUCKET_NAME }}/
        aws lambda update-function-code --function-name ${{ secrets.FUNCTION_NAME }} \
          --s3-bucket ${{ secrets.BUCKET_NAME }} --s3-key lambda_function.zip
  1. 使用ecr方式部署:

这一步需要配置aws account id,你在ECR创建完存储库之后就可以从URI上看到。

name: Deploy Lambda Function

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    env:
      AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
      AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
      AWS_DEFAULT_REGION: ${{ secrets.AWS_REGION }}

    steps:
    - name: Checkout
      uses: actions/checkout@v4

    - name: get login
      run: |
        aws ecr get-login-password --region ${{ secrets.AWS_REGION}}| docker login --username AWS --password-stdin ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com

    - name: update image

      run: |
        docker build -t docker-image:test .
        docker tag docker-image:test ${{secrets.AWS_ACCOUNT_ID }}.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/${{ secrets.FUNCTION_NAME }}:latest
        docker push ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/${{ secrets.FUNCTION_NAME }}:latest

    - name: update function
      run: |
         aws lambda update-function-code \
            --function-name ${{ secrets.FUNCTION_NAME }} \
            --image-uri ${{secrets.AWS_ACCOUNT_ID}}.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/${{ secrets.FUNCTION_NAME }}:latest

需要说明的是,我这里都是只使用github action来做update function code,并没有使用它来创建function的需求,因此没写这创建的逻辑。对于使用ecr来部署的lambda function来说,需要先提交代码到github上,运行action后生成镜像,然后再创建lambda。

最后,关于出口IP固定的配置,参考文档:使用 Lambda 函数、Amazon VPC 和无服务器架构生成静态出站 IP 地址

示例代码: https://github.com/the5fire/action-lambda-demo/commits/main/

- from the5fire.com
----EOF-----

微信公众号:Python程序员杂谈

【上一篇】 【置顶】《Django企业开发实战》「勘误」
【下一篇】 没有了

其他分类: