GKEにおけるGateway APIの基本を解説

記事タイトルとURLをコピーする

G-gen の佐々木です。当記事では、Kubernetes で展開しているサービスの外部公開用 API リソースである Gateway API について、特に GKE で使用する場合における基本的な仕様を解説します。

Gateway API の概要

Gateway API は、Kubernetes でレイヤ7の高度なトラフィックルーティングを提供するための Kubernetes アドオンであり、Ingress API 同様、レイヤ7ロードバランサーをデプロイすることでバックエンドのサービスを公開することができます。

GKE における Gateway API では、GKE クラスタで使用できる Cloud Load Balancing の各種アプリケーションロードバランサーを定義、デプロイすることができます。

Ingress API との違い

Ingress からの改良点

一般的に、Kubernetes では外部公開するアプリケーションにトラフィックをルーティングしたい場合、 Ingress を使用することができます。

Gateway は Ingress よりも後発の API リソースであり、以下のような改良が加えられています。

改良点 Ingress API の課題 Gateway API の特徴
ロール志向 1つのリソースにインフラの設定とアプリケーションのルーティング設定をまとめて定義する必要がある。そのため、インフラ担当者とアプリケーション開発者の責任範囲が曖昧になっている。 リソース定義を Gateway(インフラ定義)、HTTPRoute(ルーティング定義) のように分割することで、インフラ担当者とアプリケーション開発者がそれぞれの担当領域(ロール)でリソースを管理できる。
移植性・表現性 パスベース以外のルーティングなど、高度な機能はネイティブでサポートされておらず、GKE なら GKE 用の Ingress Controller が独自に定義したアノテーションを用いて実装する必要がある。 多くの高度な機能がネイティブでサポートされており、リソース定義がクラウドプロバイダーやオンプレミスなど環境に依存しない。
Namespace 間アクセス Ingress 単体の機能では、異なる Namespace にあるバックエンドサービスや Secret にアクセスすることができない。たとえばマイクロサービスごとに Namespace を割り当てている環境などで、1つの Ingress からそれぞれのサービスにルーティングするような構成ができない。 Gateway は異なる Namespace のリソースにアクセスすることができる。

GKE における違い

GKE における Ingress では、外部アプリケーションロードバランサー向けの Ingress と、内部アプリケーションロードバランサー用の Ingress を使用することができます。前者は Cloud Load Balancing の従来の外部アプリケーションロードバランサーを、後者は内部アプリケーションロードバランサーをデプロイします。

後述するように、Gateway API では GatewayClass により、新しい世代の(「従来の」ではない)外部アプリケーションロードバランサーや、マルチクラスタで利用できるロードバランサーをデプロイすることができるようになっています。

Google Cloud の Cloud Load Balancing を利用する場合、ロードバランサーの各コンポーネントと Ingress API、Gateway API の関係は以下の図のようになっています。

Cloud Load Balancing の各コンポーネントと Ingress API、Gateway API の関係

Gateway API のリソース

リソースの構成

Gateway API は主に以下のリソースから構成されます。

  • GatewayClass
  • Gateway
  • HTTPRoute

Gateway API の基本的なリソース構成

また、以下のような補助的なリソースがあります。

  • Policy
  • RefernceGrant

GatewayClass

Gateway から参照されるリソースで、クラスタに作成するロードバランサーのテンプレートとして機能します。GKE の場合、Google Cloud によってクラスタで利用できるロードバランサーが GatewayClass として事前定義されています。

以下は、GKE クラスタで利用可能な GatewayClass の例です。

GatewayClass の名前 対応する Cloud Load Balancing のロードバランサー
gke-l7-global-external-managed グローバル外部アプリケーションロードバランサ
gke-l7-regional-external-managed リージョン外部アプリケーションロードバランサ
gke-l7-rilb 内部アプリケーションロードバランサ
gke-l7-global-external-managed-mc マルチクラスタ用のグローバル外部アプリケーションロードバランサ
gke-l7-regional-external-managed-mc マルチクラスタ用のリージョン外部アプリケーションロードバランサ
gke-l7-rilb-mc マルチクラスタ用の内部アプリケーションロードバランサ

上記の GatewayClass の名前を Gateway のリソース定義で指定することで、対象のロードバランサーを作成することができます。

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: internal-http
spec:
  gatewayClassName: gke-l7-rilb  # 内部アプリケーションロードバランサを作成する
  listeners:
  - name: http
    protocol: HTTP
    port: 80

詳細な仕様やその他の GatewayClass については、以下の公式ドキュメントもご一読ください。

Gateway

トラフィックを処理するロードバランサーの種類(GatewayClass)、プロトコル、ポート、TLS 設定などを定義します。

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: external-http
spec:
  gatewayClassName: gke-l7-global-external-managed  # ロードバランサーの種類(GatewayClass)
  listeners:  # プロトコル、ポート、TLS 設定など、リスナーの設定
  - name: https
    protocol: HTTPS
    port: 443
    tls:
      mode: Terminate
      certificateRefs:
      - name: store-example-com

HTTPRoute

Gateway が受信したリクエストを、バックエンドの Service リソースにルーティングするためのルールを定義します。

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: store-external
  labels:
    gateway: external-http
spec:
  parentRefs:
  - name: external-http  # ルーティング設定を紐付ける Gateway リソースの名前
  hostnames:  # ルーティング設定を適用するホスト名
  - "store.example.com"
  rules:
  - backendRefs:  # Gateway が受信したリクエストをルーティングするバックエンドサービス
    - name: store-v1  # Service リソースの名前
      port: 8080

Policy

バックエンドサービスに対するヘルスチェックやトラフィック分散の方法、リクエストのタイムアウト、Identity-Aware Proxy や Cloud Armor バックエンドセキュリティポリシーの紐付けなどを定義します。

設定する Policy の種類によって、Policy リソースを Gateway リソースや Service リソースに対して紐付けます。

例えば以下のマニフェストファイルでは、Gateway リソースとして作成したロードバランサーに対する SSL ポリシーの紐付けが定義されています。

apiVersion: networking.gke.io/v1
kind: GCPGatewayPolicy
metadata:
  name: my-gateway-policy
  namespace: team1
spec:
  default:
    sslPolicy: gke-gateway-ssl-policy  # SSL ポリシーの名前
  targetRef:
    group: gateway.networking.k8s.io
    kind: Gateway
    name: my-gateway  # Policy を紐付ける Gateway リソースの名前

参考 : Configure Gateway resources using Policies

ReferenceGrant

Gateway や HTTPRoute が、異なる Namespace にあるバックエンドサービス、Secret などを参照できるようにするリソースです。

以下のマニフェストファイルは、frontend Namespace の HTTPRoute から backend Namespace の Service にトラフィックをルーティングできるような ReferenceGrant を定義しています。

apiVersion: networking.gke.io/v1
kind: ReferenceGrant
metadata:
  name: allow-frontend-to-access-backend
  namespace: backend  # Namespace間アクセスを許可するアクセス先のNamespace
spec:
  from:  # どこからのアクセスを許可するか
  - group: gateway.networking.k8s.io
    kind: HTTPRoute
    namespace: frontend
  to:  # 何に対するアクセスを許可するか
  - group: ""
    kind: Service

Gateway API を使ってみる

サンプル構成

当記事ではサンプル構成として、nginx をバックエンドサービスとする Gateway、HTTPRoute リソースを作成していきます。Gateway には Certificate Manager で作成した Google マネージド SSL 証明書を紐づけ、Gateway で作成されたロードバランサーに HTTPS でアクセスできるようにします。

当記事のサンプル構成

Gateway API の有効化

GKE クラスタで Gateway API が有効化されていない場合は有効化します。

# クラスタで Gateway API を有効化する
$ gcloud container clusters update <GKEクラスタ名> \
    --location=<クラスタのロケーション> \
    --gateway-api=standard

SSL 証明書の作成

Gateway API で作成するロードバランサーで TLS を設定するために、Certificate Manager 管理の証明書を作成します。

当記事では Google マネージド SSL 証明書を使用します。

# Google マネージド SSL 証明書を作成する
$ gcloud certificate-manager certificates create my-cert \
    --domains="<使用するドメイン>" \
    --scope=DEFAULT
  
# 証明書マップを作成する
$ gcloud certificate-manager maps create my-cert-map
  
# 証明書マップのエントリーを作成する
$ gcloud certificate-manager maps entries create [ENTRY_NAME] \
    --map="my-cert-map" \
    --certificates="my-cert" \
    --hostname="<使用するドメイン>"

サンプル Pod、Service のデプロイ

サンプルアプリケーションとして、以下のマニフェストを使用して nginx の Pod と Service をデプロイします。

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-server
  template:
    metadata:
      labels:
        app: nginx-server
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
  
---
  
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx-server
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

Gateway のデプロイ

ロードバランサーのフロントエンドとして機能する Gateway リソースを作成します。

以下のサンプルマニフェストでは、先ほど作成した証明書を使用するグローバル外部アプリケーションロードバランサーを作成する Gateway リソースをデプロイします。

# gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: external-https-gateway
  annotations:
    networking.gke.io/certmap: "my-cert-map"  # 作成した証明書マップの名前
spec:
  gatewayClassName: gke-l7-global-external-managed  # グローバル外部アプリケーションロードバランサーを使用
  listeners:
  - name: https-listener
    protocol: HTTPS
    port: 443

デプロイした Gateway リソースは以下のコマンドで確認できます。

# デプロイした Gateway の確認
$ kubectl get gateways
NAME                     CLASS                            ADDRESS       PROGRAMMED   AGE
external-https-gateway   gke-l7-global-external-managed   xxx.xxx.xxx.xxx   True         74s

Google Cloud コンソールを確認すると、アプリケーションロードバランサーが作成されていることがわかります。

Gateway のデプロイ後、ロードバランサーが作成されている

DNS レコードの設定

使用するドメインに対して、先ほど kubectl get gateways コマンドで確認したロードバランサーの外部 IP アドレスを解決できる A レコードを作成します。

以下のスクリーンショットは、Cloud DNS を使用する場合のレコードの設定例です。

DNS で A レコードを設定する

HTTPRoute のデプロイ

Gateway が受信したトラフィックをバックエンドサービスにルーティングするために、HTTPRoute をデプロイします。

以下のサンプルマニフェストでは、バックエンドである nginx サービスの80番ポートにトラフィックをルーティングする HTTPRoute リソースを作成します。

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: nginx-http-route
spec:
  parentRefs:
  - name: external-https-gateway  # Gatewayリソースの名前
  hostnames:
  - "<使用するドメイン>"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: nginx-service  # バックエンドの Service の名前
      port: 80

デプロイした HTTPRoute リソースは以下のコマンドで確認できます。

$ kubectl get httproutes
NAME               HOSTNAMES               AGE
nginx-http-route   ["<使用するドメイン>"]   13s

動作確認

作成した Gateway 関連リソースは、GKE のコンソールからも確認することができます。

GKE コンソールから Gateway の設定を確認する

それでは、使用しているドメインに対して、curl コマンドやブラウザから HTTPS でアクセスしてみます。

Gateway API で作成したアプリケーションロードバランサー経由で、HTTPS でバックエンドサービスにアクセスできています。

Gateway API で作成したロードバランサー経由で HTTPS アクセスができている

佐々木 駿太 (記事一覧)

G-gen 最北端、北海道在住のクラウドソリューション部エンジニア

2022年6月に G-gen にジョイン。Google Cloud Partner Top Engineer に選出(2024 / 2025 Fellow / 2026)。好きな Google Cloud プロダクトは Cloud Run。

趣味はコーヒー、小説(SF、ミステリ)、カラオケなど。