2021年の間に配信したIngress コントローラーやサービスメッシュに関するほぼ全てのウェビナーで、以下のような質問をいただきます。”このツールはAPIゲートウェイとどう違うのか?”、”KubernetesではAPIゲートウェイとIngress コントローラー(またはサービスメッシュ)の両方が必要なのか?”
なぜこのような混乱があるのか。それは以下のような2つの理由が考えられます:
- Ingress コントローラーとサービスメッシュは多くの API ゲートウェイのユースケースを満たすことができます。
- ベンダーによっては、APIゲートウェイツールをIngress コントローラーやサービスメッシュの代替として位置づけ、あるいは3つの機能すべてを1つのツールにまとめています。
このブログでは、これらのツールの違いと、Kubernetesに特化したAPIゲートウェイのユースケースにどれを使うべきかを取り上げます。デモを含む詳細については、ウェビナー「API Gateway Use Cases for Kubernetes」をご覧ください。
定義
APIゲートウェイ、Ingressコントローラー、サービスメッシュの中核機能がプロキシに相当する機能で、トラフィックをシステムに取り込み、またシステム内の制御を行うために設計されています。
APIゲートウェイとは?
APIゲートウェイは、クライアントからのAPIリクエストを適切なサービスへルーティングします。しかしこの単純な定義に対して、APIゲートウェイが独自の技術であるという大きな誤解があります。実際には、「APIゲートウェイ」は、様々なタイプのプロキシ(最も一般的なのはADCやロードバランサー、リバースプロキシ、そして最近ではIngress ControllerやService Mesh)を介して実装できるユースケースを総称してAPIゲートウェイと説明できます。
APIゲートウェイの役割を提供するツールにどのような機能が「必須」であるかについて、業界内ではあまり合意が得られておりません。私たちは通常、顧客が次のような機能を必要としていると考えています。(ユースケースごとに紹介します):
レジリエンスのユースケース
- A/Bテスト、カナリアデプロイメント、ブルーグリーンデプロイメント
- プロトコルの変換(JSONとXML間など)
- レート制限
- サービスディスカバリ
トラフィックマネジメントのユースケース
- メソッドベースのルーティングとマッチング
- リクエスト/レスポンスヘッダーとボディの操作
- L7リクエストルーティング
セキュリティのユースケース
- APIスキーマの強制
- クライアント認証・認可
- カスタムレスポンス
- 詳細なアクセス制御
- TLSターミネーション
これらのユースケースのほとんどは、Kubernetesで一般的に使用されているものです。プロトコルの変換やリクエスト/レスポンスヘッダーとボディの操作は、Kubernetesやマイクロサービス環境には適していないレガシーAPIに用いられる場合があり、あまり一般的ではありません。
APIゲートウェイの使用例については、弊社ブログのDeploying NGINX as an API Gateway, Part 1で詳しく説明しています。
Ingress コントローラーとは?
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の詳細については、ブログの「サービスメッシュの選び方」を参照してください。
Kubernetes環境でKubernetesネイティブツールを使用する
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 つの主要な利点をもたらします。
- YAMLはKubernetesを利用するチームにとって馴染みのある言語なので、もしAPIゲートウェイ機能として既存のKubernetesのツールを使用している場合、学習曲線を小さく、またはほぼゼロにすることがあります。このため、使用頻度がそれほど高く無いかもしれない新しいツールの設定方法を学ぶ必要がなく、チームが既存のスキルセット内で作業することができます。
- 他のKubernetesツールと同じ方法で、YAMLフレンドリーなツールを自動化することができます。既存のワークフローで簡単に利用できることで、チームに歓迎されるでしょう。そうすることでツールが利用される確率が高くなります。
- Ingress コントローラー、サービスメッシュ、またはその両方を使用することで、Kubernetesのトラフィック管理ツールスタックを小さく抑えることができます。結局のところ、すべての余分なホップは問題であり、不必要なレイテンシーや単一障害点を追加する理由はありません。そしてもちろん、Kubernetes内にデプロイされるテクノロジーの数を減らすことは、予算と全体的なセキュリティにとっても良いことです。
North-South API Gatewayのユースケース:Ingress コントローラーの利用
Ingress コントローラーは、多くのAPIゲートウェイのユースケースを可能にする可能性を秘めています。定義の項目で説明したものに加えて、私たちは組織がIngress コントローラーを実装することに最も価値を見出します。
- 認証と認可のオフロード
- 認証ベースのルーティング
- レイヤー7レベルのルーティングとマッチング(HTTP、HTTP/S、ヘッダー、Cookie、メソッド)
- プロトコルの互換性 (HTTP、HTTP/2、WebSocket、gRPC)
- レート制限
サンプルシナリオ:メソッドレベルのルーティング
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/v1
kind: VirtualServer
metadata:
name: cafe
spec:
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認証の実装をご覧ください。
East-West API Gateway のユースケース: サービスメッシュの利用
サービスメッシュはほとんどの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/v1alpha3
kind: TrafficSplit
metadata:
name: tea-svc
spec:
service: tea.1
backends:
- service: tea.1
weight: 0
- service: tea.2
weight: 100
matches:
- kind: HTTPRouteGroup
name: tea-hrg
apiVersion: specs.smi-spec.io/v1alpha3
kind: HTTPRouteGroup
metadata:
name: tea-hrg
namespace: default
spec:
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ゲートウェイツールを使用するタイミングと方法
KubernetesのAPIゲートウェイのほとんどのユースケースはIngress コントローラーやサービスメッシュで対応できますが、NGINX PlusのようなAPIゲートウェイツールが適している状況もあります。
ビジネス要件
複数のチームやプロジェクトで、Ingress コントローラーのセットを共有したり、Ingress コントローラーを環境ごとに特化させることはできますが、既存のIngress コントローラーを活用するのではなく、Kubernetes内部に専用のAPIゲートウェイをデプロイすることを選択する理由もあると考えられます。Kubernetes 内でIngress Controllerと API ゲートウェイの両方を使用することで、組織がビジネス要件を達成するための柔軟性を提供することができます。いくつかのシナリオを紹介します。
- APIゲートウェイ担当者がKubernetesに慣れておらず、YAMLを使わない場合、例えば、担当者がNGINX configに慣れているのであれば、NGINX PlusをKubernetesのAPIゲートウェイとしてデプロイすることで、その変更の手間が軽減され学習曲線が小さくなります。
- プラットフォーム運用チームは、Ingress Controllerをアプリのトラフィック管理のみに使用することを希望しています。
- クラスタ内の1つのサービスのみに適用されるAPIゲートウェイのユースケースがあります。Ingress コントローラーを使ってNorth-Southのトラフィックすべてにポリシーを適用するのではなく、APIゲートウェイをデプロイして必要なところだけにポリシーを適用することができます。
Kubernetes環境へのAPIの移行
既存のAPIをKubernetes環境に移行する場合、それらのAPIをKubernetesの外に展開されたAPIゲートウェイツールに公開することができます。このシナリオでは、APIトラフィックは通常、外部のロードバランサー(クラスタ間の負荷分散用)を経由して、APIゲートウェイとして機能するように構成されたロードバランサーに送られ、最後にKubernetesクラスタ内のIngress Controllerに送られます。
KubernetesにおけるSOAP APIのサポート
最近の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トラフィック管理
Kubernetes環境の内外にまたがるAPIの管理に関心を持つお客様は、比較するとあまり多くはありません。API管理の方針がKubernetesネイティブツールの選択よりも優先される場合、KubernetesにデプロイされたKubernetesフレンドリーなAPIゲートウェイ(API管理ソリューションと統合できる)が良い選択かもしれません。
注:Kubernetesフレンドリーツール(Kubernetes-accommodative(協調的)とも呼ばれる)はKubernetes向けに設計されておらず、Kubernetesの設定を使用した管理はできません。しかし、軽快で軽量なため、大きなレイテンシーの追加や大規模なワークアラウンドを必要とせず、Kubernetesで実行することが可能です。
NGINX入門
NGINXは、3種類のデプロイメントシナリオすべてに対応するオプションを提供しています。
Kubernetesネイティブなツール:
- NGINX Ingress Controller – Kubernetes向けのNGINX PlusベースのIngress Controllerで、高度なトラフィック制御とシェーピング、監視と可視化、認証とシングルサインオン(SSO)を提供します。
- NGINX Service Mesh – エンタープライズサイドカーとしてNGINX Plusを搭載した、軽量ですぐに利用できる、開発者に優しいサービスメッシュです。
NGINX App Protect WAFとDoSを備えたNGINX Ingress Controllerの30日間無料トライアルを提供しております。
Kubernetes環境内外のKubernetesフレンドリーなAPIゲートウェイ:
- NGINX Plus – 高可用性、アクティブヘルスチェック、DNSシステムディスカバリ、セッションパーシステンス、RESTful APIなどのエンタープライズグレードの機能を備えた、ロードバランサー、リバースプロキシ、Webサーバー、APIゲートウェイのオールインワン製品です。NGINX Controllerと統合し、完全なAPIライフサイクルソリューションとして利用できます。
APIゲートウェイとしてのNGINX Plusの使用についての詳細は、30日間の無料トライアルをリクエストし、弊社ブログのDeploying NGINX as an API Gateway, Part 1をご覧ください。