- はじめに
- Gateway API vs Ingress: アーキテクチャ比較
- 中核リソースの詳細
- IngressからGateway APIへのマイグレーション
- TLS設定と証明書管理
- トラフィック分割 (Traffic Splitting) と重みベースのルーティング
- 実務運用時の注意事項
- トラブルシューティング
- 障害事例と復旧手順
- マイグレーションチェックリスト
- おわりに
- 参考資料

はじめに
Kubernetesで外部トラフィックをクラスタ内部のサービスへルーティングする方法は、長らくIngressリソースが事実上の標準だった。しかしIngressは設計当初から単純なHTTPルーティングだけを想定していたため、プロダクション環境で求められる高度なルーティング、トラフィック分割、マルチプロトコル対応などの機能は、各コントローラごとのアノテーション(annotation)に依存せざるを得なかった。このため、Ingress NGINXで書いたアノテーションがTraefikやHAProxyでは動作しないという移植性(portability)の問題が慢性的に発生してきた。
Gateway APIは、こうした限界を根本的に解決するためにKubernetes SIG-Networkが設計した次世代のサービスネットワーキングAPIである。2023年10月のv1.0 GAを皮切りに、2024年11月のv1.2でWebSocket、タイムアウト、リトライ機能が追加され、2025年11月のv1.4でBackendTLSPolicyとReferenceGrantがStandard Channelへ昇格し、プロダクションレベルの完成度を備えるに至った。特にKubernetesコミュニティはIngress NGINXの公式サポート終了(End of Life)を2026年3月と宣言しており、それ以降はセキュリティパッチやバグ修正は提供されない。もはやGateway APIへのマイグレーションは選択ではなく必須になった。
この記事では、Gateway APIのアーキテクチャ原理から中核リソースの詳細、Ingressからのマイグレーション戦略、TLS設定、トラフィック分割、そして実務運用でのトラブルシューティングと障害復旧まで総合的に扱う。
Gateway API vs Ingress: アーキテクチャ比較
Ingressの限界
Ingressリソースは単一のリソースにロードバランサの設定とルーティング規則が混在している。クラスタ運用者とアプリケーション開発者の関心事が分離されず、高度な機能は標準化されていないアノテーションでしか実装できない。
Gateway APIの役割ベース設計
Gateway APIは 役割指向(Role-Oriented) の設計を採用し、インフラ提供者、クラスタ運用者、アプリケーション開発者の関心事を明確に分離する。
| 比較項目 | Ingress | Gateway API |
|---|---|---|
| リソース構造 | 単一のIngressリソース | GatewayClass、Gateway、HTTPRouteに分離 |
| 役割分離 | なし (1つのリソースに混在) | インフラ提供者 / クラスタ運用者 / 開発者に分離 |
| プロトコル対応 | HTTP/HTTPSのみ対応 | HTTP, HTTPS, TCP, UDP, gRPC, TLS に対応 |
| ルーティング機能 | ホスト/パスベースのみ対応 | ヘッダー、クエリパラメータ、メソッドのマッチに対応 |
| トラフィック分割 | アノテーション依存 (非標準) | ネイティブな重みベース分割 |
| TLS設定 | 基本的な終端のみ対応 | Terminate, Passthrough, BackendTLSPolicy |
| クロスネームスペース | 不可 | ReferenceGrantで安全に対応 |
| 移植性 | コントローラごとのアノテーションが必要 | 標準APIスペックで移植可能 |
| マルチテナンシー | 脆弱 | Gatewayごとのネームスペース隔離に対応 |
| 状態管理 | 限定的 | Accepted, Programmed, ResolvedRefs 条件 |
アーキテクチャ図
インフラ提供者 (Infrastructure Provider)
└─ GatewayClass: どのコントローラがGatewayを実装するかを定義
│
クラスタ運用者 (Cluster Operator)
└─ Gateway: リスナー(ポート、プロトコル、TLS)の設定
│
アプリケーション開発者 (Application Developer)
└─ HTTPRoute / GRPCRoute / TCPRoute: ルーティング規則の定義
│
└─ Service → Pod: 実際のトラフィック処理
中核リソースの詳細
1. GatewayClass
GatewayClassは クラスタスコープ のリソースで、インフラ提供者が定義する。どのコントローラがGatewayを管理するかを指定し、KubernetesのStorageClassと類似した役割を果たす。
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: envoy-gateway-class
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
description: 'Envoy Gateway ベースのプロダクション用ゲートウェイクラス'
主なコントローラごとのcontrollerNameの値:
| コントローラ | controllerName |
|---|---|
| Envoy Gateway | gateway.envoyproxy.io/gatewayclass-controller |
| NGINX Gateway Fabric | gateway.nginx.org/nginx-gateway-controller |
| Istio | istio.io/gateway-controller |
| Cilium | io.cilium/gateway-controller |
| Traefik | traefik.io/gateway-controller |
| Kong | konghq.com/kic-gateway-controller |
2. Gateway
Gatewayは ネームスペーススコープ のリソースで、クラスタ運用者が管理する。リスナー(Listener)を通じてトラフィックが入ってくるポート、プロトコル、ホスト名、TLS設定を定義する。
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: production-gateway
namespace: gateway-infra
annotations:
cert-manager.io/cluster-issuer: 'letsencrypt-prod'
spec:
gatewayClassName: envoy-gateway-class
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: All
- name: https
protocol: HTTPS
port: 443
hostname: '*.example.com'
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: wildcard-tls-cert
namespace: gateway-infra
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
gateway-access: 'enabled'
allowedRoutesの設定は、マルチテナンシー環境において中核的なセキュリティ境界を形成する。from: AllはすべてのネームスペースのRouteがこのリスナーにバインドでき、from: Selectorは特定のラベルを持つネームスペースだけを許可する。
3. HTTPRoute
HTTPRouteはアプリケーション開発者が管理するルーティング規則のリソースである。パスマッチ、ヘッダーフィルタリング、トラフィック分割、リダイレクト、URL書き換えなど豊富な機能を標準APIとして提供する。
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: api-route
namespace: backend-app
spec:
parentRefs:
- name: production-gateway
namespace: gateway-infra
sectionName: https
hostnames:
- 'api.example.com'
rules:
- matches:
- path:
type: PathPrefix
value: /v2/users
headers:
- name: X-API-Version
value: '2'
filters:
- type: RequestHeaderModifier
requestHeaderModifier:
add:
- name: X-Forwarded-By
value: 'gateway-api'
backendRefs:
- name: users-service-v2
port: 8080
weight: 100
- matches:
- path:
type: PathPrefix
value: /v1
backendRefs:
- name: api-service-v1
port: 8080
weight: 90
- name: api-service-v2
port: 8080
weight: 10
4. ReferenceGrant (クロスネームスペース参照)
Gateway APIではクロスネームスペース参照はデフォルトで遮断される。ReferenceGrantを通じて明示的に許可する必要がある。v1.4でv1へ昇格したこのリソースは、セキュリティ境界を保ちながら柔軟な構成を可能にする。
apiVersion: gateway.networking.k8s.io/v1
kind: ReferenceGrant
metadata:
name: allow-gateway-to-backend-secrets
namespace: gateway-infra
spec:
from:
- group: gateway.networking.k8s.io
kind: Gateway
namespace: gateway-infra
to:
- group: ''
kind: Secret
IngressからGateway APIへのマイグレーション
マイグレーション戦略の概要
マイグレーションは必ず 段階的に 進める必要がある。Gateway APIコントローラは既存のIngressコントローラと同一クラスタで並行して実行できるため、サービスごとに段階的に切り替えながら検証するのが安全だ。
1段階: Gateway API CRDおよびコントローラのインストール
# Gateway API標準CRDのインストール (v1.4.x)
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.1/standard-install.yaml
# 実験的機能を含むインストール (TCPRoute, UDPRoute, BackendTLSPolicyを含む)
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.1/experimental-install.yaml
# CRDインストールの確認
kubectl get crd | grep gateway.networking.k8s.io
# 出力例:
# gatewayclasses.gateway.networking.k8s.io
# gateways.gateway.networking.k8s.io
# httproutes.gateway.networking.k8s.io
# referencegrants.gateway.networking.k8s.io
# grpcroutes.gateway.networking.k8s.io
コントローラのインストールは選択した実装によって異なる。Envoy Gatewayの例:
# Envoy Gatewayのインストール
helm install envoy-gateway oci://docker.io/envoyproxy/gateway-helm \
--version v1.3.0 \
-n envoy-gateway-system \
--create-namespace
# インストールの確認
kubectl get pods -n envoy-gateway-system
kubectl get gatewayclass
2段階: ingress2gatewayツールを活用した自動変換
ingress2gatewayツールは既存のIngressリソースを解析してGateway APIリソースへ自動変換する。ただし、アノテーションの約30~40%は手動での変換が必要なため、必ず出力結果を確認する必要がある。
# ingress2gatewayのインストール
go install github.com/kubernetes-sigs/ingress2gateway@latest
# 現在のクラスタのIngressリソースを変換
ingress2gateway print --providers ingress-nginx \
--all-namespaces > gateway-resources.yaml
# 変換されたリソースの確認 (必ず手動での確認が必須)
cat gateway-resources.yaml
# 変換されたリソースをまずステージング環境へ適用
kubectl apply -f gateway-resources.yaml --dry-run=server
kubectl apply -f gateway-resources.yaml -n staging
3段階: 並行運用とトラフィックの切り替え
既存のIngressとGateway APIを同時に運用しながら、サービスごとに段階的に切り替える。
# Gatewayの状態確認 - Programmed: True の確認が必須
kubectl get gateway production-gateway -n gateway-infra -o jsonpath='{.status.conditions}'
# HTTPRouteの状態確認
kubectl get httproute -A
# DNSをGateway APIエンドポイントへ変更する前のテスト
GATEWAY_IP=$(kubectl get gateway production-gateway -n gateway-infra \
-o jsonpath='{.status.addresses[0].value}')
curl -H "Host: api.example.com" https://$GATEWAY_IP/v1/health --resolve "api.example.com:443:$GATEWAY_IP"
# 正常を確認した後にDNSを変更 (CNAMEまたはAレコード)
# すべてのサービスの切り替えが完了した後に既存のIngressリソースを削除
kubectl delete ingress api-ingress -n backend-app
4段階: 既存Ingressの整理
すべてのサービスがGateway APIへ切り替わった後、既存のIngressコントローラを整理する。必ずサービスごとに1つずつ削除しながらアクセス可否を確認する必要がある。
# Ingressリソースを1つずつ削除しながら検証
kubectl delete ingress api-ingress -n backend-app
# ただちにサービスへのアクセスをテスト
curl -I https://api.example.com/v1/health
# すべてのIngressの削除を確認してからコントローラを削除
kubectl get ingress -A # 残っているIngressがないか確認
helm uninstall ingress-nginx -n ingress-nginx
kubectl delete namespace ingress-nginx
TLS設定と証明書管理
Downstream TLS (クライアント - Gateway 区間)
GatewayのリスナーでTLS終端(Terminate)を設定する。cert-managerと連携すれば証明書の発行と更新を自動化できる。
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: tls-gateway
namespace: gateway-infra
annotations:
cert-manager.io/cluster-issuer: 'letsencrypt-prod'
spec:
gatewayClassName: envoy-gateway-class
listeners:
- name: https-wildcard
protocol: HTTPS
port: 443
hostname: '*.example.com'
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: wildcard-example-tls
allowedRoutes:
namespaces:
from: All
- name: https-specific
protocol: HTTPS
port: 443
hostname: 'admin.internal.com'
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: admin-tls-cert
allowedRoutes:
namespaces:
from: Same
cert-managerはGatewayリソースのアノテーションを検知して自動でCertificateリソースを作成し、発行された証明書をcertificateRefsに指定されたSecretへ保存する。証明書の有効期限の30日前に自動更新が行われる。
Upstream TLS (Gateway - バックエンド区間)
v1.4でStandard Channelへ昇格したBackendTLSPolicyを使うと、GatewayからバックエンドPodまでのTLS接続を設定できる。これにより端から端までの暗号化(end-to-end encryption)を実装する。
apiVersion: gateway.networking.k8s.io/v1alpha3
kind: BackendTLSPolicy
metadata:
name: backend-tls
namespace: backend-app
spec:
targetRefs:
- group: ''
kind: Service
name: secure-backend-service
validation:
caCertificateRefs:
- name: backend-ca-cert
group: ''
kind: ConfigMap
hostname: secure-backend.backend-app.svc.cluster.local
BackendTLSPolicyと対象のServiceは必ず同一のネームスペースになければならない。クロスネームスペースのBackendTLSPolicyは信頼境界の問題により対応していない。
TLS Passthrough
GatewayがTLSを終端せず、バックエンドまでそのまま転送するモードである。バックエンドのアプリケーションが自前でTLSを処理する必要があるときに使う。
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: passthrough-gateway
namespace: gateway-infra
spec:
gatewayClassName: envoy-gateway-class
listeners:
- name: tls-passthrough
protocol: TLS
port: 443
hostname: 'secure-app.example.com'
tls:
mode: Passthrough
allowedRoutes:
namespaces:
from: All
トラフィック分割 (Traffic Splitting) と重みベースのルーティング
カナリアデプロイのトラフィック分割
HTTPRouteのbackendRefsに重み(weight)を設定して、トラフィックを比率に応じて分配できる。重みは比率(proportion)なので合計が100である必要はなく、全体の重みの合計に対する各バックエンドの比率で計算される。
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: canary-route
namespace: backend-app
spec:
parentRefs:
- name: production-gateway
namespace: gateway-infra
hostnames:
- 'app.example.com'
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
# 安定版: 90%のトラフィック
- name: app-stable
port: 8080
weight: 90
# カナリア版: 10%のトラフィック
- name: app-canary
port: 8080
weight: 10
段階的なトラフィック切り替えスクリプト
カナリアデプロイ時にトラフィックの比率を段階的に調整する自動化スクリプトの例である。
#!/bin/bash
# カナリアトラフィックを段階的に増やすスクリプト
ROUTE_NAME="canary-route"
NAMESPACE="backend-app"
STAGES=(10 25 50 75 100)
WAIT_MINUTES=5
for canary_weight in "${STAGES[@]}"; do
stable_weight=$((100 - canary_weight))
echo "[$(date)] カナリアトラフィックの比率: ${canary_weight}%"
kubectl patch httproute $ROUTE_NAME -n $NAMESPACE --type='json' \
-p="[
{\"op\": \"replace\", \"path\": \"/spec/rules/0/backendRefs/0/weight\", \"value\": $stable_weight},
{\"op\": \"replace\", \"path\": \"/spec/rules/0/backendRefs/1/weight\", \"value\": $canary_weight}
]"
echo "待機 ${WAIT_MINUTES}分... (エラー率のモニタリング)"
sleep $((WAIT_MINUTES * 60))
# エラー率の確認 (Prometheusクエリの例)
ERROR_RATE=$(kubectl exec -n monitoring prometheus-0 -- \
promtool query instant \
'rate(http_requests_total{service="app-canary",code=~"5.."}[5m]) / rate(http_requests_total{service="app-canary"}[5m]) * 100' \
2>/dev/null | grep -oP '[0-9.]+' | head -1)
if (( $(echo "$ERROR_RATE > 5" | bc -l 2>/dev/null) )); then
echo "エラー率 ${ERROR_RATE}% を超過! ロールバックを実行"
kubectl patch httproute $ROUTE_NAME -n $NAMESPACE --type='json' \
-p='[
{"op": "replace", "path": "/spec/rules/0/backendRefs/0/weight", "value": 100},
{"op": "replace", "path": "/spec/rules/0/backendRefs/1/weight", "value": 0}
]'
echo "ロールバック完了。カナリアデプロイを中断。"
exit 1
fi
done
echo "カナリアデプロイ完了。トラフィックの100%切り替えに成功。"
ヘッダーベースのトラフィック分割
特定のヘッダーを持つリクエストだけを新しいバージョンへルーティングし、QAチームや社内ユーザーが先に検証できるようにする。
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: header-based-route
namespace: backend-app
spec:
parentRefs:
- name: production-gateway
namespace: gateway-infra
hostnames:
- 'app.example.com'
rules:
# 規則1: X-Canaryヘッダーがあればv2へルーティング
- matches:
- headers:
- name: X-Canary
value: 'true'
backendRefs:
- name: app-v2
port: 8080
# 規則2: デフォルトのトラフィックはv1へルーティング
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: app-v1
port: 8080
実務運用時の注意事項
Gatewayの状態モニタリング
Gateway APIリソースの状態条件(Conditions)は必ずモニタリングする必要がある。中核となる条件は3つである。
| 条件 | 意味 | 確認するタイミング |
|---|---|---|
| Accepted | リソースが構文的/意味的に有効でコントローラに受理された | リソース作成の直後 |
| Programmed | 設定がデータプレーンへ完全に反映された | トラフィック切り替え前の必須確認 |
| ResolvedRefs | 参照するすべての外部オブジェクト(Secret, Serviceなど)が有効 | TLS設定時、クロスネームスペース参照時 |
# Gatewayの状態条件を確認
kubectl describe gateway production-gateway -n gateway-infra
# HTTPRouteの状態確認
kubectl get httproute -A -o custom-columns=\
'NAME:.metadata.name,HOSTNAMES:.spec.hostnames[*],PARENT:.spec.parentRefs[0].name,ACCEPTED:.status.parents[0].conditions[?(@.type=="Accepted")].status'
allowedRoutes設定の管理
プロダクション環境ではfrom: Allではなく必ずfrom: Selectorまたはfrom: Sameを使い、どのネームスペースのRouteがGatewayにバインドできるかを明示的に制限する必要がある。これを無視すると、悪意のあるまたは誤ったHTTPRouteがプロダクションのGatewayにバインドされ、トラフィックのハイジャックが発生しうる。
リスナーのホスト名衝突の防止
同一のGatewayに同じホスト名を持つリスナーを重複して定義すると、予測できない挙動が発生する。リスナー名は一意でなければならず、ワイルドカードのホスト名(*.example.com)と具体的なホスト名(api.example.com)が共存するときの優先順位規則を理解する必要がある。具体的なホスト名がワイルドカードより優先される。
リソース整理の順序
マイグレーション完了後にリソースを整理するときは順序が重要だ。HTTPRouteを先に削除するとトラフィックが即座に切断される。必ずDNS変更を確認してから、既存のIngressリソースから先に削除する必要がある。
トラブルシューティング
問題1: GatewayがProgrammed: False状態で止まる
原因: GatewayClassのコントローラが実行されていないか、TLS証明書の参照が有効でない場合。
# コントローラPodの状態確認
kubectl get pods -n envoy-gateway-system
# Gatewayのイベント確認
kubectl describe gateway production-gateway -n gateway-infra | tail -20
# TLS Secretの存在確認
kubectl get secret wildcard-tls-cert -n gateway-infra
# GatewayClassの状態確認
kubectl get gatewayclass envoy-gateway-class -o yaml
解決: コントローラPodがCrashLoopBackOff状態ならログを確認する。TLS Secretがなければcert-managerのログを確認し、Certificateリソースの状態を点検する。
問題2: HTTPRouteはAcceptedになったがトラフィックがルーティングされない
原因: backendRefに指定したServiceが存在しないか、ポート番号が一致しないか、Podが健全でない場合。
# HTTPRouteの状態のResolvedRefs条件を確認
kubectl get httproute api-route -n backend-app -o yaml | grep -A5 "ResolvedRefs"
# バックエンドServiceの存在確認
kubectl get svc users-service-v2 -n backend-app
# Endpointsの確認 (健全なPodがあるか)
kubectl get endpoints users-service-v2 -n backend-app
# Podの状態とログの確認
kubectl get pods -n backend-app -l app=users-service-v2
kubectl logs -n backend-app -l app=users-service-v2 --tail=50
問題3: クロスネームスペース参照の失敗
原因: ReferenceGrantが正しく設定されていない場合。
# ReferenceGrantの一覧確認
kubectl get referencegrant -A
# 特定のネームスペースのReferenceGrantを詳細確認
kubectl describe referencegrant -n gateway-infra
解決: fromフィールドのnamespace、group、kindが参照するリソースと正確に一致しているかを確認する。ReferenceGrantは参照対象(to)が置かれているネームスペースに作成する必要がある。
問題4: cert-manager連携時に証明書が発行されない
# Certificateリソースの状態確認
kubectl get certificate -n gateway-infra
# cert-managerのログ確認
kubectl logs -n cert-manager deploy/cert-manager --tail=100
# Challengeの状態確認 (ACME HTTP-01)
kubectl get challenge -A
# Orderの状態確認
kubectl get order -A
解決: ClusterIssuerが正しく設定されているか、ACMEサーバーへアクセスできるか、HTTP-01 challengeのためのポート80リスナーが開いているかを確認する。
障害事例と復旧手順
事例1: マイグレーション中のDNS切り替えでトラフィックが失われる
状況: DNS TTLが高い状態でIngressを削除したため、一部のクライアントのトラフィックが失われた。
復旧手順:
- 削除したIngressリソースをただちに再作成して既存の経路を復元する。
- DNS TTLを300秒(5分)以下へ下げた後、最低でも以前のTTLの2倍の時間を待つ。
- GatewayのProgrammed状態がTrueであることを再確認する。
- DNSをGateway APIのエンドポイントへ変更する。
- 最低24時間モニタリングした後、以前のIngressを削除する。
予防: マイグレーション前にDNS TTLを60~300秒へ下げ、十分な伝播時間を確保してから切り替える。
事例2: 重み設定の誤りによる全トラフィックのダウン
状況: カナリアデプロイ時にすべてのbackendRefsのweightを0に設定したため、503エラーが発生した。
復旧手順:
# ただちに安定版へ100%のトラフィックを復元
kubectl patch httproute canary-route -n backend-app --type='json' \
-p='[
{"op": "replace", "path": "/spec/rules/0/backendRefs/0/weight", "value": 100},
{"op": "replace", "path": "/spec/rules/0/backendRefs/1/weight", "value": 0}
]'
# 適用の確認
kubectl get httproute canary-route -n backend-app -o yaml
予防: 重みを変更するときは、少なくとも1つのバックエンドが0より大きい重みを保つよう、自動化スクリプトに検証ロジックを含める。
事例3: ReferenceGrantの欠落によるTLS証明書参照の失敗
状況: GatewayとTLS Secretが別のネームスペースにあるのにReferenceGrantなしでデプロイしたため、GatewayがProgrammed状態にならなかった。
復旧手順:
- Gatewayのstatus.conditionsでResolvedRefs条件を確認する。
- 欠落しているReferenceGrantを、Secretが置かれているネームスペースに作成する。
- GatewayがProgrammed: Trueへ切り替わるかを確認する。
事例4: コントローラのアップグレード中にデータプレーンが停止
状況: Gateway APIコントローラをHelmでアップグレードする間にデータプレーンのPodが再起動し、トラフィックが一時的に中断された。
復旧手順:
- アップグレード前に必ずGatewayリソースのYAMLバックアップを実施する。
- コントローラのRollingUpdate戦略を確認する。
- 中断が発生した場合はHelm rollbackを実行する。
# アップグレード前のバックアップ
kubectl get gateway,httproute,referencegrant -A -o yaml > gateway-backup.yaml
# Helmロールバック
helm rollback envoy-gateway -n envoy-gateway-system
# データプレーンPodの状態確認
kubectl get pods -n envoy-gateway-system -w
予防: コントローラのアップグレード時はPodDisruptionBudgetを設定し、ステージング環境で先に検証する。
マイグレーションチェックリスト
マイグレーションの前、中、後に確認すべき項目をチェックリストとして整理する。
事前準備
- Gateway API CRDがクラスタにインストールされているか (
kubectl get crd | grep gateway) - 選択したGateway APIコントローラが正常に実行中か
- GatewayClassがAccepted状態か
- cert-managerがGateway API連携をサポートするバージョン(1.15+)か
- DNS TTLが300秒以下へ下げられているか
- 既存のIngressリソースの全一覧が文書化されているか
- ingress2gatewayで変換したYAMLを手動でレビューしたか
マイグレーションの実施
- GatewayリソースがProgrammed: True状態か
- すべてのHTTPRouteがAccepted: True状態か
- すべてのHTTPRouteのResolvedRefsがTrueか
- TLS証明書が正常に発行されたか (
kubectl get certificate) - クロスネームスペース参照にReferenceGrantが設定されているか
- curlまたは外部モニタリングでエンドポイントへのアクセスが確認できたか
- Gateway APIエンドポイントへのDNS切り替えが完了したか
マイグレーション完了後
- 既存のIngressリソースがすべて削除されたか
- 既存のIngressコントローラが整理されたか
- モニタリングダッシュボードがGateway APIのメトリクスを収集しているか
- アラート(Alert)規則がGatewayの状態条件を含んでいるか
- 障害対応ランブックがGateway API基準で更新されたか
- GatewayリソースのYAMLバックアップがGitなどの構成管理に保存されているか
おわりに
Gateway APIはKubernetesネットワーキングの未来である。役割ベースの設計でインフラ運用者とアプリケーション開発者の関心事をきれいに分離し、標準化されたAPIでコントローラ間の移植性を保証し、ネイティブなトラフィック分割と高度なルーティング機能を提供する。v1.4でBackendTLSPolicyとReferenceGrantがGAへ昇格したことで、プロダクション環境で必要なほぼすべての機能がStandard Channelに含まれるようになった。
Ingress NGINXの公式サポート終了が2026年3月に予定されている以上、まだマイグレーションを始めていないなら今が好機である。この記事で扱った段階的なマイグレーション戦略、ingress2gatewayツールの活用、並行運用の方式を参考に、安全に切り替えることを勧める。何よりも重要なのは、GatewayがProgrammed: True状態であることを必ず確認したうえでのみトラフィックを切り替えることだ。急がず、サービスごとに段階的に切り替えながら検証するのが最も安全な方法である。