我希望调用使用 Zappa 部署的 AWS Lambda 函数。lambda 函数的依赖关系对于通常的 zip 文件方法来说太大了(即使使用slim_handler : true
.
为此,我将 Zappa 与 Docker 容器一起使用,其中容器包含较大的依赖项,并且 Lambda 函数根据需要调用容器。
该应用程序是一个 Flask 应用程序,具有app.py
路由到函数的常用代码。使用 Zappa 部署一个 dockerized flask 应用程序非常简单,我可以成功地做到这一点,只要app.py
. 但是,一旦我添加了依赖于库的 Python,在尝试通过 AWS API 网关(由 Zappa 设置)调用 Lambda 函数时,就会出现以下错误:
Warning! Status check on the deployed lambda failed. A GET request to '/' yielded a 500 response code.
这是我正在采取的步骤。我使用 Feast 作为我想要工作的 Python 库,将 dockerized Flask 应用程序通过 Zappa 推送到 Lambda。
我创建了与 Zappa 一起工作的Dockerfile,用于部署到 AWS Lambda。
我正在使用此处概述的步骤来创建此 Dockerfile:
FROM amazon/aws-lambda-python:3.8
ARG FUNCTION_DIR="/var/task/"
COPY ./ ${FUNCTION_DIR}
# Setup Python environment
RUN pip install pipenv
RUN pip install -r requirements.txt
# Grab the zappa handler.py and put it in the working directory
RUN ZAPPA_HANDLER_PATH=$( \
python -c "from zappa import handler; print (handler.__file__)" \
) \
&& echo $ZAPPA_HANDLER_PATH \
&& cp $ZAPPA_HANDLER_PATH ${FUNCTION_DIR}
CMD ["handler.lambda_handler"]
简而言之,这使用 AWS 提供的基础镜像,将我的应用程序代码复制到镜像中,并使用pipenv
. Zappa 的具体步骤在底部,handler.py
手动添加到 Docker 映像中。“lambda_handler 函数包含将 API 网关请求路由到相应 Flask 函数的所有 Zappa 魔法。” 处理程序在 中指定,CMD
以便在使用此映像的 Docker 容器启动时运行它。
这是我的 requirements.txt 文件:
zappa
flask
feast
由于我希望 Feast 可用,因此我将其安装在虚拟环境中:
安装盛宴
这些步骤来自这里:
安装盛宴:
pip install feast
创建功能仓库:
feast init feature_repo
cd feature_repo
注册特征定义和部署的特征存储:
feast apply
将功能加载到我的在线商店中:
CURRENT_TIME=$(date -u +"%Y-%m-%dT%H:%M:%S")
feast materialize-incremental $CURRENT_TIME
为了测试 Feast 是否会成功部署在 Lambda 上,我将通过 AWS API 网关调用 Lambda 函数来获取特征向量以进行推理。所以我需要 Flask 调用必要的 Feast 代码:
获取特征向量以进行推理
我在通常的 Flask 中设置了 Feast 代码app.py
:
from flask import Flask
from feast import FeatureStore
app = Flask(__name__)
@app.route('/')
def index():
store = FeatureStore(repo_path="feature_repo/")
feature_vector = store.get_online_features(
feature_refs=[
"driver_hourly_stats:conv_rate",
"driver_hourly_stats:acc_rate",
"driver_hourly_stats:avg_daily_trips",
],
entity_rows=[{"driver_id": 1001}],
).to_dict()
return feature_vector
# We only need this for local development.
if __name__ == '__main__':
app.run()
对此的预期响应是:
{
'driver_id': [1001],
'driver_hourly_stats__conv_rate': [0.49274],
'driver_hourly_stats__acc_rate': [0.92743],
'driver_hourly_stats__avg_daily_trips': [72],
}
我还在虚拟环境中安装了 Zappa :
pipenv install zappa
...这是我的zappa_settings.json
:
"zappa_test": {
"app_function": "app.app",
"project_name": "app",
"runtime": "python3.8",
"s3_bucket": "zappa-f8s0d8fs0df",
"aws_region" : "us-east-2",
"lambda_description": "Zappa + Docker + Flask"
}
此处显示的 S3 存储桶编号是假的。
同时在虚拟环境中安装 Flask:
pipenv install flask
建立形象
我运行以下命令来构建映像:
zappa save-python-settings-file zappa_test
docker build -t zappa_test:latest .
然后我推送到 ECR:
aws ecr create-repository --repository-name zappa_test --image-scanning-configuration scanOnPush=true
重新标记图像:
docker tag zappa_test:latest XXXXX.dkr.ecr.us-east-1.amazonaws.com/zappa_test:latest
获得身份验证以推送到 ECR:
aws ecr get-login-password | docker login --username AWS --password-stdin XXXXX.dkr.ecr.us-east-1.amazonaws.com
...并推送图像:
docker push XXXXX.dkr.ecr.us-east-1.amazonaws.com/zappa_test:latest
最后,我部署了 lambda 函数:
zappa deploy zappa_test -d XXXXX.dkr.ecr.us-east-1.amazonaws.com/zappa_test
总之,这就是使用 Zappa 将 docker 映像推送到 AWS Lambda 以便通过 AWS API Gateway 调用 lambda 函数的方式。在这种情况下,我试图调用一个 lambda 函数,该函数通过 Flask 获取 Feast 数据,并在 Docker 容器中提供了依赖项。
但是,在运行deploy
命令后,我得到:
Warning! Status check on the deployed lambda failed. A GET request to '/' yielded a 500 response code.
重要的:
我已经确认所有这些步骤都有效,如果我在这样的里面放一些简单的东西app.py
:
@app.route('/')
def index():
return "Hello, world!", 200
一切都在 AWS 上正确认证,图像部署,我可以通过 Zappa 提供的 API 端点(通过 AWS 网关)完美地调用它。如上所示,当我将 Feast 代码放入其中时,我只会收到上述错误app.py
。