LambdaのEFSマウントを調べてみた
業務でLambdaでEFSを利用するケースがあり、マウントオプションに関して調べた備忘録。
Lambda,EFS
言わずもがなのAWSサービス。サービス詳細の内容は公式ドキュメントへ。
※1 Lambda デベロッパーガイド
※2 EFS ユーザガイド
マウントに関して
EFSファイル操作を扱う機能を実装していた際に、読み込み・書き込み処理のリトライってアプリ内で実装するの?マウントオプションで実現されてるのか?が気になり色々と調べてみた。
EFSのマウントは、NFSが利用されている。
出典:Red Hat Enterprise Linux 4: システム管理入門ガイド
またAWS公式から、NFSマウントオプションの推奨デフォルト値が提示されている。
※3 マウントに関する追加の考慮事項
LambdaとEFSのマウントでも、hardオプションが設定されているのか否かが当初の疑問を解消すると思い、AWS公式のドキュメントを漁りまくったが、該当するドキュメントを発見することができなかった。(ドキュメントご存知の方教えてください…)
「まあ推奨しているし、内部実装でもそのように処理されているだろう」と思ったが、気になってしまった手前諦めることができず、AWSサポートに問い合わせてみた。
「大変申し訳ございませんが、該当の内容でお客様にご提示できる情報はございません。」
なんだって!?!? 絶望。。(対応いただいた方、拙い質問に対してありがとうございました)
じゃあ実装するかと思い、SAMでEFSをマウントしたLambdaをデプロイしてみて、内部状態を調べてみた。
実装
LambdaにEFSマウントする場合は、SAMテンプレートではLambdaの設定項目に以下を追加する必要がある。
- VpcConfig
- FileSystemConfigs
また私はSAMでマウントターゲットも作成しているため、DependsOnも利用。
SAM Template (抜粋)
CmdFunction:
Type: AWS::Serverless::Function
DependsOn: MountTarget
Properties:
CodeUri: cmd/
Handler: cmd
// ommited
VpcConfig:
SecurityGroupIds:
- !Ref LambdaSecurityGroup
SubnetIds:
- !Ref Subnet
FileSystemConfigs:
- Arn: !GetAtt AccessPoint.Arn
LocalMountPath: /mnt/efs
Lambdaは大好きなGoで実装。実装が雑なのは、ご愛嬌で。。
色々調べてみたかったので、コマンドを引数とする形で実装。
Lambda
package main
import (
"context"
"fmt"
"log"
"os/exec"
"github.com/aws/aws-lambda-go/lambda"
)
type MyEvent struct {
Cmd string `json: cmd`
}
func HandleRequest(ctx context.Context, evt MyEvent) {
res, err := exec.Command("sh", "-c", evt.Cmd).Output()
if err != nil {
log.Fatal(err)
}
fmt.Println(string(res))
}
func main() {
lambda.Start(HandleRequest)
}
結果
まずは実行ユーザを調べた。(whoami)
sbx_user1051
ルートのディレクトリを一覧。(ls -l /)
total 34
dr-xr-xr-x 2 root root 1024 Mar 16 15:39 bin
dr-xr-xr-x 2 root root 1024 Jan 6 2012 boot
drwxr-xr-x 2 root root 4096 Apr 29 01:11 dev
drwxr-xr-x 50 root root 3072 Apr 11 23:46 etc
drwxr-xr-x 2 root root 1024 Jan 6 2012 home
dr-xr-xr-x 5 root root 1024 Mar 16 15:39 lib
dr-xr-xr-x 5 root root 6144 Mar 16 15:39 lib64
drwxr-xr-x 2 root root 1024 Jan 6 2012 media
drwxr-xr-x 3 root root 4096 Apr 29 01:22 mnt
drwxr-xr-x 2 root root 1024 Mar 16 15:39 opt
dr-xr-xr-x 78 root root 0 Apr 29 01:22 proc
dr-xr-x--- 2 root root 1024 Jan 6 2012 root
dr-xr-xr-x 2 root root 1024 Mar 16 15:39 sbin
drwxr-xr-x 2 root root 1024 Jan 6 2012 selinux
drwxr-xr-x 2 root root 1024 Jan 6 2012 srv
drwxr-xr-x 2 root root 1024 Jan 6 2012 sys
drwx------ 2 sbx_user1051 990 4096 Apr 29 01:22 tmp
drwxr-xr-x 13 root root 1024 Mar 16 15:38 usr
drwxr-xr-x 1 12569 users 1024 Mar 21 14:14 var
使用可能なコマンド一覧。(ls -l /bin)
total 4483
-rwxr-xr-x 1 root root 28448 Feb 25 2016 arch
lrwxrwxrwx 1 root root 4 Mar 16 15:38 awk -> gawk
-rwxr-xr-x 1 root root 28128 Feb 25 2016 basename
-rwxr-xr-x 1 root root 939200 Jun 16 2020 bash
-rwxr-xr-x 1 root root 48000 Feb 25 2016 cat
-rwxr-xr-x 1 root root 57216 Feb 25 2016 chgrp
-rwxr-xr-x 1 root root 52992 Feb 25 2016 chmod
-rwxr-xr-x 1 root root 58496 Feb 25 2016 chown
-rwxr-xr-x 1 root root 145760 Feb 25 2016 cp
-rwxr-xr-x 1 root root 129912 Oct 8 2014 cpio
-rwxr-xr-x 1 root root 40672 Feb 25 2016 cut
-rwxr-xr-x 1 root root 59584 Feb 25 2016 date
-rwxr-xr-x 1 root root 69416 Feb 25 2016 dd
-rwxr-xr-x 1 root root 95280 Feb 25 2016 df
-rwxr-xr-x 1 root root 44976 Dec 4 2020 dmesg
-rwxr-xr-x 1 root root 27904 Feb 25 2016 echo
-rwxr-xr-x 1 root root 290 Aug 17 2017 egrep
-rwxr-xr-x 1 root root 28128 Feb 25 2016 env
-rwxr-xr-x 1 root root 24416 Feb 25 2016 false
-rwxr-xr-x 1 root root 290 Aug 17 2017 fgrep
-rwxr-xr-x 1 root root 234512 Jan 17 2011 find
-rwxr-xr-x 1 root root 58352 Dec 4 2020 findmnt
-rwxr-xr-x 1 root root 373632 Oct 14 2012 gawk
-rwxr-xr-x 1 root root 150600 Aug 17 2017 grep
lrwxrwxrwx 1 root root 3 Mar 16 15:39 gtar -> tar
-rwxr-xr-x 1 root root 2253 Aug 17 2017 gunzip
-rwxr-xr-x 1 root root 93576 Aug 17 2017 gzip
-rwxr-xr-x 1 root root 28320 Dec 4 2020 kill
-rwxr-xr-x 1 root root 25472 Feb 25 2016 link
-rwxr-xr-x 1 root root 53352 Feb 25 2016 ln
-rwxr-xr-x 1 root root 32728 Dec 4 2020 login
-rwxr-xr-x 1 root root 113440 Feb 25 2016 ls
-rwxr-xr-x 1 root root 74880 Dec 4 2020 lsblk
-rwxr-xr-x 1 root root 77728 Feb 25 2016 mkdir
-rwxr-xr-x 1 root root 61184 Feb 25 2016 mknod
-rwxr-xr-x 1 root root 36512 Feb 25 2016 mktemp
-rwxr-xr-x 1 root root 36952 Dec 4 2020 more
-rwxr-xr-x 1 root root 124168 Feb 25 2016 mv
-rwxr-xr-x 1 root root 28896 Feb 25 2016 nice
-rwxr-xr-x 1 root root 85384 Aug 14 2018 ps
-rwxr-xr-x 1 root root 28672 Feb 25 2016 pwd
-rwxr-xr-x 1 root root 10992 Dec 4 2020 raw
-rwxr-xr-x 1 root root 37344 Feb 25 2016 readlink
-rwxr-xr-x 1 root root 57216 Feb 25 2016 rm
-rwxr-xr-x 1 root root 40480 Feb 25 2016 rmdir
-rwxr-xr-x 1 root root 15936 Jun 29 2021 rpm
-rwxr-xr-x 1 root root 66168 Jul 7 2012 sed
lrwxrwxrwx 1 root root 4 Mar 16 15:38 sh -> bash
-rwxr-xr-x 1 root root 28032 Feb 25 2016 sleep
-rwxr-xr-x 1 root root 109696 Feb 25 2016 sort
-rwxr-xr-x 1 root root 65120 Feb 25 2016 stty
-rwxr-xr-x 1 root root 25120 Feb 25 2016 sync
-rwxr-xr-x 1 root root 344648 Oct 7 2014 tar
-rwxr-xr-x 1 root root 27696 Dec 4 2020 taskset
-rwxr-xr-x 1 root root 55872 Feb 25 2016 touch
-rwxr-xr-x 1 root root 24416 Feb 25 2016 true
-rwxr-xr-x 1 root root 28448 Feb 25 2016 uname
-rwxr-xr-x 1 root root 25344 Feb 25 2016 unlink
-rwxr-xr-x 1 root root 1941 Aug 17 2017 zcat
いよいよお目当てのマウント状態を調べるぞ!
マウント状態を調べる方法は以下の3つがある。
- /etc/mtab を表示する
- /proc/mounts を表示する
- df コマンドを発行する
1の結果 (cat /etc/mtab)
/mnt/root-rw/opt/amazon/asc/worker/tasks/rtfs/go1.x-rapid-amzn-201803 / overlay ro,nosuid,nodev,relatime,lowerdir=/tmp/es2091527754/17769c2694755799:/tmp/es2091527754/51696035961324 0 0
/dev/vdb /dev ext4 rw,nosuid,noexec,noatime,data=writeback 0 0
/dev/vdd /tmp ext4 rw,relatime,data=writeback 0 0
none /proc proc rw,nosuid,nodev,noexec,noatime 0 0
/dev/vdb /proc/sys/kernel/random/boot_id ext4 ro,nosuid,nodev,noatime,data=writeback 0 0
/dev/root /etc/passwd ext4 ro,nosuid,nodev,relatime,data=ordered 0 0
/dev/root /var/rapid ext4 ro,nosuid,nodev,relatime,data=ordered 0 0
/dev/vdb /etc/resolv.conf ext4 ro,nosuid,nodev,noatime,data=writeback 0 0
/dev/vdb /mnt ext4 rw,noatime,data=writeback 0 0
/dev/vdc /var/task squashfs ro,nosuid,nodev,relatime 0 0
127.0.0.1:/ /mnt/efs nfs4 rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,namlen=255,hard,noresvport,proto=tcp,port=20252,timeo=600,retrans=2,sec=sys,clientaddr=127.0.0.1,local_lock=none,addr=127.0.0.1 0 0
2の結果 (cat /proc/mounts)
/mnt/root-rw/opt/amazon/asc/worker/tasks/rtfs/go1.x-rapid-amzn-201803 / overlay ro,nosuid,nodev,relatime,lowerdir=/tmp/es2091527754/17769c2694755799:/tmp/es2091527754/51696035961324 0 0
/dev/vdb /dev ext4 rw,nosuid,noexec,noatime,data=writeback 0 0
/dev/vdd /tmp ext4 rw,relatime,data=writeback 0 0
none /proc proc rw,nosuid,nodev,noexec,noatime 0 0
/dev/vdb /proc/sys/kernel/random/boot_id ext4 ro,nosuid,nodev,noatime,data=writeback 0 0
/dev/root /etc/passwd ext4 ro,nosuid,nodev,relatime,data=ordered 0 0
/dev/root /var/rapid ext4 ro,nosuid,nodev,relatime,data=ordered 0 0
/dev/vdb /etc/resolv.conf ext4 ro,nosuid,nodev,noatime,data=writeback 0 0
/dev/vdb /mnt ext4 rw,noatime,data=writeback 0 0
/dev/vdc /var/task squashfs ro,nosuid,nodev,relatime 0 0
127.0.0.1:/ /mnt/efs nfs4 rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,namlen=255,hard,noresvport,proto=tcp,port=20252,timeo=600,retrans=2,sec=sys,clientaddr=127.0.0.1,local_lock=none,addr=127.0.0.1 0 0
3の結果 (df -h)
Filesystem Size Used Avail Use% Mounted on
/mnt/root-rw/opt/amazon/asc/worker/tasks/rtfs/go1.x-rapid-amzn-201803 8.0G 6.5G 1.6G 81% /
/dev/vdb 1.5G 14M 1.4G 1% /dev
/dev/vdd 526M 872K 514M 1% /tmp
/dev/root 9.8G 538M 9.2G 6% /var/rapid
/dev/vdc 4.5M 4.5M 0 100% /var/task
127.0.0.1:/ 8.0E 0 8.0E 0% /mnt/efs
おお〜しっかり指定したローカルマウントパスでEFSマウントされてる!!!(当然)
マウントオプションも提示されている推奨値で行われている。
ってことは、アプリ側でEFS上のファイルの読み込み・書き込みのリトライ処理は入れなくていいんかなというのが現在の結論。
ちゃんとLinuxとかコンテナの勉強しなきゃな〜〜と思う今日この頃。
PS. AWSあるある ルートユーザのログインのセキュリティチェックの文字列入力、大体1回間違えがち
Discussion