試したこと
- Cloud CDNにWebサーバーのイメージをキャッシュさせるまでの流れを確認
- CDN有効化後イメージの読み込みがCDNからとなることを確認する
構成イメージ
CDN適用前
クライアントがコンテンツ読み込みむたびにWAFがバックエンドのWebサーバーへイメージをリクエストする。クライアントとコンテンツが遠いほどネットワーク遅延の影響を受けやすい。また、アクセスが集中するとWebサーバーのIO負荷やCPU利用率があがり、リクエストタイムアウトなどのエラーの原因となる。
CDN適用後
GCPのCloud CDNはグローバルHTTP(S) ロードバランサーに統合される。世界中に分散されたLBフロントエンドから一番近い場所でクライアントのHTTP(S)リクエストを受けると同時に、各ロケーションで保持するキャッシュにリクエスト対象のコンテンツがあればバックエンドまでコンテンツを取りに行くことなく高速にレスポンスを返すことができる仕組みになっている。現在は世界で100以上のロケーションに対応している。
Cloud CDNにキャッシュできるソース(オリジン)
今回はトライアルでバックエンドとなるVMの中のイメージをCloud CDNにキャッシュさせる。構成変更を避け、Webサイトのキャパシティとりあえず改善するパターンだ。新規でGCPにWebサイトを構築するときはCloud StorageにイメージをアップロードしVMとコンテンツを分離しするなどの方法で無駄のない水平方向のスケーラビリティを確保すべきだろう。
Cloud CDNのキャッシュ対象
- Cloud Storage(マルチリージョンにも対応)
- 外部バックエンド(カスタム送信元)(オンプレミス、マルチクラウド)
- Compute Engine 仮想マシン(VM)インスタンス
- Google Kubernetes Engine(GKE)コンテナ インスタンス
- App Engine、Cloud Functions、または Cloud Run のサービス
デプロイ
バックエンドサービスの作成
インスタンス テンプレートの作成
インスタンステンプレートとはロードバランサのバックエンドとなるGCEのイメージやVMサイズ・ブートディスクの種類などの項目を定義しておくもので、インスタンスグループに立ち上げるVMのレシピのようなものだ。インスタンスグループをスケール可能にするには、ステートレス(*)なイメージを指定する。ソースにはカスタムイメージも指定できる。
*VMにはユーザーデータを持たせず共有DBなどを参照させることでVMアプリケーションの独立性を高めスケールできるようにするやり方
インスタンスのFWルール
フロントエンド向けのイングレスFWルール
フロントエンドサービスからバックエンドとなるインスタンスグループへの接続を許可するファイアウォールの設定には以下のやり方がある。
- インスタンステンプレートで設定…テンプレートのファイアウォール設定でHTTPを許可
インスタンスが立ち上がる際にVMに"HTTP"のネットワークタグが付与される。同時にVPCにタグに対応するファイアルールが作成される。 - 別途作成…インスタンステンプレート内でネットワークタグをつけてお、別途作成するVPCファイアウォールのターゲットでそのタグを指定。
ちなみに、SSLをロードバランサで終端するように構成変更のであればフロントエンドサービスからのアクセスはHTTPになるため、バックエンドでHTTPS用のポートを開ける必要はないだろう。
LBヘルスチェック用のイングレスFWルール
ロードバランサーは定期的にバックエンドインスタンスの正常性を監視し、到達できないものを切り離すことでバックエンドの可用性を高めている。このため、ヘルスチェック用IPアドレスからバックエンドインスタンスに対するアクセスを許可するファイアウォールルールが必要だ。これを怠るとバックエンドインスタンスがFAILとなり、クライアントからサービスへアクセスできなくなる。
インスタンスグループの作成
ロードバランサのバックエンドに対応するインスタンスグループを作成する。
定義する項目
- 立ち上げるインスタンスのリージョン
- 冗長度
- オートスケールのパラメータ
- 伴うインスタンスの最小・最大数
- トリガー
名前付きポートの作成
HTTP(S)ロードバランサーの作成
ロードバランサ作成の準備ができたらグローバルHTTP(S)ロードバランサーを作成していく。
バックエンドサービスの作成
ロードバランサではVMやコンテナといった複数のタイプのインスタンスを紐づけ負荷分散できる。その抽象化レイヤーとしてバックエンドサービスを作成し、インスタンスグループを紐づける。
バックエンドの作成
ここにあらかじめ作成したインスタンスグループを指定する。ポートは80を指定する。これは、SSLをHTTPSロードバランサーで終端するのでロードバランサーとWebサーバー間はHTTP(暗号化なし)で通信するためだ。これにはWebサーバーが証明書処理に伴うCPU負荷からが解放されるなどの利点がある。ロードバランサーとインスタンス間でエンドツーエンドのSSLを構成する場合は、バックエンドインスタンスに検証の取れない(ブラウザから警告の出る)証明書をいれてしまうと、インスタンスがFailと判断されとクライアントに502 Bad Gatewayのようなエラーが返される原因となる。GCP内部でのロードバランサーとGCE間の通信は自動的に暗号化されるため、明示的なエンドツーエンドSSLの要件がない限りHTTPSはなくてもよさそうだ。
CDNの有効化
CDNの設定はバックエンド単位で行う。Cloud CDNをONにするだけでコンテンツの分散キャッシュがすぐに有効になる。
ヘルスチェックの作成
バックエンドの正常性確認方法を定義する。デフォルトではバックエンドのPort 80から応答があればインスタンスを正常とみなす。
チェック対象のURLパス変更やエラーとする閾値も柔軟に対応できるようになっている。
フロントエンドの作成
クライアントのエンドポイントとなるロードバランサーフロントエンドを作成する。
証明書の登録
HTTPSでサービスを提供するのでGCPにSSLサーバー証明書を登録し、フロントエンドにセットする。
外部IPアドレスの作成と割り当て
グローバルの外部IPアドレスを予約しておく。DNSではWebサイトのドメインをこのIPに解決させるためのAレコードをあらかじめ作成しておく。
WAFルールのアタッチ(オプション)
ロードバランサーにCloud ArmorのWAFルールをアタッチし、OWASP 10のようなメジャーな攻撃やreCaptchaに対する不正への対策、機械学習によるアプリケーション保護をアドオンできる。
ロードバランサの作成
Cloud CDNの効果
Cloud CDN有効化後に何度かサイトのリロードを行いコンソールを確認したところキャッシュヒット率は87.5%になっていた。初回の読み込み以降、イメージなどのコンテンツがCDNにキャッシュされるように動きが変わったことがわかる。
キャッシュのヒット状況
キャッシュのヒット状況はグラフでも確認できる。
CDN有効化後もURLは変更されない
CDNを有効化したあとも画像の送信元はロードバランサーの外部IPが維持されている。グローバルロードバランサのバックエンドにいる限りはCDNをオフにするときも構成変更は不要だ。
性能比較
CDNなし
テストした画像はリクエストから読み込み完了までに24msを要した。
クライアント(ブラウザ)のメモリにキャッシュされているときの応答時間は1ms未満であることから、24msは画像をWebサーバーへ取りに行って帰ってくるまでの時間であることがわかる。
CDNあり
CDN有効化後、同じ画像の読み込み時間は284msと遅くなってしまった。ほかのファイルの読み込み時間もだいたい250ms前後遅くなっていることがわかる。今回のテスト環境はクライアントとWebサーバーが1対1の関係にあるため局所的なテストにしかならないが、Webサーバーの負荷が十分に低くい場合にはCDNを挟んだほうが遅くなってしまうケースもあるということだろう。今回は導入の流れの確認が目的のため、実環境のように同時リクエスト数が多い状況をシミュレーションするテストでCDNの効果による全体的な応答速度の向上を確認することは見送った。
キャッシュの無効化
特定のパスに対するキャッシュを明示的にクリアすることもできるようだ。
あとがき
グローバルHTTP(S)ロードバランサーのCDNはバックエンドで有効化にチェックを入れるだけですぐにキャッシュが開始されるほどにグローバルHTTP(S)ロードバランサーに統合されており導入が簡単であることがわかった。スケーラビリティが求められる局面で積極的に使っていきたい。
リンク
https://cloud.google.com/cdn/docs/setting-up-cdn-with-mig?hl=ja
https://cloud.google.com/cdn/docs/locations?hl=ja