Cloud StorageをCDNと連携させたい

この記事を真似てみようと思ってみたけど、やり方が変わっているっぽいので

Cloud CDNを使うにはCompute Engine APIを有効化しないといけないみたい

そもそも、バケットを作ってなかった。

example.com みたいな感じでもいいんだ

Storage Transfer Serviceってなんだ?
複数のバケットにコピーをもたせることができる機能らしい
データ主権: 地理的に離れたリージョンにまたがるデータを維持します。
開発環境と本番環境で異なるバージョンを維持: 別個のバケットと名前空間を作成して、開発環境が本番環境のワークロードに影響しないようにします。
データ共有: ベンダーまたはパートナーが所有するバケットにデータを複製します。
データ集約: さまざまなバケットのデータを 1 つのバケットに結合して、分析ワークロードを実行します。
費用、セキュリティ、コンプライアンスの管理: さまざまな所有権、ストレージ クラス、保持期間でデータを維持します。

今回はそこまでしなくていいので、Single-Regionで(公開アクセス禁止で作ってみた)

この画面でロードバランサを作ってくれるみたい
キャッシュルールを細かく指定できるっぽい
署名付きURLはCloud CDNが発行するのか?

作成中

作成完了
あまり理解できてないんだけど、Cloud StorageのURLにアクセスするでいいのかな?
CDN用のURLが発行されるものだと思ってたけど

このサイトで試してみる
Cloud Storageが発行した認証済みURLを使ったら、ふつうにステータス200になるだけだった

こんな記述があった(いや、でも認証済みURLに書いてあるのと同じだな)
ストレージに適当なindex.htmlをpushして、アクセスしてみます。
https://storage.cloud.google.com/BUCKET_NAME/index.html
※ BUCKET_NAMEは作成したものに置き換えてください
上記のURLにアクセスすると別のURLへ飛ばされ、CDNのキャッシュサーバへアクセスしていることがわかります。

公開アクセス禁止を止めてみる
結果は変わらず

よくよくみたら、キャッシュ無効になってる
ここで変えなきゃいけないのか? でも、さっきCDNで自動的に静的ファイルはキャッシュするようにしたはず

そもそも、レスポンスをよくみたら、おそらくこのページが表示されてる。
認証済みURL:https://storage.cloud.google.com/zacker-playground-zenn/257-500x500.jpg?authuser=3
このURLにアクセスするとログインしている状態の自分だとアクセスできるけど、ログイン状態を持たないものでアクセスするとエラーページが表示されるっぽい。

バケットを公開にしてるのに、非公開になってるし
あれ?
ダイアログのボタンポチポチじゃなくて、ここでやらないといけなかったんだ

公開URLが出てきた
ただ、キャシュはされていない?
リダイレクトされてしまっているから、URLが違うのかな?
=> 5分くらいまったらリダイレクトされなくなった

設定を弄らなくても良さそうなんだけどなぁ
Cloud Storage は常に Cloud CDN に Cache-Control ヘッダーを提供します。値を明示的に選択しない場合は、デフォルト値が送信されます。そのため、Cloud Storage のすべての成功レスポンスは、Cloud Storage 内のオブジェクトに対してキャッシュ制御メタデータを明示的に制御した場合を除き、Cloud Storage のデフォルト値に従ってキャッシュに保存されます。FORCE_CACHE_ALL モードを使用して Cloud Storage から送信された値をオーバーライドすることもできます。

Cloud CDN自体の設定を変更してみる
さっきまでなかった、cache-controlのヘッダーが追加されてる

Load BalancerのIPアドレスにすればいい?
=> 取得はできたけど、キャッシュヒットしているわけではなさそう

この記事が参考になりそう
ここまでの話を踏まえて、では GCS + HTTP(S) LB + Cloud CDN で静的 Web サイトをホスティングする際に、各設定値はどのようにすれば良いか考えてみます。
まず以下の 2 点はある程度決め打ちできます。
Cloud CDN でキャッシュするので、GCS ではオブジェクトの Cache Metadata に no-store, max-age=0 を指定して組み込みキャッシュを無効化する
GCS に動的コンテンツはないので、Cloud CDN のキャッシュモードは FORCE_CACHE_ALL を指定して、すべてのコンテンツをキャッシュ対象にする

FORCE_CACHE_ALLにしたら、キャッシュが使われるようになったっぽい?
静的ファイルのキャッシュに戻したら、ステータスコードのログは出てるけど、キャッシュの履歴が出なくなった。

なんでこのサイトでチェックできないのか、気になっていたけどClaudeさんによると
なるほど、確かにその通りですね。
Cloud CDNは一般的なCDNヘッダー(x-cache, x-cache-hitなど)を返さず、代わりに以下のようなGoogleの独自ヘッダーを使用します:
cache-control: public, max-age=xxx
age: xxx
via: 1.1 google
このため、従来のCDNでよく見られるような:
x-cache: HIT
x-cache-hits: 1
といったヘッダーでキャッシュの状態を確認することができません。
キャッシュの状態を確認したい場合は:
age
ヘッダーの値via: 1.1 google
の存在- Cloud CDNのログ(Cloud Loggingで確認可能)
を使用する必要があります。
これは、Cloud CDNがより「Google的」な設計思想に基づいて実装されているためと言えます。
カスタムヘッダーでチェックできるらしい
https://storage.googleapis.com/xxx ではなくて、LoadBalancerのIPアドレスにアクセスしたらキャッシュヒットするようになった!
before | after |
---|---|
![]() |
![]() |

結論
- Cloud CDNはCloud Storageとかんたんに紐づけることができる(Loadbalancerの設定も勝手にやってくれる)
- Cloud StorageのコンテンツをCloud CDNを経由してアクセスするためには、Load balancerのIPアドレスを利用する必要がある(← これが本当に正しいのか若干のギモンが残る)
- カスタムヘッダを指定することによって、キャッシュヒットなどの状態を確認することができる
https://cloud.google.com/load-balancing/docs/custom-headers#variables

ギモン
- LoadbalancerのIPアドレスが固定で出力されているけど、これだとCDNの「近くのサーバに自動的に飛ばしてくれる」のメリットがなくなってしまうのでは?
Claudeさん的解答
Cloud Load Balancerの固定IPアドレスは、実際のトラフィックの経路を示すものではありません。
仕組みとしては:
DNSレベルでは、ユーザーに最も近いGoogle POPにルーティング
そのPOPで最初のTCP接続が終端
その後、Googleのグローバルネットワーク内で最適な経路を使用
つまり:
固定IPアドレスは論理的なエンドポイントとして機能
実際のトラフィックは、ユーザーに最も近いエッジロケーションから処理
Google Cloud のグローバルネットワークを利用して最適化された経路で配信
そのため、固定IPアドレスがボトルネックになることはありません。これはGoogle Cloud の「Premium Tier」ネットワークの特徴の一つです。
ただし、「Standard Tier」を使用している場合は、パブリックインターネット経由でのルーティングとなるため、このような最適化の恩恵は受けられません。

たしかに、公式ドキュメントを読んでもマルチリージョンに対応しているような雰囲気がする
プレミアム ティアは、VM インスタンスとロードバランサに対して、リージョン外部 IP とグローバル外部 IP の両方をサポートします。すべてのグローバル外部 IP アドレスでは、プレミアム ティアを使用する必要があります。複数のリージョンにバックエンドがある外部アプリケーション ロードバランサや外部プロキシ ネットワーク ロードバランサなど、高いパフォーマンスと可用性が求められるアプリケーションには、プレミアム ティアが必要です。
IPアドレスは特定のホストを指すという自分の中の常識が破壊されるような感じがするんだけど
ルーティングするときに、ホップ先を地理的に近い場所に飛ばしてくれるってことなのかな?
インターネット ユーザーからのトラフィックは、インターネット ユーザーにできるだけ近い Google ポイント オブ プレゼンス(PoP)のピアリング ネットワークまたは中継ネットワークを介して Google のネットワークに入ります。 具体的には、 Google Cloud は、Google グローバル ネットワーク全体の PoP にあるピアリング ネットワークとトランジット ネットワークに、プレミアム ティア IP アドレスのネクストホップをアドバタイズします。これらのネクストホップは、同等の BGP 指標でアドバタイズされます。これにより、ピアリング ネットワークとトランジット ネットワークは、インターネット ユーザーにできるだけ近い PoP にトラフィックを配信できます。

どうやらAnycastという技術が基盤になっているらしい
エニーキャストでは、1つのIPアドレスを複数のサーバーに適用できます。つまり、エニーキャストDNSでは多くのDNSサーバーの中から任意の1つがDNSクエリに応答することができ、通常は地理的に最も近いサーバーがレスポンスを提供します。これにより、レイテンシーが減少し、DNS解決サービスの稼働時間が増し、DNSフラッドDDoS攻撃に対する保護が適用されます。

結論(v2)
- Cloud CDNはCloud Storageとかんたんに紐づけることができる
- Loadbalancerの設定も勝手にやってくれる
- Cloud StorageのコンテンツをCloud CDNを経由してアクセスするためには、Load balancerのIPアドレスを利用する必要がある
- [✨️NEW] LoadbalancerのIPアドレスを利用すると、地理的に近いGoogleの拠点に飛ばされる
- => Loadbalancerへのアクセスが地理的な遅延を生むことの影響が小さくなる
- これはAnycastという1つのIPアドレスを複数のサーバーに適用できる技術が基盤になっている
- カスタムヘッダを指定することによって、キャッシュヒットなどの状態を確認することができる
https://cloud.google.com/load-balancing/docs/custom-headers#variables