前一陣子我們才聊過怎麼讓 RDS 保持關機狀態,結果隔壁的 EC2 不開心了:「為什麼只有資料庫可以關機?我難道就該 24 小時待命嗎?」
在地端時代,伺服器就像老派工程師,開機就不敢關,因為誰知道下次能不能再活過來?一按電源鍵,可能要等到 IT 部門集體唸經才會開得起來。
不過搬到雲端後,遊戲規則變了:只要開機 = 錢錢開始燃燒。於是老闆立刻開口:「測試機下班要關掉啊,不然每天都在幫 AWS 打工送錢?」每天省一半時間等於每天省一半費用,這可是比發年終還刺激的 KPI。當然啦,除了那些 24 小時要跟 7-11 一樣營業的服務例外。
問題來了:要是每天都靠工程師手動去開關機,不就等於幫 EC2 打卡小弟?太浪費青春了。於是我們出動 AWS EventBridge + Lambda,打造一個超省心的「自動開關機」神器。時間一到,EC2 自動下班,不只幫公司省錢,還能順便提醒你:「兄弟,該下班啦!」
今天就來教大家怎麼用 AWS EventBridge + Lambda,幫 EC2 安排一個「朝九晚五」的幸福人生。從此以後,它準時上班、乖乖下班,保證不再偷偷加班爆肝。
想像一下這個小劇場:
流程就長這樣:
EventBridge(定時喊話) → Lambda(實際操作) → EC2(乖乖聽話)
簡單暴力,不拖泥帶水。
建立 Lambda 的細節我就不再像寫教科書那樣一條一條交代了,畢竟大家都是工程師,介面點一點應該不至於迷路吧?(如果真的迷路了,拜託回去翻前幾篇,當作課本重修一下。)
這次我們的目標很單純:建一個叫 OperationEC2 的 Lambda Function。
參數?不用想太多,大部份照預設就好:
import json
import boto3
def lambda_handler(event, context):
# 從 event 中獲取參數
instance_ids = event.get('instance_ids', [])
region = event.get('region', None)
force_stop = event.get('force_stop', False)
action = event.get('action', None)
try:
# 驗證輸入參數
if not instance_ids:
raise ValueError("instance_ids 參數是必需的")
if not action:
raise ValueError("action 參數是必需的")
ec2 = boto3.client('ec2', region_name='us-east-1')
try:
if action.lower() == 'stop':
for instance_id in instance_ids:
restult = ec2.stop_instances(InstanceIds=[instance_id], Force=force_stop)
print("restult:", restult)
elif action.lower() == 'start':
for instance_id in instance_ids:
restult = ec2.start_instances(InstanceIds=[instance_id])
print("restult:", restult)
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda!')
}
except ClientError as e:
error_message = f"關閉實例時發生錯誤: {e.response['Error']['Message']}"
return {
'statusCode': 500,
'body': json.dumps({
'error': error_message,
}, ensure_ascii=False)
}
except ValueError as e:
return {
'statusCode': 400,
'body': json.dumps({
'error': f'參數錯誤: {str(e)}'
}, ensure_ascii=False)
}
在這個範例裡,我們走懶人路線 —— 把開機跟關機塞在同一支程式裡。靠 EventBridge 傳進來的參數,就能決定到底要叫 EC2 起床上班,還是叫它去睡覺。這樣一支程式搞定兩個任務,程式碼精簡,維護輕鬆,還能少開幾支 Lambda,避免日後進 AWS Console 的時候看到滿天飛的 Function 名字搞到自己頭痛。
當然啦,如果你老闆很愛搞「開機要先跳個舞,關機要先點個頭」這種特別需求,那就拆成兩支 Lambda,各自獨立比較安心。簡單說,一支全能 vs. 各自專精,就看你偏好「懶」還是「細心」囉。
還記得我們之前碎念過的最佳實踐嗎?沒錯,就是那句老話:權限要最小化。別什麼都給,結果 Lambda 一個不小心就能幫你把整個 AWS 帳號刪掉,那可不是自動化,而是「自動 Game Over」。
因為這次我們只是要讓 EC2 乖乖開機跟下班關機,所以只需要加上這幾個權限:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:StopInstances",
"ec2:StartInstances"
],
"Resource": "*"
}
]
}
接下來就是老套路 —— 先找到 Lambda 用的那個 Role,然後透過 Create Inline Policy 幫它塞權限。
編輯 Policy 的時候,請直接切換到 JSON 模式。幫你避免一格一格點 UI 了,工程師哪有空玩拼圖?把上面那段 JSON 權限複製進去就搞定。
最後,系統會很貼心地問你:「要幫這份 Policy 取什麼名字?」
這時候不要糾結,叫什麼都行,反正你半年後一定忘記。建議就來個直白的,例如 EC2-Permission
,至少比 test123
有誠意。按下 Create Policy,完工!
設定完之後,回去檢查一下 Lambda 的 Role 裡面有沒有多出剛剛那個 Policy。如果有,那就代表你的 Lambda 已經被授予「開關 EC2」的超能力了。
另外友情提醒:Lambda 在執行 start_instances
或 stop_instances
的時候,很可能三秒鐘打不完卡。AWS 預設的 timeout 太短,會讓你 Lambda 直接翻車。記得去把 最大執行時間拉長一點,不然到時候看到紅通通的錯誤訊息,你會懷疑自己是不是設定錯誤,結果只是 AWS 太心急。
想讓 EC2 準時上下班?沒問題,給它一張班表就行了。
簡單來說,EC2 就是你公司最乖的員工:排班怎麼寫,它就怎麼走。
接下來我們要在 AWS EventBridge 幫 EC2 安排班表。詳細的點點選選,前幾篇文章都碎念過了,這裡直接看重點:
然後把 Schedule 指派給我們剛剛建立的 Lambda Function —— OperationEC2。
這裡最關鍵的就是 Payload,因為它決定要叫 EC2 幹嘛:
{
"instance_ids": [
"i-08f21a48705e28xxxx"
],
"action": "start"
}
action
:填 start
,意思就是「EC2 起床!該上班了!」instance_ids
:放你要開的 EC2 ID。它是陣列,所以可以一次開多台,簡單暴力,一次喚醒整個部門。至於下班的規則?套路一樣,只是改成 18:00,payload 改成 stop
:
{
"instance_ids": [
"i-08f21a48705e28xxxx"
],
"action": "stop"
}
這樣一來,EC2 每天早上 9 點打卡上班,下午 6 點準時下班。
唯一的風險就是 —— 比你還準時下班。到時候老闆看到伺服器下班了,卻發現你還在辦公室,可能會想你是不是該幫你加點薪(做夢比較快)。
好啦,現在你知道怎麼讓 EC2 每天比你還要準時的上下班了!