Amazon EFSを作成し、EC2にマウント、Lambdaからアクセスできるようにしてみました。
前提条件
- VPC、EFS、EC2は同一リージョンに作成する(今回は東京リージョンを使用)
- LambdaはEFSに到達できるVPCに接続する必要がある
- プライベートサブネットが作成済みの状態から開始する
- EC2へSSH接続を行うためのキーペアが作成済みの状態から開始する
この記事のゴール
- Amazon EFSを作成し、LambdaからEFS内のファイルを操作する
- EC2にEFSをマウントし、EFS内のファイルを操作する
この記事で扱わないこと
- VPCの作成方法
- パブリックサブネット、プライベートサブネットの作成・設定方法
- EC2インスタンスへのSSH接続方法
必要なもの
- IAMユーザ
環境情報
# AWSリージョン
東京(ap-northeast-1)
# EC2
AMI:Amazon Linux 2 AMI (HVM), SSD Volume Type
# Lambda
ランタイム:Java 11(Corretto)
手順
AWSコンソールにて作成、設定してみる
① セキュリティグループの作成
② EFSの作成
③ EC2の作成
④ Lambdaの作成
⑤ EC2から接続
⑥ Lambdaから接続
AWSコンソールにて作成、設定してみる
① セキュリティグループの作成
(参考)公式ユーザーガイド - EFSリソースの使用 - セキュリティグループの作成
EC2用のセキュリティグループ
Lambda用セキュリティグループ
Lambdaにはデフォルトのセキュリティグループを使用するため作成しません。
EFS用セキュリティグループ
EC2用セキュリティグループと、Lambda用セキュリティグループからのインバウンドアクセスを許可します。
② EFSの作成
(参考)公式ユーザーガイド - EFS リソースの使用 - ファイルシステムの作成
EFSコンソールで「カスタマイズ」を選択してファイルシステムを作成します。
ファイルシステム設定
ネットワークアクセス設定
- VPC:Lambdaを接続するVPCを選択します。(今回はデフォルトVPCを使用)
- アベイラビリティーゾーン:デフォルトではリージョンの各アベイラビリティーゾーンが選択されています。不要なアベイラビリティゾーンがある場合は削除します。
- サブネットID:Lambdaを作成するサブネットを選択します。(今回はプライベートサブネットを使用)
- セキュリティグループ:①で作成したEFS用セキュリティグループを選択します。
ファイルシステムポリシー
EFSファイルシステムへ接続する際に、IAMロールを使用して、読み取り専用アクセス、書き込みアクセス、ルートアクセスなどを許可することができます。
今回はすべてのクライアントへのフルアクセスを許可するため、デフォルトのまま変更しません。
アクセスポイントの作成
LambdaからEFSへアクセスするために必要なアクセスポイントを作成します。
Lambdaからアクセスする際のユーザIDや、EFSで最初にルートディレクトリパスを作成する際のアクセス権限などを指定できます。
※今回はLambdaからアクセスする際のユーザIDをec2-userとするため、ユーザーID 1000
としていますが、公式ユーザーガイドなどでは 1001
を指定しています。
③ EC2の作成
①で作成したEC2用セキュリティグループを適用したEC2インスタンスを作成します。
今回、キーペアは既存のキーペアを選択します。
④ Lambdaの作成
(参考)公式ユーザーガイド - Lambda 関数のファイルシステムアクセスの設定
(参考)公式ユーザーガイド - VPC 内のリソースにアクセスするための Lambda 関数の設定
VPCに接続したLambdaを作成します。
今回は、セキュリティグループにはデフォルトセキュリティグループを指定し、プライベートサブネットを使用しています。
実行ロールに以下のポリシーをアタッチします。
-
AWSLambdaVPCAccessExecutionRole
(VPCに接続するため) -
AmazonElasticFileSystemClientReadWriteAccess
(ファイルシステムに接続するため)
「ファイルシステムの追加」から、②で作成したEFSファイルシステム、アクセスポイントを指定します。
また、Lambda関数からファイルシステムにアクセスする際に使用する /mnt/
で始まるローカルマウントパスを設定します。
⑤ EC2から接続
EFS マウントヘルパーを使用してEFS ファイルシステムをマウントします。
amazon-efs-utils パッケージのインストール
(参考)公式ユーザーガイド - Amazon Linux で amazon-efs-utils パッケージをインストールする
EC2インスタンスにSSH接続し、以下コマンドでamazon-efs-utilsパッケージをインストールします。
※Amazon Linux以外のLinuxディストリビューションの場合はこちらを参照
sudo yum install -y amazon-efs-utils
Installed:
amazon-efs-utils.noarch 0:1.28.2-1.amzn2
Dependency Installed:
stunnel.x86_64 0:4.56-6.amzn2.0.3
Complete!
EFSをマウント
(参考)公式ユーザーガイド - EFS マウントヘルパーを使用してマウントする
EFSをマウントするディレクトリを作成します。
sudo mkdir /mnt/efs
マウント前のファイルシステムを確認します。
df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 482M 0 482M 0% /dev
tmpfs 492M 0 492M 0% /dev/shm
tmpfs 492M 456K 492M 1% /run
tmpfs 492M 0 492M 0% /sys/fs/cgroup
/dev/xvda1 8.0G 1.4G 6.7G 18% /
tmpfs 99M 0 99M 0% /run/user/0
tmpfs 99M 0 99M 0% /run/user/1000
EFSコンソールにてファイルシステムIDを確認します。
ファイルシステムをマウントします。
sudo mount -t efs [ファイルシステムID]:/ [ESをマウントするディレクトリ]
sudo mount -t efs fs-00945420:/ /mnt/efs
マウント後のファイルシステムを確認します。
df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 482M 0 482M 0% /dev
tmpfs 492M 0 492M 0% /dev/shm
tmpfs 492M 460K 492M 1% /run
tmpfs 492M 0 492M 0% /sys/fs/cgroup
/dev/xvda1 8.0G 1.4G 6.7G 18% /
tmpfs 99M 0 99M 0% /run/user/0
tmpfs 99M 0 99M 0% /run/user/1000
fs-00945420.efs.ap-northeast-1.amazonaws.com:/ 8.0E 0 8.0E 0% /mnt/efs
fs-00945420.efs.ap-northeast-1.amazonaws.com:/
が出現し、/mnt/efs
にマウントが行えたことが確認できました。
⑥ Lambdaから接続
Lambdaからファイルシステムにファイルを作成し、文字列を書き込み、書き込んだ文字列を読み込みしてみます。
以下のコードを使用します。
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.ScheduledEvent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class EfsTestHandler implements RequestHandler<ScheduledEvent, String> {
private static final Logger logger = LogManager.getLogger(EfsTestHandler.class);
@Override
public String handleRequest(ScheduledEvent event, Context context) {
// ファイル名
String filepath = "/mnt/data/LambdaSample.txt";
// 書き込む文字列
String str = "This was written from Lambda.";
File file = new File(filepath);
// ファイル書き込み
FileWriter fileWriter;
try {
fileWriter = new FileWriter(file);
file.setExecutable(true);
fileWriter.write(str);
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
return "Error";
}
// ファイル読み込み
FileReader reader;
try {
reader = new FileReader(file);
BufferedReader br = new BufferedReader(reader);
String readStr = "";
while ((readStr = br.readLine()) != null) {
logger.info(readStr);
}
br.close();
} catch (FileNotFoundException e1) {
e1.printStackTrace();
return "Error";
} catch (IOException e) {
e.printStackTrace();
return "Error";
}
return "Complete";
}
}
Lambda関数をテスト実行します。
ファイルシステムへの接続が成功していれば、実行結果にComplete
と表示され、ログにThis was written from Lambda.
と出力されます。
Lambdaからファイルシステムへのファイル書き込み、書き込んだファイルの読み込みが行えることが確認できました。
Lambdaから書き込んだファイルを、EC2からも確認してみます。
ll /mnt/efs/data
-rwxrw-r-- 1 ec2-user ec2-user 29 Feb 14 05:39 LambdaSample.txt
/mnt/efs/data
配下に、Lambdaから作成したファイルが存在することが確認できました。
※Lambdaからはアクセスポイントを使用してファイルシステムに接続しているため、Lambda関数内で/mnt/data
と指定することにより、実体としてはEFSの/data
にアクセスしています。
ファイルの中身を確認してみます。
cat /mnt/efs/data/LambdaSample.tx
This was written from Lambda.
Lambdaから書き込んだ文字列が確認できました。
おわりに
設定、接続はあっけなく完了しました。
しかし、アクセスポイント作成時のPOSIXユーザIDを何にするのが適切か、など
各設定値について把握しきれず、学習が必要です。
CloudFormationを使用しての設定手順や、マウント失敗談、EC2やLambdaからファイル削除しようとしたら失敗した話も記載予定でしたが、長くなったため別記事へ記載したいと思います。
参考
AWS Web Serviceブログ
公式ユーザーガイド
- EFSリソースの使用 - セキュリティグループの作成
- EFS リソースの使用 - ファイルシステムの作成
- Lambda 関数のファイルシステムアクセスの設定
- VPC 内のリソースにアクセスするための Lambda 関数の設定
- Amazon Linux で amazon-efs-utils パッケージをインストールする
- 他の Linux ディストリビューションで amazon-efs-utils パッケージをインストールする
- EFS マウントヘルパーを使用してマウントする
参考にさせていただいた記事