はじめに
先日、仕事でEFS
を使うことがあったのですが、マウント周りの仕様を理解できておらずハマったので、しっかりと理解するために記事にまとめてみようと思います。
Elastic File Systemについて
AWSが提供するファイルストレージサービスとなり、ざっくり言えばNFS
サーバを提供するAWSサービスとなります。
マウントターゲットで各アベイラビリティゾーンからEFS
へアクセスするためのエンドポイントを設定し、アクセスポイントでクライアントからEFS
をマウントする際のディレクトリや権限を指定します。
アクセスポイントはEFS
側の領域を分割してクライアントへ提供するための機能となるため、特に領域分割せず、EFS
の領域をすべて使用する場合はアクセスポイントは使用しなくても良いです。
以下にEFS
マウント設定概要図を示します。
以下よりクライアント側、EFS
側で設定する内容を記載します。
クライアント側の設定
クライアント側からEFS
をマウントする場合、Linux
等に標準でインストールされているmount
コマンドに各種パラメータを指定するだけでもEFS
をマウントできますが、EFSマウントヘルパーと呼ばれるパッケージをインストールすることで、マウント時のパラメータ指定等を簡略化することができます。
また、後述するアクセスポイントの設定を使用してマウントするためにはEFSマウントヘルパーをインストールする必要があります。
EFSマウントヘルパーを入れないと、アクセスポイントで指定した領域・権限でのアクセスができないため、EFS
を使用するのであれば、EFSマウントヘルパーはインストールしておいたほうが良いでしょう。
EFS側の設定
EFS
の設定ではファイルシステムとアクセスポイントの作成を行う必要がありますが、それぞれ何を設定するものなのかをまとめます。
ファイルシステムの設定
以下のようなEFS
の基本設定を行います。
- EFSストレージクラス設定
- EFSバックアップ設定
- 暗号化有無設定
- マウントターゲット設定
- ファイルシステムポリシー設定
マウントターゲットはどのAZ(アベイラビリティーゾーン)にエンドポイントを作成するか、ファイルシステムポリシーは転送時暗号化強制や匿名アクセス禁止等のマウント時のポリシー設定が行なえます。
アクセスポイントの設定
クライアントからEFS
にアクセスする際のUID
(ユーザID)・GID
(グループID)やEFS側のマウントポイントの設定等を行います。
アクセスポイントの設定を行うことで、EFS
の特定の領域のみクライアント側からアクセスさせることができます。
クライアント側から見た場合、例えば前述の図のefs2
というアクセスポイントをマウントすると、EFS
側のディレクトリは/data/efs2
となりますが、クライアント側はchroot
を使ったときのようにルートディレクトリを直接マウントしているように見えます。
POSIXユーザ・グループ
EFS
の領域に書き込みを行う際、クライアント側のUID
、GID
ではなく、POSIXユーザで指定したUID
、GID
でアクセスを行います。
POSIXユーザを指定することでEFS
の領域にあるファイルはすべてPOSIXユーザ・グループで指定したUID
・GID
に固定できますが、ファイルのオーナー・グループをPOSIXユーザ・グループで固定したくない場合は、設定しないことでクライアント側のUID
、GID
にすることもできます。
また、セカンダリグループIDを指定することで、セカンダリグループIDで指定したIDからのアクセスも許可することができるため、例えば以下のようにefs2
の親ディレクトリがefs1
でそれぞれクライアントごとにアクセスポイントが異なる場合、efs1
からは/efs1/efs2
ディレクトリの配下にもファイル・ディレクトリ作成可能だが、efs2
からはefs1
で作成したファイル・ディレクトリにアクセスできないようなことが可能です。
ルートディレクトリ作成のアクセス許可
EFS
側にアクセスポイントの設定で指定したディレクトリパスが存在しない場合に、「ルートディレクトリ作成のアクセス許可」で指定したUID
、GID
、パーミッションでディレクトリを作成します。
存在しなかった場合にディレクトリを作ってくれるだけなので、あらかじめ手動でディレクトリを作成していたり、EFSマウント後に手動でディレクトリを作成する場合は指定しなくても問題ありません。
EFSのマウントについて
上記まででクライアント側、EFS側の設定についてまとめたため、以下ではEFSをマウントした際の動きについてまとめます。
EFSのルートディレクトリ権限
EFS
側のルートディレクトリはユーザ&グループがroot:root
、パーミッションは0755
となります。
マウントした際の権限
これはEFS
というよりUNIX系OSでマウントした際の仕様となりますが、例えば/mnt
にNFS
領域をマウントした場合、/mnt
がユーザ&グループID1001:1001
、パーミッション0777
としていたとしてもEFS
をマウントした際にはEFS
側の権限となります。
アクセスポイントを使わない、もしくはアクセスポイント設定でディレクトリパスやPOSIX設定を行っていない場合、「EFSのルートディレクトリ権限」で記載した権限となります。
$ ls -ld /mnt
drwxrwxrwx. X 1001 1001 X XXX DD hh:mm /mnt
$ ls -ld /mnt
drwxr-xr-x. X root root X XXX DD hh:mm /mnt
アクセスポイントを使わないマウント
EFSマウントヘルパーをインストールしていなかったり、アクセスポイントの設定をしていない場合でも、EFS
の領域をマウントすることができます。
その場合、EFS
のルートディレクトリをマウントすることになり、またPOSIXユーザ設定も行えないため、EFS
領域へアクセスする際のユーザ・グループでファイル・ディレクトリの読み書きすることになります。
ルートディレクトリを直接マウントする場合の注意点
ルートディレクトリマウント時、上述の権限となるため、root
以外ではEFS
領域に書き込みを行えません。
また、アクセスポイントの設定でPOSIXユーザの設定を行うと、POSIXユーザで指定したUID
、GID
でアクセスするため、書き込みに失敗します。
もしどうしてもルートディレクトリをマウントして、POSIXユーザ設定も使用したい場合は、EFS
領域をマウント後、ルートユーザでEFS
のルートディレクトリの権限をPOSIX設定で指定したユーザがアクセスできる権限に変更する必要があります。
$ sudo mount -t efs -o tls fs-xxxxxxxxxxxxxxxxx:/ /mnt
$ ls -ld /mnt
drwxr-xr-x. X root root X XXX DD hh:mm /mnt
$ chmod 777 /mnt
$ ls -ld /mnt
drwxrwxrwx. X root root X XXX DD hh:mm /mnt
動作確認
EFS
の設定やマウント時の動作についてまとめてきましたが、実際にどのように見えるかをいくつかのシナリオを通して改めて確認してみようと思います。
今回はマウントテスト用としてEC2インスタンスを用意してそちらで以下のシナリオを確認していこうと思います。
- 事前準備
- シナリオ1:アクセスポイントの設定無しでマウントできるか?
- シナリオ2:EFSのルートディレクトリをマウントしてec2-userで書き込みできるか?
- シナリオ3:EFSのルートディレクトリをマウントしてrootで書き込みできるか?
- シナリオ4:アクセスポイント設定でディレクトリ作成設定を行った際、ディレクトリ作成されるか?
- シナリオ5:POSIXユーザ設定を行った際、指定のユーザでファイル作成されるか?
- シナリオ6:EFSルートディレクトリ側からアクセスポイントのディレクトリにファイル作成した場合はどうなるか?
事前準備
EFS
をマウントするためにEC2インスタンスにアタッチするセキュリティグループでNFS
を許可しておきます。
また、アクセスポイントの機能を使用するため、EFSマウントヘルパーをインストールしておきます。
シナリオ1:アクセスポイントの設定無しでマウントできるか?
EC2インスタンス側にEFSをマウントするためのマウントポイントを作成しておきます。
$ sudo mkdir /efs1 && ls -ld /efs1
drwxr-xr-x. X root root X XXX DD hh:mm /efs1
「Elastic File System」→「ファイルシステム」より作成済みのファイルシステムの選択し、右上の「アタッチ」を選択すると以下のようなマウントコマンドが表示されるため、作成したマウントポイントに合わせて修正しつつ実行します。
$ sudo mount -t efs -o tls fs-xxxxxxxxxxxxxxxxx:/ /efs1
$ ls -ld /efs1
drwxr-xr-x. X root root X XXX DD hh:mm /efs1
元々のディレクトリ権限と同じなので分かりづらいですが、EFSをマウントしているため、上記はEFS
側の権限となっています。
df
コマンドを実行し、以下のように表示されていればマウント成功です。
$ df -h /efs1
Filesystem Size Used Avail Use% Mounted on
127.0.0.1:/ 8.0E 0 8.0E 0% /efs1
シナリオ2:EFSのルートディレクトリをマウントしてec2-userで書き込みできるか?
EFS
のルートディレクトリはroot:root
、0755
の権限となるため、結果としては、Permission denied
となります。
$ touch /efs1/testfile
touch: cannot touch '/efs1/testfile': Permission denied
シナリオ3:EFSのルートディレクトリをマウントしてrootで書き込みできるか?
root
であれば書き込み権限があるため、問題なく作成できます。
$ sudo touch /efs1/testfile
$ ls -la /efs1/testfile
-rw-r--r--. X root root X XXX DD hh:mm /efs1/testfile
シナリオ4:アクセスポイント設定でディレクトリ作成設定を行った際、ディレクトリ作成されるか?
今回は以下のようにアクセスポイントを作成します。
設定項目 | 設定内容 | 備考 |
---|---|---|
ファイルシステム | 作成済みのEFSファイルシステムID | |
名前 | efs_ap | 任意の名前を指定 |
ルートディレクトリパス | /efsdata | クライアント側に見せるEFS側ディレクトリパス |
POSIXユーザID | 2000 | テストのため今回は2000を指定 |
POSIXグループID | 2000 | テストのため今回は2000を指定 |
POSIXセカンダリグループID | (空欄) | 今回は未指定 |
所有者ユーザID | 2000 | POSIX設定で指定したIDと同じものを指定 |
所有者グループID | 2000 | POSIX設定で指定したIDと同じものを指定 |
アクセスポイントのアクセス許可 | 0755 | |
タグ | (空欄) | 今回は未指定 |
また、ルートディレクトリをマウントしている/efs1
とアクセスポイントの設定でマウントした際の違いを比較するため、アクセスポイントマウント用のディレクトリも作成しておきます。
$ sudo mkdir /efs2 && ls -ld /efs2
drwxr-xr-x. X root root X XXX DD hh:mm /efs2
アクセスポイントで指定した領域をマウントする場合も、「Elastic File System」→「アクセスポイント」から作成したアクセスポイントを選択し、右上の「アタッチ」を選択することでマウントコマンドを確認できます。
なお、前述の通り、アクセスポイントのマウントはEFSマウントヘルパーをインストールしておかないとマウントできないので、コマンドはEFSマウントヘルパーでのマウントコマンド例しか表示されません。
$ sudo mount -t efs -o tls,accesspoint=fsap-xxxxxxxxxxxxxxxxx fs-xxxxxxxxxxxxxxxxx:/ /efs2
マウント後、/efs1
にマウントしているルートディレクトリからの確認と、/efs2
にマウントしているアクセスポイントで指定したディレクトリからの確認を行った結果が以下となります。
$ ls -l /efs1
total x
drwxr-xr-x. X 2000 2000 X XXX DD hh:mm efsdata
$ ls -l /efs2
total 0
EFSのルートディレクトリから確認した場合、「所有者ユーザID」、「所有者グループID」、「アクセスポイントのアクセス許可」で設定した権限でディレクトリが自動的に作られていることが確認できます。
また、アクセスポイントでのマウントとなる/efs2
からの確認では、EFS
側の/efsdata
がマウントされているため、まだ何も存在しないことが確認できます。
シナリオ5:POSIXユーザ設定を行った際、指定のユーザでファイル作成されるか?
POSIX設定を行っている場合、POSIXで指定しているユーザID、グループIDでEFS領域に書き込まれるはずなので、ec2-user
で作成したファイルをcp -p
でEFS領域にコピーして、POSIXで設定したユーザID、グループIDになるかを確認してみます。
ec2-user
のホームディレクトリにec2userfile
というテストファイルを作成して、/efs2
にコピーした結果が以下となります。
$ touch ec2userfile && ls -l ec2userfile
-rw-rw-r--. 1 ec2-user ec2-user X XXX DD hh:mm ec2userfile
$ cp -p ec2userfile /efs2/ec2userfile
$ ls -l /efs2/ec2userfile
-rw-rw-r--. 1 2000 2000 X XXX DD hh:mm /efs2/ec2userfile
cp -p
で権限を保持したコピーを行っても、POSIXで指定したユーザID、グループIDに変更されていることが確認できます。
また、先程/efsdata
のディレクトリを2000:2000
、0755
の権限で作成しているため、Permission denied
にならずに正常に書き込めていることが確認できました。
シナリオ6:EFSルートディレクトリ側からアクセスポイントのディレクトリにファイル作成した場合はどうなるか?
結論から言ってしまうと、ルートディレクトリをマウントしている/efs1
はアクセスポイントで設定している権限等の設定は有効にならないので、クライアント側のユーザで作られます。
また、ec2-user
の場合、UID
・GID
が1000:1000
なので/efsdata
配下には作成できずに失敗します。
$ touch /efs1/efsdata/ec2testfile
touch: cannot touch '/efs1/efsdata/ec2testfile': Permission denied
root
で作成した場合は問題なく作成でき、アクセスポイント経由ではないので、UID
・GID
が変換されることなく作成されます。
$ sudo touch /efs1/efsdata/roottestfile
$ ls -l /efs1/efsdata/roottestfile
-rw-r--r--. X root root X XXX DD hh:mm /efs1/efsdata/roottestfile
アクセスポイントを使用したマウント構成の検討
EFS
のマウントについてまとめ。
- EFSのルートディレクトリ権限は
root:root
、0755
。 - ルートディレクトリマウントではルートユーザ以外書き込めない。
- POSIX設定を行うと、指定した
UID
、GID
で強制される。 - 「ルートディレクトリ作成のアクセス許可」を指定するとマウント時に指定した権限でディレクトリ作成。
EFS
のルートディレクトリを使用する場合、手動でルートディレクトリの権限を変更したりしなければならず、良い手段とは言えないため、「ルートディレクトリ作成のアクセス許可」でマウント時に指定した権限のディレクトリを作成するようにした上で、クライアント側からマウントして使うのが良いかと思います。
おわりに
一度イメージできてしまえば簡単なことでも、アクセスポイントやEFSのマウント方法についてイメージできていないと、私のように想定通りにアクセスできずにハマってしまいます。
同じようにハマる人の助けになれば幸いです。