在雲端架構中,備份是確保資料安全的關鍵環節。透過 AWS 提供的 EC2 快照功能,我們可以輕鬆地為 EC2 實例建立資料備份。但手動建立快照可能費時費力,因此使用 AWS Lambda 搭配 CloudWatch Events 自動化備份成為一個理想的解決方案。
本文將一步步介紹如何:
- 建立 Lambda 函數來執行快照操作
- 配置 CloudWatch Events 排程每月執行備份
- 驗證快照建立是否成功
為什麼需要自動化 EC2 備份?
使用場景:
- 災難復原:當 EC2 實例發生故障時,快速從快照還原
- 合規要求:許多產業規範要求定期備份資料
- 資料遷移:將 EC2 實例遷移到不同區域或帳戶
- 版本管理:保留不同時間點的系統狀態
為什麼選擇 Lambda + CloudWatch Events?
- 無伺服器架構:無需管理執行備份的伺服器
- 成本效益:只在執行時計費,閒置時無成本
- 高可靠性:AWS 託管服務保證高可用性
- 靈活排程:可設定每月、每週、每日等不同頻率
架構流程
系統元件:
- Lambda 函數:執行快照操作的核心邏輯
- CloudWatch Events (EventBridge):定義排程(如每月執行一次)
- IAM 角色:提供 Lambda 必要的 EC2 權限
- CloudWatch Logs:記錄執行日誌與錯誤訊息
- EC2 Snapshots:儲存備份資料
工作流程:
- CloudWatch Events 根據排程觸發 Lambda 函數
- Lambda 函數透過 IAM 角色取得 EC2 權限
- Lambda 讀取指定 EC2 實例的所有磁碟區(Volumes)
- 為每個磁碟區建立快照(Snapshot)
- 驗證快照狀態直到完成
- 記錄執行結果到 CloudWatch Logs
步驟 1:建立 Lambda 函數
- 登入 AWS Lambda 控制台
- 點擊 Create function
- 配置以下參數:
- Function name:
MonthlyEC2Backup - Runtime:
Python 3.12(或最新版本) - Permissions:選擇
Create a new role with basic Lambda permissions
- Function name:
- 點擊 Create function
步驟 2:編寫 Lambda 程式碼
在 Function code 區域,新增以下程式碼:
import boto3
import datetime
import time
def lambda_handler(event, context):
ec2 = boto3.client('ec2')
# 設定需要備份的 EC2 實例 ID
instances = ['<INSTANCE_ID>'] # 替換為你的 EC2 實例 ID
for instance_id in instances:
# 建立快照描述
description = f"Backup of {instance_id} - {datetime.datetime.now().strftime('%Y-%m-%d')}"
# 獲取實例相關的所有卷
volumes = ec2.describe_volumes(Filters=[
{'Name': 'attachment.instance-id', 'Values': [instance_id]}
])
# 為每個卷創建快照並檢查狀態
for volume in volumes['Volumes']:
volume_id = volume['VolumeId']
print(f"Creating snapshot for volume: {volume_id}")
# 建立快照
response = ec2.create_snapshot(
VolumeId=volume_id,
Description=description
)
snapshot_id = response['SnapshotId']
print(f"Snapshot {snapshot_id} created for volume {volume_id}")
# 驗證快照狀態
print(f"Verifying snapshot {snapshot_id} status...")
while True:
snapshot_status = ec2.describe_snapshots(
SnapshotIds=[snapshot_id]
)['Snapshots'][0]['State']
if snapshot_status == 'completed':
print(f"Snapshot {snapshot_id} for volume {volume_id} completed successfully!")
break
elif snapshot_status == 'error':
print(f"Snapshot {snapshot_id} for volume {volume_id} failed!")
break
else:
print(f"Snapshot {snapshot_id} is in progress...")
time.sleep(5)
return {
'statusCode': 200,
'body': 'EC2 backup completed successfully'
}
程式碼說明:
boto3.client('ec2'):建立 EC2 客戶端describe_volumes():取得 EC2 實例的所有磁碟區create_snapshot():建立快照describe_snapshots():檢查快照狀態time.sleep(5):每 5 秒檢查一次狀態
重要:將 <INSTANCE_ID> 替換為實際的實例 ID(如 i-0abcd1234efgh5678),然後點擊 Deploy。
步驟 3:配置 IAM 權限
- 進入 Lambda 函數的 Configuration → Permissions
- 點擊執行角色(Execution role)連結
- 在 IAM 控制台中,點擊 Add permissions → Create inline policy
- 使用以下 JSON 策略:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:DescribeVolumes",
"ec2:CreateSnapshot",
"ec2:DescribeSnapshots",
"ec2:CreateTags"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
}
]
}
權限說明:
ec2:DescribeVolumes:讀取磁碟區資訊ec2:CreateSnapshot:建立快照ec2:DescribeSnapshots:檢查快照狀態ec2:CreateTags:為快照新增標籤(選用)logs:*:寫入 CloudWatch Logs
步驟 4:建立 CloudWatch Events 排程
- 進入 Amazon EventBridge 控制台 → Rules
- 點擊 Create rule
- 配置規則:
- Name:
MonthlyEC2BackupSchedule - Rule type:
Schedule
- Name:
- 設定排程模式:
- 選擇 Cron-based schedule
- 輸入排程表達式:
cron(0 0 1 * ? *)
- 選擇目標:
- Target:
Lambda function - Function:
MonthlyEC2Backup
- Target:
- 點擊 Create rule
Cron 表達式說明:
cron(0 0 1 * ? *)
│ │ │ │ │ │
│ │ │ │ │ └─ 年份(* 表示任何年份)
│ │ │ │ └─── 星期(? 表示不指定)
│ │ │ └───── 月份(* 表示每月)
│ │ └─────── 日期(1 表示每月 1 號)
│ └───────── 小時(0 表示凌晨 0 點)
└─────────── 分鐘(0 表示整點)
其他常用排程範例:
- 每週日凌晨 2 點:
cron(0 2 ? * SUN *) - 每日凌晨 3 點:
cron(0 3 * * ? *) - 每月 15 號凌晨 1 點:
cron(0 1 15 * ? *)
步驟 5:測試與驗證
測試 Lambda 函數
- 在 Lambda 控制台中,點擊 Test
- 建立測試事件(可使用空的 JSON:
{}) - 執行測試並檢查輸出
檢查 CloudWatch Logs
- 進入 CloudWatch 控制台 → Log groups
- 找到
/aws/lambda/MonthlyEC2Backup - 檢查執行日誌,確認是否有錯誤訊息
驗證快照
- 進入 EC2 控制台 → Snapshots
- 確認快照狀態為 Completed
- 檢查快照描述與建立時間
常見問題與解決方案
問題 1:Lambda 執行逾時
原因:
- 預設 Lambda 執行時間限制為 3 秒
- 建立大型快照需要較長時間
解決方案:
- 在 Lambda Configuration → General configuration 中調整 Timeout 為 5-10 分鐘
- 或移除快照狀態驗證的迴圈,改為非同步處理
問題 2:權限不足錯誤
錯誤訊息:
An error occurred (UnauthorizedOperation) when calling the CreateSnapshot operation
解決方案:
- 確認 IAM 角色包含
ec2:CreateSnapshot權限 - 檢查是否有 SCP(Service Control Policy)限制
問題 3:如何備份多個 EC2 實例?
解決方案:
將 instances 擴展為列表:
instances = [
'i-0abcd1234efgh5678',
'i-0ijkl5678mnop1234',
'i-0qrst9012uvwx3456'
]
問題 4:如何自動清理舊快照?
解決方案:
在 Lambda 函數中新增清理邏輯:
# 刪除 30 天前的快照
retention_days = 30
cutoff_date = datetime.datetime.now() - datetime.timedelta(days=retention_days)
snapshots = ec2.describe_snapshots(OwnerIds=['self'])['Snapshots']
for snapshot in snapshots:
if snapshot['StartTime'].replace(tzinfo=None) < cutoff_date:
print(f"Deleting old snapshot: {snapshot['SnapshotId']}")
ec2.delete_snapshot(SnapshotId=snapshot['SnapshotId'])
成本考量
費用組成:
- Lambda 執行:免費額度每月 100 萬次請求 + 40 萬 GB-秒運算時間
- EBS 快照儲存:每 GB 每月約 $0.05 美元(依區域而異)
- CloudWatch Logs:每 GB 約 $0.50 美元
成本估算範例:
假設備份 1 個 100GB 的 EC2 實例,每月執行一次:
- Lambda 執行費用:幾乎為 0(在免費額度內)
- 快照儲存費用:100GB × $0.05 = $5.00/月
- CloudWatch Logs:可忽略(< $0.10)
成本優化建議:
- 定期清理舊快照(如保留最近 3 個月)
- 使用 EBS 快照生命週期管理(Data Lifecycle Manager)
- 評估是否需要跨區域複製快照(會增加傳輸費用)
進階優化
1. 新增 SNS 通知
在快照完成後發送通知:
sns = boto3.client('sns')
sns.publish(
TopicArn='arn:aws:sns:us-east-1:123456789012:EC2BackupNotification',
Subject='EC2 Backup Completed',
Message=f'Snapshot {snapshot_id} created successfully'
)
2. 為快照新增標籤
ec2.create_tags(
Resources=[snapshot_id],
Tags=[
{'Key': 'Name', 'Value': f'Backup-{instance_id}'},
{'Key': 'CreatedBy', 'Value': 'Lambda'},
{'Key': 'BackupDate', 'Value': datetime.datetime.now().strftime('%Y-%m-%d')}
]
)
3. 使用環境變數
將實例 ID 設定為環境變數,避免硬編碼:
import os
instances = os.environ['INSTANCE_IDS'].split(',')
結論
透過本文的實作,您已經學會:
- 建立自動化 EC2 備份系統:使用 Lambda + CloudWatch Events
- 配置適當的 IAM 權限:確保安全性與最小權限原則
- 驗證快照狀態:確保備份成功完成
- 處理常見問題:解決權限、逾時等問題
- 優化成本:透過自動清理舊快照降低費用
後續建議:
- 實作跨區域快照複製以提升災難復原能力
- 整合 AWS Backup 服務進行集中管理
- 設定 CloudWatch 告警監控備份失敗
- 建立快照還原測試流程驗證備份可用性
Related Articles
- Automated Monthly EC2 Snapshot Backup with AWS Lambda + CloudWatch Events
- AWS VPC Public and Private Subnet Design and Configuration Guide
- AWS VPC Public 與 Private Subnet 設計與配置指南
- AWS Storage Solutions Complete Comparison: Amazon FSx vs S3 Deep Dive & Selection Guide
- Ubuntu Server Auto-Update Complete Guide: Enterprise Strategy, Risk Control & Failure Recovery