我正在尝试部署一个基于图像的 Python Lambda,其中包含 AWS CDK 库。 当我尝试在 AWS 中运行该函数时,它无法启动。
我正在使用此 Dockerfile:
FROM amazon/aws-lambda-python:3.12
COPY * ${LAMBDA_TASK_ROOT}/
RUN dnf update -y
RUN dnf install -y git
RUN curl -sL https://rpm.nodesource.com/setup_20.x | bash -
RUN dnf install -y nodejs
RUN npm install -g aws-cdk
RUN --mount=type=secret,id=gitconfig,target=/root/.gitconfig pip install -r requirements.txt
CMD [ "main.lambda_handler" ]
这会在我的本地计算机上使用 Docker 启动并运行得很好。 它可以很好地部署到 AWS,但是当调用该函数时,我在日志中看到这些消息:
INIT_REPORT Init Duration: 10005.00 ms Phase: init Status: timeout
[ERROR] JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Traceback (most recent call last):
File "/var/lang/lib/python3.12/importlib/__init__.py", line 90, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 995, in exec_module
File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
File "/var/task/main.py", line 5, in <module>
import aws_cdk as cdk
File "/var/lang/lib/python3.12/site-packages/aws_cdk/__init__.py", line 1519, in <module>
from ._jsii import *
File "/var/lang/lib/python3.12/site-packages/aws_cdk/_jsii/__init__.py", line 21, in <module>
__jsii_assembly__ = jsii.JSIIAssembly.load(
File "/var/lang/lib/python3.12/site-packages/jsii/_runtime.py", line 55, in load
_kernel.load(assembly.name, assembly.version, os.fspath(assembly_path))
File "/var/lang/lib/python3.12/site-packages/jsii/_kernel/__init__.py", line 299, in load
self.provider.load(LoadRequest(name=name, version=version, tarball=tarball))
File "/var/lang/lib/python3.12/site-packages/jsii/_kernel/providers/process.py", line 354, in load
return self._process.send(request, LoadResponse)
File "/var/lang/lib/python3.12/site-packages/jsii/_kernel/providers/process.py", line 332, in send
self._next_message(), _ProcessResponse
File "/var/lang/lib/python3.12/site-packages/jsii/_kernel/providers/process.py", line 251, in _next_message
return json.loads(self._process.stdout.readline(), object_hook=ohook)
File "/var/lang/lib/python3.12/json/__init__.py", line 359, in loads
return cls(**kw).decode(s)
File "/var/lang/lib/python3.12/json/decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/var/lang/lib/python3.12/json/decoder.py", line 355, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
Exception ignored in atexit callback: <bound method _NodeProcess.stop of <jsii._kernel.providers.process._NodeProcess object at 0x7f7608954da0>>
Traceback (most recent call last):
File "/var/lang/lib/python3.12/site-packages/jsii/_kernel/providers/process.py", line 295, in stop
self._process.stdin.close()
BrokenPipeError: [Errno 32] Broken pipe
INIT_REPORT Init Duration: 111268.11 ms Phase: invoke Status: error Error Type: Runtime.Unknown
START RequestId: 6930a835-0ac0-55be-aa00-f72e6fd53c01 Version: $LATEST
Unknown application error occurred
Runtime.Unknown
END RequestId: 6930a835-0ac0-55be-aa00-f72e6fd53c01
NodeJS 运行时似乎没有按预期启动,但我无法找到任何方法立即进一步解决此问题。
问题在于的 Lambda 函数试图在执行期间导入和使用
aws-cdk
库。
aws-cdk
库用于
定义
的基础设施,而不是在 Lambda 函数内
运行时
。在 Lambda 函数中包含 CDK 会导致大型部署工件和不必要的依赖项,最终导致看到
JSONDecodeError
和
BrokenPipeError
错误,因为 NodeJS 运行时无法在初始化阶段正确启动。
以下是如何解决此问题的步骤:
-
从 Lambda 函数代码中删除
aws-cdk
: -
从的
requirements.txt
文件中删除aws-cdk
。 -
从的
Dockerfile
中删除RUN npm install -g aws-cdk
行。 -
确保的 Lambda 函数代码本身不导入或使用
aws-cdk
中的任何内容。 -
使用 CDK 单独部署的基础设施:
- 使用 CDK 定义的 Lambda 函数以及的任何其他基础设施(例如,API 网关、DynamoDB 表等)。
-
使用
cdk deploy
将的基础设施部署到 AWS。 -
将 CDK 生成的 Lambda 函数代码与的业务逻辑分开:
-
CDK 将生成一个包含的 Lambda 函数定义的 Python 文件(例如,
lambda.py
)。将此文件与的 CDK 代码分开保存。 -
将的业务逻辑放入一个单独的文件(例如,
main.py
)中。 -
在
lambda.py
中,导入main.py
并调用的处理程序函数。
示例:
lambda.py (由 CDK 生成):
from aws_cdk import (
aws_lambda as _lambda,
)
import path as path
# ... 其他 CDK 构造 ...
# 定义 Lambda 函数
my_lambda = _lambda.Function(self, 'MyLambda',
runtime=_lambda.Runtime.PYTHON_3_12,
handler='main.lambda_handler',
code=_lambda.Code.from_asset(path.join(__dirname, 'lambda_code')),
)
lambda_code/main.py (的 Lambda 函数逻辑):
import json
def lambda_handler(event, context):
# 的业务逻辑在这里...
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda!')
}
Dockerfile:
FROM amazon/aws-lambda-python:3.12
COPY lambda_code/ ${LAMBDA_TASK_ROOT}/
RUN pip install -r lambda_code/requirements.txt
CMD [ "main.lambda_handler" ]
通过这种方式,将 CDK 用于基础设施管理,并将的 Lambda 函数代码与其分离,从而避免不必要的依赖项和错误。
标签:python,aws-lambda,aws-cdk From: 78790622