Ingress を Gateway API に移行する

このページでは、Google Kubernetes Engine(GKE)のトラフィック管理を Ingress API から Gateway API に移行する方法について説明します。Gateway API は、アプリケーション トラフィックを処理するためのフルマネージドの Google Cloud ソリューションを提供します。

ダウンタイムを最小限に抑え、リスクを軽減するには、既存の Ingress API と新しい Gateway API 構成を同時に実行することが、Gateway API への移行に最も効果的な方法です。この方法では、現在のサービスに影響を与えることなく、ライブ環境で新しいゲートウェイ構成を徹底的にテストできます。新しいゲートウェイ構成を検証したら、DNS をすばやく切り替えてトラフィックを Gateway API にリダイレクトし、スムーズでリスクの低い移行を実現できます。

移行戦略は、大まかに次のフェーズで構成されます。

  1. 新しいロードバランサを構成します。
  2. 着信トラフィックを処理するルールを定義します。
  3. 新しい構成をデプロイし、新しいゲートウェイの IP アドレスへのトラフィック フローをテストします。
  4. 本番環境トラフィックを Gateway API に切り替えます。
  5. 残りの Ingress リソースをクリーンアップします。

新しいロードバランサを構成する

このフェーズでは、Kubernetes ゲートウェイ リソースをデプロイして、GKE クラスタへのトラフィックをロード バランシングします。ゲートウェイ リソースをデプロイすると、GKE はクラスタで実行されているアプリケーションに HTTP(S) トラフィックを公開するようにレイヤ 7 アプリケーション ロードバランサを構成します。必要なクラスタまたはロードバランサごとに 1 つのゲートウェイ リソースをデプロイします。

次の例では、グローバル外部アプリケーション ロードバランサを構成します。ゲートウェイを作成するには、次のマニフェストを gateway.yaml として保存します。

kind: Gateway
apiVersion: gateway.networking.k8s.io/v1
metadata:
  name: external-http-gateway
spec:
  gatewayClassName: gke-l7-global-external-managed # GKE's managed external Application Load Balancer
  listeners:
  - name: http
    protocol: HTTP
    port: 80
    allowedRoutes:
      namespaces:
        from: Same # Only allow HTTPRoutes from the same namespace

上記のマニフェストでは、次のフィールドを含むゲートウェイを記述しています。

  • gatewayClassName: gke-l7-global-external-managed: このゲートウェイの GatewayClass を指定します。このゲートウェイ クラスは、グローバル外部アプリケーション ロードバランサを使用します。
  • protocol: HTTPport: 80: ゲートウェイが HTTP トラフィック用にポート 80 を公開することを指定します。

着信トラフィックのトラフィック ルールを定義する

Route リソースは、ゲートウェイからバックエンド サービスにトラフィックをマッピングするためのプロトコル固有のルールを定義します。

このフェーズでは、Ingress マニフェストを HTTPRoute リソースに変換します。Ingress マニフェストを変換するには、ingress2gateway ツールの手順に沿って操作します。

この例では、次の Ingress リソースがあることを前提としています。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: cafe-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: cafe.example.com
    http:
      paths:
      - path: /tea
        pathType: Prefix
        backend:
          service:
            name: tea-svc
            port:
              number: 80
      - path: /coffee
        pathType: Prefix
        backend:
          service:
            name: coffee-svc
            port:
              number: 80

ingress2gateway ツールを使用してマニフェストを変換すると、出力は変換された HTTPRoute マニフェストになります。

次のサンプル マニフェストを httproute.yaml として保存します。

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: cafe-route
spec:
  # This route attaches to our new Gateway
  parentRefs:
  - name: external-http-gateway
  # The hostname is the same as before
  hostnames:
  - "cafe.example.com"
  # The routing rules are now more explicit
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /tea
    backendRefs:
    - name: tea-svc
      port: 80
  - matches:
    - path:
        type: PathPrefix
        value: /coffee
    backendRefs:
    - name: coffee-svc
      port: 80

HTTPRoute マニフェストの rules フィールドは、元の Ingress マニフェストで定義されたルーティング ルールに直接対応しています。

新しい構成をデプロイしてテストする

このフェーズでは、前の 2 つのフェーズで作成したゲートウェイと HTTPRoute のマニフェストを適用し、トラフィックがゲートウェイの新しい IP アドレスに流れることをテストします。

  1. ゲートウェイと HTTPRoute のマニフェストを適用します。

    kubectl apply -f gateway.yaml
    kubectl apply -f httproute.yaml
    
  2. ゲートウェイの IP アドレスを取得します。IP アドレスの割り当てには数分かかることがあります。

    kubectl get gateway external-http-gateway -o=jsonpath="{.status.addresses[0].value}" --watch
    

    出力は、ゲートウェイの外部 IP アドレスです(例: 203.0.113.90)。

  3. 新しいゲートウェイの IP アドレスをテストします。次の curl コマンドを使用して、IP アドレスにリクエストを送信し、cafe.example.com ホスト名を指定します。次に例を示します。

    curl --resolve cafe.example.com:80:203.0.113.90 http://cafe.example.com/tea
    curl --resolve cafe.example.com:80:203.0.113.90 http://cafe.example.com/coffee
    

    203.0.113.90 は、前の手順で取得した外部 IP アドレスに置き換えます。出力は、新しいゲートウェイの IP アドレスが DNS ルックアップを実行せずに cafe.example.com のトラフィックを正しくルーティングしていることを確認します。

新しいゲートウェイの IP アドレスにトラフィックを転送する

このフェーズでは、DNS レコードを更新して新しいゲートウェイの IP アドレスを指すようにすることで、以前の Ingress から新しいゲートウェイにライブ トラフィックを切り替えます。DNS レコードを更新する正確な手順は、DNS プロバイダによって異なります。

たとえば、Ingress で cafe.example.com を構成した場合は、DNS プロバイダで cafe.example.comA レコードを見つけて、古い Ingress IP アドレスの値を新しいゲートウェイの IP アドレスである 203.0.113.90 に変更します。

DNS レコードを更新すると、トラフィックは Ingress からゲートウェイに移行し始めますが、すべてのクライアントで切り替えがすぐに発生するわけではありません。前のレコードをキャッシュに保存している DNS リゾルバは、レコードの有効期間(TTL)値の期限が切れるまで待機してから、レコードを再度クエリして、更新された IP アドレスを取得します。このため、Ingress へのトラフィックが停止したことを確認するまで、既存の Ingress と新しいゲートウェイを並行して実行する必要があります。Ingress へのトラフィックが停止したことは、DNS 伝播が完了し、クライアントが古い IP アドレスに転送されなくなったことを示します。これは、ロードバランサまたは Ingress コントローラのトラフィックをモニタリングすることで確認できます。詳細については、DNS 伝播の確認をご覧ください。

Cloud DNS を使用すると、ターゲットの重みを使用して、トラフィックを古い IP アドレスから新しい IP アドレスに段階的に移行できます。詳細については、DNS ルーティング ポリシーとヘルスチェックを構成するをご覧ください。

残りの Ingress リソースをクリーンアップする

新しいゲートウェイが正常に動作していることを確認したら、古い Ingress リソースをクリーンアップします。

  1. Ingress リソースを削除します。

    kubectl delete ingress cafe-ingress
    
  2. ingress-nginx コントローラをアンインストールします。たとえば、Helm を使用してコントローラをインストールした場合は、次のコマンドを実行します。

    helm uninstall ingress-nginx -n ingress-nginx
    

Ingress NGINX と GKE Gateway の機能の比較

Gateway API は、より標準化された方法で上り(内向き)を構成し、ルーティング、ヘッダー、トラフィック分割などの最も一般的な機能と同等の機能を備えています。

次の表に、Ingress コントローラと Gateway API の一般的な機能で使用されるアノテーションを比較します。

機能 Ingress のアノテーション GKE Gateway のアノテーション 同等
URL の書き換え nginx.ingress.kubernetes.io/rewrite-target urlRewrite フィルタを使用した HTTPRoute 部分的に同等。GKE Gateway は、接頭辞の置換のみをサポートします。
ヘッダーの操作 nginx.ingress.kubernetes.io/proxy-set-headers または add-headers requestHeaderModifier 修飾子または responseHeaderModifier フィルタを使用した HTTPRoute 完全に同等。
パスベースの転送 Ingress オブジェクトの spec.rules.http.paths HTTPRoute オブジェクトの rules.matches.path 完全に同等。
ホストベースのルーティング Ingress オブジェクトの spec.rules.host HTTPRoute オブジェクトの hostnames 完全に同等。
トラフィック分割 nginx.ingress.kubernetes.io/canary アノテーション。 重み付けされた backendRefs を含む HTTPRoute 完全に同等。また、トラフィックをきめ細かく制御して分割できます。
認証 外部認証の nginx.ingress.kubernetes.io/auth-url
  • Identity-Aware Proxy(IAP): BackendPolicy CRD。
  • その他: サービス メッシュやカスタム フィルタなど、よりカスタムなアプローチが必要になります。
部分的に同等。Identity-Aware Proxy は、ゲートウェイを保護する推奨の方法であり、バックエンドで構成されます。

次のステップ