Amazon EFSを作成して、EC2とLambdaから使用する

AWS
AWS

皆さんこんにちは、寺田です。

業務でAmazon EFSを使用する機会に巡りあい、EFSについて調べながら、EC2にマウントし、Lambdaからアクセスできるよう設定を行いました。作成時の設定は、最初に設定した後は方法を忘れてしまうことが多いため、備忘として、再度設定方法を振り返ってみようと思います。

前提条件

  • VPC、EFS、EC2は同一リージョンに作成する(今回は東京リージョンを使用)
  • LambdaはEFSに到達できるVPCに接続する必要がある
  • プライベートサブネットが作成済みの状態から開始する
  • EC2へSSH接続を行うためのキーペアが作成済みの状態から開始する

この記事のゴール

  • Amazon EFSを作成し、LambdaからEFS内のファイルを操作する
  • EC2にEFSをマウントし、EFS内のファイルを操作する

以下の構成をイメージしています。

AWS構成イメージ

この記事で扱わないこと

  • VPCの作成方法
  • パブリックサブネット、プライベートサブネットの作成・設定方法
  • EC2インスタンスへのSSH接続方法

必要なもの

  • IAMユーザ

環境情報

# AWSリージョン
東京(ap-northeast-1)

# EC2
AMI:Amazon Linux 2 AMI (HVM), SSD Volume Type

# Lambda
ランタイム:Java 11(Corretto)

手順

AWSコンソールにて以下を作成、設定してみる

  1. セキュリティグループの作成
  2. EFSの作成
  3. EC2の作成
  4. Lambdaの作成
  5. EC2から接続
  6. Lambdaから接続

AWSコンソールから作成、設定

1. セキュリティグループの作成

EC2用セキュリティグループ

EC2インバウンドルール
EC2アウトバウンドルール

Lambda用セキュリティグループ

Lambdaにはデフォルトのセキュリティグループを使用するため作成しません。

EFS用セキュリティグループ

EC2用セキュリティグループと、Lambda用セキュリティグループからのインバウンドアクセスを許可します。

EFSインバウンドルール
EFSアウトバウンドルール

2. EFSの作成

EFSコンソールで「カスタマイズ」を選択してファイルシステムを作成します。

EFSファイルシステムの作成

ファイルシステム設定

要件に応じて適宜設定します。

EFSファイルシステム設定

ネットワークアクセス設定

  • VPC:Lambdaを接続するVPCを選択します。(今回はデフォルトVPCを使用)
  • アベイラビリティーゾーン:デフォルトではリージョンの各アベイラビリティーゾーンが選択されています。不要なアベイラビリティゾーンがある場合は削除します。
  • サブネットID:Lambdaを作成するサブネットを選択します。(今回はプライベートサブネットを使用)
  • セキュリティグループ:1で作成したEFS用セキュリティグループを選択します。
EFSネットワークアクセス設定

ファイルシステムポリシー

EFSファイルシステムへ接続する際に、IAMロールを使用して、読み取り専用アクセス、書き込みアクセス、ルートアクセスなどを許可することができます。
今回はすべてのクライアントへのフルアクセスを許可するため、デフォルトのまま変更しません。

EFSファイルシステムポリシー

アクセスポイントの作成

LambdaからEFSへアクセスするために必要なアクセスポイントを作成します。
Lambdaからアクセスする際のユーザIDや、EFSで最初にルートディレクトリパスを作成する際のアクセス権限などを指定できます。

今回はLambdaからアクセスする際のユーザIDをec2-userとするため、ユーザーID 1000 としていますが、公式ユーザーガイドなどでは 1001 を指定しています。

EFSアクセスポイント

3. EC2の作成

1で作成したEC2用セキュリティグループを適用したEC2インスタンスを作成します。

EC2インスタンス作成

今回、キーペアは既存のキーペアを選択します。

EC2キーペア設定

4. Lambdaの作成

VPCに接続したLambdaを作成します。
今回は、セキュリティグループにはデフォルトセキュリティグループを指定し、プライベートサブネットを使用しています。

Lambda VPC設定

実行ロールに以下のポリシーをアタッチします。

  • AWSLambdaVPCAccessExecutionRole(VPCに接続するため)
  • AmazonElasticFileSystemClientReadWriteAccess(ファイルシステムに接続するため)
Lambda実行ロールのアクセス権限

「ファイルシステムの追加」から、2で作成したEFSファイルシステム、アクセスポイントを指定します。
また、Lambda関数からファイルシステムにアクセスする際に使用する /mnt/で始まるローカルマウントパスを設定します。

Lambdaファイルシステムの追加

5. EC2から接続

EFS マウントヘルパーを使用してEFS ファイルシステムをマウントします。

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をマウントするディレクトリを作成します。

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を確認します。

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 にマウントが行えたことが確認できました。

6. 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からファイルシステムへのファイル書き込み、書き込んだファイルの読み込みが行えることが確認できました。

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ブログ

公式ユーザーガイド

タイトルとURLをコピーしました