Heroku 大逃殺之 Fly.io

Leon
·
·
IPFS
·
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

Like my work? Don't forget to support and clap, let me know that you are with me on the road of creation. Keep this enthusiasm together!