サービスをAzureからGCPに移行した話

:::note info
"[ゆるWeb勉強会@札幌 Advent Calendar 2022](https://adventar.org/calendars/7513)" ９日目の記事です。
:::

# サービス移行の経緯

[2022年11月28日をもってPHP7.4がEOL](https://www.php.net/supported-versions.php)となりました。さらに以降のPHP8からはWindowsでのサポートがされないようになりました。

Azure App Service（Windows）でもPHP7.4以降のランタイムは選択できず、さらにAzureはEOLとなったバージョンを積極的に廃止しているので、サービスがダウンしないように対応する必要がありました。

ここでGoogle Cloud Platform（以後 GCP）に移行することになったのは、かねてからAzureのオートスケールの速度に不満があり、社内で「Google App Engine（以後 GAE）の方が速い」という実績があったので、GCPに移行を目指すことになりました。

ちなみにその時の私は「GCP何もワカラン」。

# 移行のイメージ

![Azure-GCP移行イメージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595926/fcef0b3f-92c7-f8c1-27a0-928ca97d98f0.png)

諸々の事情で**アプリケーションのみ**をAzureからGCPへ移行します。
（この記事ではクラウド移行に焦点を当て、PHPアップデート関連は割愛します）

# まずは見積もり

「GCP何もワカラン」状態ですが、見積もりが必要なので、事前調査として無邪気に置いて動かしてみます。
この時点でクリティカルな問題は発見されなかったのですが、大きく次の点が課題としてありました。

- GCPプロジェクトの構成
- CircleCIのデプロイパイプライン（AzureからGCPへ）
- アプリケーションのGAE対応
- Azureへ残したデータベース等への接続

# 開発スタート

Goが出たので進めていきます。

## GCPプロジェクトの構成

新しいクラウドプラットフォームに触れると、とにかく調べる事が多いです。

- 組織やプロジェクト
- 料金、請求関係
- 権限（IAM）
- ロギングやメトリクスなどの監視
- etc...

ある程度慣れるとすぐに開発を始められるのですが、最初は基本的な事をおさえるのが大変ですね・・・

## CircleCIのデプロイパイプライン

AzureへのデプロイをCircleCIでやっていたので、これをGAEへデプロイされるようにしていきます。

デプロイそのものはGoogle Cloud CLIを扱えるパッケージ（Orb）を使えば簡単なのですが、IAMやCloud APIsであれこれと要求されるので進んでは止まっての繰り返しでした。

また、以降対象のひとつにLaravelアプリケーションがあったのですが、これがGAEの書き込み禁止と相性が悪い部分があり、あれこれと試行錯誤することになりました。
（これはまた別の記事で触れるかもしれません。次回作にご期待ください。）

## アプリケーションのGAE対応

シビアなシステム要件では無いので、機能自体に変更はありませんでした。主に変更すべきところは、ログハンドラやキャッシュのドライバ、リクエストのハンドリング等です。

また、GAEの設定は主に`app.yaml`で行うので、それについては色々調べることになりました。リクエストのハンドリングも`nginx.conf`や`Web.config`ではなく`app.yaml`で行うので、設定できる内容がかなり限定されますね。また、リクエストは基本的にフロントコントローラーに集められ、静的コンテンツは個別にハンドリングしなければならないのもGAEの特徴なのかなと思います。

## Azureのデータベース等への接続

通常GAEは固定IPではないので、このままではAzureのファイアウォールを通すことができません。この問題自体はCloud NAT + 静的IPアドレスで解決できたのですが「ネットワークよくワカラン」状態でいろいろと構成したので、不安が残る状態になりました。この不安を解決するためにも、後述する負荷テストを実施しました。

# 負荷テストの実施

機能テストはもちろん実施しましたが、その他にも不安があったので負荷テストを実施しました。確認したいのは次の点です。

- App Engineのスペック（クラス）、スケーリングどうする？
- GCP ～ Azure間のパフォーマンス大丈夫か？
- 構成したネットワークがボトルネックにならないか？

## ツールの選定

いくつか調べてみましたが、今回は特別なシナリオは必要ないのでシンプルに[Apache Bench](https://httpd.apache.org/docs/2.4/programs/ab.html)で実施しました。

## どれくらい負荷をかけるか

知見が少ないものの、なるべく意味のある数値を設定したいと思い、時間あたりのPVからざっくりリクエスト数と同時接続数を決めました。

リクエスト数：PV (1h） / 60
同時接続数：PV (1h） / 360

１秒間で同時接続数を捌ければよかろう、という感じです。
さらに直近の状況から「平時」と「特にアクセスが多い状況」の２パターン用意しました。

## 負荷テストの実施と結果

「いっきに負荷をかけたら会社のネットワークが・・・」という記事をどこかで見たので、少しずつ負荷をかけていき、最終的に目標の数値で実施しました。

テストの結果、ある一定のリクエスト数を超えたあたりからDB接続エラーが発生しました。そしてその原因は静的IPアドレスを設定するために構成したCloud NATにありました。やってよかった負荷テスト。

# いよいよリリース

機能検証でも問題が無かったので、ドメインのDNSを切り替えてリリースすることになりました。

## DNS切り替えに失敗

DNSを切り替えたところ、サイトに接続できない状態が続きました。digツールではDNSが変更されたことが確認できたので、いったん切り戻すことにしました。

### 失敗の原因

原因を調査したところ、次の点に問題があったことが判明しました。

- ドメイン管理の都合で、AAAAレコードが設定できなかった
- マネージドSSLはAAAAレコードが必要

マネージドSSLを使用しなければAAAAレコードがなくても大丈夫、という点も判明したので、マネージドSSLではなく別のSSL証明書を割り当ててリトライすることになりました。

## リリース リトライ

AAAAレコードとSSLの問題を解決し、再びDNSを切り替えました。

今度ははうまくいったものの、私の画面にはシステムエラーの画面が表示されました。同時に切り替え直後からアプリケーションのエラーログが観測されました。

エラーが出ているのはセッション管理をしている部分でした。セッションに関するPHP設定に違いがあったため、切り替え前のサーバーからアクセスしていた場合にエラーとなっていました。

## 移行終了

セッションに関する問題を修正してからエラーは収束し、安定稼働しています。ここ数ヶ月の山場はひとまず超えた形になりました。
（まだ不要になったリソースの削除などが残っているので完了ではないです）

# 振り返り、まとめ

## リリース時のトラブルについて

DNSの問題とPHP設定の問題がありましたが、どちらも実際の移行作業に近い状況で検証することにより検出できた可能性が高いです。
数年前にAzureへ移行した時はスムーズに進められたのがあって、警戒が薄れていたのかもしれません。その当時とはいろいろと異なっているので、これは反省すべき点です。
またDNSの切り替えはいろいろと手順が必要な状況だったので、リトライにより想像以上の遅延が生じてしまいました。その点も踏まえて念入りに検証しておくべきだったのかもしれません。

## 負荷テスト

知見が少ないなりにやってみたのですが、問題も検出され、移行に自身が持てたので良い結果だったと思います。

Apache Benchについては「本当にシンプルなツール」という感想です。エラーの詳細もわからないので、もう少し複雑な状況になったら他のツールを使うほうが良さそうです。

## マルチクラウドについて

[Accelerate State of DevOps Report](https://cloud.google.com/blog/products/devops-sre/dora-2022-accelerate-state-of-devops-report-now-out)では「複数のパブリッククラウドの利用が、組織にプラスの影響を与える」と分析されています。しかしながら、複数のクラウドプラットフォームについて熟知してその特徴を使いこなすには、それなりに多くの人材が必要になると思います。小規模な組織では難しい印象です。

## PHPのEOLについて

PHPはメジャーバージョンが7になってから、１年のバージョンアップサイクルになりました。そして、Azureもサポートが終了したバージョンの廃止を徐々に早めていっているようです。このようなところからも世の中が加速し、技術の陳腐化が早まっている印象を受けます。こういった点も踏まえて長期戦略を考えることが大切ですね。

## まとめ

トラブルもありましたが、致命的は失敗は無く、無事に移行を済ませることができました。
時間やリソースは限られるので全てに対応することはできませんが、今回の成功も失敗も良い経験として活かしていきたいものです。

**これでクリスマスは家に帰れそうだ。**