第1部:OpenRestyを使用してマイクロサービスAPIゲートウェイを構築する方法

API7.ai

January 20, 2023

OpenResty (NGINX + Lua)

この記事では、OpenRestyを活用した章に進んでいきます。マイクロサービスAPIゲートウェイを実装する方法を3つの章に分けて紹介します。この過程では、これまで学んだOpenRestyの知識だけでなく、業界、製品、技術選定など複数の次元から、新たな製品やオープンソースプロジェクトをゼロから構築する方法も示します。

マイクロサービスAPIゲートウェイの役割

まず、マイクロサービスAPIゲートウェイの役割を見てみましょう。以下の図はその概要を示しています。

マイクロサービスAPIゲートウェイ

ご存知の通り、APIゲートウェイは新しい概念ではありません。10年以上前から存在しており、その主な機能はトラフィックの入口として機能し、ビジネス関連のリクエストを一元的に処理することです。これにより、リクエストをより安全に、迅速に、正確に処理できます。従来の機能としては以下が挙げられます。

  • リバースプロキシとロードバランシング。これはNGINXの位置付けや機能と一致します。
  • 動的な機能、例えば動的なアップストリーム、動的なSSL証明書、実行時の動的なレート制限など。これらはオープンソース版のNGINXにはない機能です。
  • アップストリームのアクティブおよびパッシブなヘルスチェック、およびサービスのサーキットブレーカー。
  • APIゲートウェイを基に拡張し、フルライフサイクルのAPI管理プラットフォームとして機能させる。

近年、ビジネス関連のトラフィックはPCクライアントやブラウザだけでなく、スマートフォンやIoTデバイスからも発生するようになりました。将来的に5Gが普及すると、このトラフィックはさらに増加します。同時に、マイクロサービスアーキテクチャの構造が変化するにつれ、サービス間のトラフィックも爆発的に増加しています。この新しいビジネスシナリオにおいて、APIゲートウェイのより高度な機能が自然に求められるようになりました。

  1. クラウドネイティブに適していること。アーキテクチャは軽量で、コンテナ化が容易であるべきです。
  2. PrometheusZipkinSkyWalkingなどの統計および監視コンポーネントとの連携。
  3. gRPCプロキシのサポート、およびHTTPgRPC間のプロトコル変換。ユーザーのHTTPリクエストを内部サービスのgRPCリクエストに変換します。
  4. OpenID Relying Partyの役割を担い、Auth0やOktaなどの認証プロバイダーのサービスと連携し、トラフィックのセキュリティを最優先に扱います。
  5. 実行時にユーザー関数を動的に実行することでServerlessを実現し、ゲートウェイのエッジノードをより柔軟にします。
  6. ユーザーをロックせず、ハイブリッドクラウドデプロイメントアーキテクチャをサポートします。
  7. ゲートウェイノードはステートレスであり、自由に拡張・縮小できる必要があります。

マイクロサービスAPIゲートウェイが上記の機能を備えると、ユーザーのサービスはビジネス自体に集中できます。ビジネス実装に関係のない機能は、独立したゲートウェイレベルで解決できます。例えば、サービスディスカバリ、サーキットブレーカー、認証、レート制限、統計、パフォーマンス分析などです。

この観点から、APIゲートウェイはNGINXのすべての機能を置き換え、南北トラフィックを処理できます。また、IstioのコントロールプレーンやEnvoyのデータプレーンの役割を果たし、東西トラフィックを処理することもできます。

なぜ車輪の再発明をするのか?

マイクロサービスAPIゲートウェイの重要性が高いため、この分野は常に競争の場であり、従来のIT大手企業も長年この分野に取り組んでいます。Gartnerが2018年に発表したAPIライフサイクルレポートによると、Google、CA、IBM、Red Hat、Salesforceなどが主要なメーカーであり、開発者にとってより馴染み深いApache APISIXはビジョナリーに分類されています。

では、なぜ新しい車輪を再発明する必要があるのでしょうか?

簡単に言えば、現在のマイクロサービス向けAPIゲートウェイは私たちのニーズに十分対応していないからです。まず、クローズドソースの商用製品を見てみましょう。これらは機能が充実しており、API設計、多言語SDK、ドキュメント、テスト、リリースのフルライフサイクル管理をカバーし、SaaSサービスを提供しています。一部はパブリッククラウドと統合されており、非常に便利です。しかし同時に、2つの課題ももたらします。

1つ目の課題はプラットフォームロックインの問題です。APIゲートウェイはビジネストラフィックの入口であり、画像や動画などの非ビジネストラフィックを加速するCDNとは異なり、多くのビジネス関連ロジックがバインドされます。クローズドソースのソリューションを使用すると、他のプラットフォームにスムーズかつ低コストで移行するのは困難です。

2つ目の課題は再開発ができない問題です。一般的に、大中規模の企業には独自のニーズがあり、カスタマイズ開発が必要ですが、この場合、メーカーに依存するしかなく、二次開発ができません。

これがオープンソースのAPIゲートウェイソリューションが人気を集める理由の一つです。しかし、既存のオープンソース製品も万能ではなく、多くの欠点があります。

  1. PostgreSQLやMySQLなどのリレーショナルデータベースに依存しています。これにより、設定が変更されたときにゲートウェイノードがデータベースをポーリングするしかなく、設定が有効になるまでに時間がかかるだけでなく、コードの複雑さも増し、理解が難しくなります。同時に、データベースはシステムの単一障害点やパフォーマンスのボトルネックとなり、全体の高可用性を保証できません。Kubernetes環境でAPIゲートウェイを使用する場合、リレーショナルデータベースはさらに煩雑で、迅速なスケーリングには適していません。
  2. プラグインをホットロードできません。新しいプラグインを追加したり、既存のプラグインのコードを変更したりする場合、サービスをリロードする必要があります。これはNGINXの設定を変更した後にリロードする必要があるのと同じで、ユーザーリクエストに影響を与えます。
  3. コード構造が複雑で、把握が難しいです。一部のオープンソースプロジェクトは多層のオブジェクト指向カプセル化を行っており、単純なロジックがぼやけてしまっています。しかし、APIゲートウェイのシナリオでは、直接的な表現の方がより明確で効率的であり、二次開発にも適しています。

そのため、より軽量でクラウドネイティブ、開発者フレンドリーなAPIゲートウェイが必要です。もちろん、閉鎖的な環境で車を造るわけにはいきません。既存のAPIゲートウェイの特性を深く理解する必要があります。この時、Cloud Native Software Foundation(CNCF)のパノラマが良い参考になります。

CNCFのパノラマ

APIゲートウェイのコアコンポーネントと概念

もちろん、実装する前に、APIゲートウェイのコアコンポーネントを理解する必要があります。前述したAPIゲートウェイの機能に基づくと、少なくとも以下のコンポーネントが必要です。

1つ目はRouteです。クライアントのリクエストをいくつかのルールでマッチングし、マッチング結果に応じて対応するプラグインをロードして実行し、リクエストを指定されたアップストリームに転送します。これらのルーティングルールはhosturiheaderなどで構成されます。NGINXのlocationはルーティングの一つの実装です。

2つ目はプラグインです。APIゲートウェイの魂とも言えます。認証、トラフィック制限、IP制限、Prometheus、Zipkinなどの機能はすべてプラグインを通じて実装されます。プラグインであるため、プラグアンドプレイである必要があります。また、プラグイン同士が相互作用しないようにする必要があります。レゴブロックを組み立てるように、統一されたルールと開発インターフェースを使用して基盤とやり取りする必要があります。

次にschemaです。APIを処理するゲートウェイであるため、APIのフォーマットを検証する必要があります。例えば、データタイプ、許可されるフィールドの内容、必須のフィールドなどです。この時、schemaの層を設けて統一的な定義と検査を行います。

最後にストレージです。ユーザーの各種設定を保存し、変更があった場合にすべてのゲートウェイノードにプッシュする役割を担います。これは非常に重要な基盤コンポーネントです。その選択は、上層のプラグインの書き方、システムの高可用性や拡張性を維持できるかどうかなどを決定するため、慎重に決定する必要があります。

さらに、これらのコアコンポーネントの上に、APIゲートウェイの共通概念を抽象化する必要があります。これらは異なるAPIゲートウェイ間で共通しています。

Route

まずRouteについて説明します。ルートは3つの部分で構成されます。マッチング条件、バインドされたプラグイン、およびアップストリームです。以下の図に示す通りです。

Route

Route内で直接すべての設定を完了することが最も簡単です。しかし、APIやアップストリームが多い場合、これでは多くの重複設定が発生します。この時、ServiceUpstreamの2つの概念を使って抽象化する必要があります。

Service

次にServiceを見てみましょう。これは特定のタイプのAPIの抽象化であり、一連のRouteの抽象化と理解することもできます。通常、アップストリームサービスと1:1の対応関係があり、RouteServiceの関係は通常N:1です。以下の図で表現しました。

Service

Serviceの抽象化を通じて、重複するPluginUpstreamを分離できます。これにより、PluginUpstreamが変更された場合、複数のRouteにバインドされたデータを変更するのではなく、Serviceを変更するだけで済みます。

Upstream

最後にUpstreamについて説明します。上記の例を続けると、2つのRouteのアップストリームが同じで、バインドされたプラグインが異なる場合、アップストリームを別々に抽象化できます。以下の図に示す通りです。

Upstream

これにより、アップストリームノードが変更された場合、Routeは完全に気づかず、すべてUpstream内で処理されます。

これらの3つの主要な概念の導出プロセスからもわかるように、これらの抽象化は実用的なシナリオに基づいており、想像上のものではありません。これらは特定の技術ソリューションに関係なく、すべてのAPIゲートウェイに適用されます。

まとめ

この記事では、マイクロサービスAPIゲートウェイの役割、機能、コアコンポーネント、および抽象概念を紹介しました。これらはAPIゲートウェイの基礎です。

ここで考えてみてください。「従来の南北トラフィックとマイクロサービス間の東西トラフィックについて、APIゲートウェイが両方を処理できると思いますか?」もし既にAPIゲートウェイを使用している場合、技術選定に関する考えを書き留めることもできます。ぜひコミュニケーションやディスカッションに参加し、この記事を同僚や友人と共有して学びを深めてください。

次回: 第2部: OpenRestyを使用してマイクロサービスAPIゲートウェイを構築する方法
第3部: OpenRestyを使用してマイクロサービスAPIゲートウェイを構築する方法