如何建立 fly.toml 並快速佈署至 Fly.io
介紹
最近因為有些專案需要有 local Volume,但在 Serverless 上要用偏麻煩,除機器上的本身功能以外,還需要另外開 VM 讓 Container 能夠 mount volume,因此需要類似 Heroku、Fly.io 這類的 SaaS 的服務,可以用很少量的費用去使用到 Database/Volume 的功能...
分類
最近因為有些專案需要有 local Volume,但在 Serverless 上要用偏麻煩,除機器上的本身功能以外,還需要另外開 VM 讓 Container 能夠 mount volume,因此需要類似 Heroku、Fly.io 這類的 SaaS 的服務,可以用很少量的費用去使用到 Database/Volume 的功能...

由於近期自己蓋了幾隻 side project,慢慢發現有些服務倒了我自己也不知道,但時間久了其實當下也會忘了要修哪...
也因公司內有 status page 可以看每個服務狀態,想想這需求我也需要,因此萌生了架 status page 來幫忙確認健康狀態,接下來看看怎麼操作吧

在 AWS 的 API gateway 上就有一個項目(Authorizer)是支援 Cognito 以及客制認證的方法,好處就是在進我們寫的 API 之前有個可以做身份確認的 Lambda Function 幫我們好前處理,而本篇則會介紹如何在 Serverless framework 上設定 API gateway 的 Authorizer 以及成功讓 API 回應,串接 Cognito 做使用部分就留給之後吧!

之前鐵人賽寫了一篇文章有提到 Cold Start 的問題,不過只有粗略介紹,最近看到大家忽然又開始討論這個話題,這次就來好好的搜尋資料介紹一下。
平常在做 open source 時比較常遇到休眠狀態應該就是 Heroku,而開頭要先澄清一下他是屬於 PaaS 的架構,而 AWS、Google、Azure 裡提供的 Lambda、Cloud Run、Azure Function 這些則屬於 FaaS 架構,而最常討論 Cold start 時最常會在 FaaS 上討論,只是剛好 Heroku 使用起來也是一樣,這次文章就把他一起抓進來討論啦~
有很多各式各樣的服務,SaaS、FaaS、KaaS、IaaS... 等各式各樣的架構,每個都是為了解決某個問題所誕生的,至於好或不好其實就是看使用場景而定,所以大家在選用時要注意一下你使用的場景哦!
一般會有休眠機制是因為這些供應商在提供服務都是提供按次計費的方案,讓開發者在用時可以需要才喚醒使用,也就是說這些服務都是 事件驅動(Event-Driven)導向,意指是當前服務若收到訊息後,會呼叫對應的 Function 來處理對應服務所接收到的資料(Queue、Notify ...),但相對的就是會有休眠讓服務暫停,進而讓較少使用的服務不會因為掛在線上而一直被收費用,而重新啟動這件事就是本篇要提的Cold start。
在處理資料之後過一段時間若沒有繼續執行,雲端供應商會將模組暫停,此時 function 會處於 inactive 狀態(cold),而當 function 再度被觸發時(cold start)則會再啟動模組來執行對應 function 來處理事件,在模組與 function 之間的關係可以稱他們為 Function chain。

以 AWS 為例,在喚醒時會到 S3 去取得檔案,接著找到相關的 Lambda 並載入相關模組套件,然後再執行觸發的事件,整理過後的下:
事件處理 ➡️ 過段時間 ➡️ 暫停 function 模組(休眠) ➡️ 觸發 ➡️ 啟動 function 模組 ➡️ 事件處理...
這整個流程就是俗稱的 cold start,因為在這個過程中會花些時間,所以若是拿來處理 api 相關問題的話就會有第一批請求很久,然後之後的請求卻特別快的狀態,請大家莫急莫慌莫害怕呀!
| 平台 | 多少時間後暫停 |
|---|---|
| AWS Lambda | 10 minutes |
| Google Cloud Functions | 介於 3 minutes 之間 5+ hours 都有 |
| Azure Functions | 20 minutes |
| Heroku | 30 minutes |
前三個為
FaaS架構,而 Heroku 則為PaaS架構喔!
下圖則來自 2019/09 的一篇文章,較深色的部分則為啟動時間。

以我熟悉使用 serverless framework 部署到 AWS 來說,他們提供了一個 warm-up 的套件,可以設定排程時間讓這個 function 固定去戳其他 function,避免他們進入休眠的狀態,雖然這樣子就能達到跟一般服務一樣的常駐狀態,不過相對來說就要注意次數的使用問題,若是流量還小的話沒什麼問題,但若有一定的流量就須注意一下帳單,因為這些在互戳的過程中還是有算進費用的喔!使用上還要多注意才行。
另一方面要注意相依套件的問題,引用 google 文件的其中一段:
謹慎使用依附元件,如果您使用動態語言搭配相依的程式庫,例如匯入使用 Node.js 的模型,這些模組的載入時間會增加冷啟動期間的延遲時間。您可以透過以下方式縮短啟動延遲時間:
畢竟在載入模組的時候相依套件也是要一起抓進來,若是程式本身太多依賴的話也是會導致 cold start 的時間變長哦!
最後就在幫大家整理一下三大平台的 warm-up 資源:
為什麼要有 cold start 的機制,以供應商的角度來說他們可以提供一定的量讓使用者免費在平台上先建置服務,但若要免費就是服務會被暫時暫停,畢竟現在流量就是錢嗎 💰,像我常用的 Heroku 就會是這樣,而當你流量大的時候就看你要不要搬家,不過一般應該都懶得搬,就會形成所謂的養、套、殺🤣(離題)。
總而言之,若是需要服務時常活著,就是需要付出點流量的錢 💰,也或許你的作品服務時間可能不用那麼長,只要在服勤時間內長駐活著就可以在省下一些費用,如果有需要的話還是付一些錢給供應商,畢竟人家也幫你保管了服務你說是不是?
Serverless 架構是一個基於 FaaS(Function as a Service) 實作的一個服務,讓開發者可以更專注在開發功能,將 yml 檔設定好其餘維運的問題都交給 AWS、Google、Azure 這些服務商去處理,只要把信用卡準備好就好(?),讓開發者在寫完程式之後不用煩惱部署得問題,減少的不少的麻煩事。 那因為現任公司的服務都是基於 AWS,如此這般我就接觸到 Serverless(以下簡稱 sls) 這個框架啦 (想更深入了解 FaaS 架構可以參考 AWS) [2019/07/04 更新] 若已經暸解的朋友可以參考我的 python 版本: louis70109/aws-line-echo-bot Ruby 的範例版本: louis70109/aws-ruby-line-echo-bot
[2019/06/29 更新] 以用一個 Ruby on Rails 寫的機器人為例,在寫完個 webhook function 後,設定路由然後部署,一般主機或是虛擬機就很麻煩,要安裝佈署環境以及一安裝堆相關套件,完了之後設定 Domain 什麼的有夠花時間。但若是使用 heroku 部署就很方便,Login — Create-Deploy 馬上就結束,機器人馬上就上線了,實在是俗又大碗呀~ 但我覺得像是 LINE Message 這種 stateless 的服務,且只要一個 function + route 就能實作的程式最適合 Serverless 了,讓專案可以簡潔有力,只要寫一個 function+yml 設定並打個指令就部署了,而且 domain 還附贈 SSL,將服務交給 AWS 也不需要擔心,整個就是超級方便啊! Cold start time 問題,依照我目前使用的結果下來,在 heroku 以及 AWS Lambda 同時睡著的情況下,AWS 起床的回應速度大概 1 秒左右,而 heroku 則大概落在 10~15 秒(參考)。如下圖所示的免費方案,基本上開發階段應該是不至於到 100 萬/月 個請求吧 😆,所以這部分就別擔新大力地給他用下去~ (感謝 petertc 幫忙找這方面的問題 💪)
AWS Lambda 免費方案
接下來就讓我介紹如何使用 sls + LINE Message API 建立一個 Echo bot 吧!

npm 6.9.0 python 3.7.3 serverless 1.45.1
首先要先有個 AWS 帳號(廢話) ,如果沒有綁定信用卡記得去綁定才能繼續,接下來就可以去就可以去建立鑰匙囉!
如上圖,按下紅色框框的部分,接著按箭頭指的按鈕,就會建立一個我們要的金鑰囉!

如上圖所示,可以下載 key,AWS 不會幫忙保存 Secret key,若這視窗關掉的話 key 就不見了,所以使用者可以自行下載檔案保存,以免哪天要部署的時候找不到 key。 接著就將這兩個參數加入環境變數中:
export AWS_ACCESS_KEY_ID=<your-key-here>
export AWS_SECRET_ACCESS_KEY=<your-secret-key-here>
首先先透過以下指令讓 npm 幫忙安裝 sls 的指令。
npm install serverless -g
安裝完之後就透過 sls 指令來建立專案嚕!
serverless create — template aws-python — path aws-line-echo-bot
severless 指令可以縮寫成 sls template = 想用什麼平台以及語言就在此模板了 (參考) path = 檔案名稱

透過 severless 建立專案指令 依照不同的 template 可能會建立 N 個檔案,但主要還是以下三個檔案
.gitignore
handler.py = 主程式的地方
serverless.yml = 所有設定都在這裡,funtion 參數會對應到指定的路由
在部署前須至 serverless.yml 裡,把 runtime 的 python2.7 改至 3.7,否則會因版本問題導致錯誤。
serverless deploy # sls deploy

接著到 AWS Lambda 以及 S3 就可以看到第一次部署完的程式以及檔案囉!
既然是寫 python,那一定是要用 line-python-sdk 照著官方用法應該是要執行以下指令安裝套件
pip install line-bot-sdk
不過我們是要部署到 AWS 的 Lambda 上,且因為他是無伺服器運算的服務,所以他沒辦法跑 pip 去幫我安裝套件。 此時就要出動 requirements.txt 來管理相依套件 ,但只有加入它 sls 根本不認識,因此我們需要安裝 pulgin 來讓 sls 認得(requirements.txt)。
sls plugin install -n serverless-python-requirements


安裝指令 & package.json 如圖,安裝過程中會自動建立 package.json,且會幫忙在 serverless.yml 裡面加入 pulgin,這樣 sls 在部署時就認得 requirements.txt 囉! 接著將 LINE SDK 加入 requirements.txt, AWS 就會幫忙安裝套件了。
echo "line-bot-sdk==1.12.1" > requirements.txt
然後新增一個 setup.cfg 並加入以下內容:
[install]
prefix=
由於 AWS Lambda 上都會將套件安裝在本地端(Lambda 上),因此在執行 pip install -t . -r requirements.txt 時會需要 setup.cfg。
至於詳細原因嘛~還有請各位大大幫小弟解答 🙏
最後就處理 handler.py 以及 serverless.yml 囉!
將上述兩個 gist 分別貼到自己的 handler.py & serverless.yml,在 hanlder.py 裡的 CHANNEL KEY & TOKEN 記得換成自己的機器人 👾 哦!
接著在執行一次 sls deploy,將程式部署上去,如上圖所示,在 endpoints 那行會有一個網址,將那網址放到 LINE Webhook URL 上並 Verify 看看有沒有成功,如下圖所示。
最後對著自己的機器人發個話,看他有沒有回應你一模一樣的文字,若成功了就能往下一步應用層繼續開發囉!若失敗了就要檢查一下是不是有哪個步驟做錯了~
因為公司的緣故讓我能夠接觸到這神奇的 Serverless,經過這次的分享加深我對於 FaaS 的架構更加了熟悉,由於我也是初碰,我認為使用上可以把它當作是一個 Docker 的容器或許概念上會比較好理解,後續還有很多的設定檔都還沒詳細研究,最近讓我先研究研究一下再上來分享。
文章中有任何勘誤歡迎指正
如果覺得這篇文章有幫助的話請給我個掌聲鼓勵我一下 👋 下列是我的這次實作的專案,如果有幫助也來顆星星吧! louis70109/aws-line-echo-bot