EKSで機械学習 #7 EFSの設定

# はじめに
このシリーズでは Amazon EKSで機械学習を行っていきたいと思います

# シリーズ目次
EKSで機械学習 #1 準備編
EKSで機械学習 #2 クラスター作成編
EKSで機械学習 #3 Managed Worker Node作成編
EKSで機械学習 #4 GPU Managed Worker Node作成編
EKSで機械学習 #5 Cluster AutoScaler設定編
EKSで機械学習 #6 HPAの設定
EKSで機械学習 #7 EFSの設定 (この記事)



# この記事の目的
機械学習のデータや成果物はどこに置くかという議論ですが、
単純に考えるとAWSだとS3かEFSなどの共有ストレージかなと思います。
この記事では、EFSを設定してみました。

# Amazon EFS CSI Driver のデプロイ
これを参考します
https://docs.aws.amazon.com/eks/latest/userguide/efs-csi.html

```sh
kubectl apply -k "github.com/kubernetes-sigs/aws-efs-csi-driver/deploy/kubernetes/overlays/stable/?ref=master"
daemonset.apps/efs-csi-node created
csidriver.storage.k8s.io/efs.csi.aws.com created
```

学習はGPUで行いますが、推論はCPUで行う可能性もあり、全 worker nodeにdaemonsetを配置するようにしました。

# VPC設定の確認

```shell
aws eks describe-cluster --name ml --query "cluster.resourcesVpcConfig.vpcId" --output text --region us-west-2
vpc-xxxxxxxx (各自結果は違います)
```

```shell
aws ec2 describe-vpcs --vpc-ids vpc-xxxxxxx --query "Vpcs[].CidrBlock" --output text --region us-west-2                         
192.168.0.0/16
```

# EFSの作成
これを参考します
https://docs.aws.amazon.com/eks/latest/userguide/efs-csi.html

私の環境では、``` fs-580xxxx.efs.us-west-2.amazonaws.com ``` というエンドポイントが作成されました。

# サンプルアプリのデプロイ
## PersistentVolumeを少し書き換える

```
aws efs describe-file-systems --query "FileSystems[*].FileSystemId" --output text --region us-west-2
fs-580xxxxx
```

こんな感じで編集。5Giになっているのは無視していいらしい。
``` This value does not limit the size of your Amazon EFS file system.  ```

``` specs/pv.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: efs-pv
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  storageClassName: efs-sc
  csi:
    driver: efs.csi.aws.com
    volumeHandle: fs-580xxxxx
```

## StorageClassを確認する
以下のようになっていることを確認します

```specs/storageclass.yaml 
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: efs-sc
provisioner: efs.csi.aws.com
```

## PersistentVolumeClaimを確認する
以下のようになっていることを確認します

```specs/claim.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: efs-claim
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: efs-sc
  resources:
    requests:
      storage: 5Gi
```


### Tips
PersistentVolumeとPersistentVolumeClaimとかはこちらを参照
https://cstoku.dev/posts/2018/k8sdojo-12/

## サンプルpodの確認
``` specs/pod1.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: app1
spec:
  containers:
  - name: app1
    image: busybox
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo $(date -u) >> /data/out1.txt; sleep 5; done"]
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: efs-claim
```


```specs/pod2.yaml                                                         
apiVersion: v1
kind: Pod
metadata:
  name: app2
spec:
  containers:
  - name: app2
    image: busybox
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo $(date -u) >> /data/out2.txt; sleep 5; done"]
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: efs-claim
```

どちらもこの設定が入っていることがわかる

```yml
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: efs-claim
```


## デプロイ

```shell

k apply -f specs/
persistentvolumeclaim/efs-claim created
pod/app1 created
pod/app2 created
persistentvolume/efs-pv created
storageclass.storage.k8s.io/efs-sc created
```

## 動作確認

```sh
k get pod 
NAME                                  READY   STATUS    RESTARTS   AGE
app1                                  1/1     Running   0          49s
app2                                  1/1     Running   0          49s
```


```
kubectl exec -ti app1 -- tail /data/out1.txt
Wed Mar 4 07:17:12 UTC 2020
Wed Mar 4 07:17:17 UTC 2020
Wed Mar 4 07:17:22 UTC 2020
Wed Mar 4 07:17:27 UTC 2020
Wed Mar 4 07:17:32 UTC 2020
Wed Mar 4 07:17:37 UTC 2020
Wed Mar 4 07:17:42 UTC 2020
Wed Mar 4 07:17:47 UTC 2020
Wed Mar 4 07:17:52 UTC 2020
Wed Mar 4 07:17:57 UTC 2020


kubectl exec -ti app2 -- tail /data/out1.txt
Wed Mar 4 07:17:37 UTC 2020
Wed Mar 4 07:17:42 UTC 2020
Wed Mar 4 07:17:47 UTC 2020
Wed Mar 4 07:17:52 UTC 2020
Wed Mar 4 07:17:57 UTC 2020
Wed Mar 4 07:18:02 UTC 2020
Wed Mar 4 07:18:07 UTC 2020
Wed Mar 4 07:18:12 UTC 2020
Wed Mar 4 07:18:17 UTC 2020
Wed Mar 4 07:18:22 UTC 2020
```
app1からEFSに書き込んだデータ(/data/out1.txt)がapp2からも見えていることがわかる


### Tips
bashで入ってみる(busyboxなのでashを利用する)

```sh

k exec -it app1 ash
# df
Filesystem           1K-blocks      Used Available Use% Mounted on
overlay              157274092   8859440 148414652   6% /
tmpfs                    65536         0     65536   0% /dev
tmpfs                 31436424         0  31436424   0% /sys/fs/cgroup
fs-580xxxxx.efs.us-west-2.amazonaws.com:/     9007199254739968         0 9007199254739968   0% /data
```

きちんとマウントされていることが分かる。

# 削除
動作確認は終わったので、削除しておく
あとで、EFSは本格的に使っていく予定

```sh
kubectl delete -f specs/
persistentvolumeclaim "efs-claim" deleted
pod "app1" deleted
pod "app2" deleted
persistentvolume "efs-pv" deleted
storageclass.storage.k8s.io "efs-sc" deleted
```


# まとめ
ここでは、機械学習の共有ストレージとして、EFSを利用する設定を行い、サンプルアプリケーションが動作することを確認しました。