先驗知識
AWS 是亞馬遜云計算平臺咒劲。
EC2 是 AWS 提供的云主機顷蟆,一般采用基于 CentOS 的 Amazon Linux 系統(tǒng),像大多數(shù)云主機一樣使用腐魂。
ELB 是 AWS 提供的負載均衡服務(wù)帐偎,可以將請求轉(zhuǎn)發(fā)到目標組中的某個 EC2 實例,也會對目標組實例進行健康檢查蛔屹,只將請求轉(zhuǎn)發(fā)到健康的實例肮街。
目標
AWS AutoScaling 服務(wù)允許我們設(shè)定 AutoScaling 組(ASG)。ASG 維護了一組 EC2 實例判导,EC2 實例可以分布在不同的可用區(qū)里以保證可用性嫉父。AutoScaling 能檢查實例健康狀況,自動替換不健康的實例眼刃,能根據(jù)特定規(guī)則增減需要的實例數(shù)量绕辖,并能在啟動、銷毀 EC2 實例時觸發(fā)事件調(diào)用其他服務(wù)擂红。AutoScaling 服務(wù)能夠與 ELB 彈性負載均衡服務(wù)結(jié)合使用仪际,實例不需要公網(wǎng) IP,而且實例在啟動后會自動加入 ELB 的目標組昵骤,在終止實例前會先等待 ELB 連接耗盡树碱。
我們要實現(xiàn)的結(jié)構(gòu)如圖所示:
看上去夢寐以求,但用起來卻沒有這么舒服变秦。
給 ASG 創(chuàng)建 EC2 的啟動配置
我們需要給 ASG 提供啟動配置(Launch Configuration)成榜,啟動配置里指定了 EC2 的實例類型、AMI 鏡像蹦玫、存儲設(shè)備赎婚、IAM 角色刘绣、SSH Key、用戶數(shù)據(jù)(User Data)等一系列信息挣输,用于啟動新實例纬凤。
我們主要關(guān)心 IAM 角色和啟動腳本,其他的按需配置撩嚼。
用戶數(shù)據(jù)實際上是啟動腳本停士,當 EC2 實例啟動時,在初始化的最后以 root 身份將用戶數(shù)據(jù)作為腳本執(zhí)行完丽。你可以登錄實例恋技,在 /var/log/cloud-init-output.log
日志尾查看其輸出。
因為每次修改啟動配置都需要重新創(chuàng)建 ASG舰涌,而這就需要清空實例等十分繁瑣,所以最好將用戶數(shù)據(jù)設(shè)置為從外部獲取真正的啟動腳本來運行你稚,以便修改調(diào)試:
#!/usr/bin/env bash
aws s3 cp s3://bucket/key /tmp/myscript.sh &&
chmod +x /tmp/myscript.sh && /tmp/myscript.sh
這需要給 EC2 的 IAM 角色允許 S3 訪問權(quán)限瓷耙。
創(chuàng)建 ASG
我們根據(jù)啟動配置創(chuàng)建 ASG,設(shè)定最低刁赖、最高搁痛、所需的實例數(shù)量,將實例連接到特定的 ELB 目標組宇弛,以 ELB 的健康檢查作為 ASG 中實例的健康依據(jù)等等鸡典。
不健康的實例在健康檢查失敗且等待超時后將被終止。具體請參考 ASG 中實例的運行狀況檢查枪芒。
ASG 中實例的生命周期
ASG 中實例有生命周期的概念彻况,也就是實例有一個狀態(tài),并在不同的狀態(tài)間轉(zhuǎn)移舅踪。
ASG 中實例的生命周期如圖所示:
生命周期鉤子
在啟動的 Pending 和終止的 Terminating 狀態(tài)均可以添加鉤子纽甘,鉤子會觸發(fā)事件,并等待事件完成再進入下一狀態(tài)(當沒有鉤子時實例會自動跳到下一狀態(tài))抽碌。鉤子能設(shè)置超時時限悍赢、超時結(jié)果。
可以使用 aws-cli 或 AWS SDK 等主動完成生命周期事件货徙,或延期它左权。事件完成需要提供結(jié)果,主動完成和超時均有“繼續(xù)”和“放棄”兩種結(jié)果可選痴颊。
可以給啟動或終止階段添加多個鉤子,他們會在上一個鉤子完成且結(jié)果為“繼續(xù)”后依次執(zhí)行蠢棱。在啟動階段一旦出現(xiàn)“放棄”的結(jié)果后瀑梗,實例會跳過其他鉤子烹笔,直接開始終止過程,這也會觸發(fā)終止階段的鉤子抛丽;在終止階段出現(xiàn)“放棄”的結(jié)果后谤职,實例會跳過其他鉤子,直接終止亿鲜。
添加鉤子
使用 aws autoscaling put-lifecycle-hook
命令添加溝子允蜈,有兩種可選的 transition 值:
-
autoscaling:EC2_INSTANCE_LAUNCHING
實例啟動時 -
autoscaling:EC2_INSTANCE_TERMINATING
實例終止時
下面這個命令的例子演示了添加“啟動時鉤子,超時時限 600s蒿柳,超時后放棄該實例”:
aws autoscaling put-lifecycle-hook \
--auto-scaling-group-name ${ASG} \
--lifecycle-hook-name ${HOOK} \
--lifecycle-transition "autoscaling:EC2_INSTANCE_LAUNCHING" \
--heartbeat-timeout 600 \
--default-result "ABANDON"
如果使用了下文的 SNS 或 SQS 接收事件饶套,還需要提供 role-arn
和 notification-target-arn
。AWS 提供了比較完整的文檔 添加生命周期鉤子 來講述這一過程垒探。
報告事件完成或延期
使用 aws autoscaling complete-lifecycle-action
命令可以主動完成事件妓蛮,使生命周期繼續(xù)(CONTINUE
)或放棄(ABANDON
),根據(jù)你獲得的信息圾叼,提供 instance-id
蛤克、lifecycle-action-token
任一即可:
下面這個命令的例子演示了“完成 ${ASG}
組的實例 ${INSTANCE_ID}
上的 ${HOOK}
事件,結(jié)果為繼續(xù)”:
aws autoscaling complete-lifecycle-action \
--auto-scaling-group-name ${ASG} \
--lifecycle-hook-name ${HOOK} \
--instance-id ${INSTANCE_ID} \
--lifecycle-action-result CONTINUE
命令 aws autoscaling record-lifecycle-action-heartbeat
可以重置超時時間夷蚊,使用方法類似于上文所述的 complete-lifecycle-action
构挤。
注意,如果希望 EC2 之上的腳本來執(zhí)行上述操作惕鼓,需要給 EC2 的 IAM 角色允許 autoscaling:CompleteLifecycleAction
或 autoscaling:RecordLifecycleActionHeartbeat
權(quán)限筋现。
EC2 實例如何獲取自身的 instance-id 呢?
INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
ASG=$(aws autoscaling describe-auto-scaling-instances --output text --query 'AutoScalingInstances[?InstanceId==`'${INSTANCE_ID}'`].AutoScalingGroupName')
具體請參考 檢索實例元數(shù)據(jù) 和 控制 aws-cli 的命令輸出箱歧。
鉤子事件的傳播
AWS 允許鉤子觸發(fā)后向外傳播這一事件矾飞,有三種方式——通過 CloudWatch Events、SNS 或者 SQS呀邢。他們會攜帶足夠的信息凰慈,具體的攜帶數(shù)據(jù)請參考 AutoScaling 事件。
具體配置如果有疑問驼鹅,請參考 添加生命周期鉤子 中《向 Auto Scaling 組添加生命周期掛鉤》節(jié)的前兩步微谓。
事件被傳播后,一般使用 Amazon Lambda 或者額外的服務(wù)器來處理输钩。同樣注意豺型,如果希望 Lambda 報告事件完成或延期,請給 Lambda 的 IAM 角色允許相應(yīng)權(quán)限买乃。
很多時候我們需要在 EC2 實例上執(zhí)行腳本姻氨,這方面的內(nèi)容請參見這篇博客 AWS 使用 Simple System Manager 向 EC2 發(fā)送命令遠程執(zhí)行腳本。
事件處理的個人經(jīng)驗
在實例啟動時剪验,我們一般不把事件傳播出去交由 Lambda 處理肴焊,而是由用戶數(shù)據(jù)里的啟動腳本在執(zhí)行結(jié)束后自行報告事件完成(繼續(xù))前联,或者通知 SQS、SNS娶眷、Lambda 等來做似嗤。
因為在實例啟動時我們需要手動安裝 SSM Agent,此時該服務(wù)對外界而言不可用届宠。所以我們不能用這種方式來與 EC2 通信烁落。
在實例終止時,我們一般用 Lambda 處理豌注,并用 SSM 通知 EC2 執(zhí)行回收腳本伤塌,回收腳本自行報告事件完成(繼續(xù)),如果 SSM 失敗轧铁,再由 Lambda 報告事件完成(放棄)每聪。
擴展 ASG 的大小
AWS 提供了多種 擴展 ASG 的大小 的策略。
這里我們提供兩個簡單的手工策略來擴展 ASG 的大谐莘纭:
aws autoscaling put-scaling-policy \
--auto-scaling-group-name ${ASG} \
--policy-name "inc" \
--policy-type "SimpleScaling" \
--adjustment-type "ChangeInCapacity" \
--scaling-adjustment 1
aws autoscaling put-scaling-policy \
--auto-scaling-group-name ${ASG} \
--policy-name "dec" \
--policy-type "SimpleScaling" \
--adjustment-type "ChangeInCapacity" \
--scaling-adjustment -1
現(xiàn)在我們獲得了高可用的彈性計算服務(wù)药薯,配置過程很復(fù)雜,最好能夠采用 CloudFormation 來配置聂宾,或者使用 aws-cli 編寫腳本來完成果善。
祝大家使用愉快诊笤。