

# 自行管理的 S3 代码存储
<a name="configuration-self-managed-storage"></a>

默认情况下，当您从 .zip 文件存档中创建或更新 Lambda 函数或层时，Lambda 会将您的代码副本存储在 Lambda 托管式存储中。每个 Amazon 账户在每个区域有 300 GB 的 Lambda 托管式存储配额。

使用自行管理的 S3 代码存储时，您可以将 Lambda 配置为直接从您账户中的 S3 存储桶引用您的代码。Lambda 不会存储您的代码副本，因此该代码不会占用您的 Lambda 托管式存储配额。Lambda 会直接从您的 S3 存储桶访问您的代码。

自行管理的 S3 代码存储可用于使用.zip 文件存档创建和更新的所有函数和层。除 Glacier 存储类别外，此类存储兼容所有 S3 存储类别。

**注意**  
自行管理的 S3 代码存储不会更改最大 .zip 部署包大小，该大小仍为 250 MB（未压缩）。

**Topics**
+ [设置自行管理的 S3 代码存储](#self-managed-storage-setup)
+ [配置权限](#self-managed-storage-permissions)
+ [使用自行管理的 S3 存储创建一个函数](#self-managed-storage-create-function)
+ [将自行管理的 S3 存储用于层](#self-managed-storage-layers)
+ [切换存储模式](#self-managed-storage-switching)
+ [使用自行管理存储时的函数生命周期](#self-managed-storage-lifecycle)
+ [跨账户和跨区域使用](#self-managed-storage-cross-account)
+ [注意事项](#self-managed-storage-considerations)

## 设置自行管理的 S3 代码存储
<a name="self-managed-storage-setup"></a>

要使用自行管理的 S3 代码存储，请完成以下步骤：

1. 创建一个 S3 存储桶或使用您账户中现有的存储桶。

1. 为该存储桶启用 [S3 版本控制](https://docs.amazonaws.cn/AmazonS3/latest/userguide/Versioning.html)。Lambda 需要通过 S3 版本控制来跟踪要使用的源对象版本。每次上传新的 .zip 包时，S3 都会创建一个新版本，从而让 Lambda 可以区分更新。

1. 将 .zip 部署包上传至 S3 存储桶。

1. 向 Lambda 服务主体授予源对象的 `s3:GetObject` 和 `s3:GetObjectVersion` 权限。请参阅[配置权限](#self-managed-storage-permissions)。

1. 创建或更新您的函数或层，指定 S3 对象、S3 键、S3 对象版本，并将 `S3ObjectStorageMode` 设置为 `REFERENCE`。

## 配置权限
<a name="self-managed-storage-permissions"></a>

要使用自行管理的 S3 代码存储，请向 Lambda 服务主体 (`lambda.amazonaws.com`) 授予您的源对象访问权限。添加以下 S3 存储桶策略：

```
{
  "Version": "2012-10-17",		 	 	 
  "Statement": [
    {
      "Sid": "LambdaSelfManagedCodeAccess",
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:GetObjectVersion"
      ],
      "Resource": [
        "arn:aws:s3:::{{my-bucket}}/{{my-function.zip}}"
      ],
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Condition": {
        "ArnLike": {
          "aws:SourceArn": "arn:aws:lambda:{{us-east-1}}:{{111122223333}}:function:{{my-function}}"
        }
      }
    }
  ]
}
```

## 使用自行管理的 S3 存储创建一个函数
<a name="self-managed-storage-create-function"></a>

您可以通过 Amazon CLI 或 Amazon CloudFormation 创建一个使用自行管理的 S3 代码存储的函数。

### 使用 Amazon CLI
<a name="self-managed-storage-cli"></a>

将 `create-function` 命令与 `S3ObjectStorageMode=REFERENCE` 参数一起使用：

```
aws lambda create-function \
  --function-name my-function \
  --runtime python3.12 \
  --role arn:aws:iam::111122223333:role/lambda-execution-role \
  --handler lambda_function.lambda_handler \
  --code S3Bucket={{my-bucket}},\
S3Key={{my-function.zip}},\
S3ObjectVersion={{abc123def456}},\
S3ObjectStorageMode=REFERENCE
```

要更新现有函数以使用自行管理的 S3 存储，请执行以下操作：

```
aws lambda update-function-code \
  --function-name my-function \
  --s3-bucket {{my-bucket}} \
  --s3-key {{my-function.zip}} \
  --s3-object-version {{abc123def456}} \
  --s3-object-storage-mode REFERENCE
```

**重要**  
您必须在每次调用 `update-function-code` 时指定 `S3ObjectStorageMode=REFERENCE`。如果省略 `S3ObjectStorageMode`，则默认为 `COPY`，并且 Lambda 会将您的代码存储在 Lambda 托管式存储中。

### 使用 Amazon CloudFormation
<a name="self-managed-storage-cfn"></a>

在您的 Amazon CloudFormation 模板中，请在 `AWS::Lambda::Function` 资源的 `Code` 属性中将 `S3ObjectStorageMode` 设置为 `REFERENCE`：

```
Resources:
  MyFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: my-function
      Runtime: python3.12
      Handler: lambda_function.lambda_handler
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        S3Bucket: {{my-bucket}}
        S3Key: {{my-function.zip}}
        S3ObjectVersion: {{abc123def456}}
        S3ObjectStorageMode: REFERENCE
```

## 将自行管理的 S3 存储用于层
<a name="self-managed-storage-layers"></a>

您也可以将自行管理的 S3 代码存储用于层版本。使用 `publish-layer-version` 命令和 `S3ObjectStorageMode=REFERENCE`：

```
aws lambda publish-layer-version \
  --layer-name my-layer \
  --content S3Bucket={{my-bucket}},S3Key={{my-layer.zip}},S3ObjectStorageMode=REFERENCE \
  --compatible-runtimes python3.12
```

您可以将 Lambda 托管式存储和自行管理存储的任意组合用于函数代码和层代码。

## 切换存储模式
<a name="self-managed-storage-switching"></a>

您可以在更新函数代码或发布新的层版本时切换 Lambda 托管式存储和自行管理的 S3 代码存储。将 `S3ObjectStorageMode` 设置为 `COPY` 或 `REFERENCE`：
+ `COPY`（默认）：Lambda 会将您的源代码复制到 Lambda 托管式存储中。
+ `REFERENCE`：Lambda 会直接从 S3 存储桶引用您的源代码，而不存储副本。

当您从 `COPY` 切换到 `REFERENCE` 时，Lambda 会删除您的源代码的 Lambda 托管式副本。当您从 `REFERENCE` 切换到 `COPY` 时，Lambda 会将您的源代码副本存储到 Lambda 托管式存储中。如果您已超出 Lambda 托管式代码存储限制，则将无法切换到 `COPY`。

## 使用自行管理存储时的函数生命周期
<a name="self-managed-storage-lifecycle"></a>

Lambda 会定期从您的 S3 存储桶访问源对象，以重新优化您的函数代码。您必须维持源对象的访问权限，才能让函数保持活动状态。
+ 如果 Lambda 失去某个函数的源对象访问权限，该函数将变为 `Inactive` 状态。要恢复该函数，您需要恢复源对象的访问权限并更新该函数。
+ 如果 Lambda 失去某个层的源对象访问权限，该函数仍会处于 `Active` 状态。您可以更新函数配置（但不更新层）、更新函数代码或使用新层来更新函数配置。但使用无法访问的层更新函数配置时将会失败。

## 跨账户和跨区域使用
<a name="self-managed-storage-cross-account"></a>

您可以从不同账户和不同区域的 S3 存储桶中的源代码创建函数和层。跨区域对象检索会产生额外的 S3 数据传输费用。有关详细信息，请参阅 [S3 定价](https://www.amazonaws.cn/s3/pricing/)。

## 注意事项
<a name="self-managed-storage-considerations"></a>
+ 自行管理的 S3 代码存储只能用于 .zip 文件存档函数和层。容器映像函数可继续使用 Amazon ECR。
+ 最大 .zip 部署包大小（250MB，未压缩）不变。
+ 对于存储在自行管理的存储桶中的代码，您需要按标准的 Amazon S3 存储费率付费。Lambda 不会对同一区域内的 S3 对象检索计费。
+ 除 Glacier 存储类别外，自行管理的 S3 代码存储兼容所有 S3 存储类别。
+ 您可以使用 S3 跨区域复制等 S3 功能来跨区域共享构件，并使用 S3 生命周期策略来管理对象。