原文鏈接:https://www.leavesongs.com/SOFT/paas-service-from-heroku-to-fly-io.html
作者:Phith0n
2021年8月得知了Heroku將要在今年11月徹底下線免費服務,我只有少量服務放在Heroku上,所以沒有太在意,直到2021年10月感覺到不得不開始做遷移相關的工作了,于是開始著手準備,并有了這篇文章。
這篇文章純屬是事后記錄的一些流水賬,可能缺少截圖和代碼片段,全當是作為一個故事看,可能不具備參考性。
為什么選擇PaaS服務
從很久以前開始接觸“虛擬主機”這個行業開始,我經歷了虛擬主機、VPS、云主機、PaaS、容器等時代——從最早我不需要有任何運維成本的虛擬主機,需要完全自己運維的VPS主機,又回歸到不太需要自己運維的PaaS服務,就像兜了一個圈。
PaaS全名平臺即服務(Platform as a Service),意思是云平臺提供了一套部署“框架”,可以將你編寫的代碼通過它的方式一鍵部署在云上,并且給你提供網絡、存儲、日志等常用的服務,解決了開發人員的運維問題,我們只需要寫好代碼提交,后期所有的自動化部署、發布、運維、擴展、備份等邏輯都可以讓云平臺幫我完成。
其實容器與k8s的思想也是脫胎于此,現在看來,容器就是將這樣的需求標準化成為了一套規范。相對來說,容器的可定制化程度更高,也算是PaaS服務在2015年以后的逐步進化。
其實我一直認為,早期的虛擬主機發展到后面就是PaaS,PaaS繼續發展就是現在的容器即服務(CaaS)。所以,本文所謂的PaaS的概念,并不局限在一兩個名詞之中,而是泛指這一類基于某種特定的框架來自動化部署的平臺。
早期著名的PaaS平臺有谷歌的GAE、新浪的SAE、Heroku等,PaaS這個概念能很快打入開發群體之中的關鍵原因之一是免費。在2015年左右,正是GAE、SAE等平臺最火的時候, 我記得曾經有不少教程教大家如何部署應用到GAE,甚至有的翻墻工具也直接部署在GAE上。
發展到今天,新浪的SAE早已半入土,谷歌Cloud SAE因為高昂的學習成本與產品設計,也被我拋棄了。
我記得之前部署過服務在GAE上,但因為用錯了環境導致沒有滿足Free Tier資格仍然被扣費。其后臺管理與付費邏輯十分難懂,在賬單出來前你很難知道自己在用的服務價格,我開始抵觸這類收費標準不明確的后付費產品,就怕哪天早上起床突然發現房子被人收走了。

對于個人開發者來說,相對比較友好的平臺是Heroku,它提供了每個月550到1000小時的免費運行時間,同時還有免費的PostgreSQL和Redis服務,搭配我常用的Django環境是絕配。
對于一個全時間段運行的應用來說,一個月需要跑24 x 30 = 720個小時,免費額度完全沒有問題。但免費套餐最大的缺點就是在不活躍30分鐘后會被自動停止,等下次有人請求的時候會再重啟啟動,這會導致這個請求消耗更多時間。
免費套餐非常適合部署一些演示站點、不活躍的站點等,我在2018年做Code-Breaking的時候將官網部署在了Heroku:

這一部署就是4年,直到2022年10月我將其遷移到fly.io,它都靜靜地運行在那里,無需我任何的管理,也沒有任何錯誤。這確實滿足了我當時選擇Heroku的所有需求——對于一個短期內使用的臨時性站點,我要做的就是盡可能減少后期的管理成本,只要能一直運行就行。
想一下,這可能是存活時間最久的CTF站點之一了。
當然,我前文也說了,Heroku在8月宣布要下線免費套餐。這可能是PaaS服務最大的風險,來自于平臺政策的變化,而Heroku最便宜的套餐也是一小時0.01美刀,合計7刀一個月,還不算PostgreSQL和Redis數據庫的費用。
為什么選擇fly.io
巧的是前段時間看到一個推特博文介紹了一個平臺叫fly.io:

我了解了一下fly,這是一家來自美國的初創公司。其提供的免費服務如下:
- 3個1核256MB內存的環境,用于運行應用
- 3G的Volume,可以用于部署數據庫等
- 160GB每月的流量
其實即使不考慮免費套餐,其定價也比較親民,不用擔心免費額度用超了以后的價格問題:

于是我就決定將code-breaking遷移到fly.io上,作為Heroku的替代。
遷移代碼到fly.io
fly.io由于誕生在容器時代,所以本身就是基于容器的,有額外學習成本。
先安裝其客戶端flyctl并進行認證,然后來到code-breaking項目根目錄,執行flyctl launch。此時,flyctl會根據當前項目的結構識別出待部署應用類型,比如我的是Django:

按照指引完成配置,此時會創建Web應用和一個數據庫應用(PostgreSQL),并生成兩個文件:
- Dockerfile
- fly.toml
其中Dockerfile就是將會運行這個應用的鏡像模板,里面已經簡單幫我實現了大部分部署Django的代碼,在基礎上稍稍改動就可以直接使用。
fly.toml是fly.io的配置文件,沒有特殊的需求的情況下不用修改。
然后我執行flyctl deploy部署。默認情況下,flyctl會將當前項目發送到云端,在云端的一個虛擬機里進行鏡像編譯部署。不過,在成功編譯幾次后我就無法使用遠程編譯了,執行flyctl deploy無法連接上虛擬機,會出現“Failed to start remote builder heartbeat”的錯誤,使用flyctl deploy --local-only改成本地編譯可以解決這個問題。
部署結束后,fly.io會提供一個二級域名,通過code-breaking.fly.dev即可訪問剛才部署的應用。
當然,這只是第一步工作,后面我還需要解決域名和持久化數據的問題:
- 靜態資源的部署
- 數據庫的遷移
- 域名與證書綁定
靜態資源的部署
初始化時生成的fly.toml文件中有關于volume的配置:
[[statics]]
guest_path = "/app/public"
url_prefix = "/static/"
意思就是/app/public這個目錄下的文件將會作為靜態資源,在Web中的URL前綴是/static/。所以,我只需修改Django配置即可:
STATIC_URL = '/static/'
STATIC_ROOT = '/app/public'
數據庫的遷移
數據庫需要從Heroku遷移到fly.io,我選擇使用Navicat手工來做這件事,首先就是連接Heroku和fly.io的PostgreSQL數據庫。
Heroku的數據庫是對公網開放的,我們只需要拿到它的地址與賬號密碼,執行如下命令:
heroku pg:credentials -a [appname]
此時會輸出一個數據庫連接URL,其中會包含地址、端口和賬號密碼。
而fly.io的數據庫是一個內網地址,我需要使用flyctl自帶的proxy功能將其轉發到本地再進行連接。在創建數據庫的時候flyctl會打印其內網地址和賬號密碼,然后通過proxy命令來將端口轉發出來:
flyctl proxy 5432:5432 code-breaking-db.internal -a code-breaking-db
再使用Navicat直接連接本地的5432端口即可,后續數據遷移操作,直接在Navicat里進行。
域名與證書綁定
默認情況下,部署完成的應用將會分配一個二級域名,但我明顯需要綁定自己的域名。方法是來到官網后臺Certificates頁面,點擊“Add certificate”,此時它會要求你添加三個解析:

其實這個地方的邏輯非常不清晰,明明是綁定域名,但這個功能卻叫“Certificates”,以至于讓我在這一塊浪費了很多時間。
fly.io給我們的IP實際上是一個共享IP,是通過HTTPS證書中的hostname或HTTP頭里的Host來確認訪問者要訪問的主機,我猜這也是為什么這個功能叫“Certificates”的原因,在不添加證書的情況下我們無法正確通過自己的域名訪問到應用。
所以,來到Cloudflare中,添加好這幾個解析記錄,其中_acme-challenge最好是DNS Only:

然后回到“Certificates”頁面點擊check again,驗證成功后即綁定好了域名。
此時我們再通過Code-Breaking就正常訪問到了Code-Breaking的官網,全部的部署完成。
體驗與感受
完整部署下來,可以明顯感覺到fly.io的成熟程度遠遠落后于heroku,其flyctl客戶端仍然存在一些Bug,文檔也不齊全。雖說我輕描淡寫地描述了我整個部署的過程,但實際上其中踩坑無數,甚至遠程編譯的Bug在觸發后就再也沒解決過,官方社區也多是問題鮮有靠譜答案。
就功能上來看,fly.io也比較少,只能說剛好滿足我現在的需要。
其優點就是具有免費的額度,價格也便宜,對于個人開發者來說也很友好。而且相比于heroku來說,fly.io僅是一個初創公司,仍具有很大的想象力,相信現有的這些不足也會慢慢解決與完善。
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.jmbmsq.com/3051/
暫無評論