K8s Gateway APIがIngressに代わる?2026年サービスメッシュトラフィック管理完全移行ガイド
K8s Gateway APIがIngressに代わる?2026年サービスメッシュトラフィック管理完全移行ガイド
まだIngressにアノテーションを大量に書いてトラフィック管理していますか?カナリアデプロイのたびにnginx.ingress.kubernetes.io/canaryの構文をドキュメントで探していますか?マルチクラスタシナリオでのIngressのクラスタ間ルーティングに悩まされていますか?2026年、Kubernetes Gateway APIはGA安定版となり、Ingressの混乱の時代に別れを告げる時です。
背景知識
Ingressの限界
IngressはKubernetes 1.1から導入され、クラスタイングレストラフィック管理の標準方式でした。しかし設計に根本的な欠陥があります:
| 次元 | Ingress | Gateway API |
|---|---|---|
| ロールモデル | ロール分離なし | 3ロール(インフラ/クラスタ運用/アプリ開発) |
| 拡張性 | アノテーション依存、コントローラ間非互換 | ネイティブ拡張、標準CRD |
| プロトコル対応 | 主にHTTP/HTTPS | HTTP、gRPC、TCP、UDP、TLS |
| トラフィックルーティング | 単層パスマッチ | 多層ルーティング(Gateway→Route→Backend) |
| マルチクラスタ | 非対応 | ネイティブ対応(MultiClusterService) |
| ステータス | v1安定だが進化停止 | GA、継続的イテレーション |
Gateway APIコアリソース
Gateway APIは3つのコアロールと対応リソースを定義します:
- GatewayClass:インフラ管理者がゲートウェイタイプを定義(StorageClass類推)
- Gateway:クラスタ運用者がゲートウェイインスタンスを定義(PVC類推)
- HTTPRoute/TCPRoute/GRPCRoute:アプリ開発者がルーティングルールを定義
問題分析
なぜIngressはサービスメッシュシナリオで力不足なのか?
根本原因:Ingressはインフラ設定とアプリルーティングルールを同じリソースに結合しています。サービスメッシュシナリオでは:
- 権限競合:運用はTLS証明書を設定、開発はルーティングルールを変更—同じIngressオブジェクトで操作
- アノテーション地獄:カナリア、トラフィックミラー、リトライポリシーは全てアノテーション依存、コントローラごとに構文が異なる
- クラスタ間のブラインドスポット:Ingressは他クラスタのサービスを認識できない
- プロトコル制限:gRPC、TCP長接続などの非HTTPプロトコル対応が不完全
ステップバイステップ:IngressからGateway APIへの移行
ステップ1:Gateway API CRDとIstioのインストール
# Gateway API標準CRDのインストール(v1.2.0+)
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yaml
# Istio 1.24+のインストール(Gateway API対応内蔵)
istioctl install --set profile=ambient --set values.pilot.env.ENABLE_GATEWAY_API=true
# GatewayClass登録の確認
kubectl get gatewayclass
# NAME CONTROLLER ACCEPTED AGE
# istio istio.io/gateway-controller True 1m
ステップ2:Gatewayインスタンスの定義
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: main-gateway
namespace: infra
annotations:
istio.io/traffic-policy: |
connectionPool:
http:
h2UpgradePolicy: UPGRADE
spec:
gatewayClassName: istio
listeners:
- name: http
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: Selector
selectorLabels:
gateway-access: "true"
- name: https
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: wildcard-cert
namespace: cert-manager
allowedRoutes:
namespaces:
from: All
- name: grpc
port: 15443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: grpc-cert
ステップ3:ルーティングルールの移行
IngressからGateway API HTTPRouteへ移行、ネイティブウェイトカナリア対応:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: api-route
namespace: app
spec:
parentRefs:
- name: main-gateway
namespace: infra
sectionName: https
hostnames:
- "app.example.com"
rules:
- backendRefs:
- name: api-v1
port: 8080
weight: 80
- name: api-v2
port: 8080
weight: 20
matches:
- path:
type: PathPrefix
value: /api
ステップ4:ヘッダーベースカナリアルーティング
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: api-canary-header
namespace: app
spec:
parentRefs:
- name: main-gateway
namespace: infra
hostnames:
- "app.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /api
headers:
- type: Exact
name: X-Canary
value: "true"
backendRefs:
- name: api-v2
port: 8080
- matches:
- path:
type: PathPrefix
value: /api
backendRefs:
- name: api-v1
port: 8080
ステップ5:マルチクラスタゲートウェイ設定
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ServiceImport
metadata:
name: api-v1-multi
namespace: app
spec:
type: ClusterSetIP
ports:
- port: 8080
resolution: DNS
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: MultiClusterService
metadata:
name: api-v1-global
namespace: app
spec:
serviceImport:
name: api-v1-multi
namespace: app
clusterBackends:
- cluster: us-west-1
weight: 60
- cluster: us-east-1
weight: 40
完全コード:Istio + Gateway APIプロダクション設定
# gateway-class.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: istio-production
spec:
controllerName: istio.io/gateway-controller
parametersRef:
group: ""
kind: ConfigMap
name: istio-gw-params
namespace: infra
---
# gateway-params.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: istio-gw-params
namespace: infra
data:
concurrency: "4"
proxy-config: |
connectionPool:
http:
maxRequestsPerConnection: 1000
h2UpgradePolicy: DEFAULT
tcp:
maxConnections: 10000
outlierDetection:
consecutive5xxErrors: 5
interval: 30s
baseEjectionTime: 30s
---
# gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: prod-gateway
namespace: infra
spec:
gatewayClassName: istio-production
listeners:
- name: http-public
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: All
- name: https-public
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: prod-wildcard-cert
allowedRoutes:
namespaces:
from: All
addresses:
- type: IPAddress
value: "10.0.1.100"
---
# http-route.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: app-route
namespace: app
spec:
parentRefs:
- name: prod-gateway
namespace: infra
sectionName: https-public
hostnames:
- "app.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /api/v2
headers:
- type: Exact
name: X-Canary
value: "true"
filters:
- type: RequestHeaderModifier
requestHeaderModifier:
add:
- name: X-Route-Tag
value: canary-v2
backendRefs:
- name: api-v2
port: 8080
weight: 100
- matches:
- path:
type: PathPrefix
value: /api/v2
backendRefs:
- name: api-v2
port: 8080
weight: 20
- name: api-v1
port: 8080
weight: 80
- matches:
- path:
type: PathPrefix
value: /api
backendRefs:
- name: api-v1
port: 8080
- matches:
- path:
type: PathPrefix
value: /health
backendRefs:
- name: api-v1
port: 8080
filters:
- type: RequestHeaderModifier
requestHeaderModifier:
set:
- name: X-Health-Check
value: "true"
---
# grpc-route.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
name: grpc-route
namespace: app
spec:
parentRefs:
- name: prod-gateway
namespace: infra
hostnames:
- "grpc.example.com"
rules:
- matches:
- method:
service: "com.example.api.UserService"
method: "GetUser"
backendRefs:
- name: user-service
port: 9090
- matches:
- method:
service: "com.example.api.OrderService"
backendRefs:
- name: order-service
port: 9090
落とし穴ガイド
落とし穴1:GatewayClass未登録でGatewayがバインドできない
現象:GatewayステータスがAccepted: False、ルーティングルールが有効にならない。
解決:IstioコントローラのGateway API対応を確認、ENABLE_GATEWAY_API=true環境変数をチェック、GatewayClassのcontrollerNameがIstio登録と一致することを確認。
落とし穴2:クロスネームスペースルートが拒否される
現象:HTTPRouteのparentRefsが他namespaceのGatewayを参照しているが、ルーティングが有効にならない。
解決:GatewayのallowedRoutesでクロスネームスペースルーティングを明示的に許可。from: AllまたはSelectorでターゲットnamespaceのラベルをマッチ。
落とし穴3:TLS証明書のクロスネームスペース参照失敗
現象:GatewayのHTTPSリスナーが他namespaceの証明書を参照。
解決:Gateway APIは証明書とGatewayが同じnamespaceであることを要求。cert-managerで証明書をコピー、またはIstioのistio.io/credential-nameアノテーションを使用。
落とし穴4:カナリアウェイトの合計が100でない
現象:weight 80と30(合計110)を設定、トラフィック分配が期待と異なる。
解決:Gateway APIのweightは相対値で合計100である必要はない。ただし理解と監視のため合計100を推奨。Istioは自動的に正規化。
落とし穴5:マルチクラスタServiceImport DNS解決失敗
現象:MultiClusterService作成成功、しかしクラスタ間トラフィックがルーティングできない。
解決:Istioのクラスタ間コントロールプレーン接続を確認(東西ゲートウェイのデプロイ)、ServiceImportのresolutionフィールドがDNSであることを確認。
エラートラブルシューティング
| # | エラーメッセージ | 原因 | 解決方法 |
|---|---|---|---|
| 1 | GatewayClass not found |
CRD未インストールまたはコントローラ未登録 | Gateway API CRDをインストール、Istio Gateway API対応確認 |
| 2 | no GatewayClass controller matching |
controllerName不一致 | GatewayClass.spec.controllerNameがIstio登録と一致するか確認 |
| 3 | route is not accepted by any Gateway |
parentRefs参照エラー | Gateway名、namespace、sectionNameを確認 |
| 4 | certificate not found |
TLS証明書不在またはクロスネームスペース | 証明書がGatewayと同じnamespaceにあることを確認 |
| 5 | port conflict on Gateway listener |
同一ポートに複数リスナー | ポートごとに1リスナーのみ、プロトコル設定を統合 |
| 6 | backendRef service not found |
対象Serviceが存在しない | Service名とnamespaceを確認 |
| 7 | HTTPRoute condition Accepted=False |
ルートがGatewayに拒否 | allowedRoutesポリシーとhostnameマッチングを確認 |
| 8 | Istio proxy not ready |
Sidecar/ztunnel未注入 | istio-injection=enabledラベルまたはambientモードを確認 |
| 9 | MultiClusterService endpoint empty |
クラスタ間ディスカバリ未動作 | 東西ゲートウェイ、コントロールプレーン接続性を確認 |
| 10 | GRPCRoute method match failed |
gRPCメソッドマッチ形式エラー | package.Service/Method形式を使用 |
高度な最適化
1. トラフィックミラーリング(Shadow Traffic)
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: mirror-route
namespace: app
annotations:
istio.io/traffic-mirror: |
mirror:
hostname: mirror-service
port: 8080
mirrorPercentage:
value: 10
spec:
parentRefs:
- name: prod-gateway
namespace: infra
rules:
- backendRefs:
- name: api-v1
port: 8080
2. コネクションプールとサーキットブレーカー
GatewayClassのparametersRef ConfigMapでグローバルコネクションプールポリシーを設定。
3. エラーレートベースの自動トラフィックシフト
PrometheusメトリクスとArgo Rolloutsを組み合わせ、エラーレートに基づく自動トラフィックシフトを実現。
4. Gateway API拡張ポリシー
policyRef(v1.3+)でリトライ、タイムアウト、サーキットブレーカーポリシーをルートから分離。
比較分析
| 次元 | Ingress + nginx-ingress | Ingress + Istio VS | Gateway API + Istio | Gateway API + Envoy GW |
|---|---|---|---|---|
| 設定複雑さ | 低(単一リソース) | 中(Ingress+VS) | 中(Gateway+Route) | 中(Gateway+Route) |
| ロール分離 | なし | 部分 | 完全 | 完全 |
| カナリアデプロイ | アノテーション | VirtualService | ネイティブweight | ネイティブweight |
| gRPC対応 | 限定アノテーション | ネイティブ | ネイティブGRPCRoute | ネイティブGRPCRoute |
| マルチクラスタ | 非対応 | 対応(設定必要) | ネイティブ対応 | 拡張必要 |
| トラフィックミラー | 非対応 | 対応 | アノテーション拡張 | 拡張ポリシー |
| コミュニティ活発度 | メンテナンスモード | 活発 | 非常に活発 | 活発 |
| 学習曲線 | 低 | 高 | 中 | 中 |
| プロダクション対応 | 成熟 | 成熟 | 2026 GA成熟 | 急速成熟中 |
まとめ
まとめ:Gateway APIは2026年にKubernetesトラフィック管理の事実上の標準となりました。Ingressと比較して、ロール分離、プロトコル拡張、マルチクラスタ対応などのコア優位性を提供します。移行パスは明確:CRDインストール→Gateway作成→Route移行。Istioは最も成熟したサービスメッシュ実装としてGateway API対応が最も充実しています。新規プロジェクトはGateway APIを直接使用、既存プロジェクトはサービスごとに段階的に移行可能—IngressとGateway APIは共存できます。
オンラインツール推奨
- YAML/JSONフォーマッター:/ja/json/format
- Base64エンコード/デコード(証明書処理):/ja/encode/base64
- curl to Code(APIテスト):/ja/dev/curl-to-code
ブラウザローカルツールを無料で試す →