このドキュメントでは、TLS パススルー用に構成された Kubernetes Gateway リソースをデプロイして、Google Kubernetes Engine(GKE)で Server Name Indication(SNI)ベースのルーティングを有効にする方法について説明します。このアプローチでは、クライアントとバックエンド Pod 間のエンドツーエンドの暗号化と相互 TLS(mTLS)が維持され、HTTP 以外の TLS ベースのプロトコルがサポートされ、IP アドレスが節約されます。
このドキュメントは、コンテナ化されたワークロードの暗号化されたネットワーキングを設計、デプロイ、管理するクラウド アーキテクト、ネットワーク スペシャリスト、デベロッパーを対象としています。一般的なロールとタスクの例の詳細については、一般的な GKE ユーザーのロールとタスクをご覧ください。
概要
GKE Gateway Controller は、レイヤ 7 HTTP および HTTPS アプリケーション ロードバランサに加えて、TLS パススルーで構成されたレイヤ 4 プロキシ ネットワーク ロードバランサ(TCP プロキシ ロードバランサ)をサポートしています。
TLS パススルーを使用すると、ロードバランサは TLS セッションを終端または復号しません。代わりに、クライアントが TLS handshake を開始すると、ロードバランサは暗号化されていない ClientHello メッセージを検査して、Server Name Indication(SNI)ホスト名を読み取ります。この SNI ホスト名に基づいて、ロードバランサは暗号化された未加工の TCP ストリームを適切なバックエンド Kubernetes Service にルーティングします。ここで、アプリケーション Pod は TLS を直接終端します。
Gateway API で TLS パススルーを使用すると、次のことができます。
- エンドツーエンドの暗号化を維持し、ゼロトラスト コンプライアンスをサポートする: ロードバランサに秘密鍵や平文データへのアクセス権を付与することなく、クライアントからバックエンド Pod へのトラフィックを完全に暗号化します。
- 相互 TLS(mTLS)認証を使用する: バックエンド アプリケーション レイヤでクライアントを直接認証します。
- IPv4 アドレスを節約する: 単一の Gateway IP アドレスとポート(
443など)を使用して、異なるドメインまたはサブドメインに複数の独立した TLS サービスを多重化します。 - HTTP 以外の TLS ベースのプロトコルをサポートする: ステートフル ワークロード、データベース、カスタム gRPC サービス、または TLS で実行される独自のプロトコルの暗号化されたトラフィックをルーティングします。
サポートされている GatewayClass
次の GKE GatewayClass は、TLS パススルー リスナーと TLSRoute リソースをサポートしています。
gke-l7-regional-external-managedgke-l7-regional-external-managed-mcgke-l7-rilbgke-l7-rilb-mcgke-l7-cross-regional-internal-managed-mc
GatewayClass の機能の完全な比較については、GatewayClass の機能をご覧ください。
始める前に
作業を始める前に、次のタスクが完了していることを確認してください。
- Google Kubernetes Engine API を有効にする。 Google Kubernetes Engine API を有効化
- このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化します。gcloud CLI をインストール済みの場合は、
gcloud components updateコマンドを実行して最新のバージョンを取得します。以前のバージョンの gcloud CLI では、このドキュメントのコマンドを実行できない場合があります。
- Gateway API が有効になっている GKE バージョン 1.35 以降を実行している既存の Autopilot クラスタまたは Standard クラスタがあることを確認します。クラスタを作成する場合は、Autopilot クラスタの作成をご覧ください。既存のクラスタで Gateway API を有効にするには、クラスタで Gateway API を有効にするをご覧ください。
- OpenSSL コマンドライン ツールがインストールされていることを確認します。このツールを使用して、サンプル アプリケーションの自己署名 TLS 証明書を生成します。
GKE Gateway コントローラの要件
- Gateway API は、VPC ネイティブ クラスタでのみサポートされます。
- リージョンまたはクロスリージョンの GatewayClass を使用している場合は、プロキシ専用サブネットを有効にする必要があります。
- クラスタで
HttpLoadBalancingアドオンが有効になっている必要があります。 - Istio を使用している場合は、Istio を次のいずれかのバージョンにアップグレードする必要があります。
- 1.15.2 以降
- 1.14.5 以降
- 1.13.9 以降
- 共有 VPC を使用している場合は、ホスト プロジェクトで、サービス プロジェクトの GKE サービス アカウントに
Compute Network Userロールを割り当てる必要があります。
制限事項
TLS パススルー Gateway リソースと TLSRoute リソースをデプロイする場合は、次の制限事項に注意してください。
- リスナーで
protocol: TLS設定を構成する場合は、tls.modeフィールドをPassthrough値に明示的に設定する必要があります。GKE は、TLSリスナーのデフォルトのTerminateモードをサポートしていません。 TLSリスナーでは、certificateRefsフィールドを設定しないでください。ゲートウェイ レベルのクライアント証明書の検証(spec.tls.frontendValidationフィールド)は、TLSリスナーには適用されません。mTLS を使用するには、バックエンドでクライアント証明書を検証します。TLSリスナーは、他のTLSリスナーとのみポートを共有できます。TLSリスナーと同じポートにHTTPリスナーまたはHTTPSリスナーを構成することはできません。TLSRoute.spec.hostnamesフィールドには、1 ~ 1,024 個の SNI ホスト名(正確なホスト名またはワイルドカード接頭辞(*.example.comなど))のリストを指定する必要があります。各エントリは 253 文字以下にする必要があります。また、IP アドレスにすることはできません。TLSRoute.spec.rulesフィールドには、最大 1 つのルールを構成できます。- 各ルールは 1 つの
backendRefエントリのみをサポートします。レイヤ 4 プロキシ バックエンドは、複数のバックエンド間での重み付けによるトラフィック分割をサポートしていません。 - 単一クラスタ GatewayClass は Service バックエンドのみをサポートし、マルチクラスタ GatewayClass は ServiceImport バックエンドのみをサポートします。
TLSRoute.spec.rules.backendRefsフィールドで、portフィールドを、コンテナポートではなく、ターゲット Service または ServiceImport リソースによって宣言されたポートに設定します。- TLSRoute リソースによって参照されるバックエンド Kubernetes Service(ServiceImport としてエクスポートされた Service を含む)は、ポート プロトコルに
TCP値を使用する必要があります。 - コントローラがこのタイプの構成を拒否するため、BackendTLSPolicy リソース、Identity-Aware Proxy、Google Cloud Armor セキュリティ ポリシーを TLSRoute バックエンドに接続することはできません。
- TLSRoute リソースによって参照される Service または ServiceImport に GCPBackendPolicy リソースを接続する場合は、
spec.protocolフィールドをTCP値に設定する必要があります(spec.protocolフィールドを省略すると、デフォルトでHTTP値が設定されます。これは HTTPRoute バックエンドにのみ適用されます)。Service または ServiceImport には、1 つのHTTPポリシーと 1 つのTCPポリシーを同時に接続できます。同じspec.protocol値を持つ複数のポリシーが同じ Service または ServiceImport をターゲットにしている場合、最も古いポリシーが優先され、新しいポリシーは接続されません。 spec.protocolフィールドがTCPに設定された GCPBackendPolicy リソースは、spec.defaultフィールドの次のフィールドのみをサポートします(ServiceImport リソースをターゲットとする場合は、代わりにspec.default.scopesフィールドでクラスタ、ゾーン、リージョンごとに最後の 3 つのフィールドを設定できます)。timeoutSecconnectionDraininglogging.enabledとlogging.sampleRatesessionAffinity.type(有効な値はCLIENT_IPまたはNONE)capacityScalerPercentbalancingMode: CONNECTIONmaxConnectionsPerEndpoint
他のフィールドを含む
TCPポリシーや、TCP専用フィールド(balancingMode: CONNECTIONとmaxConnectionsPerEndpoint)を含むHTTPポリシーは作成できません。Kubernetes API サーバーは、作成時にポリシーを拒否します。詳細については、ポリシーを使用してゲートウェイ リソースを構成するをご覧ください。HTTPRoute リソースと TLSRoute リソースの両方が同じ Service または ServiceImport を参照している場合、HealthCheckPolicy リソースをそのターゲットに接続すると、個別のデフォルト ヘルスチェックが置き換えられ、同じヘルスチェック構成が両方のルートのバックエンドに適用されます。ヘルスチェックを個別に構成するには(HTTPRoute バックエンドの
HTTPヘルスチェックや、TLSRoute バックエンドのSSLまたはTCPヘルスチェックなど)、ルートごとに個別の Service を作成し、各 Service に HealthCheckPolicy リソースを接続します。両方の Service で同じ Pod を選択できます。レイヤ 7 の機能(URL の書き換え、パスベースのルーティング、HTTP ヘッダー変換など)は、レイヤ 4 TCP プロキシ ロードバランサには適用されません。
プロキシ専用サブネットを構成する
リージョン Gateway には、デプロイする各リージョンにプロキシ専用サブネット(purpose=REGIONAL_MANAGED_PROXY)が必要です。1 つのプロキシ専用サブネットが、そのリージョン内のすべてのリージョン Envoy ベースのロードバランサにサービスを提供します。リージョンにプロキシ専用サブネットがまだない場合は、プロキシ専用サブネットを構成するをご覧ください。
静的 IP アドレスを予約する
Gateway をデプロイする前に、Gateway アドレスが変更されないようにリージョン静的 IP アドレスを予約し、サンプル ホスト名を解決できるようにします。静的 IP アドレスの作成手順については、リージョン外部 HTTP(S) Gateway を作成するをご覧ください。
TLS パススルー リスナーを使用して Gateway をデプロイする
このセクションの Gateway は、ポート 443 を共有する 2 つの TLS リスナーを構成します。各リスナーは異なる SNI ホスト名と一致し、パススルー モードで接続を、接続された TLSRoute リソースに転送します。
次のマニフェストを
store-gateway.yamlとして保存します。kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: store-tls spec: gatewayClassName: gke-l7-regional-external-managed listeners: # Accept TLS connections for store.example.com without decrypting them. - name: store protocol: TLS port: 443 hostname: "store.example.com" tls: mode: Passthrough allowedRoutes: kinds: - kind: TLSRoute # A second listener on the same port, selected by a different SNI name. - name: store-german protocol: TLS port: 443 hostname: "store-de.example.com" tls: mode: Passthrough allowedRoutes: kinds: - kind: TLSRoute addresses: - type: NamedAddress value: IP_ADDRESS_NAMEIP_ADDRESS_NAME は、予約した静的 IP アドレスの名前に置き換えます。
tlsブロックにはcertificateRefsフィールドがありません。Passthroughモードでは、TLS 証明書はロードバランサではなくバックエンド Pod にあります。Gateway マニフェストを適用します。
kubectl apply -f store-gateway.yamlGateway がプログラムされていることを確認します。
kubectl get gateway store-tlsロードバランサのプロビジョニングには数分かかります。出力は次のようになります。
NAME CLASS ADDRESS PROGRAMMED AGE store-tls gke-l7-regional-external-managed 35.118.32.224 True 53s
内部 Gateway を使用する
VPC ネットワーク内にトラフィックを維持するには、gatewayClassName フィールドの値を gke-l7-rilb に変更し、Gateway マニフェストから addresses フィールドを削除します。次に、GKE はリージョン内部プロキシ ネットワーク ロードバランサを作成し、クラスタ サブネットから内部 IP アドレスを割り当てます。このページの残りの手順は変更されていません。内部 IP アドレスはインターネットから到達できないため、同じ VPC ネットワーク内の Compute Engine インスタンスからテスト リクエストを送信します。
サンプル TLS アプリケーションをデプロイする
このセクションでは、ポート 8443 で TLS を終端する 2 つの NGINX Deployment(store-v1 と store-german)をデプロイします。各 Deployment は異なる TLS 証明書を提供し、受信した SNI ホスト名を報告します。これにより、SNI に基づいてルーティングが行われたことを確認できます。
各ホスト名の自己署名 TLS 証明書と秘密鍵を生成します。
openssl req -x509 -newkey rsa:2048 -nodes -sha256 -days 365 \ -keyout store.key -out store.crt \ -subj '/CN=store.example.com' \ -addext 'subjectAltName=DNS:store.example.com' openssl req -x509 -newkey rsa:2048 -nodes -sha256 -days 365 \ -keyout store-de.key -out store-de.crt \ -subj '/CN=store-de.example.com' \ -addext 'subjectAltName=DNS:store-de.example.com'本番環境では、認証局の証明書を使用します。自己署名証明書を使用すると、この例を自己完結型にできます。
次のコマンドを実行して、各証明書と鍵を Kubernetes Secret に保存します。
kubectl create secret tls store-cert \ --cert=store.crt --key=store.key kubectl create secret tls store-de-cert \ --cert=store-de.crt --key=store-de.key次のマニフェストを
store-tls-app.yamlとして保存します。apiVersion: v1 kind: ConfigMap metadata: name: store-nginx data: default.conf: | server { listen 8443 ssl; ssl_certificate /etc/nginx/ssl/tls.crt; ssl_certificate_key /etc/nginx/ssl/tls.key; default_type text/plain; # Report which Pod answered and which SNI name it received. return 200 "backend: $hostname\nsni: $ssl_server_name\n"; } --- apiVersion: apps/v1 kind: Deployment metadata: name: store-v1 spec: replicas: 2 selector: matchLabels: app: store-v1 template: metadata: labels: app: store-v1 spec: containers: - name: nginx image: nginx:1.27 ports: - containerPort: 8443 volumeMounts: - name: config mountPath: /etc/nginx/conf.d - name: cert mountPath: /etc/nginx/ssl readOnly: true volumes: - name: config configMap: name: store-nginx - name: cert secret: secretName: store-cert --- apiVersion: v1 kind: Service metadata: name: store-v1 spec: selector: app: store-v1 ports: - port: 443 targetPort: 8443 --- apiVersion: apps/v1 kind: Deployment metadata: name: store-german spec: replicas: 2 selector: matchLabels: app: store-german template: metadata: labels: app: store-german spec: containers: - name: nginx image: nginx:1.27 ports: - containerPort: 8443 volumeMounts: - name: config mountPath: /etc/nginx/conf.d - name: cert mountPath: /etc/nginx/ssl readOnly: true volumes: - name: config configMap: name: store-nginx - name: cert secret: secretName: store-de-cert --- apiVersion: v1 kind: Service metadata: name: store-german spec: selector: app: store-german ports: - port: 443 targetPort: 8443Service に
appProtocolフィールドは必要ありません。GKE は TLSRoute トラフィックを TCP としてバックエンドに転送するため、このフィールドは効果がありません。マニフェストをクラスタに適用します。
kubectl apply -f store-tls-app.yamlPod が実行されていることを確認します。
kubectl get pods -l 'app in (store-v1,store-german)'出力は次のようになります。
NAME READY STATUS RESTARTS AGE store-german-7d9f8c5b47-2xqkd 1/1 Running 0 41s store-german-7d9f8c5b47-h6tzn 1/1 Running 0 41s store-v1-6c4b9d8f65-kp8vr 1/1 Running 0 41s store-v1-6c4b9d8f65-wm2ls 1/1 Running 0 41s
SNI ベースのルーティング用に TLSRoute リソースをデプロイする
TLSRoute リソースは Gateway リスナーに接続し、ホスト名に一致する接続を単一のバックエンド サービスに転送します。
次のマニフェストを
store-tls-routes.yamlとして保存します。kind: TLSRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: store spec: parentRefs: - kind: Gateway name: store-tls sectionName: store hostnames: - "store.example.com" rules: - backendRefs: - name: store-v1 port: 443 --- kind: TLSRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: store-german spec: parentRefs: - kind: Gateway name: store-tls sectionName: store-german hostnames: - "store-de.example.com" rules: - backendRefs: - name: store-german port: 443sectionNameフィールドは、Gateway のターゲット リスナーを選択します。portフィールドには、コンテナポートではなく Service ポート(443)を指定します。TLSRoute マニフェストを適用します。
kubectl apply -f store-tls-routes.yamlGateway コントローラがルートを受け入れたことを確認します。
kubectl get tlsroute store -o yamlstatusフィールドは次のようになります。status: parents: - controllerName: networking.gke.io/gateway parentRef: name: store-tls sectionName: store conditions: - type: ResolvedRefs status: "True" reason: ResolvedRefs - type: Accepted status: "True" reason: Accepted - type: Reconciled status: "True" reason: ReconciliationSucceededReconciled条件は、Gateway コントローラが基盤となるGoogle Cloud リソースを作成したかどうかを報告する GKE 固有のステータス条件です。Gateway リスナーがルートを受け入れたことを確認します。
kubectl get gateway store-tls -o yamlstatus.listenersフィールドの各エントリは次のようになります。- name: store supportedKinds: - group: gateway.networking.k8s.io kind: TLSRoute attachedRoutes: 1 conditions: - type: ResolvedRefs status: "True" reason: ResolvedRefs - type: Accepted status: "True" reason: Accepted - type: Programmed status: "True" reason: Programmed
トラフィック ルーティングを確認する
GKE は、TLS handshake を完了して TLS パススルー バックエンドのヘルスチェックを行います。Pod が最初のヘルスチェックに合格するまでに数分かかることがあります。
Gateway の IP アドレスを取得します。
kubectl get gateway store-tls -o jsonpath='{.status.addresses[0].value}'各ホスト名にリクエストを送信します。GATEWAY_IP は、前の手順で取得した IP アドレスに置き換えます。
curl --resolve store.example.com:443:GATEWAY_IP \ --cacert store.crt https://store.example.com curl --resolve store-de.example.com:443:GATEWAY_IP \ --cacert store-de.crt https://store-de.example.com各レスポンスには、応答した Pod の名前と、到達した SNI ホスト名がエコーされます。
backend: store-v1-6c4b9d8f65-kp8vr sni: store.example.com backend: store-german-7d9f8c5b47-2xqkd sni: store-de.example.com各リクエストで異なる認証局ファイルが使用され、両方とも成功したため、各バックエンドは独自の証明書を提供しました。ロードバランサは、暗号化された接続を終端せずに転送しました。
クライアントが HTTP リクエストを送信する前に、TLS handshake 中にルーティングが行われることを確認します。
openssl s_client -connect GATEWAY_IP:443 \ -servername store-de.example.com </dev/null 2>/dev/null \ | openssl x509 -noout -subject出力には、
store-germanバックエンドの証明書が表示されます。subject=CN=store-de.example.com-servernameフラグの値のみを変更すると、返される証明書が変更され、ロードバランサが SNI のみに基づいてバックエンドを選択したことが確認されます。一致するリスナーがない SNI ホスト名を含むリクエストを送信します。
curl --resolve other.example.com:443:GATEWAY_IP \ https://other.example.comポート
443のリスナーが SNI ホスト名other.example.comと一致しないため、接続が閉じます。
バックエンド接続容量を構成する
TLSRoute リソースによって参照される GKE Service の場合、GKE Gateway コントローラは CONNECTION バランシング モードを使用して TCP バックエンド サービスを構成し、maxConnectionsPerEndpoint フィールドのデフォルト値を 100,000,000(1e8)に設定します。
Gateway コントローラはコンテナの同時接続数の上限を自動的に決定できないため、GCPBackendPolicy リソースを使用して maxConnectionsPerEndpoint フィールドのデフォルト値を 1 から 1,000,000,000 にオーバーライドできます。バックエンド Pod の最適な接続数の上限を決定するには、次の点を評価します。
- ソフトウェアの上限: サーバーまたはアプリケーションの構成(Apache
MaxRequestWorkersディレクティブ、NGINXworker_processes * worker_connections設定、TomcatmaxConnections属性、データベース接続プールの上限など)を確認します。 - 負荷テスト: 分離された Pod に対する同時接続数を徐々に増やしながら、CPU、メモリ、レイテンシ、ソケットまたはファイル記述子の上限をモニタリングします。
カスタム GCPBackendPolicy を適用する
TLSRoute バックエンド サービスの maxConnectionsPerEndpoint フィールドのデフォルト値をオーバーライドするには、spec.protocol フィールドを TCP に設定し、balancingMode フィールドを CONNECTION に設定した GCPBackendPolicy リソースを接続します。
次のマニフェストを
backend-policy.yamlとして保存します。apiVersion: networking.gke.io/v1 kind: GCPBackendPolicy metadata: name: store-v1-backend-policy spec: protocol: TCP default: balancingMode: CONNECTION maxConnectionsPerEndpoint: 1000 targetRef: group: "" kind: Service name: store-v1ポリシーを適用します。
kubectl apply -f backend-policy.yaml
バックエンド ポリシーの構成の詳細については、ポリシーを使用して Gateway リソースを構成するをご覧ください。
TLS パススルーのヘルスチェックを構成する
デフォルトでは、TLS パススルー TLSRoute リソースに関連付けられたバックエンド サービス の場合、GKE Gateway Controller は SSL タイプのヘルスチェックを自動的にプロビジョニングします。
プローバーからの SNI 拡張機能がない場合を処理する
TLS パススルー バックエンドのヘルスチェックを構成する場合は、 Google Cloud ヘルスチェック プローバーが TLS エンドポイントとどのようにやり取りするかを考慮する必要があります。
バックエンド アプリケーションで TLS handshake を完了するために有効な SNI ホスト名が必要な場合、デフォルトの SSL ヘルスチェックは失敗します。この問題を解決するには、次のいずれかの方法を使用します。
- フォールバック証明書を構成する: SNI 拡張機能なしで TLS 接続が到着したときに、デフォルトのフォールバック TLS 証明書を提供するようにバックエンド サーバーまたは Pod を構成します。
- HealthCheckPolicy で TCP ヘルスチェックを使用する: HealthCheckPolicy リソース(
config.typeフィールドをTCPに設定)を Service に接続して、未加工の TCP ポート接続を確認し、TLS handshake を回避します。
カスタム HealthCheckPolicy を適用する
カスタム ヘルスチェック パラメータを構成する場合、または TCP ヘルスチェックに切り替える場合は、HealthCheckPolicy リソースを使用します。
次のマニフェストを
health-check-policy.yamlとして保存します。apiVersion: networking.gke.io/v1 kind: HealthCheckPolicy metadata: name: store-health-check spec: default: checkIntervalSec: 10 timeoutSec: 5 healthyThreshold: 2 unhealthyThreshold: 3 config: type: TCP tcpHealthCheck: port: 8443 targetRef: group: "" kind: Service name: store-serviceポリシーを適用します。
kubectl apply -f health-check-policy.yaml
ヘルスチェックの構成の詳細については、ポリシーを使用して Gateway リソースを構成するをご覧ください。
高度な構成
このセクションでは、TLS パススルー ゲートウェイと TLSRoute リソースでサポートされている高度なルーティング パターン、マルチテナント構成、マルチクラスタ デプロイについて説明します。
ワイルドカード ホスト名の一致
TLSRoute リソースは、ホスト名のワイルドカード プレフィックス マッチングをサポートし、複数のルートが同じ受信トラフィックに一致する場合は、決定論的な優先順位ルールに従います。
次のマニフェストを保存して、ワイルドカード TLSRoute を定義します。
apiVersion: gateway.networking.k8s.io/v1
kind: TLSRoute
metadata:
name: wildcard-tls-route
spec:
parentRefs:
- name: store-tls
sectionName: store
hostnames:
- "*.example.com"
rules:
- backendRefs:
- name: store-v1
port: 443
優先順位と競合解決のルール
複数の TLSRoute リソースが同じ Gateway リスナーに接続し、重複するホスト名または同一のホスト名を要求する場合、GKE Gateway コントローラは、他の Gateway ルートと同じホスト名の特異性と作成タイムスタンプ ルールを使用して競合を解決します。
- ホスト名の完全一致(
store.example.comなど)は、ワイルドカード一致(*.example.comなど)よりも優先されます。また、長いワイルドカード一致は、より広範なワイルドカード一致(*.comなど)よりも優先されます。 - 2 つ以上の TLSRoute リソースがまったく同じホスト名を宣言している場合、作成タイムスタンプ(
metadata.creationTimestamp)が最も古いルートが優先されます。作成タイムスタンプが一致する場合は、辞書順で小さい<namespace>/<name>識別子が優先されます。Gateway Controller は、競合するルートを受け入れません。競合するルートは、Conflictedの理由でAccepted: False条件を報告します。
ルートの優先順位について詳しくは、ルートのマージ、優先度、検証をご覧ください。
ReferenceGrant を使用した Namespace をまたがるルーティング
マルチテナント環境では、一元化されたプラットフォーム チームがインフラストラクチャの名前空間(gateway-infra など)で Gateway を管理し、アプリケーション チームがデベロッパーの名前空間(store-ns など)で TLSRoute リソースと Service リソースを管理できます。
Gateway リスナーで、すべての Namespace(または選択した Namespace)からのルートを許可します。
apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: shared-tls-gateway namespace: gateway-infra spec: gatewayClassName: gke-l7-regional-external-managed listeners: - name: tls-passthrough protocol: TLS port: 443 tls: mode: Passthrough allowedRoutes: namespaces: from: All kinds: - kind: TLSRouteアプリケーション Namespace(
store-ns)で、gateway-infraNamespace の Gateway が TLSRoute リソースまたは Service リソースを参照できるようにする ReferenceGrant リソースを作成します。apiVersion: gateway.networking.k8s.io/v1beta1 kind: ReferenceGrant metadata: name: allow-gateway-infra namespace: store-ns spec: from: - group: gateway.networking.k8s.io kind: Gateway namespace: gateway-infra to: - group: "" kind: Serviceアプリケーションの名前空間(
store-ns)で、共有 Gateway を参照する TLSRoute リソースを作成します。apiVersion: gateway.networking.k8s.io/v1 kind: TLSRoute metadata: name: store-tls-route namespace: store-ns spec: parentRefs: - name: shared-tls-gateway namespace: gateway-infra sectionName: tls-passthrough hostnames: - "store.example.com" rules: - backendRefs: - name: store-service port: 443
マルチクラスタ TLS パススルー Gateway
フリート内の複数の GKE クラスタに TLS パススルーを使用するマルチクラスタ Gateway をデプロイできます。
- サポートされているマルチクラスタ GatewayClass(
gke-l7-regional-external-managed-mc、gke-l7-rilb-mc、gke-l7-cross-regional-internal-managed-mc)を使用します。 - ServiceExport リソースを使用して、フリート全体にバックエンド サービスをエクスポートします。
TLSRoute リソースで、ServiceImport リソースを使用してマルチクラスタ バックエンドを参照します。
apiVersion: gateway.networking.k8s.io/v1 kind: TLSRoute metadata: name: mc-store-tls-route spec: parentRefs: - name: mc-tls-gateway sectionName: tls-passthrough hostnames: - "store.example.com" rules: - backendRefs: - group: net.gke.io kind: ServiceImport name: store-service port: 443
マルチクラスタ Gateway の複数の IP アドレス
クロスリージョン マルチクラスタ Gateway をデプロイする場合(gke-l7-cross-regional-internal-managed-mc GatewayClass を使用する場合など)、spec.addresses フィールドに複数の IP アドレスを定義して、異なるリージョン間で内部 VIP を公開できます。
1 つの Gateway に複数の IP アドレスを構成すると、GKE Gateway コントローラは各 IP アドレスを個別の転送ルールに変換します。同時に、コントローラは共有ターゲット プロキシを参照し、同じ基盤となるルーティング構成を再利用します。コントローラは、基盤となる TLSRoute リソースに IP アドレスの数を乗算しません。これにより、ルートの重複と割り当ての枯渇を防ぐことができます。
次の例は、2 つのリージョンにエフェメラル IP アドレスが構成されたマルチクラスタ Gateway を示しています。
kind: Gateway
apiVersion: gateway.networking.k8s.io/v1
metadata:
name: internal-cross-region-tls-gateway
spec:
gatewayClassName: gke-l7-cross-regional-internal-managed-mc
addresses:
- type: networking.gke.io/ephemeral-ipv4-address/us-west1
value: "us-west1"
- type: networking.gke.io/ephemeral-ipv4-address/us-east1
value: "us-east1"
listeners:
- name: tls-passthrough
protocol: TLS
port: 443
tls:
mode: Passthrough
allowedRoutes:
kinds:
- kind: TLSRoute
内部マルチクラスタ Gateway のデプロイの詳細については、内部マルチクラスタ Gateway をデプロイするをご覧ください。
HTTP 接続の統合
RFC 7540(セクション 9.1.1)によると、次の両方の条件が満たされている場合、ウェブブラウザと HTTP/2 クライアントは、確立された TLS 接続を複数のリクエストに再利用できます。
- ターゲットのホスト名が同じ IP アドレスに解決される。
- サーバーから提示された TLS 証明書は、両方のホスト名に対して信頼できる。たとえば、
*.example.comなどのワイルドカード証明書やマルチドメインのサブジェクト代替名(SAN)を使用すると、1 つの証明書で複数のホスト名をカバーできます。
レイヤ 4 TCP プロキシ ロードバランサは、最初の TLS handshake の後に HTTP リクエスト ヘッダーを検査しないため、ロードバランサは、既存の接続を介して、最初に一致したバックエンド Pod に統合されたリクエストを転送します。
接続の結合に関する問題を回避するには:
- 重複しない個別の TLS 証明書を使用する: 同じ Gateway IP アドレスの背後で多重化された異なるバックエンド サービス間で、ワイルドカード証明書や共通の SAN ID を共有しないでください。
- HTTP 421 Misdirected Request を返す: HTTP
:authority(またはHost)ヘッダーを確認するようにバックエンド HTTPS サーバーを構成します。リクエストされたホストがサーバーの想定されるドメインと一致しない場合は、HTTP 421 Misdirected Requestステータス コードを返して、クライアントに新しい接続を開くよう促します。 - HTTP/2 ORIGIN フレームを有効にする: 配信元サーバーで RFC 8336 ORIGIN フレームのサポートを採用し、接続の再利用に有効なホスト名を明示的に宣言します。
クリーンアップ
このページで使用したリソースについて、 Google Cloud アカウントに課金されないようにするには、リソースを削除します。
TLSRoute リソースを削除します。
kubectl delete tlsroute store store-germanGateway リソースを削除します。
kubectl delete gateway store-tlsサンプルの Deployment、Service、Secret リソースを削除します。
kubectl delete -f store-tls-app.yaml kubectl delete secret store-cert store-de-cert
次のステップ
- GatewayClass の機能について学習する。
- Gateway のセキュリティについて確認する。
- ポリシーを使用して Gateway リソースを構成する方法を学習する。