- Authors
- Name
- なぜGateway APIがIngressを置き換えるのか
- 比較:Gateway API vs Ingress vs Service Mesh
- Gateway API CRDとコントローラのインストール
- HTTPRoute:コアコンセプトとパターン
- GRPCRoute:ネイティブgRPCトラフィック管理
- 段階的なIngress移行手順
- トラフィック分割とカナリアデプロイメント
- TLS終端パターン
- 本番環境トラブルシューティング
- 実装比較:Envoy Gateway vs NGINX Gateway Fabric vs Istio
- 実践パターン:マルチチームプラットフォーム
- まとめ
- 参考文献

なぜGateway APIがIngressを置き換えるのか
Kubernetes Ingressリソースは長年コミュニティに貢献してきましたが、その制約がモダンなワークロードのボトルネックとなりました。ベンダー固有のアノテーション、ネイティブgRPCサポートの欠如、ロール分離の不在、そして単一リソースに全てを詰め込む設計が、Gateway API誕生の原動力となりました。
Gateway API(v1.0でGA、GRPCRouteはv1.1.0でGA)は、ロール指向・プロトコル対応・ポータブルなネットワーキングモデルを導入します。v1.2では、GRPCRouteとReferenceGrantの旧v1alpha2バージョンがStandardチャネルとExperimentalチャネルの両方から削除され、成熟度と本番環境対応を示しています。
アーキテクチャ概要
┌─────────────────────────────────────────────────────────────────┐
│ クラスタ管理者 │
│ │
│ ┌──────────────┐ │
│ │ GatewayClass │ どのコントローラがGatewayを処理するか定義 │
│ └──────┬───────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ プラットフォーム / インフラチーム │
│ │ Gateway │ リスナー、TLS、許可ルートを設定 │
│ └──┬───┬───┬───┘ │
│ │ │ │ │
│ ▼ ▼ ▼ アプリケーション開発者 │
│ ┌────┐┌─────────┐┌──────────┐ │
│ │HTTP││GRPCRoute││TLSRoute │ サービスごとのルーティングを定義 │
│ │Route│└─────────┘└──────────┘ │
│ └─┬──┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────┐ │
│ │ バックエンドサービス / Pod │ │
│ └──────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
ロール分離モデル
| ロール | リソース | 責務 |
|---|---|---|
| インフラストラクチャプロバイダー | GatewayClass | ゲートウェイコントローラのデプロイと管理 |
| プラットフォームオペレーター | Gateway | リスナー、TLS終端、クロスネームスペースポリシーの設定 |
| アプリケーション開発者 | HTTPRoute、GRPCRoute | サービスごとのルーティングルール定義 |
この分離により、開発者はTLS証明書を扱う必要がなくなり、プラットフォームオペレーターはアプリケーションレベルのルーティングロジックを理解する必要がなくなります。
比較:Gateway API vs Ingress vs Service Mesh
| 機能 | Ingress | Gateway API | Service Mesh (Istio) |
|---|---|---|---|
| HTTPルーティング | 基本的なパス/ホスト | 高度(ヘッダー、クエリパラメータ、メソッド) | フルL7ルーティング |
| gRPCネイティブ | 非対応(アノテーションで回避) | 対応(GRPCRoute GA) | 対応 |
| TLS終端 | Ingressごと | Gatewayのリスナーごと | サイドカー/ウェイポイントごと |
| トラフィック分割 | アノテーションベース | ネイティブ(weightフィールド) | ネイティブ(VirtualServiceまたはHTTPRoute) |
| ロール分離 | なし | GatewayClass / Gateway / Route | 複雑なRBAC |
| クロスネームスペース | 制限的 | ReferenceGrant | ServiceEntry |
| TCP/UDPサポート | 非対応 | TCPRoute / UDPRoute | 対応 |
| ポータビリティ | アノテーション依存 | 適合性テストによりポータビリティ保証 | ベンダーロックインリスク |
| カナリア/Blue-Green | アノテーション必要 | ウェイトベースルーティング内蔵 | 内蔵 |
| East-Westトラフィック | 非対応 | 対応(GAMMAイニシアチブ) | 主要ユースケース |
Gateway API CRDとコントローラのインストール
ステップ1:Gateway API CRDのインストール
# Standard Channel CRDのインストール(HTTPRoute、GRPCRoute GAリソースを含む)
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yaml
# CRDのインストール確認
kubectl get crds | grep gateway
# 期待される出力:
# gatewayclasses.gateway.networking.k8s.io
# gateways.gateway.networking.k8s.io
# grpcroutes.gateway.networking.k8s.io
# httproutes.gateway.networking.k8s.io
# referencegrants.gateway.networking.k8s.io
# (オプション)Experimental ChannelのインストールでTCPRoute、TLSRoute、UDPRouteを追加
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/experimental-install.yaml
ステップ2:Gatewayコントローラのデプロイ
ニーズに合った実装を選択します。主要な選択肢:
# オプションA:Envoy Gateway
helm install eg oci://docker.io/envoyproxy/gateway-helm \
--version v1.3.0 \
-n envoy-gateway-system --create-namespace
# オプションB:NGINX Gateway Fabric
helm install ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric \
--version 2.4.2 \
-n nginx-gateway --create-namespace
# オプションC:Istio(Gateway APIサポート付き)
istioctl install --set profile=minimal
HTTPRoute:コアコンセプトとパターン
HTTPRouteはGateway APIの主力リソースです。HTTPおよびTLS終端済みHTTPS接続を、豊富なマッチング機能で処理します。
基本的なHTTPRoute設定
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: envoy-gateway
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: production
namespace: infra
spec:
gatewayClassName: envoy-gateway
listeners:
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- name: wildcard-tls
namespace: cert-manager
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
gateway-access: 'true'
- name: http
protocol: HTTP
port: 80
---
apiVersion: gateway.networking.k8s.io/v1
kind: ReferenceGrant
metadata:
name: allow-cert-ref
namespace: cert-manager
spec:
from:
- group: gateway.networking.k8s.io
kind: Gateway
namespace: infra
to:
- group: ''
kind: Secret
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: api-routes
namespace: app-team
spec:
parentRefs:
- name: production
namespace: infra
hostnames:
- 'api.example.com'
rules:
- matches:
- path:
type: PathPrefix
value: /v2/users
headers:
- name: X-API-Version
value: '2'
backendRefs:
- name: users-v2
port: 8080
weight: 90
- name: users-v3
port: 8080
weight: 10
- matches:
- path:
type: PathPrefix
value: /v2/users
backendRefs:
- name: users-v2
port: 8080
- matches:
- path:
type: PathPrefix
value: /healthz
backendRefs:
- name: health-service
port: 8080
応用:HTTPからHTTPSへのリダイレクトとリクエスト修正
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: redirect-to-https
namespace: app-team
spec:
parentRefs:
- name: production
namespace: infra
sectionName: http
hostnames:
- 'api.example.com'
rules:
- filters:
- type: RequestRedirect
requestRedirect:
scheme: https
statusCode: 301
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: api-with-modifications
namespace: app-team
spec:
parentRefs:
- name: production
namespace: infra
sectionName: https
hostnames:
- 'api.example.com'
rules:
- matches:
- path:
type: PathPrefix
value: /api
filters:
- type: RequestHeaderModifier
requestHeaderModifier:
add:
- name: X-Request-ID
value: 'generated-by-gateway'
remove:
- X-Internal-Debug
- type: URLRewrite
urlRewrite:
path:
type: ReplacePrefixMatch
replacePrefixMatch: /v1
backendRefs:
- name: api-backend
port: 8080
GRPCRoute:ネイティブgRPCトラフィック管理
GRPCRouteはgRPCトラフィックのファーストクラスサポートを提供します。HTTPRouteでパスマッチングを使ってgRPCをラップするのとは異なり、GRPCRouteはgRPCのサービス名とメソッド名を直接理解します。
GRPCRoute設定
apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
name: grpc-user-service
namespace: grpc-apps
spec:
parentRefs:
- name: production
namespace: infra
hostnames:
- 'grpc.example.com'
rules:
# gRPCサービス名によるルーティング
- matches:
- method:
service: com.example.UserService
method: GetUser
backendRefs:
- name: user-service
port: 50051
# ヘッダーマッチング付きサービス名ルーティング
- matches:
- method:
service: com.example.UserService
headers:
- name: x-canary
value: 'true'
backendRefs:
- name: user-service-canary
port: 50051
# その他のgRPCメソッドへのデフォルトルート
- matches:
- method:
service: com.example.UserService
backendRefs:
- name: user-service-stable
port: 50051
weight: 95
- name: user-service-canary
port: 50051
weight: 5
GRPCRoute vs HTTPRoute:gRPCでの使い分け
| シナリオ | 推奨 | 理由 |
|---|---|---|
| gRPCサービス/メソッドマッチング | GRPCRoute | ネイティブサポート、簡潔な構文 |
| パスマッチングのみのgRPC | HTTPRouteでも可 | パスベースのマッチングはよりシンプル |
| 同一ホストでHTTPとgRPCの混在 | HTTPRoute + GRPCRouteを分離 | 各ルートタイプがプロトコルを処理 |
| gRPC-Web(ブラウザクライアント) | HTTPRoute | gRPC-WebはHTTP/1.1フレーミングを使用 |
段階的なIngress移行手順
IngressからGateway APIへの移行は段階的に行うべきです。本番環境での一括切り替えは絶対に避けてください。
移行アーキテクチャ
┌──────────────────────┐
│ DNS / LB │
│ api.example.com │
└──────────┬───────────┘
│
┌──────────▼───────────┐
│ トラフィック分割 │
│ (DNS重み付けまたはLB) │
└──┬───────────────┬───┘
│ │
┌────────▼─────┐ ┌──────▼────────┐
│ Ingress │ │ Gateway │
│ (既存) │ │ (新規) │
│ │ │ │
│ nginx-ctrl │ │ envoy-gw │
└──────┬───────┘ └──────┬─────────┘
│ │
└────────┬────────┘
│
┌────────▼────────┐
│ 同一バックエンド │
│ サービス群 │
└─────────────────┘
フェーズ1:既存Ingressリソースの監査
# 全ネームスペースのIngressリソースを一覧表示
kubectl get ingress -A -o wide
# 分析用に全Ingressリソースをエクスポート
kubectl get ingress -A -o yaml > ingress-backup.yaml
# アノテーション依存関係の確認
kubectl get ingress -A -o json | \
jq -r '.items[] | .metadata.name + " -> " + (.metadata.annotations | keys | join(", "))'
# ingress2gatewayによる自動変換
# インストール: go install github.com/kubernetes-sigs/ingress2gateway@latest
ingress2gateway print --all-namespaces
フェーズ2:Ingressと並行してGatewayリソースを作成
# 既存のIngressと並行してGatewayをデプロイ
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: migration-gateway
namespace: infra
annotations:
purpose: 'ingress-migration-phase2'
spec:
gatewayClassName: envoy-gateway
listeners:
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- name: wildcard-tls
allowedRoutes:
namespaces:
from: All
フェーズ3:Ingressルールに対応するHTTPRouteを作成
# 進める前にGatewayがProgrammed状態であることを確認
kubectl get gateway migration-gateway -n infra -o jsonpath='{.status.conditions}'
# 期待値: type=Programmed, status=True
# 警告: GatewayがProgrammed=Trueを示すまでIngressリソースを削除しないでください
フェーズ4:段階的なトラフィック移行
# 各HTTPRouteを個別に検証
for route in $(kubectl get httproute -A -o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}{"\n"}{end}'); do
ns=$(echo $route | cut -d/ -f1)
name=$(echo $route | cut -d/ -f2)
echo "--- $ns/$name を確認中 ---"
kubectl get httproute $name -n $ns -o jsonpath='{.status.parents[*].conditions}' | jq .
done
# DNS切り替え前にcurlでテスト
GATEWAY_IP=$(kubectl get gateway migration-gateway -n infra \
-o jsonpath='{.status.addresses[0].value}')
curl -H "Host: api.example.com" https://$GATEWAY_IP/healthz --resolve "api.example.com:443:$GATEWAY_IP"
フェーズ5:Ingressリソースを一つずつ削除
# Ingressを一つずつ削除し、検証してから次に進む
kubectl delete ingress old-api-ingress -n app-team
# 直ちにサービスの到達性を確認
curl -f https://api.example.com/healthz || echo "ロールバックが必要です"
# ロールバックが必要な場合:
kubectl apply -f ingress-backup.yaml
トラフィック分割とカナリアデプロイメント
Gateway APIはウェイトベースのトラフィック分割により、カナリアデプロイメントをファーストクラスの機能として提供します。
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: canary-deployment
namespace: app-team
spec:
parentRefs:
- name: production
namespace: infra
hostnames:
- 'app.example.com'
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
# Stable:トラフィックの95%を受信
- name: app-stable
port: 8080
weight: 95
# Canary:トラフィックの5%を受信
- name: app-canary
port: 8080
weight: 5
段階的にトラフィックを移行する場合:
# カナリアのウェイトを段階的に増加
# 5% -> 10% -> 25% -> 50% -> 100%
# 各ステップでエラー率とレイテンシを確認
# カナリアメトリクスの監視(Prometheusの例)
# rate(http_requests_total{app="app-canary",code=~"5.."}[5m])
# / rate(http_requests_total{app="app-canary"}[5m])
TLS終端パターン
cert-managerとGatewayレベルTLS
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: secure-gateway
namespace: infra
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
gatewayClassName: envoy-gateway
listeners:
- name: https-wildcard
protocol: HTTPS
port: 443
hostname: '*.example.com'
tls:
mode: Terminate
certificateRefs:
- name: wildcard-example-com
- name: https-specific
protocol: HTTPS
port: 443
hostname: 'api.specific.com'
tls:
mode: Terminate
certificateRefs:
- name: api-specific-cert
- name: tls-passthrough
protocol: TLS
port: 8443
hostname: 'mtls.example.com'
tls:
mode: Passthrough
本番環境トラブルシューティング
一般的な障害ケースとリカバリ
問題1:Gatewayが「Programmedでない」状態で停止
# Gatewayのステータスコンディションを確認
kubectl describe gateway production -n infra
# 一般的な原因:
# 1. GatewayClassコントローラが実行されていない
kubectl get pods -n envoy-gateway-system
# 2. 無効なTLS証明書リファレンス
kubectl get secret wildcard-tls -n infra
# 3. リスナーの競合(重複するポート/ホスト名)
kubectl get gateway -A -o jsonpath='{range .items[*]}{.metadata.name}: {range .spec.listeners[*]}{.port}/{.hostname} {end}{"\n"}{end}'
問題2:HTTPRouteがGatewayにアタッチされない
# ルートのステータスを確認
kubectl get httproute api-routes -n app-team -o yaml | yq '.status'
# 一般的な原因:
# 1. クロスネームスペースのReferenceGrantが不足
kubectl get referencegrant -A
# 2. Gatewayリスナーでネームスペースが許可されていない
kubectl get ns app-team --show-labels
# ラベルがGatewayのallowedRoutesセレクタと一致することを確認
# 3. GatewayリスナーとHTTPRoute間のホスト名不一致
# HTTPRouteのホスト名はリスナーのホスト名のサブドメインであるか一致する必要がある
問題3:移行後の503エラー
# バックエンドのエンドポイントが正常か確認
kubectl get endpoints users-v2 -n app-team
# サービスポートがHTTPRouteのbackendRefポートと一致するか確認
kubectl get svc users-v2 -n app-team -o jsonpath='{.spec.ports}'
# ゲートウェイコントローラのログを確認
kubectl logs -n envoy-gateway-system -l app=envoy-gateway --tail=100
# Envoyプロキシ設定が正しく生成されたか検証
# (Envoy Gateway固有)
kubectl get envoyproxy -A
問題4:gRPCリクエストがUNAVAILABLEで失敗
# バックエンドがHTTP/2をサポートしているか確認
kubectl exec -it deploy/user-service -n grpc-apps -- \
grpcurl -plaintext localhost:50051 list
# Gatewayリスナーのプロトコルが正しいか確認
# gRPCにはHTTPS(TLS終端付き)が必要、
# またはコントローラがHTTP/2クリアテキスト(h2c)をサポートする必要がある
# GRPCRouteのステータスを確認
kubectl get grpcroute -A -o yaml | yq '.items[].status'
運用上の警告
Ingressリソースを一度に全て削除しないこと。 サービスを一つずつ移行し、各削除後に到達性を確認してください。
トラフィックをルーティングする前にGatewayのProgrammedステータスを必ず確認すること。 AcceptedだがProgrammedでないGatewayはデータプレーンがプロビジョニングされていません。
クロスネームスペース参照にはReferenceGrantが必須です。 これがないと、ネームスペースAのルートからネームスペースBのバックエンドやネームスペースCのシークレットを参照できません。
Gateway API v1.2ではv1alpha2 GRPCRouteが削除されました。 アップグレード前に、コントローラがv1 GRPCRouteをサポートしていることを確認してください。
kubectl get crds grpcroutes.gateway.networking.k8s.io -o jsonpath='{.spec.versions[*].name}'で確認できます。ウェイトベースの分割は最も近い整数に丸められます。 ウェイトを1と99に設定した場合、実際の分割はコントローラの実装によりわずかに異なる場合があります。
TLS PassthroughリスナーではHTTPヘッダーを検査できません。 ヘッダーベースのルーティングが必要な場合は、代わりにTLS Terminateモードを使用してください。
本番環境用ヘルスチェックスクリプト
#!/bin/bash
# gateway-health-check.sh
# Gateway APIの本番環境変更後に実行
set -euo pipefail
echo "=== Gatewayステータス ==="
kubectl get gateways -A -o custom-columns=\
'NAMESPACE:.metadata.namespace,NAME:.metadata.name,CLASS:.spec.gatewayClassName,PROGRAMMED:.status.conditions[?(@.type=="Programmed")].status,ACCEPTED:.status.conditions[?(@.type=="Accepted")].status'
echo ""
echo "=== HTTPRouteステータス ==="
kubectl get httproutes -A -o custom-columns=\
'NAMESPACE:.metadata.namespace,NAME:.metadata.name,HOSTNAMES:.spec.hostnames[*],ACCEPTED:.status.parents[*].conditions[?(@.type=="Accepted")].status'
echo ""
echo "=== GRPCRouteステータス ==="
kubectl get grpcroutes -A -o custom-columns=\
'NAMESPACE:.metadata.namespace,NAME:.metadata.name,ACCEPTED:.status.parents[*].conditions[?(@.type=="Accepted")].status' 2>/dev/null || echo "GRPCRouteが見つかりません"
echo ""
echo "=== ReferenceGrant一覧 ==="
kubectl get referencegrants -A
echo ""
echo "=== 残存Ingressリソース(移行完了後は空であるべき) ==="
kubectl get ingress -A
実装比較:Envoy Gateway vs NGINX Gateway Fabric vs Istio
| 機能 | Envoy Gateway | NGINX Gateway Fabric | Istio |
|---|---|---|---|
| データプレーン | Envoy Proxy | NGINX | Envoy(サイドカーまたはambient) |
| HTTPRoute | フルサポート | フルサポート | フルサポート |
| GRPCRoute | フルサポート | フルサポート | フルサポート |
| TLSRoute | サポート | サポート | サポート |
| TCPRoute / UDPRoute | サポート | 部分的 | サポート |
| カスタム拡張 | EnvoyProxy、BackendTrafficPolicy | SnippetsFilter | VirtualService、DestinationRule |
| East-West(メッシュ) | 主要フォーカスではない | なし | 主要な強み |
| レート制限 | BackendTrafficPolicy | RateLimitPolicy | EnvoyFilterまたはWASM |
| 最適な用途 | 純粋なIngress/Egressゲートウェイ | NGINX習熟チーム | フルサービスメッシュ + ゲートウェイ |
実践パターン:マルチチームプラットフォーム
# プラットフォームチームが共有Gatewayをデプロイ
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: platform-gateway
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: shared-gateway
namespace: platform
spec:
gatewayClassName: platform-gateway
listeners:
- name: https-web
protocol: HTTPS
port: 443
hostname: '*.web.example.com'
tls:
mode: Terminate
certificateRefs:
- name: web-wildcard
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
tier: web
- name: https-api
protocol: HTTPS
port: 443
hostname: '*.api.example.com'
tls:
mode: Terminate
certificateRefs:
- name: api-wildcard
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
tier: api
---
# チームAが独自のルートをデプロイ(TLSの知識不要)
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: team-a-frontend
namespace: team-a
spec:
parentRefs:
- name: shared-gateway
namespace: platform
sectionName: https-web
hostnames:
- 'app.web.example.com'
rules:
- backendRefs:
- name: frontend
port: 3000
---
# チームBがgRPCルートを独立してデプロイ
apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
name: team-b-grpc
namespace: team-b
spec:
parentRefs:
- name: shared-gateway
namespace: platform
sectionName: https-api
hostnames:
- 'payments.api.example.com'
rules:
- matches:
- method:
service: com.example.PaymentService
backendRefs:
- name: payment-grpc
port: 50051
まとめ
Kubernetes Gateway APIは、クラスタネットワーキングの管理方法における根本的な転換を表しています。主な要点:
- HTTPRouteはHTTP/HTTPSトラフィックの主要ルーティングリソースであり、豊富なマッチング、フィルタリング、トラフィック分割機能を備えています。
- GRPCRouteはアノテーションの回避策なしに、ネイティブなgRPCサービス/メソッドレベルのルーティングを提供します。
- Ingressからの移行は段階的に行うべきです:Gateway API CRDのインストール、コントローラのデプロイ、既存Ingressと並行してルートを作成、検証、そしてIngressリソースを一つずつ削除。
- ロール分離(GatewayClass、Gateway、Route)により、プラットフォームチームとアプリケーションチームが独立して作業できます。
- 本番トラフィックに依存する前に、Gatewayステータスが
Programmed: Trueを示すことを必ず確認してください。
エコシステムは成熟しています。Envoy Gateway、NGINX Gateway Fabric、Istioの全てが堅牢なGateway API実装を提供しています。既存のスタックとEast-West(メッシュ)機能の必要性に基づいて選択してください。