DigitalOceanからHetznerへの移行:ゼロダウンタイムで$1,432から$233へ
5時間前原文(isayeter.com)
概要
- DigitalOceanからHetzner専用サーバーへの大規模本番移行事例
- MySQL 248GB/30DB、34サイト、GitLab EE、Neo4j、モバイルアプリの無停止移行
- インフラコストの高騰と年間$14,388のコスト削減
- CentOS7→AlmaLinux9.7へのOSアップグレードも同時実施
- 詳細なゼロダウンタイム移行戦略と各種トラブル対応
DigitalOceanからHetznerへの移行背景
- トルコ国内のインフラコスト高騰、為替変動によるドル建て請求負担の増加
- DigitalOceanで月額**$1,432**支払い、性能に対してコスト効率が悪化
- Hetzner AX162-R(256GB DDR5 RAM/1.92TB NVMe/48コアCPU)で月額$233、年間**$14,388**のコストダウン
- DigitalOcean製品自体の品質には満足、だが長期利用で価格差を痛感
移行対象システム概要
- 30個のMySQLデータベース(合計248GB)
- 34のNginx仮想ホスト(複数ドメイン対応)
- GitLab EE(バックアップ42GB)
- Neo4j Graph DB(30GB)
- Supervisorによるバッチワーカー管理
- Gearmanジョブキュー
- 数十万ユーザー対応のモバイルアプリ
- 旧サーバー: CentOS 7(EOL、セキュリティ更新なし)
- 新サーバー: AlmaLinux 9.7(RHEL9互換、CentOS後継)
ゼロダウンタイム移行戦略(6フェーズ)
- Phase 1: 新サーバーに全スタック構築(Nginx, PHP, MySQL8, Neo4j, GitLab EE, Supervisor, Gearman)
- SSL証明書は**/etc/letsencrypt/をrsyncでコピー、移行後certbot renew --force-renewal**で一括更新
- Phase 2: Webファイル(/var/www/html, 65GB, 150万ファイル)をrsyncで同期
- 切替直前に増分同期を実施
- Phase 3: MySQLマスター・スレーブレプリケーション
- mydumperで並列ダンプ、binlog位置を記録しリアルタイム同期
- Phase 4: DNS TTL短縮(A/AAAAレコードのみ3600→300秒、MX/TXTは変更せず)
- 1時間待機でTTL反映、5分以内で切替可能に
- Phase 5: 旧サーバーのNginxをリバースプロキシ化
- Pythonスクリプトで全34サイト設定をproxyへ自動変換
- DNS伝播中も旧IPアクセスは新サーバーへ転送、ユーザー影響ゼロ
- Phase 6: DNS切替&旧サーバー停止準備
- Pythonスクリプトで全Aレコードを新IPへ一括切替
- 旧サーバーは1週間コールドスタンバイ後に完全停止
MySQL移行詳細
- mydumper/myloaderによる高速並列ダンプ&リストア
- 48コア活用で従来mysqldumpの数日→数時間に短縮
- コマンド例:
- mydumper --threads 32 --compress --trx-consistency-only --skip-definer --chunk-filesize 256 -v 3 --outputdir /root/mydumper_backup/
- myloader --threads 32 --overwrite-tables --ignore-errors 1062 --skip-definer -v 3 --directory /root/mydumper_backup/
- MySQL 5.7→8.0アップグレード
- mysqlcheck --check-upgradeで互換性確認
- mysql.userテーブルのカラム不一致問題発生(45列→51列)、sysスキーマもテーブル化でエラー
- sysデータベース削除後、mysqld --upgrade=FORCEで解決
- レプリケーションエラー(重複キー)
- ダンプ2回実行間のデータ差分で発生、slave_exec_mode = 'IDEMPOTENT'で重複エラー自動スキップ
- SUPER権限問題
- read_only=1でもSUPER権限ユーザーは書き込み可能、全アプリユーザーからSUPERをrevokeし正常化
切替前検証・DNS・プロキシ
- /etc/hosts編集でローカルから新サーバー動作を事前検証
- DigitalOcean DNS APIでTTL短縮、A/AAAAのみ変更
- Nginxリバースプロキシ自動生成スクリプトで全サイト一括対応
- proxy_ssl_verify offで自己管理環境下のSSL検証省略
本番切替手順
- 新サーバー: STOP SLAVE, SET GLOBAL read_only=0, RESET SLAVE ALL, supervisorctl start all
- 旧サーバー: nginx設定テスト&リロード(プロキシ稼働)、supervisorctl stop all
- ローカル: DNS切替スクリプト実行(10秒以内に全Aレコード更新)
- 5分待機、旧サーバーのcrontabをコメントアウト
- GitLabのwebhook IP修正もAPIスクリプトで一括対応
結果とまとめ
- 月額$1,432→$233、年間$14,388節約
- 全サービス無停止移行、サーバースペックも大幅向上
- 移行自動化・スクリプト化・段階的検証による業務リスク最小化
- 大規模本番環境のコスト最適化・最新OS/DB化・無停止移行ノウハウ