AWS Lambda 自主管理代码存储:解除区域配额,但单函数包大小不变

2026-07-30 23 预计阅读时间: 1 分钟
来源: infoq.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:8 分钟

AWS Lambda 现在可以直接引用客户自有 S3 存储桶中的部署包。这个变化解决的是账户在单个 Region 内累计存放多少函数代码的问题,而不是放宽单个函数部署包的大小限制。与此同时,Lambda 托管代码存储的默认配额也从 75 GB 提升到了 300 GB。

这两个数字很容易让人误判:团队可以保存更多函数版本,并不代表某个 ZIP 包可以变得更大。

变化发生在存储层,而不是函数打包层

过去,函数版本、Layer 和持续发布产生的部署包会不断消耗 Lambda 的区域级代码存储配额。函数数量多、发布频率高,或者长期保留旧版本的账户,容易在 CI/CD 发布时撞上配额上限。

自主管理代码存储把部署包留在客户控制的 S3 存储桶中,由 Lambda 引用对应对象。它带来两个直接结果:

  • 使用自主管理模式的代码不再受 Lambda 每 Region 代码存储总配额约束。
  • 继续使用 Lambda 托管存储的账户,默认可用容量从 75 GB 增加到 300 GB。

但现有的单函数部署包限制没有变化。遇到依赖过重、原生库体积庞大等问题时,仍然需要通过裁剪依赖、拆分 Layer、延迟加载资源或调整部署形态来处理,不能把区域配额提升当成函数体积提升。

覆盖 S3 对象不等于发布新代码

另一个关键边界是部署触发机制。即使函数引用的是 S3 对象,直接覆盖同一个对象键也不会自动让 Lambda 加载新内容。上传完成后,仍然必须调用 UpdateFunctionCode

因此,不建议让发布流水线长期覆盖 releases/function.zip。更稳妥的办法是使用提交哈希、构建号或内容摘要生成不可变对象键,再显式更新函数代码。这样既能避免 S3 缓存与并发覆盖问题,也能准确追踪某个函数版本对应哪个制品。

可以这样实践:用不可变对象键发布

下面的 Bash 示例假设目标 Lambda 函数、S3 存储桶以及必要的 IAM 权限已经配置完成。运行前需要修改 FUNCTION_NAMEBUCKETAWS_REGION。示例创建一个最小 Python 函数,将 ZIP 包上传到带时间戳的对象键,然后显式调用更新接口。

#!/usr/bin/env bash
set -euo pipefail

FUNCTION_NAME="orders-handler"
BUCKET="my-lambda-artifacts"
AWS_REGION="us-east-1"
BUILD_ID="$(date -u +%Y%m%dT%H%M%SZ)"
S3_KEY="lambda/${FUNCTION_NAME}/${BUILD_ID}.zip"

WORK_DIR="$(mktemp -d)"
trap 'rm -rf "$WORK_DIR"' EXIT

cat > "$WORK_DIR/lambda_function.py" <<'PY'
import json


def handler(event, context):
    return {
        "statusCode": 200,
        "body": json.dumps({"build": "self-managed-storage-example"}),
    }
PY

(
  cd "$WORK_DIR"
  zip -q function.zip lambda_function.py
)

aws s3 cp \
  "$WORK_DIR/function.zip" \
  "s3://${BUCKET}/${S3_KEY}" \
  --region "$AWS_REGION"

aws lambda update-function-code \
  --function-name "$FUNCTION_NAME" \
  --s3-bucket "$BUCKET" \
  --s3-key "$S3_KEY" \
  --region "$AWS_REGION"

aws lambda wait function-updated \
  --function-name "$FUNCTION_NAME" \
  --region "$AWS_REGION"

aws lambda get-function-configuration \
  --function-name "$FUNCTION_NAME" \
  --region "$AWS_REGION" \
  --query '{FunctionName:FunctionName,LastModified:LastModified,CodeSize:CodeSize}'

这段流程最重要的不是 ZIP 命令,而是两个部署约束:每次构建产生新的 S3 键,并且每次上传后都执行 update-function-code。如果改为覆盖固定键,也仍然需要调用更新接口;仅执行 aws s3 cp 不会完成发布。

在生产环境中,还可以启用 S3 Versioning,并把对象版本 ID 写入部署记录。制品生命周期规则也应谨慎设置:如果 Lambda 仍需读取某个对象,就不能提前删除对应版本。

Terraform 暂时不要假设已有原生字段

Terraform Provider 对这一能力的支持仍是一个待处理的增强请求。因此,现阶段不应猜测尚未发布的资源参数,也不应把未经验证的字段写进基础设施模块。

可以把职责暂时拆开:Terraform 管理函数、IAM、S3 存储桶和加密策略,发布系统使用 AWS CLI 或 SDK 上传制品并调用 UpdateFunctionCode。如果必须把部署动作接入 Terraform,可以用外部脚本过渡,但要明确它会引入本地工具依赖、状态不可见和重复执行等问题。

例如,下面是一个可改造的过渡方案。它假设前面的发布脚本保存为 scripts/deploy-lambda.sh

variable "artifact_digest" {
  type        = string
  description = "SHA-256 digest of the Lambda deployment artifact"
}

resource "terraform_data" "deploy_lambda" {
  triggers_replace = {
    artifact_digest = var.artifact_digest
  }

  provisioner "local-exec" {
    command = "bash scripts/deploy-lambda.sh"
  }
}

这个配置只适合作为短期桥接。Provider 提供正式支持后,应优先迁移到可声明、可比较并能进入 Terraform 状态的资源配置。

采用前检查四件事

引入自主管理代码存储前,建议确认以下边界:

  • 当前瓶颈是否真的是区域级累计代码存储,而不是单函数包大小。
  • Lambda 服务主体和部署角色是否具备读取目标 S3 对象及 KMS 解密所需的权限。
  • 发布流水线是否会在上传后显式调用 UpdateFunctionCode
  • S3 Versioning、生命周期、跨区域部署和制品回滚策略是否与函数版本管理一致。

对于函数和版本数量较多的账户,这项能力能把代码制品纳入现有的 S3 治理体系,并解除区域累计容量压力。对于只维护少量函数的团队,300 GB 的托管默认配额可能已经足够,继续使用托管模式反而更省运维成本。选择标准应该是制品规模、治理需求和发布复杂度,而不是单纯追求新的存储方式。


相关推荐