Leon
Leon

https://editor.leonh.space/

Heroku 大逃殺之 Fly.io

Heroku 要砍免費服務了,免費仔該何去何從?資深免費仔帶你搬家到 Fly.io,讓我們重返榮耀!
圖片來自 a16z

Heroku 打算在 2022 年 11 月 28 終止所有免費服務,我輩免費仔只能付費升級,或是搬家,既然是免費仔,付費升級就不是個選項,要搬家的話,新家的選擇大概有這些:

  • Render
  • Fly.io
  • Northflank
  • Koyeb
  • Deta
  • Qoddi
  • Cyclic.sh
  • Railway

這篇記錄了搬家到 Fly.io 的過程。

Fly.io

Heroku、Fly.io 以及前面列的一大堆服務,都可以概括為 serverless 服務,更精確的分類是 PaaS,其中的 P 為 platform,所謂 platform 表示語言/框架的複合意義,PaaS 的優勢在於我們不用去管理更底層的 infrustructure,也就是硬體層、OS 層、web server 層都無須操心,由 PaaS 業者自理。

Fly.io 的特色個人認為有二:

  • 有東京節點,離台灣較近,速度當然也比較快囉!
  • 初階費率低廉,雖然本人是免費仔,還是要考慮付費時的費率方案,以 Fly.io 單一共享 CPU 的費率來看,還是頗便宜的。

前置作業

第一步當然是開帳號,眼睛閉閉帳號開一開之後,與 Heroku 類似,要裝 Fly.io 的 CLI 工具。

如果是 Windows,不需要 Administrator 權限,開 PowerShell 執行此命令:

$ iwr https://fly.io/install.ps1 -useb | iex

裝好就登入吧:

$ flyctl auth login

至此前置作業告一段落,後面我們進入專案目錄配置 Fly.io 設定。

建立 Fly.io App

我們這整個專案對 Fly.io 來說就是一套 app,最基本的 app 裡面大概會跑一個 web 服務,稍微複雜一點的大概會多跑一個 database 服務,在本文的範例中,我們只有一個 web 服務。

先初始化一個 Fly.io app:

$ flyctl launch

上面的子命令為 launch,但它其實只是產生配置檔而已,並沒有真的 launch 什麼。

跑起來會跳出一些資訊還有問題:

Detected a Python app
Using the following build configuration:
        Builder: paketobuildpacks/builder:base
? Overwrite "C:\Users\leonh\Projects\katsuyo-backend\Procfile"? Yes
? App Name (leave blank to use an auto-generated name): katsuyo

? App Name (leave blank to use an auto-generated name): katsuyo
? Select organization: Katsuyo (katsuyo)
? Select region: nrt (Tokyo, Japan)
Created app katsuyo in organization katsuyo
Wrote config file fly.toml
? Would you like to set up a Postgresql database now? No
We have generated a simple Procfile for you. Modify it to fit your needs and run "fly deploy" to deploy your application.

整理如下:

  • 自動偵測到這是個 Python 專案。
  • 要改寫 Procfile 嗎?Yes(反正有版控不怕不怕)。
  • 幫這個 Fly.io app 取名字。
  • 選定要放在 Fly.io 的哪個組織下,每個 Fly.io 帳號都有一個自己的「Personal」組織,當然也可以另外創建更多組織,本例的組織就是另外創的 Katsuyo,這樣感覺事業做比較大,比較唬人。
  • 要放在哪個機房,東京應該是首選。
  • 以上設定都寫入 fly.toml 和 Procfile,還沒真正部署,可以再改。
  • 最後一題,要設定 PostgreSQL 嗎?不用。
  • 最後提示我們用 fly deploy 部署,不過最好先檢查一下配置再說。

先看 Procfile:

# Modify this Procfile to fit your needs
web: gunicorn server:app

格式和 Heroku 相同,印象中這是來自某個開源專案的通用格式,但是是哪個忘記了。

它幫我們配置了用 Gunicorn 來跑專案,但在這裡的範例專案中用的是 Uvicorn,所以改一下:

# Modify this Procfile to fit your needs
web: uvicorn app.main:app --host 0.0.0.0 --port 8080

此處設定 Uvicorn 與參數:

  • 指定了 Python ASGI 程式進入點,這部分請根據自身專案而改。
  • 不綁定任何 IP,因為我們不知道,也不需要知道 Fly.io 給的 IP 是什麼。
  • 監聽 8080 埠,因為在 fly.toml 中,預設配置就是把 HTTP、HTTPS 請求送到機台內的 8080 埠。

Procfile 的部分告一段落,來看看 fly.toml 吧:

# fly.toml file generated for katsuyo on 2022-08-27T11:38:16+08:00

app = "katsuyo"
kill_signal = "SIGINT"
kill_timeout = 5
processes = []

[build]
  builder = "paketobuildpacks/builder:full"

[env]
  PORT = "8080"

[experimental]
  allowed_public_ports = []
  auto_rollback = true

[[services]]
  http_checks = []
  internal_port = 8080
  processes = ["app"]
  protocol = "tcp"
  script_checks = []
  [services.concurrency]
    hard_limit = 25
    soft_limit = 20
    type = "connections"

  [[services.ports]]
    force_https = true
    handlers = ["http"]
    port = 80

  [[services.ports]]
    handlers = ["tls", "http"]
    port = 443

  [[services.tcp_checks]]
    grace_period = "1s"
    interval = "15s"
    restart_limit = 0
    timeout = "2s"

此處多數的配置可以望文生義,其中幾行要關注一下:

  • 前面提過的 internal_port = 8080 指定了 Python app 應該監聽 8080 埠。
  • 那 [env] 區塊內的設定,是讓 app 可以讀取到系統內的環境變數,可隨喜配置。
  • builder = "paketobuildpacks/builder:base" 指定了運作時的容器映像,預設的 base 沒有 C 函式庫,本範例中的 Python 剛好有需要 SQLite,libsqlite3.so.0 是一定要的,所以得改為 paketobuildpacks/builder:full 。這部分詳細說明參閱 Paketo Buildpack 文件

fly.toml 的其他部分先擱著,以現有的設定部署看看:

$ flyctl deploy

可以看到一堆嘰哩呱啦訊息,大部分是層層容器映像下載和部署的訊息。

如果一切沒問題,應該跑完就上線了,恭喜,灑花,轉圈圈!

但實際上不會這麼順利,否則我早就財富自由了。通常初次部署都會遇到各種疑難雜症,只能根據部署丟出的錯誤訊息來一一排除囉!

以我手上的範例專案來說,它就需要安裝字體,無奈 Fly.io 用的 builder / buildpack 架構下似乎沒有夠簡單的方法能讓我跑 apt install fonts-noto-cjk,所以雖然部署成功,但其中字體的顯示卻是異常的,殘念。

CLI 常用命令

看當前專案 app 資訊

$ flyctl info

可以看到當前專案 app 的諸元:

App
  Name     = katsuyo
  Owner    = katsuyo
  Version  = 3
  Status   = running
  Hostname = katsuyo.fly.dev

Services
PROTOCOL PORTS
TCP      80 => 8080 [HTTP]
         443 => 8080 [TLS, HTTP]

IP Adresses
TYPE ADDRESS             REGION CREATED AT
v4   168.220.91.169             11h34m ago
v6   2a09:8280:1::1:657d        11h34m ago

另一個類似的命令:

$ flyctl status
App
  Name     = katsuyo
  Owner    = katsuyo
  Version  = 3
  Status   = running
  Hostname = katsuyo.fly.dev
  Platform = nomad

Instances
ID              PROCESS VERSION REGION  DESIRED STATUS  HEALTH CHECKS           RESTARTS        CREATED
6bcb55a9        app     3       nrt     run     running 1 total, 1 passing      0               6h7m ago

個人認為這兩個命令大可合併,或作為彼此的替身。

看 log

$ flyctl logs

當然就是看專案即時 log 啦!

結語

簡單的試用一下 Fly.io,初步的感受是配置有點繁雜,那 fly.toml 看起來好像很厲害,但本人更愛好像 Netlify / Vercel 那樣的傻瓜配置,如果 PaaS 還要搞那麼多配置那不如回到 IaaS 自己搭架構就好,想單體就單體,想微服務就微服務,爽快。


ALL RIGHTS RESERVED 版权声明

喜欢我的文章吗?
别忘了给点支持与赞赏,让我知道创作的路上有你陪伴。

加载中…

发布评论