個人開発のWebサイトでMariaDBからPostgreSQLへの変更を伴うサーバー移行をした話

これは私が個人で開発・運営しているJA-Fleetというサイトのサーバーに関する記事です。
飛行機が趣味の方いらっしゃいましたらぜひアクセスしてください。

https://ja-fleet.noobow.me/

# 背景
サーバー移行前、JA-Fleetは以下の環境で運営していました。
2018年8月に構築して、一部のミドルウェアはバージョンアップしながら運営してきました。
>サーバー：さくらのVPS 1Gプラン（CPU:2コア、メモリ:1G、SSD：50GB）
>OS：Cent OS 7
>Webアプリ部：ASP.net Core MVC（C#、.NET 7）
>DBMS：MariaDB 10.5
>リバースプロキシ：Caddy（Let's Encrypt組み込み）

ちなみに、AWSではなくさくらを使っている理由は単純に安いからです。


今回、以下の理由からサーバー移行をすることを決めました。
* CentOS 7のEoLが迫っていた
* .NETを8にバージョンアップしようと思ったがCentOS 7をサポートしていない
* DBMSをMariaDBからPostgreSQLに変更したかった

MariaDBからPostgreSQLに変更したい理由は何？っていう疑問があると思いますが
色々理由はありますがここでは省略します。
また、大してアクセスのない個人サーバーでEoLそこまで気にする必要あるのという疑問もありますが、今回のサーバー移行案件を自分の腕試しも含めて「やってみたかった」というところがあります。

# 概要
細かくはもっと色々なことをしていますが、
大まかには以下のようなステップで移行の検証・準備から実際の移行までを行いました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149348/509bf099-e86b-2231-2b49-2be33fa958c5.png)
**準備**
	①構築手順検証環境で
	　環境構築の内容・手順を確立
	②データ移行環境にて
	　旧環境からエクスポートしてdumpで
	　データ移行の手順を確立
	③新環境に環境構築
**切り替え**
	④旧環境でのサービスを停止
	　移行データをエクスポート
	⑤データ移行環境で新環境（PostgreSQL）用の
	　dumpを作成
	⑥新環境にデータをインポート
	⑦新環境でのサービスを開始
	⑧DNSを新環境へ切り替え

# 課題と対応
今回のサーバー移行に伴う課題と対応は以下の通りでした。
## OSの決定
ご存知の通りCentOSはCentOS Streamになってしまい、
CentOS Stream 8や9を本番運用する環境に適用するのは一般的ではありません。
代替としては、CentOSと二大巨頭となるUbuntuか
CentOS代替プロジェクトとして立ち上がったAlmaLinuxまたはRocky Linuxが考えられます。
Ubuntuは長期にわたって安定して運営されているプロジェクトであり、Linuxのディストリビューション別のシェアも1位なのですが、ご存知のようにCentOSとは色々とコマンドが違うのでやめました。
ということで、AlmaLinuxとRocky Linuxのどちらにするかということになりますが、CentOSの創設者が立ち上げたということでその安心感と経緯からRocky Linuxにすることにしました。
## 移行方式の決定
費用を抑えるなら（VPSで借りるサーバーを一台だけという状態を保持するなら）
移行前の環境を解約して新環境を構築する、または移行前の環境でOS再インストールして新環境を構築するという方法も考えられなくはないですが、言うまでもなくダウンタイムが非常に長くなってしまうのと環境構築時に移行前の環境を参照できなくなってしまいます。
移行前の環境を維持して運営を継続しながら新しいサーバーを借りて環境構築して、タイミングを決めて新環境に切り替える、新環境での運営に問題がなければ旧環境を解約するという手順を取ることにしました。
今回対象はWebサイトですので、新環境への切り替えはDNSを書き換えることで同一URLのまま行うことができます。ユーザーにとっては短時間のダウンタイムがある以外は環境移行の対応は必要ありません。
ダウンタイムが最小になる、旧環境を参照しながら新環境を構築できる、万が一の場合は切り戻しができるということを考えると、一時的にサーバー費用は2倍になってしまっても最善の方法と言えます。

## 環境構築内容・手順の確立
**（図の①）**
移行前の環境はサイト運営開始当初に試行錯誤しながら構築した環境なので、どういう手順で何をインストールすればよいのかがはっきりしていませんでした。（構築当初にある程度はメモしていましたが、途中からやめてしまって不完全なものになっていました）
新環境で「あれが足りない」「この設定が追加で必要だった」と試行錯誤するのは、また同じように完全な手順が残せない・実際に運用していく本番環境にゴミが残ってしまうので避けたいところです。
そこでさらに別の環境で環境構築の内容を確定させることにしました。この環境については、インターネット上のサーバーである必要はないので、費用をかけないために自分のPC上のVMware Workstation Playerで行いました。
最終的に過不足のない環境構築手順・内容を確定させるまで、2～3回環境構築を繰り返しました。

## MariaDBからPostgreSQLへの移行
今回のサーバー移行の中で一番「どうやってやる？」と考える必要がある部分になります。
そのため、記事のタイトルにも入れておきました。
DDLをエクスポート・データをInsert文でエクスポートして実行するという原始的な方法も考えられますが、いい感じに移行してくるツールがないか調べてみました。
すると、PGLoaderというツールを使っている例がいくつか出てきました。

https://github.com/dimitri/pgloader

色々なソースからテーブル定義なども含めてPostgreSQLにロードするためのツールであり、MySQL(MariaDB)もソースとして対応しています。
IN/OUTはファイルではなく実際のデータベースに接続することになります。
VPS上の旧環境・新環境を直接IN/OUTにすることも可能ではありますが、PGLoaderだけでは対応できず手動対応が発生する可能性があることや本番環境にゴミを残したくないことも考慮して、こちらもVMware上にMariaDB・PostgreSQLが両方インストールされているデータ移行専用環境を構築してまずは検証し、実際に切り替える際のデータ作成もその環境で行うこととしました。（図の②）
早速、旧環境のMariaDBからデータをエクスポート、データ移行環境のMariaDBにインポート、PGLoaderを実行とやってみました。
そうすると、デーブル定義とデータは正しくPostgreSQL側に移行されているものの、ViewとFunctionが全く移行されておらず、生成列(Generated Column)が通常の列になっている事がわかりました。そのため、これらは手動でSQLを実行して対応することにしました。
以上より、実際の切り替えは以下の手順で行うことにしました。（図の⑤、⑥）
1.旧環境のMariaDBからデータをエクスポート
2.データ移行環境のMariaDBにインポート
3.PGLoaderを実行
4.手動対応分のSQLを実行
5.データ移行環境のPostgreSQLから移行後データをエクスポート
6.新環境のPostgreSQLにインポート

実行したコマンド
```
# MariaDBからのエクスポート（旧環境）
mysqldump -uユーザー名 -p -A -n > エクスポートファイル名.dump

# MariaDBへのインポート（データ移行環境）
mysql -uユーザー名 -p < エクスポートファイル名.dump.dump

# PostgreSQLにデータベース作成（データ移行環境）
psql -U ユーザー名 postgres
create database データベース名;

# PGLoaderでMariaDB→PostgreSQL（データ移行環境）
pgloader mysql://ユーザー名:パスワード@localhost/スキーマ名 postgresql://ユーザー名:パスワード@localhost/データベース名

# 手動対応分のSQL実行（データ移行環境）
psql -U ユーザー名 データベース名
\i SQLファイル名.sql

# 完成したデータをPostgreSQLからエクスポート（データ移行環境）
pg_dump -Fc -U ユーザー名 データベース名 > エクスポートファイル名.dump

# PostgreSQLにインポート（新環境）
pg_restore --clean --if-exists -d データベース名 エクスポートファイル名.dump
```

## 切り替えの手順
**（図の④～⑧）**
以上で環境構築とデータ移行の課題が解決しました。
では最後は実際にサーバーをどう切り替えるかということになります。
まず、あらかじめ新環境を構築して一旦データも投入してサイトの動作が問題ないことを確認しておきます。
そのうえで、最新のデータで最終的に切り替える必要がありますので、切り替え日時を決めて告知しそのタイミングでサイトを停止します。これでデータの更新が発生しなくなるので、このタイミングでデータ移行（前項で解説した内容）を実行すれば、データの欠落なく新環境へ移行できることになります。
最後にDNSを切り替えてURLが新環境を参照するようにすれば完了になります。
これは一般的な話で今回特有の話ではないのでご存じの方も多いと思いますが、DNSの切り替えはあらかじめTTLを十分短くしておいてユーザー側で旧サーバーを参照してしまうことがなるべく発生しないようにします。

# おわりに
今回、趣味でやってるサイトの話ではありますが、
これを仕事でやるならトラブルを起こさないためにどうやるか？を考えながらやりました。
（似たような案件は何度か仕事で経験があります）
その結果、特にトラブルなくサーバー移行完了することができ、大変満足しています。