Nod-REDを使ったAPI開発の実際
こんにちは、タケヒロです!
今回は、「ローコードでのAPI実装において、いかに可用性を高めるか」というテーマで、弊社で実際に行っている実装寄りの取り組みをご紹介します。
提携会社様と様々な情報のやりとりを行う手段のひとつとして、APIを用いたデータ連携があります。
API実装の際にはkintoneやSalesforceなどのSaaSのAPIを利用することもありますが、つい先日開始した新しいサービス開発では弊社でAPIをスクラッチで開発する必要があり、それにあたりプラットフォームやフレームワーク含めて採用技術の検討を行いました。
システム要件は以下のような感じです。
要件毎に実現した内容を挙げていきます。
具体的な手順や実装内容についてはネット上にたくさんの情報がありますが、いただいた質問にはなるべくお答えしますので、お気軽にコメントいただければ幸いです!
1.サクッと立ち上げ、なるべく楽に運用したい
まず、処理実装はNode-REDで行うことにしました。
Node-REDは「フローベースド」なプログラミングツールで、処理の単位となる「ノード」と、ノード間を流れるデータをネットワークとして視覚的に表現し、理解しやすく実装することができるのが特徴のフレームワーク(開発ツール)です。
「サクッと立ち上げ、楽に運用する」という点において、「視覚的に理解しやすい」ことは非常に強力です。
開発環境・体制が整っていれば、Node.js + Expressといった構成でAPI環境を作るというのも、比較的アジャイルにREST APIを公開するためのひとつの手段です。
ただ弊社のように専門の開発チームがない中で、ちょっとしたAPI機能を作るという要件においては、なるべくノーコード/ローコードで機能提供できることは大きなメリットです。
(このあたりは、前回、前々回の記事をご参考にしていただければと思います。)
その点で、Node-REDのような比較的学習障壁が低い開発環境はとても有利です。
プラットフォームは、弊社で既に採用しているAWSで、全体の構成としては以下のようなイメージになります。
Node-REDはEC2(Amazon Linux)に直接インストールしました。インスタンスファミリーはt.microなので、無料枠内です。
Node-REDはNode.jsで書かれたフレームワークで動作が軽く、今回のAPIもDBからの取得値を少し加工して返すだけの処理だったのでこれで充分です。
2.データソースはRDB(AWS RDS)とAWS S3
Node-REDは、標準で提供されている基本的なノードに加え、独自でノードを開発・共有することもできます。
また、開発された便利なノードはNode-RED Libraryでたくさん共有されており、標準外の機能を再利用することも可能です。
今回は、DB(MySQL)へのクエリ実行が必要なので、node-red-contrib-stackhero-mysqlというノードを使わせていただきました。
ノードの追加は、Node-REDのワークスペースのハンバーガーメニューから「パレットの管理」を選択し、「ノードを追加」から検索して行います。
また、今回は、RDSの他、S3のBucketに格納された画像ファイルへのアクセスも行うので、node-red-contrib-aws-sdkをインストールしました。
node-red-contrib-aws-sdkをインストールすると、aws sdkノードを使えるようになります。
aws sdkノードを使えば、以下のようにSDKを初期化するだけで、Node.jsのsdkライブラリを使用することができます。
日頃からAWS SDKを使っている方には非常に便利なのではないでしょうか。
const s3 = new AWS.S3();
3.24時間365日稼働
当APIは、24時間・365日の提供が必要なので、以下のふたつの対応を行いました。
■処理サーバの多重化
AWSの場合、サーバの多重化はとても簡単です。
Target Groupに、複数EC2インスタンスを追加し、ALB(Application Load Balancer)で指定するだけで自動的に振り分けを行ってくれます。
今回は、EC2にNode-REDをインストールした時点でスナップショットを取り、それを用いてEC2インスタンスを起動することで、インスタンスの複製を行いました。
■ヘルスチェック(死活監視)
更に、ヘルスチェック(死活監視)の機能を実装しました。
多重化されているとはいえ、例えばLoad Balancerやネームサーバ(Route 53)の障害でAPIにアクセスできないといった場合も考えられます。
そのような場合を想定し、公開したエンドポイントに対して外部から一定間隔でアクセスを行い、アクセスエラーが発生した際に障害通知させる方式の監視機能です。
今回は、APIサーバ(Node-RED)にヘルスチェック用のエンドポイントを実装し、Lambda関数を使用して5分おきにアクセスし、エラーの場合はSlack通知を行うような仕組みにしました。
4.特定のリクエスト元のみに接続を許可
当APIはインターネットに対して広く公開するものではなく、特定のサーバ(弊社提携先)からのみアクセスが必要なAPIです。
なので、無駄にどこからでもアクセスできる状態にしておくのはセキュリティ上好ましくありません。
またNode-REDで提供するのはAPI機能だけですが、(基本的に)同じURLで、Node-REDのワークスペースにもアクセスできてしまいます。
そこで特定のIPアドレスからのアクセスのみAPIにアクセス可能とし、また別のIPアドレス(弊社オフィス)からはワークスペースへのアクセスを許可することにします。
また、さらにセキュリティ強度を増すため、APIアクセスの際にはHTTPのリクエストヘッダにあらかじめリクエスト元に共有しておいたApiKeyを設定してもらい、それを検証することにしました。
AWSでは、Security Groupにポート番号とIPアドレスを指定することで、簡単にソースIP認証を行うことができます。ただ今回は、リクエスト対象のエンドポイント毎(API/ワークスペース)に、リクエスト元のIPアドレスの許可/非許可を別途設定し、かつAPIの場合はApiKeyの検証までさせるため、Security GroupではなくApplication Load Balancerのリスナー定義でこれらの制御を行うことにしました。
以下イメージのNo.2がAPIへのアクセスで、No.3がワークスペースへのアクセスに対する制限を定義している部分です。
No.1は、ヘルスチェック(死活監視)のために準備したエンドポイントになります。
5.異なるAWSアカウントで構築したDBへの接続
今回API機能を実装したAWSアカウントは、このサービスのために新規追加したアカウントですが、データソースとなるDBのうち、他のAWSアカウントで構築されたものがあります。
このように、別のAWSアカウント(または別のVPC)上にあるリソースにアクセスする方法はいくつか考えられますが、AWSであれば、VPC Peeringを利用するのが簡単です。
異なるVPC同士をPeering接続することで、例えばひとつのEC2上のアプリから、異なるVPCに定義されたRDSへのアクセスが可能となります。
ご参考までに、弊社で採用しているEAI(前回、前々回の記事ご参照)は、システム間連携ソリューションですが、その役割的に、異なるAWSアカウントで構築されたシステム間の連携を行うことが多くあります。
弊社の場合、EAIをEC2に導入していますが、複数のAWSアカウントで定義されたVPCとPeering設定を行うことで、シームレスに各リソースにアクセスできるようにしています。
VPC Peeringの設定には少しだけ知識が必要になりますが、それほど難しくはないので、ぜひ試してみていただければと思います。
以上、大分ざっくりですが、弊社でのAPI機能構築の例をご紹介しました。
個人的には、Node-REDはRaspberry Piにインストールし、IoTの勉強のために少し使ったことがある程度でした。
「導入は簡単だけど、ミッションクリティカルな業務へそのまま適用するには少し物足りない」という印象を勝手に抱いていましたが、その拡張性の高さから非機能要件をちゃんと補強してあげれば十分に実用に耐え得ることが分かりました。
今後もう少し運用機能(ログ出力や監視等)も補強し、さらに運用しやすいシステムに育てていこうと思っています。
●前回の記事
●次回の記事