セルフホストしたアプリをマシン移行する汎用的な仕組みについて考える

現在VPS上で、仮想通貨の自作トレードアプリを稼働しています。これは元々自宅サーバでやっていたのですけれど、引越しのときに数日から下手すると10日以上のダウンが見込まれたので、その間に相場の急変があったらたまらないということで、VPSに移行しました。

目次

アプリケーションを動作させるマシンを移行したい

で、ようやく環境も落ち着いてきたので、いつまでもグローバル空間に置く必要はないし、自宅サーバに戻そうと考えています。もちろん手順を踏めばすぐできるんですけれど、ここで、少し汎用的に考えられないか、と思いました。セルフホスト勢にとってマシン移行は常に生じる汎用的な悩みです。

実際、このサイトはWordPressをセルフホストしているのですが、VPS,ConoHaの大規模障害(永遠にこする)や引越し前後において頻繁に引越しをしています。それはやはり面倒くささがあったわけです。

個人的には、マシンの移行はもっと気軽にやりたい、という思いがあります。それはもしもの役にも立つでしょう。何をやるべきで、何をやらないのか、自動化できる部分はなにか、自動しない部分はなにか、そういうことを汎用的に考えたい、と思いました。

中継地点を介した移行

考えたところ、基本的には以下のような中継地点を挟むものになると思います。

graph LR mA(移行元) mB(移行先) st(中継地点) repo(リポジトリ) mA -->|push| st st -.->|pull| mB repo -.->|pull| mB

この絵がすべてです。

なんでダイレクトに送らないのかと言うと、移行元から移行先にダイレクトにpushできる権限があるとは限らない、からです。これは完全に自宅サーバしか使わない!というならダイレクトでいいかもしれませんが、実際には自宅が使えなくなることはあります(今回の場合)し、アプリケーションによっては自宅サーバはやめたほうがよいものもあります。

なので、移行元からpushできて、移行先がpullできる、そういう中継地点を用意するのが汎用的です。この中継地点の役割は、アクセス制御と一時的なストレージ、ただそれだけです。グローバルなアクセスが必要ならS3のようなクラウドサービスでもいいですし、VPSでもいいでしょう。移行元も移行先も同一ネットワークなら、わざわざ外に出す必要はなく、両者がSSHで通信できるサーバならなんでもいい。

具体的な作業自体は、アプリケーションごとに個別で判断します。この切り分けによって、搬出と搬入のタイミングをずらせるとか、データの整理が明確になるといった副次的な効能もあります。

ここで重要なことは、何を引越して何を引っ越さないのかを明確に切り分けることです。具体的には、以下の3つに分かれると思います。

  • リポジトリから引き継ぐ
    • ソースコードや設定ファイルのテンプレートなど
  • ファイルの移行で引き継ぐ
    • エクスポートしたファイルやデータストアやアプリケーションログなど
  • 引き継がない
    • OS/インフラの差分に基づく設定ファイルなど

それぞれ何が対象となるかはアプリケーションごとに変わるでしょう。すべてのパターンを考えて統一的にやろうとしないことです。また、引き継げない部分がある以上全自動の夢も捨てるのが筋です。変に自動的に翻訳するみたいなことするのはトラブルの元です。セルフホストでそこまでする必要があることは皆無ですし、もしやる場合は差分が出なくなるように環境から選定すべきでしょうね。

そのうえで手順は以下のように言えるでしょう。

  1. 移行元と移行先で、リポジトリから引き継ぐものをアップデート
  2. 移行元をstopして、中継地点に搬出
  3. 移行先に、中継地点から搬入
  4. データのインポート、差分の編集
  5. 移行先で動作開始

自前で開発したものか、あるいは他人が開発したものを使わせてもらっているか、色々あると思いますが、この手順に集約できるかと思われます。

この方法は基本的にダウンタイムが生じます。工夫次第で発生させないのも可能かと思いますが、セルフホストでそこまで頑張る意味は薄いんじゃないでしょうか。

とはいえダウンタイムは短いほうがよいので、短くするなら差分の編集は搬出前にやると良いのですけれど、個人的には搬入後に揃ってからのほうがいいかと思います。搬入のどさくさで差分が上書きされるリスクや、また何かしら動かさないと編集できないとかもありえるので…。

データのインポートはファイルシステムレベルなのか、アプリケーションレベルで実行したほうがいいのか、これもアプリケーションによるでしょうねぇ…。まぁ、都度判断ですね。

まとめ

ここまでの流れをやや詳細に図示すると以下になります。

flowchart TB subgraph Repo["コード管理"] Code["ソースコード / 設定テンプレート"] end subgraph Relay["中継地点"] ExportData["エクスポートデータ / DBダンプ / アプリログ"] end subgraph Source["移行元"] SrcApp["アプリ停止"] SrcData["データ抽出・ダンプ"] SrcEnv["【破棄】OS・インフラ固有設定"] end subgraph Target["移行先(自宅サーバなど)"] TgtEnv["【新規作成】OS・インフラ固有設定の編集"] TgtApp["アプリ起動・動作検証"] TgtData["データインポート"] end %% コードの流れ Code -->|Pull| Source Code -->|Pull| Target %% データと状態の流れ SrcApp --> SrcData SrcData -->|Push / アップロード| Relay Relay -->|Pull / ダウンロード| TgtData TgtData --> TgtEnv TgtEnv --> TgtApp %% スタイル classDef storage fill:#e1f5fe,stroke:#0288d1,stroke-width:2px; classDef nodeBox fill:#f5f5f5,stroke:#616161,stroke-width:1px; class Repo,Relay storage; class Source,Target nodeBox;

やることは、事前準備として「リポジトリからpullするもの、中継地点で飛ばすもの、直接編集するもの」の切り分け。そのうえで5つの手順の具体的な操作の当てはめ

整理してみると、当たり前といえば当たり前なんですが。あらかじめ分類したものを適合させるだけだと思ったほうが、脳の負荷が多少下がるので…。

とりあえず、トレードアプリから移行するかー。手順を抽象化したところで具体化するのは結局めんどくさいのであった。というより、そういう面倒くささを残したところが肝なのですが…。

<関連記事>

この記事をいいなと思っていただけた方、よければ高評価・チャンネル登録……はないので、コメント・SNSでシェア・ブックマーク、RSSフィード登録を、よろしくお願い致します。

コメント

コメントする

目次