Kubeflow 1.0 on AWS #2 Notebookの作成

# はじめに

これは、Kubeflow 1.0 をAWSで構築する記事です。
動作確認が主な目的ですので、本番環境での利用は全く想定していません。

# 前回まで
[Kubeflow 1.0 on AWS #1 構築](https://qiita.com/asahi0301/items/21866199e347b9fc1f72)

# 今回の内容
Kubeflow上で Jupyter Notebookを作成してみます


# Notebookの作成(GUI)
New Serverを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107953/16eb1cad-f21f-76c6-58ee-76dbd5f92926.png)

demo1と名前で Notebook を作成します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107953/0c425460-0337-c812-be94-834084286a6a.png)


こんな感じでで作成中になります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107953/a1901015-c3f0-1259-5b84-f082950f0e2c.png)

作成が終わって、CONNECTを選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107953/6b1c8b60-62dc-8c07-cb40-a0a5a10bc4b3.png)


Notebookに繋がりました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107953/1cb64375-7c9a-06c1-49fe-f33b8ce2769e.png)

# Notebookを操作してみる
デフォルトだとpython3しかないようです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107953/043dc4ab-bbff-9f2e-4298-ffb15d2abfd8.png)

rootもsudoも使えないので、root権限が必要な作業はカスタムイメージを作成する必要がありそうです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107953/9f1c78be-c840-9281-e31f-1418ec8cf86e.png)

スクショは載せていないですが、gitは入ってました

Keras は入っていないっぽい( pip等で入れればいいだけなので大した問題ではない）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107953/7ec05a5d-3aac-2a07-4c44-1a814d5e08d9.png)


試しに[こちら](https://qiita.com/fukuit/items/b3fa460577a0ea139c88)と同じコード(keras)を流すと動きました。学習時間を短縮するために、epoch数は2に変えました

Kerasのバージョンが違うっぽいので、 accをaccuracyに置換しました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107953/173dbeca-d6dd-6c24-028a-3c8f6c3b7eb9.png)

## 所感
Notebookとしては問題なく動いているようです

# 環境確認
```shell
get all -n anonymous
NAME          READY   STATUS    RESTARTS   AGE
pod/demo1-0   2/2     Running   0          28m

NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
service/demo1   ClusterIP   10.100.123.227   <none>        80/TCP    28m

NAME                     READY   AGE
statefulset.apps/demo1   1/1     28m
```

kubectl get pv  | grep demo1                    
pvc-e68e0e8e-6eae-11ea-8b88-0ee99a06437c   10Gi       RWO            Delete           Bound    anonymous/workspace-demo1   gp2                     30m
```

Notebookの実態は、StatefulSetであり、PV(AWSなのでEBS)がついていることがわかります。
そして、Serviceとして、ClusterIPを持っているようです。

## istioのvirtualserviceの確認
```sh
kubectl get virtualservice -A
NAMESPACE   NAME                         GATEWAYS                      HOSTS                      AGE
anonymous   notebook-anonymous-demo1     [kubeflow/kubeflow-gateway]   [*]                        37m
kubeflow    argo-ui                      [kubeflow-gateway]            [*]                        23h
kubeflow    centraldashboard             [kubeflow-gateway]            [*]                        23h
kubeflow    google-api-vs                                              [www.googleapis.com]       23h
kubeflow    google-storage-api-vs                                      [storage.googleapis.com]   23h
kubeflow    grafana-vs                   [kubeflow-gateway]            [*]                        23h
kubeflow    jupyter-web-app              [kubeflow-gateway]            [*]                        23h
kubeflow    katib-ui                     [kubeflow-gateway]            [*]                        23h
kubeflow    kfam                         [kubeflow-gateway]            [*]                        23h
kubeflow    metadata-grpc                [kubeflow-gateway]            [*]                        23h
kubeflow    metadata-ui                  [kubeflow-gateway]            [*]                        23h
kubeflow    ml-pipeline-tensorboard-ui   [kubeflow-gateway]            [*]                        23h
kubeflow    ml-pipeline-ui               [kubeflow-gateway]            [*]                        23h
kubeflow    tensorboard                  [kubeflow-gateway]            [*]                        23h
bash-4.2# 
```

notebook-anonymous-demo というvirtualserviceが作成されていることが分かります。


```sh
kubectl get virtualservice notebook-anonymous-demo1 -n anonymous -o yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  creationTimestamp: "2020-03-25T15:40:06Z"
  generation: 1
  name: notebook-anonymous-demo1
  namespace: anonymous
  ownerReferences:
  - apiVersion: kubeflow.org/v1beta1
    blockOwnerDeletion: true
    controller: true
    kind: Notebook
    name: demo1
    uid: e68f6959-6eae-11ea-9e97-0a81a7804a98
  resourceVersion: "567338"
  selfLink: /apis/networking.istio.io/v1alpha3/namespaces/anonymous/virtualservices/notebook-anonymous-demo1
  uid: e693d4ed-6eae-11ea-9e97-0a81a7804a98
spec:
  gateways:
  - kubeflow/kubeflow-gateway
  hosts:
  - '*'
  http:
  - match:
    - uri:
        prefix: /notebook/anonymous/demo1/
    rewrite:
      uri: /notebook/anonymous/demo1/
    route:
    - destination:
        host: demo1.anonymous.svc.cluster.local
        port:
          number: 80
    timeout: 300s
````

こちらの設定で、/notebook/anonymous/demo1/　というpathなら、notebookにつながるようになっていることが分かります。



ちなみにstatefulset自体のyamlは以下のようになっています

```sh
kubectl get statefulset demo1 -n anonymous -o yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  creationTimestamp: "2020-03-25T15:40:05Z"
  generation: 1
  name: demo1
  namespace: anonymous
  ownerReferences:
  - apiVersion: kubeflow.org/v1beta1
    blockOwnerDeletion: true
    controller: true
    kind: Notebook
    name: demo1
    uid: e68f6959-6eae-11ea-9e97-0a81a7804a98
  resourceVersion: "567535"
  selfLink: /apis/apps/v1/namespaces/anonymous/statefulsets/demo1
  uid: e690c53b-6eae-11ea-9e97-0a81a7804a98
spec:
  podManagementPolicy: OrderedReady
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      statefulset: demo1
  serviceName: ""
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: demo1
        notebook-name: demo1
        statefulset: demo1
    spec:
      containers:
      - env:
        - name: NB_PREFIX
          value: /notebook/anonymous/demo1
        image: gcr.io/kubeflow-images-public/tensorflow-1.15.2-notebook-cpu:1.0.0
        imagePullPolicy: IfNotPresent
        name: demo1
        ports:
        - containerPort: 8888
          name: notebook-port
          protocol: TCP
        resources:
          requests:
            cpu: 500m
            memory: 1Gi
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /home/jovyan
          name: workspace-demo1
        - mountPath: /dev/shm
          name: dshm
        workingDir: /home/jovyan
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext:
        fsGroup: 100
      serviceAccount: default-editor
      serviceAccountName: default-editor
      terminationGracePeriodSeconds: 30
      volumes:
      - name: workspace-demo1
        persistentVolumeClaim:
          claimName: workspace-demo1
      - emptyDir:
          medium: Memory
        name: dshm
  updateStrategy:
    rollingUpdate:
      partition: 0
    type: RollingUpdate
status:
  collisionCount: 0
  currentReplicas: 1
  currentRevision: demo1-dc56967ff
  observedGeneration: 1
  readyReplicas: 1
  replicas: 1
  updateRevision: demo1-dc56967ff
  updatedReplicas: 1
```

# notebookを削除する
GUIから普通に削除します。PersistentStorageを使っているとデータは残るようです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107953/6e7eec50-2566-92df-7366-4448bf8c61be.png)

GUIからは消えましたが、確かにPV/PVCが残っていることは確認できました

```sh
kubectl get pvc -n anonymous
NAME              STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
workspace-demo1   Bound    pvc-e68e0e8e-6eae-11ea-8b88-0ee99a06437c   10Gi       RWO            gp2            48m
```

# もう一度 notebookを作成する
demo2というnotebookを新規で作成し、既存のストレージを作成するという選択肢があるので、それを選択しました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107953/bfa6e129-f14b-f50b-c747-cc3ef27f6587.png)

接続してみます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107953/b2289cc1-0c10-98ec-72d1-d3f67c2f8297.png)

予想通りですが、データが残っていることが分かります。
既存のPVCを指定できるので、例えば、EFSでPVCを作成して、Notebookのデータは共有ストレージに保存する的なこともできそうです。（いつかやってみたいと思います）