Skip to content
Published on

Kubernetes Gateway API 実践マイグレーション — IngressからGatewayへ

Authors
  • Name
    Twitter
Kubernetes Gateway API Migration

はじめに

Kubernetesのネットワーキングスタックが進化しています。長い間標準だったIngress APIは、現在Gateway APIに置き換えられつつあります。Gateway APIは2023年にGA(General Availability)を達成し、2025年からはほとんどのIngress ControllerがGateway APIをサポートし始めました。

この記事では、既存のIngressリソースをGateway APIへマイグレーションする実践的な手順をステップごとに解説します。

Ingress vs Gateway API:なぜ移行が必要か?

Ingressの限界

Ingress APIはシンプルなHTTPルーティングには十分ですが、以下のような限界があります:

  • ロール分離が不可能:インフラ管理者とアプリケーション開発者の関心事が一つのリソースに混在
  • プロトコルの制限:HTTP/HTTPSのみサポート、TCP/UDP/gRPCは非標準アノテーションが必要
  • ベンダーロックイン:nginx、traefikなど実装ごとに異なるアノテーション
  • ヘッダーベースルーティング非対応:重み付けトラフィック分割が不可能

Gateway APIの利点

┌─────────────────────────────────────┐
GatewayClass                │  ← インフラプロバイダー(プラットフォームチーム)
├─────────────────────────────────────┤
Gateway                   │  ← クラスタオペレーター
├─────────────────────────────────────┤
HTTPRoute / TCPRoute / GRPCRoute  │  ← アプリケーション開発者
└─────────────────────────────────────┘
  • ロールベース設計:GatewayClass → Gateway → Routeの3層モデルで関心事を分離
  • 豊富なルーティング:ヘッダー、クエリパラメータ、メソッドベースのマッチング
  • マルチプロトコル:HTTP、gRPC、TCP、UDP、TLSをネイティブサポート
  • ポータビリティ:標準APIによりベンダーロックインを最小化

コアリソースの理解

GatewayClass

インフラプロバイダーが定義する最上位リソースです。どのコントローラーがGatewayを管理するかを指定します。

apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: nginx
spec:
  controllerName: gateway.nginx.org/nginx-gateway-controller

Gateway

実際のリスナー(ポート、プロトコル)を定義します。クラスタオペレーターが管理します。

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: main-gateway
  namespace: infra
spec:
  gatewayClassName: nginx
  listeners:
    - name: http
      protocol: HTTP
      port: 80
    - name: https
      protocol: HTTPS
      port: 443
      tls:
        mode: Terminate
        certificateRefs:
          - name: wildcard-cert
            kind: Secret
      allowedRoutes:
        namespaces:
          from: All

HTTPRoute

アプリケーション開発者がルーティングルールを定義します。

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: my-app-route
  namespace: app-ns
spec:
  parentRefs:
    - name: main-gateway
      namespace: infra
  hostnames:
    - 'app.example.com'
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /api
      backendRefs:
        - name: api-service
          port: 8080
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: frontend-service
          port: 3000

実践マイグレーション手順

Step 1:Gateway API CRDのインストール

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

# 実験的機能を含む(TCPRoute、TLSRouteなど)
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/experimental-install.yaml

# インストール確認
kubectl get crd | grep gateway

Step 2:既存Ingressの分析

マイグレーション前に既存のIngressを把握します:

# すべてのIngressリソースを一覧表示
kubectl get ingress -A -o wide

# 特定のIngressの詳細を確認(アノテーション含む)
kubectl get ingress my-ingress -o yaml

既存Ingressの例:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/ssl-redirect: 'true'
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - app.example.com
      secretName: app-tls
  rules:
    - host: app.example.com
      http:
        paths:
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-svc
                port:
                  number: 8080
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web-svc
                port:
                  number: 3000

Step 3:ingress2gatewayツールの活用

Kubernetes SIGが提供する公式変換ツールを活用します:

# ingress2gatewayのインストール
go install github.com/kubernetes-sigs/ingress2gateway@latest

# 現在のクラスタのIngressをGateway APIに変換
ingress2gateway print --all-namespaces

# 特定のNamespaceのみ変換
ingress2gateway print --namespace production

# ファイルに出力
ingress2gateway print --namespace production > gateway-resources.yaml

Step 4:変換されたリソースの検証と適用

# dry-runで検証
kubectl apply -f gateway-resources.yaml --dry-run=server

# 適用
kubectl apply -f gateway-resources.yaml

# 状態確認
kubectl get gateway -A
kubectl get httproute -A
kubectl describe gateway main-gateway -n infra

Step 5:トラフィック分割(カナリアデプロイメント)

Gateway API固有の強力な機能である重み付けトラフィック分割:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: canary-route
spec:
  parentRefs:
    - name: main-gateway
  hostnames:
    - 'app.example.com'
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: app-v1
          port: 8080
          weight: 90
        - name: app-v2
          port: 8080
          weight: 10

Step 6:ヘッダーベースルーティング

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: header-route
spec:
  parentRefs:
    - name: main-gateway
  rules:
    - matches:
        - headers:
            - name: X-Version
              value: beta
      backendRefs:
        - name: app-beta
          port: 8080
    - backendRefs:
        - name: app-stable
          port: 8080

段階的移行戦略

IngressとGateway APIは同一クラスタで共存できます:

  1. Phase 1:Gateway API CRDのインストール + GatewayClass/Gatewayの作成
  2. Phase 2:新規サービスからHTTPRouteを使用
  3. Phase 3:既存のIngressを一つずつHTTPRouteに移行
  4. Phase 4:すべてのIngressを削除しIngress Controllerをクリーンアップ
# 移行進捗のモニタリング
echo "Ingress: $(kubectl get ingress -A --no-headers | wc -l)"
echo "HTTPRoute: $(kubectl get httproute -A --no-headers | wc -l)"

注意事項とトラブルシューティング

アノテーションマッピング

Ingressのアノテーションは、Gateway APIではPolicyリソースFilterに置き換えられます:

IngressアノテーションGateway API対応
rewrite-targetURLRewriteFilter
ssl-redirectGatewayリスナーでHTTPからHTTPSへのリダイレクト
rate-limitBackendPolicyまたは実装固有のPolicy
corsHTTPRouteフィルターまたはPolicy
# URL Rewriteの例
rules:
  - matches:
      - path:
          type: PathPrefix
          value: /old-api
    filters:
      - type: URLRewrite
        urlRewrite:
          path:
            type: ReplacePrefixMatch
            replacePrefixMatch: /new-api
    backendRefs:
      - name: api-svc
        port: 8080

よくある間違い

  1. parentRefsのNamespace省略:GatewayとHTTPRouteが異なるNamespaceにある場合、必ずnamespaceを指定する
  2. allowedRoutes未設定:Gatewayで別のNamespaceのRouteを許可するにはfrom: Allの設定が必要
  3. ReferenceGrantの欠落:クロスNamespaceのバックエンド参照にはReferenceGrantが必要
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: allow-route-from-app
  namespace: backend-ns
spec:
  from:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
      namespace: app-ns
  to:
    - group: ''
      kind: Service

まとめ

Gateway APIは単なるIngressの代替ではなく、Kubernetesネットワーキングのパラダイムシフトです。ロールベース設計、豊富なルーティング機能、マルチプロトコルサポートにより、より安全で柔軟なトラフィック管理が可能になります。既存のIngressと共存できるため、今から段階的に移行を始めることをおすすめします。

クイズ

Q1:Gateway APIの3層リソースモデルにおける各層の名前と担当者は? GatewayClass(インフラプロバイダー/プラットフォームチーム)、Gateway(クラスタオペレーター)、HTTPRoute/TCPRouteなど(アプリケーション開発者)

Q2:Ingressでベンダー固有の設定に使用されていた方法は? アノテーション(annotations)。nginx、traefikなど実装ごとに異なる非標準アノテーションを使用しており、これがポータビリティを低下させる主な原因でした。

Q3:Gateway API CRDをインストールするkubectlコマンドは? kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml

Q4:既存のIngressをGateway APIリソースに自動変換する公式ツールは? ingress2gateway。Kubernetes SIGが提供しており、ingress2gateway printコマンドで変換結果を確認できます。

Q5:Gateway APIで重み付けカナリアデプロイメントを実装するにはどのフィールドを使用しますか?

backendRefsweightフィールド。例:v1にweight: 90、v2にweight: 10を設定すると、90:10の比率でトラフィックが分割されます。

Q6:HTTPRouteとGatewayが異なるNamespaceにある場合の注意点2つは?
  1. parentRefsにGatewayのnamespaceを明示する必要がある。2) GatewayのlistenersでallowedRoutes.namespaces.fromを"All"に設定する必要がある。

Q7:クロスNamespaceでバックエンドサービスを参照する際に必要なリソースは? ReferenceGrant。対象のNamespaceに作成し、どのNamespaceのどのリソースが自身のServiceを参照できるかを明示します。

Q8:Ingressのrewrite-targetアノテーションはGateway APIでどのように代替されますか?

HTTPRouteのfiltersでURLRewriteFilterを使用します。type: URLRewriteurlRewrite.pathの設定でパスを書き換えます。