メディア・プロモーション事業部でpixivの広告配信システムを開発しているあやぬんです。
今回pixivの広告システムで利用しているGCPのロードバランサ(以下GCLB)で待望のHTTPS・URLリダイレクト機能が4/14にGA1となったので、本番環境・開発環境へ導入した方法を紹介します。
従来のGCLBに対する課題
今までGCLBはHTTPおよびHTTPSのバックエンドサービスに対して、ただトラフィックを流すだけで、リダイレクトの機能はありませんでした。
Google Issue Trackerには2015年からHTTPSリダイレクトの要望が上がっており世界中のユーザーが待ち望んでいました。 https://issuetracker.google.com/issues/35904733
HTTPSリダイレクトを自分で実装する場合は内部でNginxを起動させてリダイレクトをさせるか、アプリケーション側でリダイレクトをする処理を埋め込む他なかったため非常にコストが高い作業となっていました。
GCLBにおけるHTTPSリダイレクトの仕組み
HTTPSリダイレクトには以下の2つの役割をもつロードバランサを定義することで実現を行なっています。
- 80ポートに来るHTTPトラフィックを受け取って301などのリダイレクトをするレスポンスを返すロードバランサ(図1上側)
- 443ポートに来るHTTPSトラフィックを受け取ってアプリケーションに流すロードバランサ(図1下側)
今回のポイントは「80ポートに来るHTTPトラフィックを受け取って302などを返すLB」です。 HTTPのリクエストは全てこのロードバランサへ流すようにします。 これまではHTTPトラフィックをバックエンドサーバーで処理していましたが、ロードバランサ側でトラフィックをリダイレクトすることにより、アプリケーションの負荷を下げることができます。 さらにアプリケーションに繋がるロードバランサでHTTPトラフィックを許可しなくてもよくなるのでアプリケーション自体のセキュリティを高めることができます。
このように2つのロードバランサを作ることによって今までに構築したロードバランサに手を入れることなくHTTPSリダイレクト機能を使えることも大きいですね。
gcloudコマンドを使ってHTTPSリダイレクトをする
httpのリダイレクト用の設定ファイルをつくる
今回はサンプルとして https-redirect
というurl-mapを作成するので、そのための設定ファイルを作成します。
yamlとして書くと以下のようになります。
kind: compute#urlMap name: https-redirect defaultUrlRedirect: redirectResponseCode: "MOVED_PERMANENTLY_DEFAULT" httpsRedirect: True
compute#urlMap
リソースにはGCLBのurl-mapに関する全ての設定を記述できます。
HTTPSリダイレクトを行うには defaultUrlRedirect
という設定を追加することで利用が可能です。
defaultUrlRedirect
にはリダイレクトをするときのResponseCodeを指定するredirectResponseCode
とHTTPSリダイレクトをするかどうかを決めるhttpsRedirect
という項目があります。
httpsRedirect
はHTTPSリダイレクトをさせたいので今回固定でtrue
にします。
redirectResponseCode
は以下のものから選ぶことができます。
この項目を指定しなかった場合のデフォルトは MOVED_PERMANENTLY_DEFAULT
(301)です。
FOUND
MOVED_PERMANENTLY_DEFAULT
PERMANENT_REDIRECT
SEE_OTHER
TEMPORARY_REDIRECT
上記で作成したyamlをもとにURL Mapを作成する
gcloud compute url-maps import
コマンドを使って先ほど作った設定ファイルを基にしたurl-mapを作成します。
ここで指定するurl-mapの名前はyamlで指定したnameと同じものを指定してください。
gcloud compute url-maps import https-redirect \ --source path/to/設定ファイル.yaml \ --global
target-http-proxiesを作る
forwarding-rulesとurl-mapsをつなぐためのtarget-http-proxiesを cloud compute target-http-proxies create
コマンドを使って作ります。
今回は例として http-lb-proxy
という名前にしてあります。
gcloud compute target-http-proxies create http-lb-proxy \ --url-map=https-redirect \ --global
リダイレクトさせるIPアドレスを指定する
実際にHTTPSへリダイレクトさせるIPアドレスをgcloud compute forwarding-rules create
コマンドを使って、先ほど作ったtarget-http-proxiesに紐付けます。
名前はtest-app-forwarding-rules
としましょう。
ここでHTTPのトラフィックを受け付けるため、--ports
に80番を指定します。
このforwarding-rulesは複数紐付けることができるので1つ作るだけで全てのサイトに対応させることができます。
このコマンドを実行する前には必ず静的IPアドレスの予約をしておいてください。
gcloud compute forwarding-rules create test-app-forwarding-rules \ --target-http-proxy=http-lb-proxy \ --address=[取得した静的IPアドレスの名前] \ --ports=80 \ --global
確認
指定したIPアドレスに紐付いているドメインへHTTPでリクエストするとHTTPSにリダイレクトされていることが確認できました。
Terraformを使う
今まで読んできた人には自動化のために毎回コマンドを叩かないといけないのか…みたいな気持ちになった人がいるかと思いますが、Terraformを使ってHTTPSリダイレクトのロードバランサを作ることができます。
Terraformのバージョンは2020/04/30現在の最新であるv0.12.24を使っています。
TerraformでHTTPSリダイレクトを構成するには Terraform Google Provider 3.20 以上のバージョンが必要です。
Terraformのコードを書く
基本的なコードの構成や手順はgcloud
コマンドを使う時と同じです。
まずTerraformのproviderを定義します。
provider "google" { version = ">= 3.20.0" project = "test-project" }
google-beta
のproviderでは先ほどファイルを移動した時に指定したバージョンを指定してください。
静的IPアドレスを作る
google_compute_global_address
を使って静的IPアドレスを予約します。
resource "google_compute_global_address" "default" { name = "test-address" }
url-mapを作る
url-mapはgoogle_compute_url_map
というリソースで作成できます。
google_compute_url_map
には default_url_redirect
というブロックがあるのでここにリダイレクトの設定を書いていきます。
redirect_response_code
の設定はgcloud
コマンドの時と同じものです。
ここではgoogle-beta
のproviderを使用するため、provider = google-beta
を追加してください。
resource "google_compute_url_map" "default" { name = "https-redirect" default_url_redirect { redirect_response_code = "MOVED_PERMANENTLY_DEFAULT" https_redirect = true } }
target-proxyを作る
google_compute_target_http_proxy
というリソースを使ってtarget-proxyを作ります。
url_map
には先ほど作ったgoogle_compute_url_map
リソースのself linkを指定します。
resource "google_compute_target_http_proxy" "default" { name = "https-redirect-proxy" url_map = google_compute_url_map.default.self_link }
forwarding-ruleを作る
forwarding-ruleはgoogle_compute_global_forwarding_rule
リソースを用いて作成します。
target
にはgoogle_compute_target_http_proxy
のself linkを、ip_address
にはgoogle_compute_global_address
のself linkを指定します。
HTTPのトラフィックを受け付けるため、port_range
に80番を指定します。
resource "google_compute_global_forwarding_rule" "default" { name = "website-forwarding-rule" target = google_compute_target_http_proxy.default.self_link ip_address = google_compute_global_address.default.address port_range = "80" }
terrafrom apply
をする
実際にできたTerraformのコードはこのようになりました。
provider "google" { version = ">= 3.20.0" project = "test-project" } resource "google_compute_global_address" "default" { name = "test-address" } resource "google_compute_global_forwarding_rule" "default" { name = "website-forwarding-rule" target = google_compute_target_http_proxy.default.self_link ip_address = google_compute_global_address.default.address port_range = "80" } resource "google_compute_target_http_proxy" "default" { name = "https-redirect-proxy" url_map = google_compute_url_map.default.self_link } resource "google_compute_url_map" "default" { name = "https-redirect" default_url_redirect { redirect_response_code = "MOVED_PERMANENTLY_DEFAULT" https_redirect = true } }
これをファイルに保存し、terraform apply
を実行することでHTTPSリダイレクトを行うロードバランサが作成されます。
リージョナルのロードバランサを作りたい場合
リージョナルのロードバランサを作りたい場合は以下のように書き換えると動いてくれます。
- resource "google_compute_global_address" "default" { + resource "google_compute_address" "default" { name = "test-address" + region = "us-central1" } - resource "google_compute_global_forwarding_rule" "default" { + resource "google_compute_forwarding_rule" "default" { name = "website-forwarding-rule" - target = google_compute_target_http_proxy.default.self_link - ip_address = google_compute_global_address.default.address + target = google_compute_region_target_http_proxy.default.self_link + ip_address = google_compute_address.default.address port_range = "80" + region = "us-central1" } - resource "google_compute_target_http_proxy" "default" { + resource "google_compute_region_target_http_proxy" "default" { name = "https-redirect-proxy" - url_map = google_compute_url_map.default.self_link + url_map = google_compute_region_url_map.default.self_link + region = "us-central1" } - resource "google_compute_url_map" "default" { + resource "google_compute_region_url_map" "default" { name = "https-redirect" + region = "us-central1" default_url_redirect { redirect_response_code = "MOVED_PERMANENTLY_DEFAULT" https_redirect = true } }
まとめ
pixivの広告配信システムではこのHTTPSリダイレクト機能を無停止で本番環境・開発環境を共に導入できました。 すでに動いているロードバランサを書き換えることなくHTTPSリダイレクトの機能を使えるよう設計されていたので本番のプロダクトに全く影響なく導入ができて感動しています。
GCLBにはHTTPSリダイレクトの他にもURLリダイレクトやURL rewriteなどの機能があります。より詳しく知りたい方は https://cloud.google.com/load-balancing/docs/https/setting-up-traffic-management を参考にすると良いでしょう。
広告開発チームではGCPの能力を無限に引き出せるエンジニアを募集しています。ここまで読んだあなたはきっとGCPがチョットデキルはずなのでご応募お待ちしております。