EKSにKubeflowをインストールする

awskubernetesmachinelearning

Kubernetes上で機械学習を行うためのツールキットKubeflowを EKSにインストールする。 m5.large * 4のクラスタをCDKで作成した。

CDKでEKSクラスタの作成からHelm ChartでのLocustのインストールまでを一気に行う - sambaiz-net

まずKubeflowのCLIツールkfctlをインストールする。 内部でeksctlが呼ばれるがフラグでprofileを指定できないので環境変数に入れておく。

$ curl -L https://github.com/kubeflow/kfctl/releases/download/v1.2.0/kfctl_v1.2.0-0-gbc038f9_darwin.tar.gz > kfctl.tar.gz
$ tar -xvf kfctl.tar.gz
$ ./kfctl version
kfctl v1.2.0-0-gbc038f9

$ eksctl version
0.32.0

$ export AWS_PROFILE=***

AWS用の設定ファイルを持ってきて、RegionやRole、Cognito UserPoolあるいはusernameとpasswordによる認証の設定をKfAwsPluginに書く。UserPoolの作成もCDKで行える。それとACMで証明書を発行しておく。

CDKでCognito UserPoolとClientを作成しトリガーやFederationを設定する - sambaiz-net

AWSのサービスにアクセスするのにServiceAccountに関連づけられたRoleを用いる場合はenablePodIamPolicy: trueにして、ワーカーノードのRoleを用いる場合はrolesにそのロール名を書く。 KfDefにはManifestごとのKustomizeに関する設定が並んでいるがそのままで問題ない。

kustomizeでkubernetesのmanifestを環境ごとに生成する - sambaiz-net

$ mkdir <cluster_name> && cd <cluster_name>
$ curl -L https://raw.githubusercontent.com/kubeflow/manifests/v1.1-branch/kfdef/kfctl_aws_cognito.v1.2.0.yaml > kfctl_aws.yaml
$ cat kfctl_aws.yaml 
apiVersion: kfdef.apps.kubeflow.org/v1
kind: KfDef
metadata:
  namespace: kubeflow
spec:
  applications:
  - kustomizeConfig:
      repoRef:
        name: manifests
        path: namespaces/base
    name: namespaces
  ...
  - kustomizeConfig:
      repoRef:
        name: manifests
        path: stacks/aws/application/spartakus
    name: spartakus
  plugins:
  - kind: KfAwsPlugin
    metadata:
      name: aws
    spec:
      auth:
        certArn: arn:aws:acm:ap-northeast-1:******:certificate/******
        cognitoAppClientId: *******
        cognitoUserPoolArn: arn:aws:cognito-idp:ap-northeast-1:******:userpool/*****
        # cognitoDomain's prefix 
        cognitoUserPoolDomain: ********
        # OR
        # basicAuth:
        #  password: 12341234
        #  username: [email protected]
      region: ap-northeast-1
      enablePodIamPolicy: true
      # If you don't use IAM Role for Service Account, you can still use node instance roles.
      #roles:
      #- eksctl-kubeflow-aws-nodegroup-ng-a2-NodeInstanceRole-xxxxxxx
  repos:
  - name: manifests
    uri: https://github.com/kubeflow/manifests/archive/v1.2-branch.tar.gz
  version: v1.2-branch

kfctl applyするとManifestのビルドの後デプロイされる。クラスタと同名のディレクトリ内で行う必要があり、metadataのnameにこの名前が書き込まれる。名前が異なりEKSクラスタが見つからないとService Account is not supported on non-EKS clusterのエラーで失敗する。

$ mkdir <cluster_name> && cd <cluster_name>
$ kfctl apply -V -f kfctl_aws.yaml
...
INFO[0108] Applied the configuration Successfully!       filename="cmd/apply.go:75"

$ tree kustomize/
kustomize/
├── application
│   └── kustomization.yaml
...
└── spartakus
    ├── kustomization.yaml
    └── spartakus-config.yaml

$ kubectl -n kubeflow get pod
NAME                                                     READY   STATUS             RESTARTS   AGE
admission-webhook-bootstrap-stateful-set-0               1/1     Running            2          3m4s
admission-webhook-deployment-5bc67cb78-4876h             0/1     Pending            0          2m2s
alb-ingress-controller-5b777c5cc7-842c6                  1/1     Running            0          2m38s
application-controller-stateful-set-0                    1/1     Running            0          3m57s
...

ALBが作成されるまで数分待ってistio-ingressのアドレスが出たらDNSの設定を行い、Cognitoのredirect_uriにALBの/oauth2/idpresponseを加える。 いつまで経っても出ない場合、alb-ingress-controllerのログを見てみると原因が分かるかもしれない。 CertificateNotFoundになっている場合はarnが間違いなく失効してないか確認する。

$ kubectl logs alb-ingress-controller-**** -n kubeflow
$ kubectl apply -f - <<EOF
apiVersion: kubeflow.org/v1
kind: Profile
metadata:
  name: sambaiz
spec:
  owner:
    kind: User
    name: [email protected]
EOF

アクセスしログインするとKubeflowのprofileの作成が始まる。PERMISSION_DENIED:authzadaptor-handler.handler.istio-system: のようなエラーが出た場合は authzadaptor のログを見てみる。 例えばEmail verifiedがfalseだと Email is not verified false のエラーが流れてくる。

$ kubectl logs -f authzadaptor-******  -n istio-system

profileは同名のkubernetesのnamespaceと対応し、profile ownerにはnamespaceのAdmin Roleが与えられる。また、他のユーザーに権限を与えることもできる。

$ kubectl get ingress -n istio-system
NAME            HOSTS   ADDRESS                                                                      PORTS   AGE
istio-ingress   *       *******.ap-northeast-1.elb.amazonaws.com   80      6m44s

Notebook Serversを作成するとprofileのnamespaceにPodが立ち上がる。

New Notebook Servers

$ kubectl get pod -n sambaiz
NAME                                               READY   STATUS    RESTARTS   AGE
ml-pipeline-ui-artifact-84f654dd94-b2lbv           2/2     Running   0          20m
ml-pipeline-visualizationserver-5ff65bf999-77jrg   2/2     Running   0          20m
sambaiz-test-0                                     2/2     Running   0          2m35s