Skip to content
Published on

Ingress から Gateway API へ — なぜ、何が、どう変わるのか

Authors

はじめに: なぜ今 Gateway API なのか

ここ数年、Kubernetes で L7 トラフィックを外部へ公開する標準は事実上 Ingress でした。しかし2026年現在、状況は明らかに変わりました。Ingress API は frozen の状態 で新しい機能はもう追加されず、その後継として Gateway API が標準の座を確立しつつあります。同時に、最も広く使われていた ingress-nginx はメンテナンスモードに近い流れで、新機能よりセキュリティパッチ中心に運用されています。

本記事は「なぜ変えるべきか(Why)」「何が変わるのか(What)」「どう変えるのか(How)」の3つの軸で構成します。単に新しい API を紹介するのではなく、既存の Ingress 資産を持つチームが現実的にどの順序で移行できるかに焦点を当てます。

Ingress の限界 — なぜ変えるべきか

Ingress は単純なルーティングには優れていますが、運用規模が大きくなるほど2つの根本的な限界が現れます。

1. アノテーション地獄

Ingress 標準仕様(rules/paths/backend/tls)は基本的なホスト・パスルーティングしかカバーしません。ところが実務では、ヘッダベースルーティング、トラフィックの重み付け分割(カナリア)、タイムアウト、リトライ、CORS、認証、rewrite など多くの高度な機能が必要です。Ingress 標準にはこうした機能がないため、各コントローラは アノテーション でこれを回避しました。

metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "20"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "120"
    nginx.ingress.kubernetes.io/configuration-snippet: |
      more_set_headers "X-Custom: value";

問題はこのアノテーションが コントローラごとに完全に異なる 点です。ingress-nginx の nginx.ingress.kubernetes.io/canary-weight は Traefik では動作せず、Traefik のミドルウェアアノテーションは ingress-nginx では無意味です。結果として Ingress リソースが特定のコントローラに強く依存し、コントローラを変えるにはすべてのアノテーションを書き直す必要があります。これが「アノテーション地獄」と呼ばれる可搬性の問題です。

さらに configuration-snippet のような自由テキストのアノテーションは任意の nginx 設定を注入でき、セキュリティ上も危険で、実際に関連する脆弱性が報告されたこともあります。

2. 役割分離の欠如

1つの Ingress リソースには、インフラの関心事(TLS 証明書、入口設定)とアプリケーションの関心事(どのパスをどのサービスへ送るか)が混在しています。大規模組織では、プラットフォームチームが入口・証明書・ポリシーを管理し、各アプリケーションチームは自分のサービスのルーティングだけを管理したいものです。しかし Ingress にはこの責任を分離する標準メカニズムがありません。すべてのチームが同じ Ingress リソースを触るか、名前空間単位で不自然に分割するしかありません。

Gateway API のリソースモデル — 何が変わるのか

Gateway API は上記2つの問題に正面から取り組むため、役割ベースで分離された複数のリソース を導入します。中核のリソースは次のとおりです。

  • GatewayClass: どの実装(コントローラ)を使うかを定義するクラスタスコープのリソース。Ingress の IngressClass に対応し、通常はインフラ提供者が作成します。
  • Gateway: 実際の入口(リスナー、ポート、プロトコル、TLS)を定義します。プラットフォーム/インフラチームが所有します。
  • HTTPRoute: HTTP ルーティングルール(ホスト名、パス、ヘッダマッチング、トラフィック分割、フィルタ)を定義します。アプリケーション開発者が所有します。
  • TLSRoute / TCPRoute / GRPCRoute / UDPRoute: HTTP 以外のプロトコル用のルートリソース。
  • ReferenceGrant: クロス名前空間参照を明示的に許可するリソース。

この分離のおかげで、インフラチームは Gateway を、アプリチームは HTTPRoute をそれぞれ管理しつつ、1つの入口を共有できます。

概念マッピング表

既存の Ingress 概念が Gateway API のどこに対応するかをまとめると次のとおりです。

Ingress 概念Gateway API 対応備考
IngressClassGatewayClassクラスタスコープ、実装選択
Ingress(入口部分)Gateway + listenerポート/プロトコル/TLS 定義
Ingress(ルーティング規則部分)HTTPRouteホスト/パス/マッチ規則
spec.rules.hostHTTPRoute hostnamesホストマッチ
spec.rules.http.pathsHTTPRoute rules.matchesパス/ヘッダマッチ
pathType Prefix/ExactPathPrefix/Exact matchほぼ同じ意味
backend.servicebackendRefsサービス参照
spec.tlsGateway listener TLS入口で終端
canary アノテーションbackendRefs weight標準トラフィック分割
rewrite アノテーションURLRewrite filter標準フィルタ
ヘッダ操作アノテーションRequestHeaderModifier filter標準フィルタ

核心は アノテーションで回避していた機能の多くが Gateway API では標準仕様のフィールド になる点です。トラフィック分割、rewrite、ヘッダ操作、リダイレクトなどがすべて可搬な標準の形で表現されます。

実習 YAML 比較

同じ要件を Ingress と Gateway API でそれぞれ表現して違いを見ます。

基本のホスト/パスルーティング

Ingress では次のとおりです。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: shop-ingress
spec:
  ingressClassName: nginx
  rules:
    - host: shop.example.com
      http:
        paths:
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-service
                port:
                  number: 8080

Gateway API では Gateway と HTTPRoute に分かれます。

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: shop-gateway
spec:
  gatewayClassName: envoy
  listeners:
    - name: http
      protocol: HTTP
      port: 80
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: shop-route
spec:
  parentRefs:
    - name: shop-gateway
  hostnames:
    - shop.example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /api
      backendRefs:
        - name: api-service
          port: 8080

トラフィックの重み付け分割(カナリア)

Ingress(ingress-nginx)では別途カナリア用 Ingress とアノテーションが必要でした。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: shop-canary
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "20"
spec:
  ingressClassName: nginx
  rules:
    - host: shop.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: shop-v2
                port:
                  number: 80

Gateway API では backendRefs の weight として標準化され、1つのリソースで表現されます。

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: shop-canary
spec:
  parentRefs:
    - name: shop-gateway
  hostnames:
    - shop.example.com
  rules:
    - backendRefs:
        - name: shop-v1
          port: 80
          weight: 80
        - name: shop-v2
          port: 80
          weight: 20

TLS とヘッダフィルタ

Gateway で TLS を終端し、HTTPRoute でヘッダを追加する例です。

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: secure-gateway
spec:
  gatewayClassName: envoy
  listeners:
    - name: https
      protocol: HTTPS
      port: 443
      tls:
        mode: Terminate
        certificateRefs:
          - name: shop-tls
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: secure-route
spec:
  parentRefs:
    - name: secure-gateway
  hostnames:
    - shop.example.com
  rules:
    - filters:
        - type: RequestHeaderModifier
          requestHeaderModifier:
            add:
              - name: X-Env
                value: prod
      backendRefs:
        - name: shop-service
          port: 80

移行戦略 — どう変えるのか

移行は一度で終えようとせず、段階的に進めます。

ingress2gateway ツール

Kubernetes SIG Network は、既存の Ingress(および一部のプロバイダ CRD)を Gateway API リソースへ変換してくれる ingress2gateway ツールを提供しています。標準 Ingress フィールドを HTTPRoute/Gateway へ変換し、一部のプロバイダ固有アノテーションも可能な範囲でマッピングします。

ingress2gateway print --input-file=ingress.yaml

このツールは出発点を作ってくれるだけで、すべてのアノテーションを自動変換できるわけではありません。 標準化されていないコントローラ固有の機能(自由テキストの snippet など)は手動レビューが必要です。したがって変換結果は必ずレビューし、再現可能な環境で動作を検証すべきです。

段階的な移行

推奨する順序は次のとおりです。

  1. 準備: Gateway API をサポートするコントローラをクラスタに追加インストールします。既存の Ingress コントローラはそのまま残します。
  2. 並行運用: 新しいサービスやカナリアトラフィックから Gateway/HTTPRoute で公開します。DNS または重みでトラフィックを徐々に移します。
  3. 変換: ingress2gateway で既存 Ingress を一括変換し、結果をレビュー・修正します。
  4. 検証: ステージングでルーティング、TLS、ヘッダ、タイムアウトの動作が同一か確認します。
  5. カットオーバー: トラフィックを Gateway へ完全に移した後、既存 Ingress を削除します。

この過程で、2つのシステムが同じホストを同時に公開しないよう注意が必要です。

コントローラ別の Gateway API サポート状況

Gateway API は標準仕様であり、それを実装するコントローラは複数あります。適合性レベル(Core / Extended 機能のサポート度合い)はコントローラごとに異なります。

実装データプレーン備考
Envoy GatewayEnvoyCNCF、Gateway API 中心の設計
ContourEnvoyHTTPProxy と Gateway API の両方をサポート
IstioEnvoyサービスメッシュ、Gateway API サポートが成熟
TraefikTraefikIngress・CRD・Gateway API すべてサポート
CiliumeBPF/EnvoyCNI 統合 Gateway サポート
KongKongGateway API サポート
NGINX Gateway FabricNGINXNGINX ベースの Gateway API 実装
HAProxyHAProxyGateway API サポート進行中

実際に選択する際は、公式の適合性レポート(conformance)を確認し、必要な機能(トラフィック分割、ヘッダマッチングなど)がサポートされているか検証するのが安全です。

落とし穴とトラブルシューティング

移行過程でよく遭遇する問題です。

1. HTTPRoute が Gateway に attach されない。 parentRefs が誤っているか、Gateway listener の allowedRoutes(名前空間/種類の制限)に阻まれている場合です。HTTPRoute の status で attach 条件を確認します。

kubectl get httproute shop-route -o yaml | grep -A20 status

2. クロス名前空間参照が拒否される。 Gateway と HTTPRoute、または HTTPRoute と backend Service が別の名前空間にあるときは ReferenceGrant が必要です。これを明示的に許可して初めて参照が成立します。

3. 変換したら動作が微妙に異なる。 アノテーションベースの機能(特に rewrite、正規表現パス、snippet)は意味が正確に1:1で対応しないことがあります。まず標準フィルタで表現可能か確認し、不可能なら実装固有の拡張機能を検討します。

4. TLS 証明書が適用されない。 Gateway listener の certificateRefs が指す Secret が別の名前空間にある場合は ReferenceGrant が必要です。cert-manager は Gateway API 統合をサポートするので、Gateway リソースに直接証明書発行を連携できます。

5. 2つのコントローラが同じホストを掴む。 並行運用中に既存 Ingress と新しい Gateway が同一ホストを公開するとトラフィックが混ざります。カットオーバーまではホストまたは重みで明確に分離します。

おわりに

Gateway API への移行は単なる API の置き換えではなく、運用モデルの進化です。なぜ(アノテーション地獄と役割分離の欠如)、何が(GatewayClass/Gateway/HTTPRoute への責任分離と標準フィルタ)、どう(ingress2gateway と段階的な並行移行)を順に理解すれば、無理なく移行を設計できます。

2026年のコンテキストでは Ingress はまだ動作しますが frozen であり、ingress-nginx はメンテナンス中心です。したがって新規設計は Gateway API を第一候補に置き、既存資産は検証を経て段階的に移すのが合理的です。変換ツールは出発点にすぎず、すべてのアノテーションを代替してくれるわけではないので、鍵は常に検証です。

参考資料