※ 当ページには【広告/PR】を含む場合があります。
2023/04/15
2024/01/11
Serverless FrameworkでもAWS で「APIGateway」→「VPC Lambda」→「EFS」を一発で構築してみる
お久しぶりの純度100%のAWSネタです。今回はLambdaの比較的新しい機能である「VPC Lambda」をシンプルに理解する上で、CloudFormationのようなサーバレス構築ツール無しに、ダッシュボードから手動でポチポチと設定していきます。近年サーバレスでの利用パターンとして注目も集まっている「APIGateway → VPC Lambda → EFS」での連携パターンを作成してみます。簡略的な構築イメージとしては、以下のような構成を試します。この記事では、VPC LambdaをAWSダッシュボードから手っ取り早く"Hello World"するための手順を順次確認していきます。以降で順を追って作業の中身を細かく説明していきます。
【AWS独習術】AWSをじっくり独学したい人のためのオススメ書籍&教材特集
図解即戦力 Amazon Web Servicesのしくみと技術がこれ1冊でしっかりわかる教科書 VPC Lambdaを使うための事前準備
まずは本題に入る前に、事前に覚えておかなければならない用語や、VPC LammbdaからEFSを使うために理解しなければならない知識を復習しておきます。EFSの仕組みをおさらい
EFSは一種の"外付けハードディスク"のような使い方をする仮想ファイルシステムです。通常EFSは、EC2インスタンス(のファイルシステム)にデバイスマウントすることによって、EFSの保持するファイルの読み書き・実行を行うことができます。ここでの「EC2にEFSをマウントする」というのは、一般にやるようなLinuxパソコンにUSBストレージをデバイスマウントさせることとは異なる仕組みを持ちます。AWS公式の技術リファレンスから、一つのVPC内に存在するEC2とEFSの構成図の一例を拝借して説明すると、参考|Amazon EFS の仕組み - AWSドキュメントまず、EFSは一つのVPCに所属
していることがわかります。EFS単体では、あくまでも「スケーラブルな拡張ファイルシステム」であり、そのままだと何もできない状態です。そこで、このEFSをVPC内にあるEC2インスタンスに接続するためには、「マウントターゲット(MT)」を作成しなければなりません。MTはサブネットグループを担当する各アベイラビリティゾーン(AZ)に最低1つ設置することで、同一AZに存在するEC2インスタンスとの通信が可能となり、EFSへのアクセスが可能となります。図を観てのとおり、MTはネットワークインターフェイス(ENI)の一種で、AZからサブネットIPが一つ割り当てられることが分かります。ここでのポイントは、「EFS自体にサブネットIPを直接割り当てるわけではない」という点です。これをしっかりと理解しておくと、後述する少々ややこしいEFSのネットワーク設定
につまずくこともないでしょう。LambdaからEFSを使うためのアクセスポイントの必要性
かつてのEFSアクセスポイントが導入される以前の構成から説明していきましょう。通常、Lambdaは特定のAZには所属せず、VPC内に作成されます。逆にいうと、ユーザーが特定のサブネットIP制限しなければLambdaはVPC内のすべてのAZに所属することになります。これがまずいことに、1つのLambdaであっても、VPC内に存在するAZ(MT)の数だけサブネットIPが割り当てられてしまうため、LambdaがすべてのMTへアタッチに時間(コールドスタート時間)と、Lambdaの処理実行時間が長くなってしまうおそれがあります。また、VPCに存在するLambdaの数によっては、サブネットIPがあっという間に枯渇してしまうことも懸念されます。こういったかつての課題を解決するために、Lambdaには「Hyperplane ENI」、EFSに「アクセスポイント」という仕組みが新たに追加されました。先程の構成例の図を現状の構成に修正したものが以下になります。長くなるのでここでは深堀りしませんがHyperplane ENI
については、以下の解説ブログで詳しく説明されていて読み物としても面白いです。参考|VPC Lambdaを実現しているAWS内の裏側と設計の心得三箇条これらの仕組みを使うことで、VPC Lambdaへ紐付けされるAZ(サブネットグループ)を簡単に選択でき、Lambdaに割り当てるサブネットIPを制御できるようになります。また、同一のVPC内に複数のVPC Lambdaが存在したとしても、Hyperplane ENI
を可能な限り自動でIPを共有してくれるので、無駄にサブネットIPを消費して枯渇してしまうことも防いでくれます。もう一つ大きな変更点として、「セキュリティグループ」と呼ばれるファイヤーウォールとして機能するフィルタールールも利用できるようになりました。一つのVPC Lambdaには一つのセキュリティグループを、EFSアクセスポイントは各MTごとに一つのセキュリティグループをそれぞれ設定することができます。具体的なセキュリティグループの設定に関しては後述しています。アクセスポイントの「マウントパス」と「ルートパス」
後述する設定手順でも出てきますが、EFSアクセスポイントの設定の用法として注意したいのが、「マウントパス」と「ルートパス」です。この二つのパスの違いを詳しく解説されている海外の技術ブログから拝借しますと、出典|Using Elastic File System (EFS) with AWS Lambdaというように理解しやすく図解されております。まず、マウントパス
とは、VPC Lambda側に設定するものです。AWSダッシュボードからは[Lambda] > [関数] > VPC Lamnda関数名 > [設定] > [ファイルシステム]
から確認できますが、VPC Lambda側での正式名は「ローカルマウントパス」
です。Lambdaの実体もEC2同様のLinuxインスタンスですので、Lambda自身も内部にローカルファイルシステムを保持しています。そして、EFSのアクセスポイント接続先を内部のローカルファイルシステムにマウントする場所が、「ローカルマウントパス」
です。ファイルパスはユーザーが自由に決めて良いのですが、この例では/mnt/msg
とされています。通例として/mnt
以下のディレクトリを使うことがほとんどでしょう。EFSがマウントされると、このLambdaは/mnt/msg
のフォルダから、EFSの中身にアクセスすることができます。他方、ルートパス
とは、EFSアクセスポイントの接続先の仮想ディレクトリ名です。これはEFSのルートディレクトリを直接外部に晒したくない場合や、フォルダごとにユーザーアクセスを制御したい場合に役に立つ設定です。この例ではEFSの/lambda
ディレクトリ以下がマウントの対象になり、同層にある/foldfer1
などはLambda側からアクセスすることはできません。つまり、この例をマウントすると、/mnt/msg(VPC Lambdaマウントパス) <--> EFSルートパス /lambda
がアクセスポイントを通じて接続されると理解できます。LambdaのIAMロール
まず前提として、VPC LambdaをVPC内で生成するためのIAMロールが必要になってきます。LambdaをVPCに配置するときにENI(Elastic Network Interface)が一つ付与されることで、LambdaがVPCのインスタンス等に通信が可能になります。そこで、ENIを生成するポリシー・AWSLambdaVPCAccessExecutionRole
がVPC Lamdbaに必要になります。また、VPC Lambdaの用途や目的に応じて、EFSへの操作権限も細かく付与する必要があることも押さえておきましょう。今回はHello World程度の練習ですので必要ないのですが、VPC LambdaからEFSへの読み書きにAmazonElasticFileSystemClientReadWriteAccess
相当のポリシーも必要になります。独自ロールで書くと、だいたい下のようなものを割り当てます。企業の部署内などで、IAMユーザーのロールを直接編集できないのであればその旨を管理者に相談してください。
【AWS独習術】AWSをじっくり独学したい人のためのオススメ書籍&教材特集
図解即戦力 Amazon Web Servicesのしくみと技術がこれ1冊でしっかりわかる教科書 VPCにセキュリティグループを設定する
VPCは新しく作成しても良いですが、ここではデフォルトVPC
にそのままLambdaをアタッチしていくことを考えます。まずVPCで行うことは、「セキュリティグループの設置」です。セキュリティグループはネットワークでいうところのVPC版ファイヤーウォールですので、本番環境で使う際にはしっかりとセキュリティグループの「インバウンドルール」と「アウトバウンドルール」を設計する必要があります。なおここでは、"Hello World"を試したいだけですので、さほどたいしたフィルターの設置は検討しません。セキュリティグループの設計は様々な考え方がありますが今回は、EFSを使うためのVPS Lambdaのセキュリティグループ・lambda-sg
と、EFS自体に使うセキュリティグループ・efs-sg
を分けて作成します。まずlambda-sg
はインバウンドで送信元の全てのトラフィックを受け取り、送信先はEFS(ポート2049)に絞ってアウトバウンドのルールをつけてみました。次にefs-sg
では、EFS用のポート・2049以外のTCPパケットは落とし、さらに送信元をlambda-sg
限定に指定しています。アウトバウンドは特にフィルターするルールは設置していません。今回は必要最低限のファイヤーウォールとしてVPC Lambda/EFSにつけておけば良いでしょう。
【AWS独習術】AWSをじっくり独学したい人のためのオススメ書籍&教材特集
図解即戦力 Amazon Web Servicesのしくみと技術がこれ1冊でしっかりわかる教科書 EFSとアクセスポイントを生成する
では「EFS」のダッシュボードに移りを新規でファイルシステムを作成してみます。EFSの配置先のVPCを指定するほかは全てデフォルトの設定のままMyFileSystem
という名前で作成します。もう一つ、EFSのLinux側へのマウント設定に「アクセスポイント」が必要になります。アクセスポイントは、先程作成したファイルシステムにマウントされる時に作成される仮想のルートフォルダとして機能します。例えばアクセスポイントを適当に一つ"Hello World"用にhello-func-ap
というアクセスポイントを作ってみましょう。一つのアクセスポイントには、その実行プロセスを代表するPOSIXユーザー
も作成されます。ファイルシステムに対して、多数のアクセスポイントを作成することができるので、「EFS内で実現するマイクロコンテナシステム」と言っても良いでしょう。よってアクセスポイントで、様々な用途別に切り分けるような使い方が可能です。マウントターゲットのセキュリティグループには要注意
※2023/04/19更新分 ... マウントターゲットに指定するセキュリティグループが間違っていたので差し替えました。失礼しました。個人的な経験上、VPC LambdaとVPC内部で通信がうまくいかない原因を探してえらく時間を取られてしまったポイントでもあります。通常、EFSのファイルシステムをデフォルトで作成すると、ENIをはじめとするネットワーク設定が自動で割り当てされます。[ファイルシステム] > 作成したFS > [ネットワーク]
を覗くと、EFSに割り当てされたネットワークの諸元がリストとして確認できます。何も指定がない場合、リストのセキュリティグループ
には、自動でデフォルトセキュリティグループ
がデフォルトで設定されます。よって、先程独自にカスタマイズしたセキュリティグループ(ここではefs-sg
)が自動では選択されないことに注意が必要です。そこで、リストの右上の[管理]
のボタンを押し、各マウントターゲットのセキュリティグループを正しく指定し直します。これで、アクセスポイントにマウントされたVPC Lambdaのセキュリティグループが正しく紐つけされている状態になります。
【AWS独習術】AWSをじっくり独学したい人のためのオススメ書籍&教材特集
図解即戦力 Amazon Web Servicesのしくみと技術がこれ1冊でしっかりわかる教科書 VPC Lambdaを作成する
次にいよいよ「VPC Lambda」を作成していきます。Lambdaのダッシュボードから作業しますが、注意が必要なのは、「VPC LambdaとEFSは同一のリージョンに設置する」必要があります。異なるリージョンや他のVPCを超えてVPC Lambdaを通信したい場合には、別途、NATGatewayやEIPなどのパブリック設定を行わないといけなくなります。ここではランタイムをnode18
もしくはnode20
に選択しています。また、Lambdaの実行ロールに上述した事前準備していたロールを割り当てましょう。Lambda生成後にindex.mjs
で、とりあえずレスポンスの中身だけ変えておきましょう。このままでは通常のLambdaですので、ここからVPC仕様に設定を続けます。まず[設定] > [VPC]
とたどり、[編集]
からVPCの編集
を設定していきます。Lambdaを設置するVPCを指定し、VPC Lambdaが利用するローカルIPのサブネットの範囲、そしてセキュリティグループ(ここでがlambda-sg
)を指定して、[保存]
ボタンを押します。エラーが出なければ、LambdaがVPC Lambdaとして認識され、ファイルシステムの割り当てが有効になります。[設定] > [ファイルシステム]
とたどり、[ファイルシステムの追加]
をクリックしましょう。このVPC Lambdaに、先程作成したEFSとそのアクセスポイント、マウント先のLinuxインスタンスからみた絶対パスをそれぞれ設定します。これで、このVPC Lambda・myHelloVPCLambda
は、アクセスポイント・hello-func-ap
に属したプロセスで走ることになります。セットアップができたら一度、[テスト]
でテストを実行してみましょう。問題がなければ、VPC Lambdaが仕上がっています。もし、Network Error
などでパケットがVPC内で送信・受信されていないようなら、セキュリティグループ周りの設定などを疑ってみてください。
【AWS独習術】AWSをじっくり独学したい人のためのオススメ書籍&教材特集
図解即戦力 Amazon Web Servicesのしくみと技術がこれ1冊でしっかりわかる教科書 APIGatewayとの紐付け
先程までで、VPC Lambdaが構築できましたが、ここからはAPIGatewayとVPC Lambdaを紐つけて、外部からアクセスする方法を簡単に試してみたいと思います。従来型のREST APIでも呼び出せるかも知れませんが、ここでは「HTTP API(APIGatewayV2)」を利用します。APIGatewayのダッシュボードから[APIの作成] > HTTP API [構築]
をクリックします。まずはAPIの作成から設定します。APIGatewayにLambdaを割り当てるには、統合
を作成する必要があります。統合のタイプからLambda
、リージョンはVPC Lambdaと同一の地域、そして先程作成したVPC Lambdaを選択して、myHelloVPCLambdaAPI
と名付けて[次へ]
を押します。次にAPIルートの設定をします。特に"Hello World"を返すだけなのでANY
メソッドを指定しておきます。最後にデプロイするステージもシステムにおまかせ($default
)します。内容を確認して、APIをそのまま以下の内容でデプロイさせます。作成&デプロイが完了できたらAPIエンドポイント(ここではhttps://<hash値>.execute-api.ap-northeast-1.amazonaws.com/myHelloVPCLambda
)にブラウザからアクセスしてみましょう。うまくレスポンスが返ってくればOKです!めでたしめでたし。
【AWS独習術】AWSをじっくり独学したい人のためのオススメ書籍&教材特集
図解即戦力 Amazon Web Servicesのしくみと技術がこれ1冊でしっかりわかる教科書 まとめ
ということで「VPC Lambda」でのHello Worldのまでの手順は以上で完了です。とはいえ、肝心のマウントしたEFS自体にはアクセスしてはいないので、次回以降では「AWS Datasync」を使った簡単なファイルをVPC Lambdaから読み書きしてみたいと思います。参考サイト
Lambda から共有ファイルストレージの EFS が利用可能になりました!