IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

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

    the5fire发表于 2024-06-26 09:22:03
    love 0

    背景

    一个每天只需要运行一次的策略(每天只需要去交易所拿一次行情数据,计算完成后输出结果),放到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的需求,因此没写这创建的逻辑。

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

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

    阅读原文
    Django视频教程


沪ICP备19023445号-2号
友情链接