Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

HTTPSリダイレクトの場当たり対応はもう不要

By Bernhard WeisshuhnJan 27, 20214 min read

このページはEnglishDeutschEspañolFrançaisItalianoPortuguêsでもご覧いただけます。

DoiT Internationalでクラウド全般のご支援をしていると、よく話題に上るテーマがいくつかあります。なかでも、前職時代から私につきまとってきた質問がこちらです。

「GKEの(デフォルトの)GCLB Ingressコントローラーで、HTTPトラフィックをHTTPSにリダイレクトする正しい方法は?」

これまでは、リダイレクト専用のバックエンドを別途用意するといった回避策をご提案するか、GCLBの高度なトラフィック管理機能を持たないサードパーティ製のIngressソリューションに頼るしかありませんでした。

ところが、Google CloudがGKE Ingressロードバランサーでのリダイレクトをネイティブサポートしたことで、状況は大きく変わりました。

本記事では次の点を取り上げます。

  • これがなぜ画期的なのか
  • これを活用してInfrastructure as Codeの運用をどのようにシンプル化できるか

Photo by Jamie Street on Unsplash

なぜ重要なのか

暗号化されていないHTTPは、もはや過去のものになりつつあります。AWSGCPといったクラウドプラットフォームの無料証明書サービスに加え、Let's EncryptZeroSSLBuyPass Go SSLなどの独立系プロバイダーも揃っている今、本番環境のフロントエンドロードバランサーでTLSを使わない理由はどこにもありません。

むしろ興味深いのは、ポート80をどう扱うか(あるいは扱わないか)という点です。ポートを閉じておき、ブラウザが次にポート443でTLSを試すのに任せる、という選択もあります。ただしこの方法は不要な遅延を招きますし、サイトを指す完全修飾のhttpリンクがどこかに紛れ込んでいれば、エラーページが表示されてしまいます。ブラウザがTLS接続を優先するようになり、さらに細かな調整ができるブラウザ拡張機能もあるとはいえ、ポート80を開けておく意義はあります。加えて、TLS接続を強制する仕組みとしてHTTP Strict Transport SecurityUpgrade Insecure Requests宣言の存在も忘れてはなりません。

ただし、ブラウザがこれらのディレクティブを認識するには、最低でも一度はダウンロードする必要があります。ブラウザにあらかじめハードコードされたhstsアドレスという限られたグループに含まれていない限り、これは避けられません。TLSが計算負荷をほぼ上乗せしなくなった現在、同じコンテンツを暗号化版と非暗号化版の両方で提供する理由はなく、むしろ避けるべき理由はいくつもあります。

多くのユースケースで望ましいのは、HTTPからHTTPSへのHTTPステータス301または308によるリダイレクトです。では、ローカルな小細工や追加のインフラ管理に頼らず、Kubernetesでこれをスマートに実現する方法はあるのでしょうか。

Kubernetes IngressでのHTTPSリダイレクト

HTTPポートからのリダイレクトは、本来Ingressコントローラーが担うべき仕事です。Ingress仕様の初期ベータ版ではingress.kubernetes.io/ssl-redirectというアノテーションに言及がありましたが、実際の実装は各コントローラー固有のカスタムアノテーションを通じてようやく広まっていきました。

定番のnginx Ingressコントローラーは、TLSが有効ならデフォルトでリダイレクトを行います。一方Google Cloudでは、GKEのデフォルトIngressコントローラーingress-gceGCLBロードバランサーを利用しています。GCLB自体は非常に優秀なのですが、HTTPからHTTPSへのリダイレクトには長らく対応していませんでした。これがついに、HTTPトラフィック管理におけるリダイレクトサポートの導入で解消されました。とはいえ、Ingress宣言の内側からこれを利用する方法は依然として用意されておらず、数多くの小細工や回避策、そして落胆を生み出していたのです。

そう、これまでは。🎉

対応するGKEバージョン

以下で紹介する手法が公式にサポートされるのはKubernetes 1.18.10-gke.600以降ですが、現在提供されている1.17.x-gke系でも動作します。stableリリースチャネルをお使いの場合は、クラスターを1.17系にアップグレードすることで利用可能になりますし、regularrapidチャネルであれば任意のバージョンで利用できます。

執筆時点で対応しているGKEバージョン

GKE IngressのSSLリダイレクト対応:FrontendConfig

そしてついに、GKEがHTTPSリダイレクトをネイティブにサポートしました。実装にはFrontendConfig CRDが用いられます(ちなみに、このCRDはSSLポリシーの管理にも使われます)。

リダイレクト時のHTTPステータスコードは5種類から選択できます。

以下はステータス308(恒久的リダイレクト)を使用した例です。

apiVersion: networking.gke.io/v1beta1
kind: FrontendConfig
metadata:
 name: my-frontend-config
spec:
 redirectToHttps:
   enabled: true
   responseCodeName: PERMANENT_REDIRECT

このFrontendConfigリソースとIngressオブジェクトの紐付けは、Ingress宣言のアノテーションキーnetworking.gke.io/v1beta1.FrontendConfigを通じて行います。

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  annotations:
    networking.gke.io/v1beta1.FrontendConfig: "my-frontend-config"
...

これを動作させるにはv1beta1のapiVersionを指定する必要がある点にご注意ください。今後、非ベータ版にもサポートが広がる見込みなので、将来のクラスターアップグレードに備えて宣言の内容をチェックしておくとよいでしょう。

より完全な動作例をGitHubで公開しています。この機能の設定方法の詳細は、GoogleのIngress Features公式ドキュメントをご覧ください。

関連情報

GCPがコミュニティ声に耳を傾け、長く待たれていたこの機能を実装してくれたことを心から嬉しく思います。2021年は、ローカルな小細工を一掃し、クリーンで宣言的かつ正攻法のアプローチで、暗号化なしのHTTPに別れを告げる年にしましょう!