GCP Cloud CDNでWebサーバーコンテンツをキャッシュする!

GCP

試したこと

構成イメージ

CDN適用前

クライアントがコンテンツ読み込みむたびにWAFがバックエンドのWebサーバーへイメージをリクエストする。クライアントとコンテンツが遠いほどネットワーク遅延の影響を受けやすい。また、アクセスが集中するとWebサーバーのIO負荷やCPU利用率があがり、リクエストタイムアウトなどのエラーの原因となる。
file

CDN適用後

GCPのCloud CDNはグローバルHTTP(S) ロードバランサーに統合される。世界中に分散されたLBフロントエンドから一番近い場所でクライアントのHTTP(S)リクエストを受けると同時に、各ロケーションで保持するキャッシュにリクエスト対象のコンテンツがあればバックエンドまでコンテンツを取りに行くことなく高速にレスポンスを返すことができる仕組みになっている。現在は世界で100以上のロケーションに対応している。
file

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 のサービス

file

デプロイ

バックエンドサービスの作成

インスタンス テンプレートの作成

インスタンステンプレートとはロードバランサのバックエンドとなるGCEのイメージやVMサイズ・ブートディスクの種類などの項目を定義しておくもので、インスタンスグループに立ち上げるVMのレシピのようなものだ。インスタンスグループをスケール可能にするには、ステートレス(*)なイメージを指定する。ソースにはカスタムイメージも指定できる。
file

*VMにはユーザーデータを持たせず共有DBなどを参照させることでVMアプリケーションの独立性を高めスケールできるようにするやり方

インスタンスのFWルール

フロントエンド向けのイングレスFWルール
フロントエンドサービスからバックエンドとなるインスタンスグループへの接続を許可するファイアウォールの設定には以下のやり方がある。

  • インスタンステンプレートで設定…テンプレートのファイアウォール設定でHTTPを許可
    file
    インスタンスが立ち上がる際にVMに"HTTP"のネットワークタグが付与される。同時にVPCにタグに対応するファイアルールが作成される。
  • 別途作成…インスタンステンプレート内でネットワークタグをつけてお、別途作成するVPCファイアウォールのターゲットでそのタグを指定。

ちなみに、SSLをロードバランサで終端するように構成変更のであればフロントエンドサービスからのアクセスはHTTPになるため、バックエンドでHTTPS用のポートを開ける必要はないだろう。

LBヘルスチェック用のイングレスFWルール
ロードバランサーは定期的にバックエンドインスタンスの正常性を監視し、到達できないものを切り離すことでバックエンドの可用性を高めている。このため、ヘルスチェック用IPアドレスからバックエンドインスタンスに対するアクセスを許可するファイアウォールルールが必要だ。これを怠るとバックエンドインスタンスがFAILとなり、クライアントからサービスへアクセスできなくなる。
file

インスタンスグループの作成

ロードバランサのバックエンドに対応するインスタンスグループを作成する。
定義する項目

  • 立ち上げるインスタンスのリージョン
  • 冗長度
  • オートスケールのパラメータ
    • 伴うインスタンスの最小・最大数
    • トリガー
      file
      名前付きポートの作成
      file

HTTP(S)ロードバランサーの作成

ロードバランサ作成の準備ができたらグローバルHTTP(S)ロードバランサーを作成していく。
file

file

バックエンドサービスの作成

ロードバランサではVMやコンテナといった複数のタイプのインスタンスを紐づけ負荷分散できる。その抽象化レイヤーとしてバックエンドサービスを作成し、インスタンスグループを紐づける。
file

バックエンドの作成

ここにあらかじめ作成したインスタンスグループを指定する。ポートは80を指定する。これは、SSLをHTTPSロードバランサーで終端するのでロードバランサーとWebサーバー間はHTTP(暗号化なし)で通信するためだ。これにはWebサーバーが証明書処理に伴うCPU負荷からが解放されるなどの利点がある。ロードバランサーとインスタンス間でエンドツーエンドのSSLを構成する場合は、バックエンドインスタンスに検証の取れない(ブラウザから警告の出る)証明書をいれてしまうと、インスタンスがFailと判断されとクライアントに502 Bad Gatewayのようなエラーが返される原因となる。GCP内部でのロードバランサーとGCE間の通信は自動的に暗号化されるため、明示的なエンドツーエンドSSLの要件がない限りHTTPSはなくてもよさそうだ。

file

CDNの有効化

CDNの設定はバックエンド単位で行う。Cloud CDNをONにするだけでコンテンツの分散キャッシュがすぐに有効になる。
file

ヘルスチェックの作成

バックエンドの正常性確認方法を定義する。デフォルトではバックエンドのPort 80から応答があればインスタンスを正常とみなす。
file

チェック対象のURLパス変更やエラーとする閾値も柔軟に対応できるようになっている。
file

フロントエンドの作成

クライアントのエンドポイントとなるロードバランサーフロントエンドを作成する。
file

証明書の登録

HTTPSでサービスを提供するのでGCPにSSLサーバー証明書を登録し、フロントエンドにセットする。
file

外部IPアドレスの作成と割り当て

グローバルの外部IPアドレスを予約しておく。DNSではWebサイトのドメインをこのIPに解決させるためのAレコードをあらかじめ作成しておく。
file

WAFルールのアタッチ(オプション)

ロードバランサーにCloud ArmorのWAFルールをアタッチし、OWASP 10のようなメジャーな攻撃やreCaptchaに対する不正への対策、機械学習によるアプリケーション保護をアドオンできる。
file

ロードバランサの作成

file

Cloud CDNの効果

Cloud CDN有効化後に何度かサイトのリロードを行いコンソールを確認したところキャッシュヒット率は87.5%になっていた。初回の読み込み以降、イメージなどのコンテンツがCDNにキャッシュされるように動きが変わったことがわかる。
file

キャッシュのヒット状況

キャッシュのヒット状況はグラフでも確認できる。
file

CDN有効化後もURLは変更されない

CDNを有効化したあとも画像の送信元はロードバランサーの外部IPが維持されている。グローバルロードバランサのバックエンドにいる限りはCDNをオフにするときも構成変更は不要だ。
file

性能比較

CDNなし

テストした画像はリクエストから読み込み完了までに24msを要した。
file

クライアント(ブラウザ)のメモリにキャッシュされているときの応答時間は1ms未満であることから、24msは画像をWebサーバーへ取りに行って帰ってくるまでの時間であることがわかる。
file

CDNあり

CDN有効化後、同じ画像の読み込み時間は284msと遅くなってしまった。ほかのファイルの読み込み時間もだいたい250ms前後遅くなっていることがわかる。今回のテスト環境はクライアントとWebサーバーが1対1の関係にあるため局所的なテストにしかならないが、Webサーバーの負荷が十分に低くい場合にはCDNを挟んだほうが遅くなってしまうケースもあるということだろう。今回は導入の流れの確認が目的のため、実環境のように同時リクエスト数が多い状況をシミュレーションするテストでCDNの効果による全体的な応答速度の向上を確認することは見送った。
file

キャッシュの無効化

特定のパスに対するキャッシュを明示的にクリアすることもできるようだ。
file

あとがき

グローバル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

タイトルとURLをコピーしました