2021年の間に配信したIngress コントローラーやサービスメッシュに関するほぼ全てのウェビナーで、以下のような質問をいただきます。”このツールはAPIゲートウェイとどう違うのか?”、”KubernetesではAPIゲートウェイとIngress コントローラー(またはサービスメッシュ)の両方が必要なのか?”
なぜこのような混乱があるのか。それは以下のような2つの理由が考えられます:
このブログでは、これらのツールの違いと、Kubernetesに特化したAPIゲートウェイのユースケースにどれを使うべきかを取り上げます。デモを含む詳細については、ウェビナー「API Gateway Use Cases for Kubernetes」をご覧ください。
APIゲートウェイ、Ingressコントローラー、サービスメッシュの中核機能がプロキシに相当する機能で、トラフィックをシステムに取り込み、またシステム内の制御を行うために設計されています。
APIゲートウェイは、クライアントからのAPIリクエストを適切なサービスへルーティングします。しかしこの単純な定義に対して、APIゲートウェイが独自の技術であるという大きな誤解があります。実際には、「APIゲートウェイ」は、様々なタイプのプロキシ(最も一般的なのはADCやロードバランサー、リバースプロキシ、そして最近ではIngress ControllerやService Mesh)を介して実装できるユースケースを総称してAPIゲートウェイと説明できます。
APIゲートウェイの役割を提供するツールにどのような機能が「必須」であるかについて、業界内ではあまり合意が得られておりません。私たちは通常、顧客が次のような機能を必要としていると考えています。(ユースケースごとに紹介します):
これらのユースケースのほとんどは、Kubernetesで一般的に使用されているものです。プロトコルの変換やリクエスト/レスポンスヘッダーとボディの操作は、Kubernetesやマイクロサービス環境には適していないレガシーAPIに用いられる場合があり、あまり一般的ではありません。
APIゲートウェイの使用例については、弊社ブログのDeploying NGINX as an API Gateway, Part 1で詳しく説明しています。
Ingress コントローラー(Kubernetes Ingress Controller、略してKIC)は、L4からL7に特化したプロキシで、Kubernetesにトラフィックを取り込み、サービスへ転送し、また外部への接続を行います。(ingress-egressまたはNorth-South トラフィック)トラフィック管理に加えて、Ingress Controllerは可視化、トラブルシューティング、セキュリティ、認証など、APIゲートウェイの特殊なユースケース以外のすべての機能を提供することができます。
Ingress Controllerを基本的なトラフィック管理以外にどのように利用できるかについては、ブログのIngressコントローラーの選択ガイド, Part 1: 要件の特定で詳しく説明されています。
Service Meshは、Kubernetesサービス間を流れるトラフィック(サービス間またはEast Westトラフィック)を処理し、一般的にエンドツーエンドの暗号化(E2EE)を実現するために使用されます。サービスメッシュの採用状況は多くありませんが、高度なデプロイメントを提供する場合やE2EEの要件がある組織で増加しています。サービスメッシュは、サービスメッシュサイドカーによってデータプレーンレベルで実現され、アプリケーションに非常に近い分散型(軽量)APIゲートウェイとして使用することができます。
Service Meshの詳細については、ブログの「サービスメッシュの選び方」を参照してください。
Mark Church氏がNGINX Sprint 2.0の基調講演「Kubernetes and the Future of Application Networking」で、「APIゲートウェイ、ロードバランサー、サービスメッシュは、同様の機能を提供し、今後もますますその役割は近くなっていくだろう」と語ったように、私たちはこの意見に心から同意し、さらに、どこで(そしてどのように)使うかに基づいて、適したツールを選ぶことが重要であると付け加えます。ナタもバターナイフも切るための道具ですが、ナタを朝のトーストに使うことはないでしょう。
それでは、どのように自分に合った道具を選べばいいのでしょうか?簡単に説明すると、Kubernetes内部でAPIゲートウェイ機能が必要な場合、通常はYAMLのようなKubernetesネイティブの設定ツールを使って設定できるツールを選ぶのがベストです。一般的には、Ingress コントローラーやサービスメッシュがそれにあたります。しかし、こんな声も聞こえてきます。「APIゲートウェイツールはIngressコントローラー(またはサービスメッシュ)よりも多くの機能を備えているのです。そうするとそれらを見逃すことになりませんか?」いいえ、そうではありません。多くの機能を持つことが良いツールの条件ではなく、特にKubernetesでは、そのツールの複雑さが命取りになることがあります。
注:Kubernetesネイティブ(Knativeではありません)とは、Kubernetesのために設計・構築されたツールのことを指します。一般的には、Kubernetes CLIで動作し、Helmを使ってインストールでき、Kubernetesの機能と統合されています。
ほとんどのKubernetesユーザは、Kubernetesネイティブな方法で設定できるツールを好みます。なぜなら、開発またはGitOpsエクスペリエンスへの変更を避けることができるからです。YAML フレンドリーなツールは、3 つの主要な利点をもたらします。
Ingress コントローラーは、多くのAPIゲートウェイのユースケースを可能にする可能性を秘めています。定義の項目で説明したものに加えて、私たちは組織がIngress コントローラーを実装することに最も価値を見出します。
APIリクエストのPOST
メソッドを拒否するために、Ingress コントローラーを使用して、メソッドレベルのマッチングとルーティングを実装したいとします。
攻撃者の中には、APIの定義に従わないリクエストタイプを送信することでAPIの脆弱性を探す者もいます。例えば、GETリクエストのみを受け付けると定義されているAPIにPOSTリクエストを送信するような場合です。ウェブアプリケーションファイアウォール(WAF)はリクエストの文字列とボディを見て、攻撃を判断するためこの種の攻撃を検知できません。したがって、IngressレイヤーでAPIゲートウェイを使用して不正なリクエストをブロックするのがベストプラクティスです。
例として、新しいAPI /coffee/{coffee-store}/brand
がクラスタに追加されたとします。最初のステップは NGINX Ingress Controller を使って API を公開することです。単に API をupstreams:フィールドに追加するだけです。
apiVersion: k8s.nginx.org/v1kind: VirtualServermetadata: name: cafespec: host: cafe.example.com tls: secret: cafe-secret upstreams: -name: tea service: tea-svc port: 80 -name: coffee service: coffee-svc port: 80
メソッドレベルのマッチングを有効にするには、routes
:フィールドに /coffee/{coffee-store}/brand
のパスを追加し、$request_method
変数を使用して GET
と POST
リクエストを区別する 2 つの条件を追加します。HTTP GET
メソッドを使用するトラフィックは、自動的に coffee
serviceに渡されます。POST
メソッドを使用したトラフィックは、”"You
are
rejected!"
“というメッセージとともにエラーページに誘導されます。このようにして、新しいAPIを不要なPOST
トラフィックから保護することができます。
routes: - path: /coffee/{coffee-store}/brand matches: - conditions: - variable: $request_method value: POST action: return: code: 403 type: text/plain body: "You are rejected!" - conditions: - variable: $request_method value: GET action: pass: coffee - path: /tea action: pass:tea
エラーページでメソッドレベルのルーティングとマッチングを使用する方法の詳細については、NGINX Ingress Controller docsをご覧ください。APIゲートウェイ機能にIngress コントローラーを使用したセキュリティ関連の例については、ブログ記事、OktaとNGINX Ingress ControllerによるKubernetes向けOpenID Connect認証の実装をご覧ください。
サービスメッシュはほとんどのAPIゲートウェイのユースケースに必須ではなく、多くの要件はIngressレイヤーで実現可能です。しかし、アーキテクチャが複雑化すればするほど、サービスメッシュの利用価値が高まります。最も有益だと考えるユースケースは、E2EEとトラフィック分割に関連するもので、A/Bテスト、カナリアデプロイメント、ブルーグリーンデプロイメントなどが挙げられます。
HTTP/Sの基準に基づく条件付きルーティングで、サービス間のカナリアデプロイメントを設定したいとします。
この利点は、新機能や新バージョンなどのAPI変更を、本番トラフィックの大部分に影響を与えることなく、徐々に展開できることです。
現在、NGINX Ingress コントローラーはNGINX サービスメッシュによって管理される2つのサービス間でトラフィックをルーティングしています。Coffee.frontdoor.svc
とTea.frontdoor.svc
です。これらのサービスはNGINX Ingress Controllerからトラフィックを受け取り、Tea.cream1.svc
などの適切なアプリにルーティングします。Tea.cream1.svc
をリファクタリングして、新しいバージョンをTea.cream2.svc
と呼ぶことにします。ベータテスターに新しい機能についてのフィードバックを提供するため、ベータテスターの固有のセッション Cookie に基づいてカナリアトラフィックのスプリットを構成し、通常のユーザが Tea.cream1.svc
のみを利用できるようにします。
NGINX Service Meshを使用して、Tea.frontdoor.svc
をフロントとするすべてのサービス(Tea.cream1.svc
とTea.cream2.svc
など)の間でトラフィックを分割することから始めます。 条件付きルーティングを有効にするには、HTTPRouteGroup
リソース(tea-hrg
という名前)を作成し、それをTrafficSplitに関連付けます。 その結果、ベータユーザーからのリクエスト(セッションクッキーをversion=beta
に設定したリクエスト)だけがTea.frontdoor.svc
からTea.cream2.svc
にルーティングされることになります。一般ユーザは引き続きTea.frontdoor.svc
の後ろでバージョン1のサービスのみを利用することになります。
apiVersion: split.smi-spec.io/v1alpha3kind: TrafficSplitmetadata: name: tea-svcspec: service: tea.1 backends: - service: tea.1 weight: 0 - service: tea.2 weight: 100 matches: - kind: HTTPRouteGroup name: tea-hrgapiVersion: specs.smi-spec.io/v1alpha3kind: HTTPRouteGroupmetadata: name: tea-hrg namespace: defaultspec: matches: - name: beta-session-cookie headers: - cookie: "version=beta"
この例では、ベータテスター全員がTea.cream2.svc
を利用することを意味する0:100の分割でカナリア展開を開始しますが、もちろんベータテストの実施方法に沿った任意の比率で開始することができます。 ベータテストが完了したら、シンプルなカナリアデプロイメント(Cookie ルーティングなし)を使用して、Tea.cream2.svc
の動作状況をテストすることができます。
NGINX サービスメッシュによるトラフィックの分割の詳細については、当社のドキュメントを参照してください。上記のトラフィックの分割設定は、ルートサービスがバックエンドサービスとしてリストされているため、自身を参照する形となります。この構成は現在Service Mesh Interface specification(smi-spec)ではサポートされていませんが、この仕様は現在アルファ版であり、変更される可能性があります。
KubernetesのAPIゲートウェイのほとんどのユースケースはIngress コントローラーやサービスメッシュで対応できますが、NGINX PlusのようなAPIゲートウェイツールが適している状況もあります。
複数のチームやプロジェクトで、Ingress コントローラーのセットを共有したり、Ingress コントローラーを環境ごとに特化させることはできますが、既存のIngress コントローラーを活用するのではなく、Kubernetes内部に専用のAPIゲートウェイをデプロイすることを選択する理由もあると考えられます。Kubernetes 内でIngress Controllerと API ゲートウェイの両方を使用することで、組織がビジネス要件を達成するための柔軟性を提供することができます。いくつかのシナリオを紹介します。
既存のAPIをKubernetes環境に移行する場合、それらのAPIをKubernetesの外に展開されたAPIゲートウェイツールに公開することができます。このシナリオでは、APIトラフィックは通常、外部のロードバランサー(クラスタ間の負荷分散用)を経由して、APIゲートウェイとして機能するように構成されたロードバランサーに送られ、最後にKubernetesクラスタ内のIngress Controllerに送られます。
最近のAPIのほとんどはRESTを使って作成されていますが、RESTfulまたはgRPCのサービスやAPIはKubernetesプラットフォームを最大限に活用できることもあり、構成変更のされていないSOAP APIがまだ残っている可能性があります。SOAP APIはマイクロサービス向けに最適化されていないため、Kubernetesには推奨されませんが、構成変更されるまでSOAP APIをKubernetesにデプロイする必要が出てくるかもしれません。APIはRESTベースのAPIクライアントと通信する必要がある可能性が高く、その場合、SOAPとRESTのプロトコル間を変換する方法が必要です。この機能をIngress コントローラーで実行することもできますが、非常に多くのリソースを必要とするため、推奨ではありません。代わりに、SOAPとRESTの間を変換するために、APIゲートウェイツールをPodごと、あるいはサービスごとのプロキシとしてデプロイすることをお勧めします。
Kubernetes環境の内外にまたがるAPIの管理に関心を持つお客様は、比較するとあまり多くはありません。API管理の方針がKubernetesネイティブツールの選択よりも優先される場合、KubernetesにデプロイされたKubernetesフレンドリーなAPIゲートウェイ(API管理ソリューションと統合できる)が良い選択かもしれません。
注:Kubernetesフレンドリーツール(Kubernetes-accommodative(協調的)とも呼ばれる)はKubernetes向けに設計されておらず、Kubernetesの設定を使用した管理はできません。しかし、軽快で軽量なため、大きなレイテンシーの追加や大規模なワークアラウンドを必要とせず、Kubernetesで実行することが可能です。
NGINXは、3種類のデプロイメントシナリオすべてに対応するオプションを提供しています。
Kubernetesネイティブなツール:
NGINX App Protect WAFとDoSを備えたNGINX Ingress Controllerの30日間無料トライアルを提供しております。
Kubernetes環境内外のKubernetesフレンドリーなAPIゲートウェイ:
APIゲートウェイとしてのNGINX Plusの使用についての詳細は、30日間の無料トライアルをリクエストし、弊社ブログのDeploying NGINX as an API Gateway, Part 1をご覧ください。
"This blog post may reference products that are no longer available and/or no longer supported. For the most current information about available F5 NGINX products and solutions, explore our NGINX product family. NGINX is now part of F5. All previous NGINX.com links will redirect to similar NGINX content on F5.com."