FargateからのEFSマウントを試す

zennに移行しました: https://zenn.dev/cumet04/articles/fargate-with-efs
qiita側の記事を消す予定は特にありませんが、更新することはありません。

---

EFSがFargateで使えるようになったようです。
https://aws.amazon.com/jp/about-aws/whats-new/2020/04/amazon-ecs-aws-fargate-support-amazon-efs-filesystems-generally-available/

これはストレージ依存を脱しきれないもろもろのコンテナ化が捗りますね！

というわけで軽く動作確認してみました。

## 試す構成
最小限の手間で、FargateのコンテナからEFSの中身が読めていることを確認します。

* Fargateでhttpdコンテナを起動し、web閲覧できるようにしておく
* コンテナはドキュメントルートにEFSをマウントしておく
* 編集確認用にEC2を用意＆EFSをマウントしておく

この状態を作った上でEC2からEFS内のファイルを読み書きし、httpdをweb経由で閲覧することでFargateコンテナからEFSが読めることを確認します。
なお、通常Fargateをweb公開する際はALBを経由しますが、ここでは一時的なテスト目的のためコンテナのパブリックIPにブラウザで直接アクセスするかたちをとります。

## httpdなFargateを作る
EFSを試す下準備として、まずはただのhttpdをweb経由で閲覧できるようにします。

### Fargateタスク定義
※ECSクラスタは適当に作っておきます
Fargate起動タイプでタスク定義を作成します。

現時点ではEFS読み取りもせず、かつDockerHubのパブリックイメージを使用するためタスクロール・タスク実行ロールともに無しで問題ありません。

「コンテナの追加」では、適当なコンテナ名・イメージ(httpd)・ポートマッピング(80)を設定します。
また、デフォルトではCloudwatchLogsへのログ出力が設定されているため、「ストレージとログ」欄にある「Auto-configure CloudWatch Logs」のチェックを外しておきます。[^1]

[^1]: 外さないとタスク実行ロールが要求されるため、ここでは面倒なのでログ自体を無効化します

### タスクの実行
タスク定義が作成できたら、タスクを実行します。タスクの実行画面にて、

* 作成したタスク定義
* 適当なVPCとサブネット
* ご自身のグローバルIPから80ポートへアクセス可能なセキュリティグループ
* パブリックIPの自動割当: ENABLED

でタスク実行します。ここでは、VPCはAWSアカウントデフォルトのものを使います。[^2]

[^2]: EFSとFargateの通信の都合上、デフォルトVPC＆セキュリティグループを使うのが思考停止で進められるので楽。詳細は後述

### 閲覧確認
タスクの実行ダイアログを完了するとクラスタのタスクリストにコンテナが出現するのでRUNNINGになるまで待ちます。[^3]

[^3]: 要するにパブリックIPの付与を待ちます

RUNNINGになったらタスク詳細ページに行き、パブリックIPの欄にあるIPをコピー＆ブラウザのアドレスバーに貼り付けます。
見慣れた「It works!」が見えたらokです。

## コンテナにEFSをマウントする

コンテナの閲覧確認ができたら、本命のEFSをマウントします。

### EFSファイルシステムを作成する
マウント対象のファイルシステムを作成します。

EFSのページに行き、ファイルシステムの作成より進みます。
VPCなどはデフォルトのまま[^2]、ほかも特別な設定はせず作成を完了させます。

### マウント用のIAMロールを作成する
Fargateの設定に進む前に、タスクロールとして指定するIAMロールを作成します。

IAMロール作成画面にて

* ユースケース: Elastic Container Service -> Elastic Container Service Task
* 権限ポリシー: AmazonElasticFileSystemClientReadOnlyAccess

でロールを作成します。

### EFSマウント用にタスク定義を設定する
最初に作成したタスク定義から新しいリビジョンを作成します。変更点は

* タスクロールに先程作成したロールを指定
* ボリューム欄にてボリュームの追加を行い、作成したEFSを指定する
  - 名前・ボリュームタイプ・ファイルシステムIDが指定されてればok
* コンテナ定義のストレージとログ欄にて、マウントポイントを指定しコンテナパスを`/usr/local/apache2/htdocs`にする

となります。

### 新しいタスク定義を起動＆閲覧する
タスク定義を更新したら、前回起動したコンテナを破棄し新しい定義のコンテナを起動します。

起動時の設定のポイントは以下です:

* 「プラットフォームのバージョン」を**明示的に(LATESTではなく)1.4**にする
* セキュリティグループには先程の80ポートのものに加え、VPCデフォルトのものを追加しておく[^2]

ポイントは一つ目のプラットフォームバージョンです。
4/9現在、LATESTは1.3を指しているため、EFSを使う場合は1.4を明示的に指定しないと起動時にエラーとなります。

自分は最初このあたりでハマっていたのですが、twitterで丁寧に教えていただきました。関連ツイートも参考になります。
https://twitter.com/toricls/status/1248122352174424064
https://twitter.com/toricls/status/1247975937074843648

タスクが起動し、コンテナIPをブラウザから閲覧して`Index of /`が見えていれば成功です。
ドキュメントルートを空ディレクトリ(EFS)でマウントしたため、デフォルト設定にてDirectoryIndexが見える想定です。


## EFSのファイルを編集してみる
適当なEC2インスタンスからEFSをマウントし、ファイルの書き込みを行います。

AmazonLinux (1 or 2) のIAMかつssh用+VPCデフォルトのセキュリティグループ[^2]を付与してEC2インスタンスを起動します。

EFSのマウント手順の詳細は省略しますが、ここでは手軽に以下を実行します:

```bash
sudo yum install amazon-efs-utils
sudo mount -t efs fs-xxxxxxxx:/ /opt
```

`/opt`にマウントしているため、ここに適当にテストファイルを配置します:

```bash
echo 'efs works!' | sudo tee /opt/index.html
```

この状態でFargateコンテナのIPにアクセスし、上記の通り「efs works!」が表示されていれば成功です。

## 補足: ネットワーク周りについて
ここでは設定の手間を省略するためにFargate・EFS・EC2すべてでデフォルトVPC＆defaultセキュリティグループを使いましたが、
本来必要な要件は「Fargateコンテナ（やEC2）からEFSにTCP/2049の通信が通ること」です。

特に難しくはないのでセキュリティグループを設定してもよいのですが、今回はテストなので略しました。

## まとめ
プラットフォームバージョンの注意点はありますが、他には特にトリッキーな設定やCLIでしかできない設定などはなく、AWSコンソールからポチポチするだけで簡単に使える状態になっていました。

今後もFargateが捗りますね！