Lambda Layers 概述
AWS Lambda Layers 是一種可以包含程式庫、自訂執行環境、設定檔或其他相依性的分發機制。透過 Layers,您可以將共用的程式碼和資料與函數程式碼分開管理,使函數部署套件更加精簡,同時促進程式碼重用。
Layers 的核心優勢
- 程式碼重用:多個函數可共享相同的程式庫和相依性
- 精簡部署套件:減少函數程式碼的大小
- 獨立版本控制:相依性可獨立於函數進行更新
- 分離關注點:核心業務邏輯與相依性分離管理
- 跨帳戶共享:可與其他 AWS 帳戶或公開分享 Layer
Layers 的限制
| 項目 | 限制 |
|---|
| 每個函數最多附加的 Layers | 5 個 |
| 解壓縮後總大小(含所有 Layers) | 250 MB |
| Layer 版本數量 | 無限制 |
| Layer 壓縮套件大小 | 50 MB(直接上傳)/ 250 MB(透過 S3) |
使用場景
Lambda Layers 適用於以下常見場景:
1. 共享程式庫
將常用的程式庫打包成 Layer,供多個函數使用:
- Python:numpy、pandas、requests 等
- Node.js:axios、lodash、moment 等
- Java:常用的 JAR 檔案
2. 自訂執行環境
建立包含特定版本或修補程式的執行環境:
1
2
| # 例如:包含特定版本的 Python 套件
python/lib/python3.11/site-packages/
|
3. 共享設定檔
將設定檔、憑證或其他靜態資源集中管理:
1
2
3
4
5
| # 設定檔範例
config/
├── database.json
├── api-keys.json
└── feature-flags.json
|
4. 企業內部共享
在組織內部共享通用工具函數、驗證邏輯或加密模組。
建立 Layer
步驟一:準備 Layer 內容
建立符合 Lambda 執行環境要求的目錄結構:
1
2
3
4
5
6
7
8
9
| # 建立工作目錄
mkdir -p my-layer/python/lib/python3.11/site-packages
# 安裝相依性到指定目錄
pip install requests -t my-layer/python/lib/python3.11/site-packages/
# 壓縮 Layer 內容
cd my-layer
zip -r ../my-layer.zip .
|
步驟二:使用 AWS CLI 建立 Layer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # 建立 Lambda Layer
aws lambda publish-layer-version \
--layer-name my-python-layer \
--description "Python requests library layer" \
--zip-file fileb://my-layer.zip \
--compatible-runtimes python3.11 python3.12 \
--compatible-architectures x86_64 arm64
# 輸出範例
{
"LayerVersionArn": "arn:aws:lambda:ap-northeast-1:123456789012:layer:my-python-layer:1",
"LayerArn": "arn:aws:lambda:ap-northeast-1:123456789012:layer:my-python-layer",
"Version": 1,
"Description": "Python requests library layer",
"CompatibleRuntimes": ["python3.11", "python3.12"],
"CompatibleArchitectures": ["x86_64", "arm64"]
}
|
透過 S3 上傳大型 Layer
1
2
3
4
5
6
7
8
9
| # 上傳 Layer 套件到 S3
aws s3 cp my-large-layer.zip s3://my-bucket/layers/my-large-layer.zip
# 使用 S3 URI 建立 Layer
aws lambda publish-layer-version \
--layer-name my-large-layer \
--description "Large dependency layer" \
--content S3Bucket=my-bucket,S3Key=layers/my-large-layer.zip \
--compatible-runtimes python3.11
|
發布 Layer 版本
每次發布 Layer 都會建立新版本,版本號碼自動遞增且不可變更:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| # 更新 Layer 內容後發布新版本
aws lambda publish-layer-version \
--layer-name my-python-layer \
--description "Updated version with bug fixes" \
--zip-file fileb://my-layer-v2.zip \
--compatible-runtimes python3.11 python3.12
# 查詢 Layer 所有版本
aws lambda list-layer-versions \
--layer-name my-python-layer
# 輸出範例
{
"LayerVersions": [
{
"LayerVersionArn": "arn:aws:lambda:ap-northeast-1:123456789012:layer:my-python-layer:2",
"Version": 2,
"Description": "Updated version with bug fixes"
},
{
"LayerVersionArn": "arn:aws:lambda:ap-northeast-1:123456789012:layer:my-python-layer:1",
"Version": 1,
"Description": "Python requests library layer"
}
]
}
|
附加 Layer 到函數
建立函數時附加 Layer
1
2
3
4
5
6
7
8
| # 建立新函數並附加 Layer
aws lambda create-function \
--function-name my-function \
--runtime python3.11 \
--role arn:aws:iam::123456789012:role/lambda-execution-role \
--handler index.handler \
--zip-file fileb://function.zip \
--layers arn:aws:lambda:ap-northeast-1:123456789012:layer:my-python-layer:2
|
更新現有函數的 Layers
1
2
3
4
5
6
7
8
9
10
11
| # 更新函數的 Layer 配置
aws lambda update-function-configuration \
--function-name my-function \
--layers \
arn:aws:lambda:ap-northeast-1:123456789012:layer:my-python-layer:2 \
arn:aws:lambda:ap-northeast-1:123456789012:layer:my-utils-layer:1
# 移除所有 Layers
aws lambda update-function-configuration \
--function-name my-function \
--layers []
|
查詢函數的 Layer 配置
1
2
3
4
5
6
7
8
9
10
11
12
| # 取得函數配置
aws lambda get-function-configuration \
--function-name my-function \
--query 'Layers'
# 輸出範例
[
{
"Arn": "arn:aws:lambda:ap-northeast-1:123456789012:layer:my-python-layer:2",
"CodeSize": 1234567
}
]
|
Layer 路徑結構
Lambda 會將 Layer 內容解壓縮到 /opt 目錄下。不同執行環境有不同的路徑要求:
Python
1
2
3
| python/lib/python3.11/site-packages/
# 解壓縮後:/opt/python/lib/python3.11/site-packages/
# Lambda 自動加入 PYTHONPATH
|
Node.js
1
2
3
4
| nodejs/node_modules/
# 或
nodejs/node18/node_modules/
# 解壓縮後:/opt/nodejs/node_modules/
|
Java
1
2
3
| java/lib/
# 解壓縮後:/opt/java/lib/
# JAR 檔案自動加入 CLASSPATH
|
Ruby
1
2
3
| ruby/gems/3.2.0/
ruby/lib/
# 解壓縮後:/opt/ruby/gems/3.2.0/
|
自訂路徑
1
2
3
4
5
| # 任何自訂內容放置於根目錄
bin/
lib/
config/
# 解壓縮後:/opt/bin/、/opt/lib/、/opt/config/
|
在函數中存取 Layer 內容
1
2
3
4
5
6
7
8
9
10
11
12
| import json
# 存取 Layer 中的設定檔
def lambda_handler(event, context):
# Layer 內容位於 /opt 目錄
with open('/opt/config/settings.json', 'r') as f:
settings = json.load(f)
return {
'statusCode': 200,
'body': json.dumps(settings)
}
|
跨帳戶共享 Layer
授權其他帳戶存取 Layer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| # 授權特定帳戶存取 Layer
aws lambda add-layer-version-permission \
--layer-name my-python-layer \
--version-number 1 \
--statement-id account-123456789012 \
--action lambda:GetLayerVersion \
--principal 123456789012
# 授權整個組織存取
aws lambda add-layer-version-permission \
--layer-name my-python-layer \
--version-number 1 \
--statement-id org-access \
--action lambda:GetLayerVersion \
--principal "*" \
--organization-id o-1234567890
|
公開分享 Layer
1
2
3
4
5
6
7
| # 將 Layer 設為公開(任何 AWS 帳戶都可使用)
aws lambda add-layer-version-permission \
--layer-name my-public-layer \
--version-number 1 \
--statement-id public-access \
--action lambda:GetLayerVersion \
--principal "*"
|
使用其他帳戶的 Layer
1
2
3
4
| # 使用跨帳戶 Layer
aws lambda update-function-configuration \
--function-name my-function \
--layers arn:aws:lambda:ap-northeast-1:987654321098:layer:shared-layer:3
|
查詢與移除權限
1
2
3
4
5
6
7
8
9
10
| # 查詢 Layer 權限政策
aws lambda get-layer-version-policy \
--layer-name my-python-layer \
--version-number 1
# 移除特定權限
aws lambda remove-layer-version-permission \
--layer-name my-python-layer \
--version-number 1 \
--statement-id account-123456789012
|
版本管理
列出所有 Layers
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| # 列出帳戶中所有 Layers
aws lambda list-layers
# 輸出範例
{
"Layers": [
{
"LayerName": "my-python-layer",
"LayerArn": "arn:aws:lambda:ap-northeast-1:123456789012:layer:my-python-layer",
"LatestMatchingVersion": {
"LayerVersionArn": "arn:aws:lambda:ap-northeast-1:123456789012:layer:my-python-layer:2",
"Version": 2
}
}
]
}
|
刪除 Layer 版本
1
2
3
4
5
6
| # 刪除特定版本
aws lambda delete-layer-version \
--layer-name my-python-layer \
--version-number 1
# 注意:無法刪除正在被函數使用的 Layer 版本
|
取得 Layer 版本詳細資訊
1
2
3
4
5
6
7
8
| # 取得特定版本資訊
aws lambda get-layer-version \
--layer-name my-python-layer \
--version-number 2
# 透過 ARN 取得
aws lambda get-layer-version-by-arn \
--arn arn:aws:lambda:ap-northeast-1:123456789012:layer:my-python-layer:2
|
最佳實踐
1. 規劃 Layer 結構
- 將相關的相依性分組到同一個 Layer
- 避免單一 Layer 過大,影響冷啟動時間
- 使用有意義的命名慣例
1
2
3
| # 建議的命名格式
{team}-{purpose}-{runtime}
# 範例:platform-common-libs-python311
|
2. 版本策略
- 使用語意化版本控制追蹤變更
- 在 Layer 描述中記錄變更內容
- 保留穩定版本,及時清理過時版本
1
2
3
| aws lambda publish-layer-version \
--layer-name my-layer \
--description "v2.1.0 - Added retry logic, fixed connection timeout"
|
3. 安全性考量
- 定期更新 Layer 中的相依性以修補安全漏洞
- 審慎管理跨帳戶存取權限
- 避免在 Layer 中儲存敏感資訊
4. 效能優化
- 只包含必要的相依性
- 移除不需要的測試檔案和文件
- 考慮使用 arm64 架構以降低成本
1
2
3
4
| # 清理不必要的檔案
find . -type d -name "__pycache__" -exec rm -rf {} +
find . -type d -name "tests" -exec rm -rf {} +
find . -type f -name "*.pyc" -delete
|
5. CI/CD 整合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # 在 CI/CD 流程中自動發布 Layer
#!/bin/bash
LAYER_NAME="my-python-layer"
VERSION=$(date +%Y%m%d%H%M%S)
# 建立 Layer 套件
pip install -r requirements.txt -t python/lib/python3.11/site-packages/
zip -r layer.zip python/
# 發布新版本
aws lambda publish-layer-version \
--layer-name $LAYER_NAME \
--description "Build: $VERSION" \
--zip-file fileb://layer.zip \
--compatible-runtimes python3.11
|
參考資料