升级Localstack至v3后Lambda触发“Handler not set”错误排查
尝试将Localstack升级至v3版本后,所有版本号大于2.0的Localstack镜像均出现Lambda调用错误,报错信息为ValueError: Handler not set。当前有5个Lambda函数复用同一镜像,列出Lambda函数时可看到所有函数的处理器配置,且该架构在Localstack 1.4版本中可正常运行。
报错日志
time="2024-03-01T15:08:27Z" level=warning msg="Cannot list external agents" func=go.amzn.com/lambda/agents.ListExternalAgentPaths file="/home/runner/work/lambda-runtime-init/lambda-runtime-init/lambda/agents/agent.go:24" error="open /opt/extensions: no such file or directory" teams-localstack | 2024-03-01T15:08:27.057 INFO --- [ asgi_gw_2] localstack.request.aws : AWS dynamodb.ListTables => 200 teams-localstack-lambda-teams-custom-events-7c7b33a738a1a44641260166299bda67 | Traceback (most recent call last): teams-localstack-lambda-teams-custom-events-7c7b33a738a1a44641260166299bda67 | File "/var/app/awslambdaric/__main__.py", line 15, in main teams-localstack-lambda-teams-custom-events-7c7b33a738a1a44641260166299bda67 | handler = args[1] teams-localstack-lambda-teams-custom-events-7c7b33a738a1a44641260166299bda67 | ~~~~^^^ teams-localstack-lambda-teams-custom-events-7c7b33a738a1a44641260166299bda67 | IndexError: list index out of range teams-localstack-lambda-teams-custom-events-7c7b33a738a1a44641260166299bda67 | teams-localstack-lambda-teams-custom-events-7c7b33a738a1a44641260166299bda67 | During handling of the above exception, another exception occurred: teams-localstack-lambda-teams-custom-events-7c7b33a738a1a44641260166299bda67 | teams-localstack-lambda-teams-custom-events-7c7b33a738a1a44641260166299bda67 | Traceback (most recent call last): teams-localstack-lambda-teams-custom-events-7c7b33a738a1a44641260166299bda67 | File "<frozen runpy>", line 198, in _run_module_as_main teams-localstack-lambda-teams-custom-events-7c7b33a738a1a44641260166299bda67 | File "<frozen runpy>", line 88, in _run_code teams-localstack-lambda-teams-custom-events-7c7b33a738a1a44641260166299bda67 | File "/var/app/awslambdaric/__main__.py", line 25, in <module> teams-localstack-lambda-teams-custom-events-7c7b33a738a1a44641260166299bda67 | main(sys.argv) teams-localstack-lambda-teams-custom-events-7c7b33a738a1a44641260166299bda67 | File "/var/app/awslambdaric/__main__.py", line 17, in main teams-localstack-lambda-teams-custom-events-7c7b33a738a1a44641260166299bda67 | raise ValueError("Handler not set") teams-localstack-lambda-teams-custom-events-7c7b33a738a1a44641260166299bda67 | ValueError: Handler not set teams-localstack-lambda-teams-custom-events-7c7b33a738a1a44641260166299bda67 | time="2024-03-01T15:08:27Z" level=warning msg="First fatal error stored in appctx: Runtime.ExitError" func=go.amzn.com/lambda/appctx.StoreFirstFatalError file="/home/runner/work/lambda-runtime-init/lambda-runtime-init/lambda/appctx/appctxutil.go:157" teams-localstack-lambda-teams-custom-events-7c7b33a738a1a44641260166299bda67 | time="2024-03-01T15:08:27Z" level=warning msg="Process runtime-1 exited: exit status 1" func="go.amzn.com/lambda/rapid.(*rapidContext).setupEventsWatcher.func1" file="/home/runner/work/lambda-runtime-init/lambda-runtime-init/lambda/rapid/start.go:236" teams-localstack-lambda-teams-custom-events-7c7b33a738a1a44641260166299bda67 | time="2024-03-01T15:08:27Z" level=error msg="Init failed" func=go.amzn.com/lambda/rapid.handleInitError file="/home/runner/work/lambda-runtime-init/lambda-runtime-init/lambda/rapid/exit.go:109" InvokeID= error="Runtime exited with error: exit status 1" teams-localstack-lambda-teams-custom-events-7c7b33a738a1a44641260166299bda67 | time="2024-03-01T15:08:27Z" level=error msg="Runtime init failed to initialize: InitDoneFailed. Exiting." func=main.main file="/home/runner/work/lambda-runtime-init/lambda-runtime-init/cmd/localstack/main.go:238" teams-localstack-lambda-teams-custom-events-7c7b33a738a1a44641260166299bda67 exited with code 0
Docker Compose配置
version: "3" services: teams-postgres: environment: POSTGRES_PASSWORD: sealion POSTGRES_USER: sealion POSTGRES_DB: teams POSTGRES_PORT: 5432 ports: - "5432:5432" healthcheck: interval: 5s retries: 5 image: postgres:13 networks: - sealion-network teams-lambda: image: teams-lambda:latest build: dockerfile: Dockerfile.lambda context: . container_name: teams-lambda networks: - sealion-network privileged: true teams-localstack: container_name: teams-localstack environment: - services=s3,sns,sqs,lambda,stepfunctions,dynamodb # - HOSTNAME_EXTERNAL=teams-localstack - LAMBDA_REMOTE_DOCKER=true - LOCALSTACK_HOST=localstack - LAMBDA_REMOVE_CONTAINERS=false - PROVIDER_OVERRIDE_LAMBDA=v2 # - LAMBDA_EXECUTOR=docker # - HOST_TMP_FOLDER=/tmp/localstack - DOCKER_HOST=unix:///var/run/docker.sock - AWS_DEFAULT_REGION=us-west-2 - USE_LOCALSTACK=true # - DEBUG=true - LAMBDA_FORWARD_URL=http://teams-lambda:8080 env_file: - .env healthcheck: interval: 5s start_period: 10s test: [ CMD, bash, -c, awslocal dynamodb list-tables ] timeout: 10s image: localstack/localstack-pro:3.0.0 networks: [ sealion-network ] ports: - "127.0.0.1:53:53" - "127.0.0.1:5053:53/udp" - "127.0.0.1:443:443" - "127.0.0.1:4510-4530:4510-4530" - "127.0.0.1:4566:4566" - "127.0.0.1:4571:4571" volumes: - "${TMPDIR:-/tmp}/localstack:/var/lib/localstack" - "/var/run/docker.sock:/var/run/docker.sock" - ./localstack/init.py:/etc/localstack/init/ready.d/init.py # Ready hook privileged: true volumes: postgres_data_container: dynamodata: {} networks: { sealion-network: null }
Lambda镜像Dockerfile
FROM xyz as deps RUN apt install gcc g++ git COPY . ${LAMBDA_TASK_ROOT} ADD poetry.lock pyproject.toml poetry.toml ./ RUN poetry install --no-dev --no-interaction --no-ansi -vvv --no-root FROM xyz:python-3.11 COPY --from=deps /var/app/.venv /var/app/.venv COPY . .
从报错日志看,awslambdaric启动时未收到handler参数,触发IndexError后抛出ValueError: Handler not set。核心原因是Localstack v2+版本对Lambda镜像运行机制做了变更,现有配置存在两处冲突:
LAMBDA_FORWARD_URL配置错误:该变量用于将Lambda请求转发到外部HTTP服务,与当前使用镜像运行Lambda的场景不匹配,导致runtime无法获取handler信息。- Lambda镜像缺少启动配置:你的镜像未定义
ENTRYPOINT和CMD来指定Lambda runtime和handler路径,Localstack v2+不再像v1.4那样自动传递handler参数到镜像内部。
1. 移除冲突环境变量
编辑teams-localstack的环境变量,删除LAMBDA_FORWARD_URL=http://teams-lambda:8080,该配置不适用于镜像化Lambda的运行模式。
2. 修改Lambda镜像Dockerfile
在Dockerfile末尾添加Runtime启动命令,指定awslambdaric入口和handler路径(替换为你实际的handler位置,比如src.handler表示src.py中的handler函数):
FROM xyz as deps RUN apt install gcc g++ git COPY . ${LAMBDA_TASK_ROOT} ADD poetry.lock pyproject.toml poetry.toml ./ RUN poetry install --no-dev --no-interaction --no-ansi -vvv --no-root FROM xyz:python-3.11 COPY --from=deps /var/app/.venv /var/app/.venv COPY . . # 添加Lambda Runtime启动配置 ENV PATH="/var/app/.venv/bin:$PATH" ENTRYPOINT [ "/var/app/.venv/bin/python", "-m", "awslambdaric" ] CMD [ "src.handler" ] # 替换为实际的handler路径,格式为module.function_name
3. 同步Lambda函数配置
确保在init.py中创建Lambda函数时,Handler参数与Dockerfile中CMD的内容完全一致,示例:
awslocal lambda create-function \ --function-name teams-custom-events \ --runtime python3.11 \ --handler src.handler \ --code ImageUri=teams-lambda:latest \ --role arn:aws:iam::123456789012:role/lambda-role
4. 优化Localstack配置(可选)
移除PROVIDER_OVERRIDE_LAMBDA=v2,Localstack v3默认使用新版Lambda provider,该配置已无必要。同时确认LAMBDA_REMOTE_DOCKER=true保持启用,确保Localstack使用外部Docker环境运行Lambda镜像。
内容的提问来源于stack exchange,提问作者Shan Eapen Koshy

