GCPからOCIに移行するメモ

GCP、機能的に不満はないけど円安が厳しくなってきたのでコスパがいいという噂のOCIに移行することにしました。事前にいくつか検証したところ問題なさそうです。コストはおおよそ半分~1/3程度になることを見込んでいます。
だいたい年間数十万円(月数万円程度)からは、1年分前払いすると営業さんがついてくれるので、気軽に移行の質問を投げれるのでお勧めです。また、この方式で課金した場合、その時のインスタンスなどの単価を為替にかかわらず固定してもらえるというメリットもあります。

まずどこからやるか悩んだのですが、MySQLから始めることにしました。GCPのHA構成とくらべ、OCIのHA構成のほうが4割程度安くなり、かつ若干スペックも向上します。
MySQL5.7から8.0への移植だったのですが、若干大変だったのはPrimary Keyが必須だったことです。そのため、GPIKをオンにして対応しました。
インスタンス構築後だったのですが、HA構成なのでおそらくダウンタイムなく構成変更が可能でした。フォルトドメインが別のものがプライマリになっていました。
OCIのMySQLは単体ではグローバルIPを持っていないので、ネットワークロードバランサ(L3LB)を前段に立てて、CloudRunのNATを有効にして出口IPを固定した状態で特定IPを開放してMySQLにルーティングするようにしました。

MySQL5.4から8.0への移植だったのですが、
とありますが、おそらく5.1、5.5、5.6、5.7のいずれかかと思われます。

5.7でした!

次にストレージの移管です。手元のデータだと100万ファイル350GB程度の量なので、RCloneでサクっとコピーすることにしました。(7時間くらいかかった)その間、新しいファイルが生成されるので、Google Cloud Functionsでストレージのトリガー起動するコードを書いて、差分ファイルが生まれるごとにOCIバケットにコピーするようにしました。
なお、コードはだいたいClaude 3に書いてもらいました。たまに古いドキュメントに基づいたコードを返して着ますが、おおむね優秀です。

いよいよアプリケーションです。Cloud Runに近いプロダクトとしてはContainer Instanceがありますが、超絶シンプルな機能しかありません。
- 自動ではスケールしない
- 複数マシン立ち上げたらそれぞれIPが動的割り当てされるのでなんらかLB参加がひつよう
- ホストインスタンス起動時にコンテナを指定したら以降は環境変数ふくめ編集はできない
かといってGKEに相当するOKEは個人的に重たいので、以下のような感じでやってみたいと思います。
- マシンスペックが高いので2~3インスタンス固定で運用
- ダウンしたら自動再起動する。永続化ストレージがないのはCloud Runと同じ
- 新しいバージョンをデプロイするときは、新しいコンテナで2~3インスタンス立ててLBレイヤーで切り替える。問題あれば切り戻し、なければインスタンスを落とす。
OCIにはAlways Free枠で高性能なArmインスタンスも使えるので、コンテナをマルチアーキテクチャでビルドしておきます。そして、Container Instanceを起動するためのコードをClaude 3に書いてもらい、ドキュメントを見ながら細かく修正していきます。
なお、JS SDKのドキュメントがものすごく見づらいのですが、Claude 3におおよそのコードを書いてもらった後、変数名をキーに検索すると効率よく最新のリファレンスを見つけることができます。また、デベロッパーツールをひらいて通信を見ながらコンソールを見ていると、ほぼほぼ等価なリクエストが飛んでいるので、そのJSONデータを参考に修正すると一発で通りました。

あと細かいのはQueueとロギングだけどここは後程

あたらしいコンテナバージョンを作成したら切り替える。という作業をどこでやるのかは悩みどころです。いったんCloudflareでエフェメラルIP(Network Load Blancerを消さない限り変わらない)を指定して、オレンジクラウドOnで切り替えればNLB単位でバージョンを切り替えれるしいいかなと思っていました。
しかしいまよく考えたらBunnyCDNも併用してて画像のリサイズを月々定額でやってる関係上、3か所(wwwの有無と画像用)のCDNオリジンの面倒かな~とかも思いました。
だいたいの作業はNodeJSのコード化しているので、問題ないのだけど、どうしたものかな。

コードでできているという意味では、バックエンドセット単位で切り替えるのもありかもしれない。
- 新しいバージョンのバックエンドセットを作成する
- この時点で新旧まざったアクセス振り分けがなされる
- 旧バージョンのバックエンドセットに含まれるバックエンドを「バックアップ用」にして重み0にする
- 削除すると切り戻しが面倒なので
こちらもだいたい2つのステップそれぞれ10-30秒程度で反映されるので、悪くない選択肢かもしれない。

Queueに関しては、いったん移行せずCloud Tasksをそのまま採用しています。OCIのQueueはどちらかというと、能動的にPushして能動的にPullする感じです。Cloud Tasksは「再実行管理つきHTTP Post」として使っているので、そのままだと移植できません。もしかすると、OCIの通知機能か何かで代替したほうがいいかもしれないがこれから調べます。

同様にストレージに関しても、S3互換URLではCORSの設定ができないとか、そのままだとエンドポイントに独自ドメインを割り当てが難しいとかあって、いったんそのままGCSを活用しつつ、ユーザーがブラウザからアップしたファイルをサーバ間でGCP→OCIにコピーしています。
Cloudflareもプランによるけど1リクエスト100MBまでのペイロードだし、ここは引き続き検討ですね。チャンクでもいいんだけど昨今のネットワーク環境・メモリ量を考えると200~300MBくらいまで1リクエストでサクっとアップできた方が楽なんですよね。

全体的に、PaaS的なものが減ってIaaSに近づいたんだけど、インフラのシンプルさをいろいろ試行錯誤していった結果、CDN→FW→コンテナ→DB&ストレージ+Queueくらいを考慮すればいいことが分かったので、そこまでPaaSじゃないとダメということはありませんでした。
それよりは、円安の昨今、価格帯性能で利用するアーキテクチャを選ぶのもよいのではないでしょうか。
自分もインキュベーション的なものはGCPやFirebaseを活用し、月の運用費が3万円を超えはじめたサービスはOCIへ集約していこうと思います。

なおBigQueryとそこに書き込むFunction群はそのまま運用。強すぎるんだよなぁ。