EKSでS3をボリュームとして扱う

  
[公式ユーザガイド](https://docs.aws.amazon.com/eks/latest/userguide/s3-csi.html)に従って進めていきます。

### 環境

```bash
[root@ip-192-168-0-50 ~]# k version
Client Version: v1.28.3-eks-e71965b
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.28.4-eks-8cb36c9
```

### S3バケットを作成

CLIでぱぱっと作っておきます。試験用なのでデフォルト設定で作成します。

```bash
[root@ip-192-168-0-50 ~]# aws s3 mb s3://eks-mount-test
make_bucket: eks-mount-test
```

### サービスアカウント用のIAMポリシーを作成

公式ユーザガイドからそのまま引用します。Resourceブロックを前手順で作成したS3バケットのものに修正します。

```json
{
   "Version": "2012-10-17",
   "Statement": [
        {
            "Sid": "MountpointFullBucketAccess",
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::eks-mount-test"
            ]
        },
        {
            "Sid": "MountpointFullObjectAccess",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:AbortMultipartUpload",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::eks-mount-test/*"
            ]
        }
   ]
}
```

こちらもCLIで作っちゃいましょう。

```bash
[root@ip-192-168-0-50 s3-mount]# aws iam create-policy --policy-name "AmazonS3CSIDriverPolicy" --policy-document file://policy.json
{
    "Policy": {
        "PolicyName": "AmazonS3CSIDriverPolicy",
        "PolicyId": "ANPA273BYGZPWGYZEMVO6",
        "Arn": "arn:aws:iam::XXXXXXXXXXXX:policy/AmazonS3CSIDriverPolicy",
        "Path": "/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 0,
        "PermissionsBoundaryUsageCount": 0,
        "IsAttachable": true,
        "CreateDate": "2024-01-04T08:10:37+00:00",
        "UpdateDate": "2024-01-04T08:10:37+00:00"
    }
}
```

### IAMロールの作成＋IAMポリシーのアタッチ+サービスアカウントの作成

これらをeksctlで設定します。

```bash
CLUSTER_NAME=eks-work-cluster
REGION=ap-northeast-1
ROLE_NAME=AmazonEKS_S3_CSI_DriverRole
POLICY_ARN=$(aws iam list-policies --scope Local --query 'Policies[?PolicyName==`AmazonS3CSIDriverPolicy`].Arn' --output text)
eksctl create iamserviceaccount \
    --name s3-csi-driver-sa \
    --namespace kube-system \
    --cluster $CLUSTER_NAME \
    --attach-policy-arn $POLICY_ARN \
    --approve \
    --role-name $ROLE_NAME \
    --region $REGION
```

確認します。

```bash
[root@ip-192-168-0-50 s3-mount]# k get sa -n kube-system s3-csi-driver-sa -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXXX:role/AmazonEKS_S3_CSI_DriverRole
  creationTimestamp: "2024-01-04T08:16:36Z"
  labels:
    app.kubernetes.io/managed-by: eksctl
  name: s3-csi-driver-sa
  namespace: kube-system
  resourceVersion: "1609018"
  uid: 34af2261-8279-43e1-b04f-e43d8635decf
```

### Mountpoint s3 CSI driverのデプロイ

いくつか方法が提供されているようでしたが、最もシンプルそうだったKustomizeを使ってデプロイしました。

```bash
[root@ip-192-168-0-50 s3-mount]# kubectl apply -k "github.com/awslabs/mountpoint-s3-csi-driver/deploy/kubernetes/overlays/stable/"
Warning: resource serviceaccounts/s3-csi-driver-sa is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
serviceaccount/s3-csi-driver-sa configured
secret/aws-credentials-99tfgtg98h created
daemonset.apps/s3-csi-node created
csidriver.storage.k8s.io/s3.csi.aws.com created
```

### サンプルアプリケーションのデプロイ

公式ユーザガイドにて提供されているサンプルアプリケーションをデプロイして動作検証してみます。

[Static Provisioning Example](https://github.com/awslabs/mountpoint-s3-csi-driver/blob/main/examples/kubernetes/static_provisioning/README.md)

readme.mdに記載がある通り、 _bucketName_ と _bucketRegion_ は自らの環境のものに変更してからapplyしましょう。

```bash
[root@ip-192-168-0-50 s3-mount]# vi static_provisioning.yaml
[root@ip-192-168-0-50 s3-mount]# k apply -f static_provisioning.yaml
persistentvolume/s3-pv created
persistentvolumeclaim/s3-claim created
pod/s3-app created
```

Podに入って確認します。

```bash
[root@ip-192-168-0-50 s3-mount]# k get po
NAME     READY   STATUS    RESTARTS   AGE
s3-app   1/1     Running   0          3m13s
[root@ip-192-168-0-50 s3-mount]# k exec s3-app -it -- bash
[root@s3-app /]# mount | grep s3
mountpoint-s3 on /data type fuse (rw,nosuid,nodev,noatime,user_id=0,group_id=0,default_permissions)
```

mountpoint-s3というファイルシステムでマウントされているようです。
  
折角なので少し触ってみます。

```bash
[root@s3-app /]# cd /data/
[root@s3-app data]# ls
'Fri Jan  5 08:11:18 UTC 2024.txt'
[root@s3-app data]# echo hogehoge > hoge.txt
[root@s3-app data]# ls -l
total 1
-rw-r--r-- 1 root root 26 Jan  5 08:11 'Fri Jan  5 08:11:18 UTC 2024.txt'
-rw-r--r-- 1 root root  9 Jan  5 08:22  hoge.txt
[root@s3-app data]# cat hoge.txt
hogehoge
[root@s3-app data]# rm hoge.txt
rm: remove regular file 'hoge.txt'? y
[root@s3-app data]# ls -l
total 1
-rw-r--r-- 1 root root 26 Jan  5 08:11 'Fri Jan  5 08:11:18 UTC 2024.txt'

```

ファイルの作成、読み取り、削除が問題なく出来ました。

```bash
[root@s3-app data]# mkdir fuga
[root@s3-app data]# ls
'Fri Jan  5 08:11:18 UTC 2024.txt'   fuga
[root@s3-app data]# echo fugafuga > fuga/fuga.txt
[root@s3-app data]# cat fuga/fuga.txt
fugafuga
[root@s3-app data]# rm -rf fuga/
[root@s3-app data]# ls -l
total 1
-rw-r--r-- 1 root root 26 Jan  5 08:11 'Fri Jan  5 08:11:18 UTC 2024.txt'
```

ディレクトリも作成、削除が出来るようです。

### まとめ

永続化したいデータの保存先としてS3バケットが選択肢に加わるのは大きなメリットだと思います。EFSを使った場合のパフォーマンスの比較等を今後機会があれば試したいですな。以上。