2026年K8s Gateway API移行完全ガイド:IngressからGateway APIへ
2026年K8s Gateway API移行完全ガイド:IngressからGateway APIへ
もし2026年になってもKubernetes Ingressでクラスタートラフィックを管理しているなら、クラウドネイティブトラフィック管理の未来を見逃している。Gateway APIは2025年末にKubernetes GA APIとして正式になり、主要ベンダー(Istio、Contour、Traefik、Kong)が全面的にサポートしている。Ingressの設計上の欠陥——単一ロール、拡張性が低い、複雑なルーティングを表現できない——は、マイクロサービスの規模が爆発的に増加する今日、もはや受け入れられない。
Gateway APIは、Gateway、GatewayClass、HTTPRouteなどのロール分離APIを導入し、マルチチーム協調、マルチクラスター展開、トラフィック分割とミラーリングをサポートしている。本記事では、アーキテクチャ比較から始め、完全な移行ステップを提供し、トラフィック管理、マルチテナント、マルチクラスターのシナリオをカバーする。
なぜGateway APIがIngressに取って代わるのか?
| 比較項目 | Ingress | Gateway API |
|---|---|---|
| API成熟度 | GA(ただし進化は停止) | GA(2025.11) |
| ロール分離 | なし(すべてクラスター管理者が管理) | 3ロール(インフラ/クラスター/アプリ) |
| ルーティング表現力 | 限定的(path+host) | 強力(header/query/weight/mirror) |
| マルチプロトコルサポート | HTTP/HTTPSのみ | HTTP/TLS/TCP/UDP/gRPC |
| トラフィック分割 | annotation hackが必要 | ネイティブサポート(weightフィールド) |
| マルチテナント | サポートなし | ネイティブサポート(ネームスペース分離) |
| 拡張性 | annotationに依存 | ネイティブ拡張(PolicyAttachment) |
| クロスクラスター | サポートなし | Multi-cluster Gatewayをサポート |
核心の違い:Ingressはすべての設定を混在させるが、Gateway APIはロール分離を実現している——インフラチームがGatewayClassを管理し、運用チームがGatewayを管理し、開発チームがRouteを管理する。
一、アーキテクチャ比較
1.1 Ingressアーキテクチャ
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
rules:
- host: api.example.com
http:
paths:
- path: /v1/users(/|$)(.*)
pathType: Prefix
backend:
service:
name: user-service
port:
number: 8080
問題:すべての設定が1つのIngressオブジェクトに詰め込まれ、annotationが乱立し、異なるベンダーのannotationは互換性がない。
1.2 Gateway APIアーキテクチャ
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: istio
spec:
controllerName: istio.io/gateway-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: api-gateway
namespace: infra
spec:
gatewayClassName: istio
listeners:
- name: http
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
shared-gateway-access: "true"
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: user-route
namespace: app-team
spec:
parentRefs:
- name: api-gateway
namespace: infra
rules:
- matches:
- path:
type: PathPrefix
value: /v1/users
backendRefs:
- name: user-service
port: 8080
weight: 90
- name: user-service-canary
port: 8080
weight: 10
利点:ロールが明確——GatewayClassはプラットフォームチームが定義し、Gatewayは運用チームが設定し、HTTPRouteは開発チームが管理する。
二、ステップバイステップ移行ガイド
2.1 Gateway API CRDのインストール
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml
2.2 コントローラーのインストール(Istioの場合)
istioctl install --set profile=minimal
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: istio
spec:
controllerName: istio.io/gateway-controller
EOF
2.3 IngressからGateway+HTTPRouteへの移行
移行スクリプトの考え方:
for ingress in $(kubectl get ingress -A -o name); do
namespace=$(echo $ingress | cut -d'/' -f1 | cut -d'.' -f1)
name=$(echo $ingress | cut -d'/' -f2)
kubectl get $ingress -o yaml | python3 ingress2gateway.py > gateway-route.yaml
kubectl apply -f gateway-route.yaml
echo "Migrated $ingress, verify before deleting"
done
2.4 自動移行ツール
import yaml
import sys
def ingress_to_gateway_route(ingress_data):
metadata = ingress_data['metadata']
spec = ingress_data['spec']
gateway = {
'apiVersion': 'gateway.networking.k8s.io/v1',
'kind': 'Gateway',
'metadata': {
'name': f"{metadata['name']}-gateway",
'namespace': metadata.get('namespace', 'default'),
},
'spec': {
'gatewayClassName': 'istio',
'listeners': [],
},
}
routes = []
for rule in spec.get('rules', []):
host = rule.get('host', '*')
listener_name = f"http-{host.replace('.', '-')}" if host != '*' else 'http'
gateway['spec']['listeners'].append({
'name': listener_name,
'port': 80,
'protocol': 'HTTP',
'hostname': host if host != '*' else None,
})
for path in rule.get('http', {}).get('paths', []):
route = {
'apiVersion': 'gateway.networking.k8s.io/v1',
'kind': 'HTTPRoute',
'metadata': {
'name': f"{metadata['name']}-route",
'namespace': metadata.get('namespace', 'default'),
},
'spec': {
'parentRefs': [{'name': f"{metadata['name']}-gateway"}],
'rules': [{
'matches': [{
'path': {
'type': 'PathPrefix',
'value': path.get('path', '/'),
}
}],
'backendRefs': [{
'name': path['backend']['service']['name'],
'port': path['backend']['service']['port']['number'],
}],
}],
},
}
routes.append(route)
return gateway, routes
if __name__ == '__main__':
ingress = yaml.safe_load(sys.stdin)
gw, routes = ingress_to_gateway_route(ingress)
for doc in [gw] + routes:
print('---')
print(yaml.dump(doc, default_flow_style=False))
三、トラフィック管理
3.1 トラフィック分割(カナリアリリース)
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: canary-route
spec:
parentRefs:
- name: api-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /api/v2
backendRefs:
- name: api-v2-stable
port: 8080
weight: 95
- name: api-v2-canary
port: 8080
weight: 5
3.2 トラフィックミラーリング
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: HTTPRouteFilter
metadata:
name: mirror-filter
spec:
type: RequestMirror
requestMirror:
backendRef:
name: api-mirror
port: 8080
3.3 ヘッダーベースのルーティング
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: header-route
spec:
parentRefs:
- name: api-gateway
rules:
- matches:
- headers:
- type: Exact
name: X-Feature-Flag
value: new-ui
backendRefs:
- name: frontend-v2
port: 80
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: frontend-v1
port: 80
3.4 gRPCルーティング
apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
name: grpc-route
spec:
parentRefs:
- name: api-gateway
rules:
- matches:
- method:
service: "com.example.UserService"
method: "GetUser"
backendRefs:
- name: user-grpc-service
port: 50051
四、マルチクラスターとマルチテナント
4.1 マルチクラスターGateway
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: allow-cross-namespace
namespace: app-team
spec:
from:
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespace: infra
to:
- group: ""
kind: Service
4.2 マルチテナント分離
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: tenant-a-gateway
namespace: tenant-a
spec:
gatewayClassName: istio
listeners:
- name: http
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: Same
テナント分離戦略比較:
| 戦略 | 分離レベル | リソースオーバーヘッド | 管理の複雑さ | 適用シナリオ |
|---|---|---|---|---|
| 共有Gateway | Routeレベル | 低 | 低 | 小規模、信頼できるテナント |
| ネームスペース分離 | ネームスペースレベル | 中 | 中 | 中規模、一般的な分離 |
| 独立Gateway | Gatewayレベル | 高 | 高 | 大規模、厳密な分離要件 |
5つのよくある落とし穴
| # | 落とし穴 | 結果 | 解決策 |
|---|---|---|---|
| 1 | Ingressを削除してからGatewayを作成 | トラフィック中断 | まず並行稼働させ、検証後に削除 |
| 2 | HTTPRouteが他のネームスペースのGatewayを参照 | 認可が拒否される | ReferenceGrantを作成 |
| 3 | GatewayのallowedRoutesが厳密すぎる | Routeがバインドできない | ネームスペースセレクターを確認 |
| 4 | GatewayClassのパラメータを無視 | コントローラーの動作が期待と異なる | GatewayClassSpec.parametersRefを慎重に確認 |
| 5 | トラフィック分割のウェイト合計が100でない | 動作が未定義(実装依存) | ウェイト合計が100になることを確認 |
10のよくあるエラートラブルシューティング
| # | エラー現象 | 考えられる原因 | トラブルシューティング方法 |
|---|---|---|---|
| 1 | HTTPRouteのParents条件がAccepted: False |
Gatewayがそのネームスペースを許可していない | GatewayのallowedRoutesを確認 |
| 2 | トラフィックがバックエンドに到達しない | Routeマッチングルールが間違っている | kubectl describe httprouteでResolvedRefsを確認 |
| 3 | GatewayNotReady |
コントローラーがインストールされていないか実行されていない | GatewayClassとコントローラーPodを確認 |
| 4 | TLS証明書が有効にならない | 証明書Secretが存在しないか形式エラー | Secretのタイプがkubernetes.io/tlsであることを確認 |
| 5 | カナリアトラフィックの比率が正しくない | ウェイトの計算エラー | ウェイト合計が100で比率が正しいことを確認 |
| 6 | クロスネームスペース参照が拒否される | ReferenceGrantが不足 | クロスネームスペース参照を許可するReferenceGrantを作成 |
| 7 | GRPCRouteが有効にならない | GatewayリスナーにH2Cが設定されていない | protocol: HTTPのリスナーを追加しH2Cを有効化 |
| 8 | トラフィックミラーリングが動作しない | コントローラーがRequestMirrorをサポートしていない | コントローラー実装がこの拡張をサポートしていることを確認 |
| 9 | Gateway IPが割り当てられない | コントローラーにLBが設定されていない | コントローラーのServiceとLoadBalancerを確認 |
| 10 | 移行後にパフォーマンスが低下 | コントローラー設定が最適化されていない | IngressとGatewayのプロキシ設定を比較 |
おすすめツール
Gateway API移行プロセスで、以下のツールが設定やエンコードの問題処理に役立つ:
- JSONフォーマットツール — Gateway APIのStatusと条件情報をフォーマットし、ルーティングステータスのデバッグに便利
- Base64エンコードツール — TLS証明書と鍵のBase64エンコード、Kubernetes Secret用
- ハッシュ計算ツール — Gateway設定のバージョンフィンガープリントを生成、設定変更検出とロールバック判断用
まとめ:Gateway APIはIngressの「アップグレード版」ではなく、トラフィック管理の「再設計」である。3ロール分離により、プラットフォーム、運用、開発がそれぞれの役割を担う。ネイティブトラフィック分割により、カナリアリリースはもうannotation hackに依存しない。マルチプロトコルサポートにより、gRPCやTCPサービスも統一されたトラフィック管理を享受できる。2026年、Ingressはすでにメンテナンスモードに入り、Gateway APIが唯一の方向である。移行の核心原則:まず並行稼働、次に検証、最後に切り替え——一度に切り替えず、IngressとGateway APIをしばらく共存させ、トラフィックが正常であることを確認してからIngressを削除する。
ブラウザローカルツールを無料で試す →