Roll With IT

tamakiのIT日記

Fly.io の Volumes を試してみた

はじめに

Next.js と Rails を使ってオリジナルの Web アプリを開発しています。

github.com

当Webアプリには写真保存機能があり、Rails の ActiveStorage を介して外部ストレージに保存する構成にしています。本番環境の外部ストレージをFly.io の Volumes で試してみることにしました。

先に結論から申し上げると、私の開発環境では Fly.io の Volumes は本番環境のストレージとして不向きでした。結果的には外部ストレージは AmazonS3 に乗り換えることになりましたが、Fly.io の Volumes は、まだ日本語の情報も少なく自分と同じくハマる人がいるのではないかと思い、今回試した結果をまとめることにしました。この記事が何らかの形でお役に立てれば幸いです。

以下は、AmazonS3 に乗り換えた記事になります。

shirotamaki.hatenablog.com

Fly.io の Volumes とは

Fly.io が提供している永続的なストレージのことです。

物理サーバー上の NVMe ドライブを分割して提供しているハードウェアで、データベースのファイルを保存したり、設定やセッション、ユーザーデータなどのアプリの状態を保存したり、デプロイや再起動後に持続する必要がある情報を保存したりすることができます。デフォルトのボリュームサイズは 3GB になります。最大サイズは 500GB。分割も可能のようです。

Databases & Storage · Fly Docs

Volumes 利用時に考慮すべき内容

  • Volume は、1 つのアプリに紐付く
  • Volume は、1 つのリージョンしか指定できない。リージョンの複数指定は不可
  • Volume は、1 つの Machine(VM)に紐付ける必要がある。Volume と Machine は 1 対 1 でマッピングが必要
  • Volume は、Volume 内で自動的に複製は作られない
  • Volume は、ホストする NVMe ドライブが故障すると、アプリのインスタンスがダウンする。アプリの Volume を持つ複数の Machine を実行することでハードウェアの障害を軽減することができる
  • Volume は、万が一ドライブが故障した場合はデータが失われてしまう。バックアップ方法は別で検討する必要がある

Volumes · Fly Docs

Volumes 設定時のルール

  • 1 つのアプリにつき少なくとも 2 つの Volume の実行が必要
  • 1 つの Volume は 1 つの Machine にのみ接続が可能
    • そのため、2 つの Volume を準備する場合は、2 つの Machine を用意する必要がある

Volumes · Fly Docs

無料枠

今回は無料枠内で設定を行いました。

  • Up to 3 shared-cpu-1x 256mb VMs
    • VM は Machine のこと
  • 3GB persistent volume storage (total)
    • 今回は 1GB を 3 つ用意する
  • 160GB outbound data transfer
    • outbound data transfer とは、コンピューターネットワークや通信分野において、外部へ転送されるデータ(HTTP 通信)のこと

Fly App Pricing · Fly Docs

Fly.io を初期化する

fly launch済みだったので、途中の設定から進めましたがうまくいかず...。コミュニティに質問を投げたところやり直した方がいいとのことで、初期化してやり直すことにしました。

fly launchは、Fly.io を立ち上げるコマンドになります。Rails アプリをデプロイする前段階の必要な設定を自動で行ってくれます。

登場人物

  • Machine(VM):3 台
  • Volume:3 台 × 1GB
  • App :Rails API を用意する( App 名:outdoor-heart-sutra-backend)
  • DB: PostgreSQL を用意する(DB 名前:outdoor-heart-sutra-backend-db)

Fly.io を初期化しデプロイをやり直す手順

1 . Fly.io のダッシュボードからアプリと DB を削除する

Dashboard_·_Fly.png

2 . ローカルのDockerfilefly.tomlを削除する

3 . fly launch を実行する。

Image

4 . 新しいDockerfilefly.tomlが生成される。

5 . fly deployをする

6 . もし You hit a Fly API error with request ID: XXXXXX に遭遇しても慌てない。再びfly deployをする。成功するまで何回もやり直す(サーバーが混雑していて一時的に通信できていない可能性が高い)

7 . 上手く行ったらfly open する。

8 . 設定が反映される。

Flyioにデプロイできないときの対処法と、ActiveStorageをfly.ioで動かす方法 by lef237 · Pull Request #54 · lef237/quotelist · GitHub

fly launch 後の状態

fly statusで状態の確認が可能です。

デフォルトで、Machine が 2 台用意されています。fly launch時に指定したリージョンnrt(東京)が設定されていることが確認できます。

❯ fly status
App
  Name     = outdoor-heart-sutra-backend
  Owner    = personal
  Hostname = outdoor-heart-sutra-backend.fly.dev
  Image    = outdoor-heart-sutra-backend:deployment-01H2MXM3JKRRCQNPMEESTRGE4D
  Platform = machines

Machines
PROCESS ID              VERSION REGION  STATE   CHECKS  LAST UPDATED
app     148ed5d5a3d668  5       nrt     started         2023-06-11T11:05:20Z
app     4649xxxxxxxxxxx 5       nrt     started         2023-06-11T11:05:20Z

fly volumes listで Volume の設定状況が確認できます。Volume はまだ設定していないので何も表示されません。

❯ fly volumes list
 ID STATE   NAME    SIZE    REGION  ZONE    ENCRYPTED   ATTACHED VM CREATED AT

Volume を作成

Volume を作成します。ストレージ名は、英数字、アンダースコアのみ使用可能です。

❯ fly volumes create <ストレージ名> --region <リージョン名> --size <サイズ>

- ストレージ名:outdoor_heart_sutra_backend_data
- リージョン: nrt(東京)
- サイズ: 1GB

警告が表示されますが無視します。

❯ fly volumes create outdoor_heart_sutra_backend_data --region nrt --size 1
 Warning! Individual volumes are pinned to individual hosts. You should create two or more volumes per application. You will have downtime if you only create one. Learn more at https://fly.io/docs/reference/volumes/
 ? Do you still want to use the volumes feature? Yes
         ID: vol_lgz1vpp7j7kv78m3
       Name: outdoor_heart_sutra_backend_data
        App: outdoor-heart-sutra-backend
     Region: nrt
       Zone: 6082
    Size GB: 1
  Encrypted: true
 Created at: 10 Jun 23 08:12 UTC

Volume が 1 台追加できています。

MachineID 148ed5d5a3d668 と VolumeID vol_lgz1vpp7j7kv78m3マッピングに成功しています。

❯ fly volumes list
ID                      STATE   NAME                                SIZE    REGION  ZONE    ENCRYPTED   ATTACHED VM     CREATED AT
vol_lgz1vpp7j7kv78m3    created outdoor_heart_sutra_backend_data    1GB     nrt     e73c    true        148ed5d5a3d668  1 day ago

Add Volume Storage · Fly Docs

Machine と Volume の対を 1 組追加する

Machine を削除する

先に不要になった Machine を削除します。

Machine 対 Volume のマッピングしたセットをもう一組追加したいのですが、クローン 方式で行うことにします。

まず先にマッピングしていない Machine を削除します。

❯ fly machine destroy <削除したいMachineID>
 machine <MachineID> was found and is currently in stopped state, attempting to destroy...
 <MachineID> has been destroyed

Scale the Number of Machines · Fly Docs

クローンする

すでにマッピング済みの MachineID を引数に渡し clone を実行します。

 fly machine clone 148ed5d5a3d668
 Cloning machine 148ed5d5a3d668 into region nrt
 Volume 'outdoor_heart_sutra_backend_data' will start empty
 Provisioning a new machine with image registry.fly.io/outdoor-heart-sutra-backend:deployment-01H2JH5NCPN0X4RV99W0D1WB9N@sha256:c4bb537636be6b041fe026bd04f7bbccc50b2c7c50dd17b08d7c9b7f34d52312...
   Machine 5683d3d0bd40d8 has been created...
   Waiting for machine 5683d3d0bd40d8 to start...
 No health checks found
 Machine has been successfully cloned!

クローン後の結果

Volume2 台のマッピングが成功しています。

❯ fly volumes list
ID                      STATE   NAME                                SIZE    REGION  ZONE    ENCRYPTED   ATTACHED VM     CREATED AT
vol_3q80vd3wlwkrgzy6    created outdoor_heart_sutra_backend_data    1GB     nrt     a588    true        5683d3d0bd40d8  1 day ago
vol_lgz1vpp7j7kv78m3    created outdoor_heart_sutra_backend_data    1GB     nrt     e73c    true        148ed5d5a3d668  1 day ago

fly statusで確認ができます。Machine が 1 台追加され合計 2 台になっています。

❯ fly status
App
  Name     = outdoor-heart-sutra-backend
  Owner    = personal
  Hostname = outdoor-heart-sutra-backend.fly.dev
  Image    = outdoor-heart-sutra-backend:deployment-01H2QVEXXPGDS97AXPJQC5Q3PQ
  Platform = machines

Machines
PROCESS ID              VERSION REGION  STATE   CHECKS  LAST UPDATED
app     148ed5d5a3d668  11      nrt     started         2023-06-12T14:32:13Z
app     5683d3d0bd40d8  11      nrt     started         2023-06-12T14:33:35Z

Volume をマウントするために App を設定する

新しい Volume をマウントするために設定が必要です。fly.toml とは、Fly.io アプリケーションの設定ファイルです。Fly.io は、このファイルに従ってデプロイと実行を行います。

Active storage images are not persisting in disk

 # backend/fly.toml

app = "outdoor-heart-sutra-backend"
primary_region = "nrt"
console_command = "/rails/bin/rails console"

[env]
  RAILS_STORAGE = "/mnt/volume/storage"

[http_service]
  internal_port = 3000
  force_https = true
  auto_stop_machines = true
  auto_start_machines = true
  min_machines_running = 1

[[statics]]
  guest_path = "/rails/public"
  url_prefix = "/"

[[mounts]]
  source = "outdoor_heart_sutra_backend_data"
  destination = "/mnt/volume"

storage.yml ファイルでは、Active Storage がどのようにファイルを保存するかを設定します。

# backend/config/storage.yml

local:
  service: Disk
  public: true
  root: <%= ENV.fetch('RAILS_STORAGE', Rails.root.join("storage")) %>

デプロイする

❯ fly deploy

PostgreSQL

fly launch時に Postgresql をデータベースに設定したので、

243152027-8749019e-017b-46b4-8788-9353c23194bb_png__2016×2610_.png

以下、自動で生成されます。

名前は App 名の後ろに-dbと付きます。

❯ flyctl status -a outdoor-heart-sutra-backend-db

ID              STATE   ROLE    REGION  CHECKS              IMAGE                               CREATED                 UPDATED
5683d3d3ad1338  started primary nrt     3 total, 3 passing  flyio/postgres-flex:15.3 (v0.0.42)  2023-06-10T11:28:31Z    2023-06-10T11:28:46Z

Free builder とは

Free builder というアプリは、デプロイ用に自動的に作成されます。

デプロイ時に fly CLI は自動的にアプリを作成し、そのアプリを使用してデプロイビルドを実行してくれます。デプロイをやり直す時に削除しても問題ないようです。万が一削除しても、次にデプロイするときに再び作成されます。

Cursor_と_Dashboard_·_Fly.png

Free builder is created by itself. - Questions / Help - Fly.io

おわりに

これで Fly.io の Volumes の設定は完了です。

しかし、冒頭でも案内した通り、結果として今回は Volumes の導入は断念し Amazon S3 に乗り換えることにしました。

詳細は以下記事にまとめています。

shirotamaki.hatenablog.com