Litestream 0.5.0への移行はもう少し待つのがおすすめです
Litestreamは、SQLiteデータベースをリアルタイムでクラウドストレージにバックアップするオープンソースツールです。私はこのツールが大好きで、すべてのプロジェクトで使っています。
LitestreamはFly.ioが保有しており、同社はLiteFSという代替プロジェクトを優先するため、Litestreamの開発を約2年間停止していました。2週間前、Litestreamの生みの親でありリード開発者でもあるBen Johnsonが、開発の軸足を再びLitestreamに戻したことを発表し、新バージョン0.5.0を公開しました。
私も早速Litestream 0.5.0を試してみましたが、他のLitestreamユーザーには、本番環境への導入はもう1、2回リリースを重ね、より十分なテストが行われてからにすることをおすすめします。新バージョンへの移行は決してスムーズではありませんでした。
追記: Litestream 0.5.1が公開され、私が遭遇した問題のほとんど(ただしすべてではありません)は修正されています。
追記2(2025-10-17): Litestream 0.5.2ですべてのバグが解消されたため、SQLiteを使っている自分のアプリにも順次導入していく予定です。
補足: これはLitestreamへの不満ではありません。私はLitestreamが大好きですし、開発が再開されたことを心から嬉しく思っています。ただ、他のユーザーが私と同じバグに悩まされないように共有しているだけです。
想定されていた移行作業
以前のバージョンからLitestream v0.5.0以降へアップグレードする際に、意図された変更として対応が必要な作業は2つあります。
- バックアップ形式が変更されたため、Litestream 0.5.0では以前のバージョンで作成されたバックアップから復元できません。
litestream.ymlの設定ファイル形式が少し変更されました。以前はreplicasという配列フィールドでしたが、0.5.0からはreplica(単数形)という辞書形式に変わりました。
詳細については、Litestreamが公開している移行ガイドが参考になります。
Litestream 0.5.0の利点のひとつは、公式のlitestream Dockerイメージが用意されたことです。(追記: 読者のplacardloopさんが指摘しているように、これは新しく追加されたものではなく、私が気づいていなかっただけでした。)以前は、Dockerコンテナごとに正しいバージョンのLitestreamをダウンロードしてコンテナ内で使えるようにするための定型的な記述が大量に必要でしたが、今ではDockerfileの1行で済むようになりました。
COPY --from=litestream/litestream:0.5.0 /usr/local/bin/litestream /app/litestreamLitestream 0.5.0へのテスト移行
Litestream 0.5.0を試すため、自分のプロジェクトであるWhat Got Doneで検証してみました。このプロジェクトがテストに適していた理由は次のとおりです。
- すでにサービスの終了を告知しており、ユーザーはサイトの利用を停止していること。
- Litestream 0.3.13のバグが原因でサーバーが繰り返し停止しており、そのバグが0.5.0で修正されていたこと。
Backblazeバックエンドへのアップロードが失敗する
移行を開始するために、まずLitestream 0.3.13でデータの最新コピーをダウンロードし、それをLitestream 0.5.0で新しい形式に変換してBackblazeのクラウドストレージへアップロードしようとしました。しかし、次のようなエラーが発生しました。
error" db=store.db replica=s3 error="write ltx file: s3: upload to db/0000/0000000000000001-0000000000000001.ltx: operation error S3: PutObject, resolve auth scheme: resolve endpoint: endpoint rule error, Custom endpoint `s3.us-west-002.backblazeb2.com` was not a valid URI"同じreplica設定は以前のバージョンでは問題なく動作していたため、少し戸惑いました。
access-key-id: ${LITESTREAM_ACCESS_KEY_ID}
secret-access-key: ${LITESTREAM_SECRET_ACCESS_KEY}
dbs:
- path: ${DB_PATH}
replica:
url: s3://${LITESTREAM_BUCKET}/db
endpoint: ${LITESTREAM_ENDPOINT}BackblazeのS3エンドポイントの指定方法をいくつか試してみましたが、バックアップを実行する前にすべて設定エラーとして拒否されてしまいました。私が使っていた設定だけが有効な設定として受け付けられたのですが、実際にはバックアップに失敗しました。
Backblaze replica fails with “Custom endpoint … was not a valid URI” #789としてissueを登録したところ、Litestreamの開発者であるCory LaNouさんが翌日に修正してくれました。
Backblazeへ新しい形式でデータをアップロードできるようになったことで、What Got DoneへのLitestream 0.5.0の組み込みを進められるようになりました。
-if-replica-existsが消えた
What Got DoneにLitestream 0.5.0をデプロイしましたが、サーバーは次のエラーで起動に失敗しました。
flag provided but not defined: -if-replica-existsコマンドのドキュメントを確認すると、-if-replica-existsはまだサポートされていると記載されていました。
$ litestream restore -help | grep if-replica-exists --after-context=1
-if-replica-exists
Returns exit code of 0 if no backups found.実際には、このフラグは誤って削除されてしまったもので、0.5.1で復活する予定とのことでした。
transaction not availableで復元が失敗する
-if-replica-existsが使えなくなっても諦めず、起動スクリプトから該当オプションを削除しました。しかし今度は別のエラーでサーバーが起動しませんでした。
level=ERROR msg="failed to run" error="cannot calc restore plan: transaction not available"調べてみると、これは次の未解決のLitestreamのissueと一致しており、深刻度は「CRITICAL - Complete Data Loss(致命的 - データ完全消失)」とされていました。
Litestreamがディレクトリを自動作成しなくなった
この時点では、とにかく何でも試して復旧させたいという気持ちだったので、Dockerコンテナ内でソースからビルドして、Litestreamの最新の開発版を実行してみました。
幸い、最新版では私が遭遇していたtransaction not availableの問題を回避でき、処理は先へ進みました。
しかし、まだもうひとつ乗り越えるべきエラーが残っていました。
level=ERROR msg="failed to run" error="create temp database path: open /app/data/store.db.tmp: no such file or directory"これは比較的シンプルなエラーだったので、原因にはだいたい見当がつきました。以前のバージョンのLitestreamでは、SQLiteデータベースの復元先として/app/data/store.dbを指定し、/app/dataというパスが存在しない場合、ファイル書き込みの前に自動的にディレクトリを作成してくれていました。
ソースコードを確認すると、この処理フローでディレクトリを作成するロジックがなくなっていることがわかりました。修正自体は簡単だったので、パッチを作成しました。
成功!
mkdir修正を適用した自分のLitestreamフォークを使ったところ、What Got Doneは無事に再び稼働するようになりました。
振り返り
リリース前のフォークを使ってLitestream 0.5.xをなんとか動かすことはできましたが、他のプロジェクトへの導入はあと1、2回のリリースを待つことにします。0.5.0での変更はLitestreamチームの想定以上に影響が大きかったようで、現在もいくつかの深刻なバグに悩まされています。
- CRITICAL: Restore fails with ’nonsequential page numbers’ after checkpoint during Litestream downtime #752
- Local LTX Level 0 files are never compacted/removed #784
また、開発版では修正済みですが、まだ正式リリースには含まれていない(追記: これらは0.5.1で修正されました)深刻なバグもいくつかあります。
- Restore does not update LTX ID information #781
- Age encryption configuration silently ignored in v0.5.0+ #790
- [Regression] LTX transactions get deleted in 0.5.0, cannot restore more than a few seconds #771
補足: 改めてですが、これはLitestreamへの批判ではありません。ストリーミングレプリケーションを正しく実装するのは非常に困難ですし、Litestreamチームが成し遂げていることは、私自身が作れるものよりはるかに堅牢です。バグ報告に迅速に対応し、すぐに修正してくれたLitestreamチームには心から感謝しています。
記事をランダムに読む