Amazon Linux 2 に goofys を使って S3 バケットをマウントする手順

# はじめに

EC2 上の Amazon Linux 2 で S3 バケットをマウントする場合、[goofysのREADMEでは Mac のことしか書かれていない](https://github.com/kahing/goofys) ので自分用に Amazon Linux 2 にインストールする場合の方法を記載する。
OS は Amazon Linux 2 (ap-northeast-1 の ami-06098fd00463352b6) を利用。 

## マウントするS3バケットの作成

これは好きな場所に作成。 今回は ap-northeast-1 (東京) なので、同リージョンにバケットを作成。 パブリックアクセスポリシーは「パブリックアクセスをすべてブロック：オン」としておく。

## IAM Role の準備

まずは作成した S3 バケットを読み書き可能なPolicyを作成する。 具体例は以下の通り。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:ListStorageLensConfigurations",
                "s3:ListAccessPointsForObjectLambda",
                "s3:GetAccessPoint",
                "s3:PutAccountPublicAccessBlock",
                "s3:GetAccountPublicAccessBlock",
                "s3:ListAllMyBuckets",
                "s3:ListAccessPoints",
                "s3:ListJobs",
                "s3:PutStorageLensConfiguration",
                "s3:CreateJob"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::[バケット名]",
                "arn:aws:s3:::[バケット名]/*"
            ]
        }
    ]
}
```

その後、このポリシーを付与した IAM Role を作成する。 Role のユースケースは EC2 として、EC2 インスタンスにアタッチ可能とし、goofysをマウントするインスタンスにアタッチする。

## VPC Endpoint の作成 (オプショナル)

VPC 内から直接同リージョンにある S3 へとアクセスするためのエンドポイントを作成し、VPC のルーティングを設定する。

Management Console > VPC > エンドポイント を選択し、`com.amazonaws.ap-northeast-1.s3` の `タイプ: Gateway` を選択。 あとは、アタッチする VPC を選択し、VPC 内から直接 S3 にアクセスするルートテーブルを選択した後、エンドポイントを作成すればOK。

これを設定するのは、EC2-S3のデータ転送が複数のAvailability Zoneをまたがず、直接データ転送するためである。 これを設定しない場合、以下のようにデータ転送料金が発生する可能性がある。 ただし、別になくても普通に動くので、あくまでオプションで。

> NATゲートウェイ料金の例
データ転送料金: 標準の EC2 データ転送料金が請求されます。1 GB のデータが EC2 インスタンスから NAT ゲートウェイを経由して S3 へ転送された場合、Amazon EC2 から S3 へのデータ送信は同じリージョン内で行われるため、EC2 インスタンスから S3 へのデータ転送に対する料金は発生しません。また、NAT ゲートウェイと EC2 インスタンス間のデータ転送に対しても料金は発生しません。プライベート IP アドレスを使用してトラフィックが同じアベイラビリティーゾーンにとどまるためです。NAT ゲートウェイと EC2 インスタンスが異なるアベイラビリティーゾーンにある場合は、データ転送料金が請求されます。詳細については、EC2 料金ページのデータ転送セクションをご覧ください。
https://aws.amazon.com/jp/vpc/pricing/

## goofys バイナリのダウンロード

[Github のリリースページからバイナリをダウンロードできる](https://github.com/kahing/goofys/releases) ので、これをダウンロードする。 これを使えば、Go をインストールする必要はない。　Go を使わずに単に goofys を使うだけなら、多分この方が楽。
以下、root ユーザーで実行。 

```bash
# 必要なライブラリをインストール
$ yum -y install fuse

# バイナリを /opt/goofys 以下にダウンロード
$ mkdir -p /opt/goofys
$ cd /opt/goofys
$ wget https://github.com/kahing/goofys/releases/download/v0.24.0/goofys
# バイナリをルートのみで実行可能に設定
$ chmod 700 goofys

# マウント先に空のディレクトリを作成
$ mkdir -p /mnt/s3
```

## `/etc/fstab` の設定

インスタンスの起動時に S3 バケットをマウントするように `/etc/fstab` を開いて以下を書き加える。 `--use-content-type` を付与しているのは、[S3にアップロードする際に S3 上での Content-Type を自動識別するため。](https://dev.classmethod.jp/articles/goofys-auto-setting-metadata-content-type/) 

```text
/opt/goofys/goofys#[バケット名]   /mnt/s3        fuse     _netdev,allow_other,--uid=[ファイル所有者ID],--gid=[ファイルグループID],--file-mode=[ファイルのパーミッション],--dir-mode=[ディレクトリのパーミッション],--use-content-type    0       0

# 具体例 - root:root でマウントし、すべてのユーザーが読み書き可能なマウントを行う
/opt/goofys/goofys#[バケット名]   /mnt/s3        fuse     _netdev,allow_other,--uid=0,--gid=0,--file-mode=0777,--dir-mode=0777,--use-content-type    0       0
```

## mount / unmount 

```bash
# fstab に書かれている /mnt/s3 部分をマウント
$ mount /mnt/s3

# fstab に書かれている /mnt/s3 部分を強制的にアンマウント
$ umount -f /mnt/s3
```

この場合、gooyfs のログは `/var/log/messages` に書かれているので、成功したか否かはここを見る。 うまくいったなら、以下のようなログが出る。

```
Apr 20 04:51:39 ip-172-31-21-231 /opt/goofys/goofys[17260]: main.INFO File system has been successfully mounted.
```

もしくは、 `/etc/fstab` で正常に動作するか否か、インスタンスを再起動すればよい。


## 動作チェック

あとは普通に書き込みなどができるかをチェック。

```bash
$ touch /mnt/s3/ok
$ ls -al /mnt/s3
drwxrwxrwx 2 root root 4096 Apr 20 04:55 .
drwxr-xr-x 3 root root   16 Apr 20 04:35 ..
-rwxrwxrwx 1 root root    0 Apr 20 04:36 ok
```