LabHub

ブログ

Kubernetes Gateway APIとEnvoyトラフィック管理 2026

한국어English日本語

Kubernetes Gateway APIとEnvoy Gatewayによるトラフィック管理実践 2026

概要

2026年3月現在、Kubernetes Ingress NGINXのメンテナンス終了が目前に迫り、Gateway APIへの移行は選択ではなく必須になった。Gateway APIはv1.4までリリースされ、BackendTLSPolicy、Named Rules、supportedFeaturesなどの中核機能がStandardチャネルへ昇格し、Envoy Gatewayはv1.6.xまで進化しながらSecurityPolicy、グローバル/ローカルのRate Limiting、mTLSなどエンタープライズ級のトラフィック管理機能を提供している。

この記事ではGateway APIの中核リソース構造を理解し、Envoy Gatewayを実装として選んで運用環境で実際にトラフィックを管理する方法を扱う。カナリアデプロイ、トラフィックミラーリング、ヘッダーベースのルーティング、Rate Limiting、BackendTLSPolicyを活用したバックエンドmTLSまで、実践ですぐに適用できるパターンをコードとともに示す。

Gateway API vs Ingress: なぜ移行すべきか

IngressリソースはKubernetesの初期からHTTPトラフィックルーティングの標準だったが、ベンダーごとのアノテーションに依存する構造的な限界があった。Gateway APIはこの問題を根本的に解決する。

比較項目IngressGateway API
プロトコル対応HTTP/HTTPSのみHTTP, gRPC, TCP, UDP, TLS をすべてサポート
ルーティング表現力ホスト/パスベースのみヘッダー、クエリパラメータ、メソッドでのマッチが可能
役割分離単一リソースにすべての設定GatewayClass、Gateway、Routeで役割を分離
ベンダー依存アノテーションベースの拡張 (ベンダー依存)標準化されたCRDベースの拡張 (移植可能)
トラフィック分割ネイティブ非対応重みベースのトラフィック分割をネイティブ対応
TLS管理基本的なTLS終端のみBackendTLSPolicyでバックエンドmTLSに対応
マルチテナンシー限定的ネームスペース間のルート共有をネイティブ対応

中核となる移行の動機は3つだ。第一に、Ingress NGINXが2026年3月にメンテナンス終了を控えており、セキュリティパッチが停止する。第二に、Gateway APIはL4/L7プロトコルを統合的に管理できるため、TCP、UDP、gRPCのワークロードを別のメカニズムなしで処理する。第三に、4つのペルソナ(インフラ提供者、クラスタ運用者、アプリケーション管理者、アプリケーション開発者)に合わせた役割分離が、マルチチーム環境で運用効率を最大化する。

アーキテクチャ

Gateway APIリソースの階層構造

Gateway APIは3つの階層に分かれる。GatewayClassはインフラ提供者が定義するテンプレートだ。Gatewayはクラスタ運用者がGatewayClassを基に作成するロードバランサのインスタンスだ。Route(HTTPRoute、GRPCRoute、TLSRoute、TCPRoute)はアプリケーション開発者がトラフィックのルーティング規則を定義するリソースだ。

この階層構造のおかげで、クラスタ運用者はTLS証明書とリスナーのポートを管理しながら、アプリケーション開発者は自分のネームスペースの中で独立してルーティング規則をデプロイできる。ReferenceGrantリソースを通じてネームスペース間の参照権限を明示的に制御できる。

Envoy Gatewayのアーキテクチャ

Envoy GatewayはGateway APIの実装であり、コントロールプレーンとデータプレーンで構成される。コントロールプレーンはGateway APIリソースを監視(watch)し、これをEnvoyプロキシの設定へ変換する。データプレーンは実際のトラフィックを処理するEnvoyプロキシのインスタンス群だ。Envoy GatewayコントローラがGatewayリソースを検知すると、自動でEnvoyプロキシのDeploymentとServiceをプロビジョニングする。

Envoy Gatewayならではの差別化要素は、BackendTrafficPolicy、SecurityPolicy、ClientTrafficPolicy、EnvoyExtensionPolicyのような拡張CRDを通じてRate Limiting、認証/認可、トラフィック制御を宣言的に管理できる点だ。

Gateway API実装の比較

運用環境でGateway APIの実装を選ぶときは次の比較を参考にする。

実装データプレーンGateway APIバージョン主な特徴
Envoy GatewayEnvoy Proxyv1.2+ネイティブなRate Limiting、SecurityPolicy、AI Gateway拡張
Istio (Ambient)Envoy Proxy / ztunnelv1.1+サービスメッシュ統合、Ambientモードでサイドカー不要
NGINX Gateway FabricNGINXv1.2+NGINXベース、既存のNGINX利用者に馴染みやすい
Cilium GatewayeBPF / Envoyv1.1+eBPFベースのL4高速化、ネットワークポリシー統合
Kong GatewayKong Proxyv1.2+プラグインのエコシステム、API管理の統合
TraefikTraefik Proxyv1.1+自動証明書管理、手軽な設定

この記事ではEnvoy Gatewayを中心に扱うが、Gateway APIの標準に従うため、中核リソース(GatewayClass、Gateway、HTTPRoute、GRPCRoute)の定義は他の実装でも同じように適用される。

中核リソースの説明

GatewayClassとGateway

GatewayClassはどのコントローラがGatewayを管理するかを指定するクラスタスコープのリソースだ。Gatewayは実際のリスナー(ポート、プロトコル、TLS設定)を定義するネームスペーススコープのリソースだ。

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-gateway
  namespace: infra
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  gatewayClassName: envoy-gateway
  listeners:
    - name: https
      protocol: HTTPS
      port: 443
      tls:
        mode: Terminate
        certificateRefs:
          - kind: Secret
            name: wildcard-tls
            namespace: infra
      allowedRoutes:
        namespaces:
          from: Selector
          selector:
            matchLabels:
              gateway-access: 'true'
    - name: http
      protocol: HTTP
      port: 80
      allowedRoutes:
        namespaces:
          from: Same

この設定ではHTTPSリスナーはgateway-access: "true"ラベルが付いたネームスペースのRouteだけを許可する。HTTPリスナーは同じネームスペースのRouteだけを許可し、HTTPSリダイレクト専用として使う。allowedRoutesによるこうした細分化されたアクセス制御が、Ingressに比べたGateway APIの最大の利点の一つだ。

HTTPRoute

HTTPRouteはHTTPトラフィックのルーティング規則を定義する。Gateway API v1.4で導入されたNamed Rules機能を使うと、各規則に名前を付けて可観測性とポリシーのターゲティングを強化できる。

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: api-route
  namespace: app
spec:
  parentRefs:
    - name: production-gateway
      namespace: infra
      sectionName: https
  hostnames:
    - 'api.example.com'
  rules:
    - name: health-check
      matches:
        - path:
            type: Exact
            value: /healthz
      backendRefs:
        - name: api-service
          port: 8080
    - name: api-v2
      matches:
        - path:
            type: PathPrefix
            value: /api/v2
          headers:
            - name: X-API-Version
              value: '2'
      backendRefs:
        - name: api-v2-service
          port: 8080
    - name: api-default
      matches:
        - path:
            type: PathPrefix
            value: /api
      backendRefs:
        - name: api-v1-service
          port: 8080

Named Rules(name: health-checkname: api-v2name: api-default)は、Envoyのメトリクスで各規則ごとのトラフィック統計を確認するときに有用だ。またBackendTrafficPolicyで特定の規則だけをターゲティングできるため、細分化されたトラフィックポリシーの適用が可能だ。

GRPCRoute

GRPCRouteはgRPCトラフィックをネイティブにルーティングする。Gateway API v1.1からStandardチャネルに含まれ、GA状態だ。

apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
  name: grpc-route
  namespace: app
spec:
  parentRefs:
    - name: production-gateway
      namespace: infra
      sectionName: https
  hostnames:
    - 'grpc.example.com'
  rules:
    - matches:
        - method:
            service: myapp.UserService
            method: GetUser
      backendRefs:
        - name: user-service-grpc
          port: 50051
    - matches:
        - method:
            service: myapp.OrderService
      backendRefs:
        - name: order-service-grpc
          port: 50051

GRPCRouteを使うGatewayはHTTP/2を必須でサポートする必要がある。Envoy GatewayはデフォルトでHTTP/2をサポートするため、追加の設定なしでgRPCルーティングが動作する。

BackendTLSPolicy

BackendTLSPolicyはGateway API v1.4でStandardチャネルへ昇格したリソースで、GatewayとバックエンドPodの間のTLS接続を設定する。これによりゲートウェイからバックエンドまでのend-to-end暗号化を実装できる。

apiVersion: gateway.networking.k8s.io/v1alpha3
kind: BackendTLSPolicy
metadata:
  name: backend-tls
  namespace: app
spec:
  targetRefs:
    - group: ''
      kind: Service
      name: api-service
  validation:
    caCertificateRefs:
      - group: ''
        kind: ConfigMap
        name: backend-ca-cert
    hostname: api-service.app.svc.cluster.local

この設定は、Gatewayがapi-serviceへリクエストを転送するときにTLSを使うよう強制し、ConfigMapに保存されたCA証明書でバックエンドの証明書を検証する。hostnameフィールドはバックエンド証明書のSAN(Subject Alternative Name)と一致する必要がある。

トラフィック管理パターン

カナリアデプロイ (重みベースのトラフィック分割)

Gateway APIの重みベースのトラフィック分割は、カナリアデプロイの中核メカニズムだ。backendRefsにweightを指定してトラフィックの比率を調整する。

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: canary-route
  namespace: app
spec:
  parentRefs:
    - name: production-gateway
      namespace: infra
      sectionName: https
  hostnames:
    - 'app.example.com'
  rules:
    - name: canary-split
      matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: app-stable
          port: 8080
          weight: 90
        - name: app-canary
          port: 8080
          weight: 10

この設定は全トラフィックの90%を安定版(app-stable)へ、10%をカナリア版(app-canary)へルーティングする。カナリアの検証が完了したらweightを段階的に調整して0/100へ切り替える。

FlaggerのようなProgressive Deliveryツールと組み合わせると、メトリクスベースの自動カナリアプロモーションを実装できる。FlaggerはGateway APIをネイティブにサポートするため、HTTPRouteのbackendRefsのweightを自動で調整する。

運用時に注意すべき点は、weightが相対的な比率だということだ。weight: 90とweight: 10は9:1の比率であり、weight: 9とweight: 1も同じ9:1の比率だ。可読性のために合計を100に揃えることを推奨する。

トラフィックミラーリング

トラフィックミラーリングは、プロダクションのトラフィックのコピーをテスト環境へ送り、実トラフィックで検証するときに使う。ミラーされたトラフィックのレスポンスはクライアントへ返されないため、プロダクションに影響を与えない。

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: mirror-route
  namespace: app
spec:
  parentRefs:
    - name: production-gateway
      namespace: infra
      sectionName: https
  hostnames:
    - 'api.example.com'
  rules:
    - name: mirror-to-staging
      matches:
        - path:
            type: PathPrefix
            value: /api
      filters:
        - type: RequestMirror
          requestMirror:
            backendRef:
              name: api-staging
              port: 8080
      backendRefs:
        - name: api-production
          port: 8080

注意点がある。1つのHTTPRoute規則に複数のRequestMirrorフィルタを適用することはできない。複数の宛先へのミラーリングが必要なら、別の規則を定義するか、ミラーリング先のサービスで再度分岐する構造を設計する必要がある。

ヘッダーベースのルーティング

A/Bテストや特定のユーザーグループへ新しいバージョンを公開するときに、ヘッダーベースのルーティングを活用する。

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: header-routing
  namespace: app
spec:
  parentRefs:
    - name: production-gateway
      namespace: infra
      sectionName: https
  hostnames:
    - 'app.example.com'
  rules:
    - name: beta-users
      matches:
        - headers:
            - name: X-Beta-User
              value: 'true'
      backendRefs:
        - name: app-beta
          port: 8080
    - name: internal-debug
      matches:
        - headers:
            - name: X-Debug-Mode
              value: 'enabled'
          path:
            type: PathPrefix
            value: /api
      filters:
        - type: ResponseHeaderModifier
          responseHeaderModifier:
            add:
              - name: X-Debug-Backend
                value: 'debug-v2'
      backendRefs:
        - name: app-debug
          port: 8080
    - name: default
      matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: app-production
          port: 8080

規則の順序が重要だ。Gateway APIは最も具体的なマッチを優先して適用するが、同じ具体性を持つ規則は定義された順に評価される。ヘッダーマッチのある規則を、デフォルトの規則より先に配置する必要がある。

Rate Limiting (Envoy Gateway BackendTrafficPolicy)

Envoy GatewayはBackendTrafficPolicy CRDを通じて、グローバルなRate LimitingとローカルなRate Limitingの両方をサポートする。v1.6からは両方を同時に適用できる。

apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
  name: api-rate-limit
  namespace: app
spec:
  targetRefs:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
      name: api-route
  rateLimit:
    type: Global
    global:
      rules:
        - clientSelectors:
            - headers:
                - name: X-API-Key
                  type: Distinct
          limit:
            requests: 1000
            unit: Hour
        - clientSelectors:
            - headers:
                - name: X-API-Tier
                  value: 'premium'
          limit:
            requests: 10000
            unit: Hour
        - limit:
            requests: 100
            unit: Minute

この設定は3段階でRate Limitingを適用する。第一に、X-API-Keyヘッダーの固有値ごとに1時間あたり1000件を許可する。第二に、X-API-Tierがpremiumのリクエストは1時間あたり10000件まで許可する。第三に、どの条件にも該当しないリクエストは1分あたり100件に制限する。

グローバルなRate Limitingには別途RedisベースのRate Limitサービスが必要だ。Envoy GatewayをHelmでインストールするときにrateLimit.backend.redis.hostの値を設定する必要がある。

# Envoy Gatewayインストール時、グローバルRate Limitingのための Redis 設定
helm install eg oci://docker.io/envoyproxy/gateway-helm \
  --version v1.6.3 \
  -n envoy-gateway-system --create-namespace \
  --set rateLimit.backend.redis.host=redis.infra.svc.cluster.local \
  --set rateLimit.backend.redis.port=6379

ローカルなRate LimitingはRedisなしで各Envoyインスタンス自体で動作するため設定は簡単だが、Pod数によって実際の許容量が変わる点を考慮する必要がある。Envoy Podが3個でローカルの上限が1分あたり100件なら、クラスタ全体では最大で1分あたり300件が許可されうる。

Envoy Gatewayのインストールと初期設定

Helmベースのインストール

# Gateway API CRDのインストール (v1.4.0)
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.0/standard-install.yaml

# Envoy Gateway の Helm インストール
helm install eg oci://docker.io/envoyproxy/gateway-helm \
  --version v1.6.3 \
  -n envoy-gateway-system --create-namespace

# GatewayClassの確認
kubectl get gatewayclass
# NAME            CONTROLLER                                      ACCEPTED
# eg              gateway.envoyproxy.io/gatewayclass-controller    True

# Gateway作成後にプロキシのプロビジョニングを確認
kubectl get gateway -n infra
kubectl get pods -n envoy-gateway-system

インストール後、GatewayClassのACCEPTED状態がTrueかどうかを必ず確認する。Falseの場合はコントローラPodのログを確認する必要がある。

supportedFeaturesの確認

Gateway API v1.4からGatewayClassのstatusにsupportedFeaturesフィールドが追加された。これにより、実装がどの機能をサポートしているかをプログラム的に確認できる。

# GatewayClassがサポートする機能の一覧を確認
kubectl get gatewayclass eg -o jsonpath='{.status.supportedFeatures}' | jq .

この結果からHTTPRouteRequestMirror、HTTPRouteBackendTimeout、GRPCRouteListenerHostnameMatchingなどの機能のサポート有無を確認できるため、運用環境で特定の機能を使う前に互換性を検証するのに有用だ。

トラブルシューティング

RouteがGatewayに接続されない場合

最もよくある問題は、HTTPRouteがGatewayにattachされないことだ。次の順序で診断する。

第一に、HTTPRouteのparentRefsが正しいGatewayを参照しているかを確認する。namespaceを省略すると同じネームスペースのGatewayを探すため、別のネームスペースのGatewayを参照するときは必ずnamespaceを明示する必要がある。

第二に、GatewayのallowedRoutesの設定を確認する。from: Selectorを使う場合、HTTPRouteがあるネームスペースに該当するラベルが必要だ。ネームスペースへのラベル追加を忘れるケースが多い。

# HTTPRouteの状態確認
kubectl get httproute api-route -n app -o yaml | yq '.status'

# Gatewayリスナーの状態確認
kubectl get gateway production-gateway -n infra -o yaml | yq '.status.listeners'

# ネームスペースのラベル確認と追加
kubectl get ns app --show-labels
kubectl label ns app gateway-access=true

第三に、sectionNameが指定されている場合は、Gatewayリスナーの名前と正確に一致しているかを確認する。

トラフィックがバックエンドに到達しない場合

Routeが正常にattachされているのに502または503エラーが発生する場合は、バックエンドサービスの状態を点検する。

# バックエンドサービスとエンドポイントの確認
kubectl get svc api-service -n app
kubectl get endpoints api-service -n app

# Envoyプロキシのログ確認
kubectl logs -n envoy-gateway-system -l app.kubernetes.io/component=proxy --tail=100

# Envoyプロキシの設定ダンプ
kubectl port-forward -n envoy-gateway-system deploy/envoy-production-gateway 19000:19000 &
curl localhost:19000/config_dump | jq '.configs[] | select(.["@type"] | contains("route"))'

BackendTLSPolicyを適用している場合は、バックエンドPodのTLS証明書が正しく設定されているか、hostnameが証明書のSANと一致しているかを確認する。

Rate Limitingが動作しない場合

グローバルなRate Limitingが動作しないときのチェックリストは次のとおりだ。Redisの接続状態を確認する。Rate LimitサービスのPodが正常に動作中かを確認する。BackendTrafficPolicyのtargetRefsが正しいHTTPRouteを参照しているかを確認する。

# Rate Limitサービスの状態確認
kubectl get pods -n envoy-gateway-system -l app.kubernetes.io/component=ratelimit

# Rate Limitサービスのログ
kubectl logs -n envoy-gateway-system -l app.kubernetes.io/component=ratelimit --tail=50

# Redis接続テスト
kubectl exec -n envoy-gateway-system deploy/envoy-ratelimit -- redis-cli -h redis.infra.svc.cluster.local ping

障害事例と復旧手順

事例1: Gateway更新中のトラフィック断

Gatewayリソースのリスナーを変更するとEnvoyプロキシが再起動されることがある。プロダクション環境でリスナーを追加/削除するときに無停止を保証するには、次の手順に従う。

まずPodDisruptionBudget(PDB)を設定して最小の利用可能Pod数を保証する。Envoy Gateway v1.6ではEnvoyProxy CRDを通じてPDBを直接設定できる。変更前にEnvoyプロキシのreplica数を十分に確保する(最低2個以上)。リスナーの変更はトラフィックの少ない時間帯に実施し、変更直後にGatewayのstatus.listenersを監視して、すべてのリスナーがAccepted/Programmed状態かどうかを確認する。

事例2: 誤ったHTTPRouteのデプロイによるルーティング障害

HTTPRouteに誤ったbackendRefを指定したり、weightを0に設定したりすると、特定パスのトラフィックがドロップされる。復旧手順は次のとおりだ。

# 問題のあるHTTPRouteを即座にロールバック
kubectl rollout undo httproute api-route -n app  # HTTPRouteはrolloutをサポートしていない

# 代わりに以前のバージョンのマニフェストを再適用
kubectl apply -f httproute-previous-version.yaml

# あるいはGitOps環境でgit revertした後に自動同期
git revert HEAD
git push origin main

HTTPRouteにはDeploymentのようなrollout機能がないため、必ずGitOps(ArgoCD, Flux)を通じてマニフェストをバージョン管理する必要がある。Gitの履歴がそのままロールバックのメカニズムになる。

事例3: Rate LimitのRedis障害時のトラフィック急増

グローバルなRate LimitingのRedisがダウンすると、デフォルトではEnvoyはRate Limitサービスに接続できないときにリクエストを許可(fail-open)する。これは可用性を優先する設計だが、バックエンドが急激なトラフィック増加に耐えられないことがある。

対応策として、グローバルなRate LimitingとローカルなRate Limitingを併用する。ローカルなRate LimitingはRedisに依存しないため、Redis障害時にも基本的なトラフィック保護が可能だ。Redisは必ず高可用性構成(Redis SentinelまたはRedis Cluster)でデプロイする。

運用チェックリスト

デプロイ前チェックリスト

モニタリングチェックリスト

アップグレードチェックリスト

Ingressからのマイグレーションチェックリスト

# ingress2gatewayツールを使った変換
go install github.com/kubernetes-sigs/ingress2gateway@latest
ingress2gateway print --providers ingress-nginx --all-namespaces

# 変換結果をファイルへ保存して確認
ingress2gateway print --providers ingress-nginx --all-namespaces > gateway-resources.yaml

まとめ

Gateway APIは2026年現在、Kubernetesネットワーキングの新しい標準として確固たる地位を築いた。v1.4でBackendTLSPolicy、Named Rules、supportedFeaturesがStandardチャネルへ昇格し、運用環境での信頼性が大きく高まった。Envoy Gateway v1.6は、グローバル/ローカルのRate Limitingの同時適用、SecurityPolicyのTCPRoute拡張、mTLS設定などエンタープライズの要求を満たす機能を備えている。

既存のIngressからの移行を計画しているなら、ingress2gatewayツールを活用した段階的なマイグレーションを推奨する。Gateway APIと既存のIngressは同一クラスタで共存できるため、サービス単位で安全に移行できる。最も重要なのは、GitOpsによるマニフェストのバージョン管理と、十分なモニタリング/アラート体制を構築することだ。

参考資料

コメント

まだコメントはありません。

ログインするとコメントできます