LoginSignup
0
0

More than 1 year has passed since last update.

EKSでRayクラスター作成

Last updated at Posted at 2022-01-21

概要

AWS EKS上でRayクラスターを作成してJupyter notebookを利用する手順を記載する。

EKSの作成には、AWSコンソールを利用する方法とeksctlを使う方法があるが、eksctlだとEKSを利用するのに必要なAWSリソースも同時に作成してくれるので今回はeksctlを使う。

EKSはEKS ClusterとEKS Nodegroupからなる。EKS ClusterがKubernetesクラスターのうちコントロールプレーンを担い、EKS Nodegroupがデータプレーン(=実際にコンテナ稼働するワーカーノード群)を担う。

参考

  • EKS作成

  • Helm

EKS作成後にRayクラスターをKubernetes上にデプロイする。Helmは、Kubernetesリソースのデプロイを支援するツール。

  • Helm Chart

Ray公式が紹介しているものを利用

前提

  • AWSアカウントを持っていること
  • 踏み台サーバ(EC2)が作成済み

手順

  1. eksctlでEKS Cluster&EKS Nodegroup作成
  2. Rayクラスター作成
  3. Jupyter notebookへアクセス

0. Kubectlのインストール

curl -o kubectl https://amazon-eks.s3.us-west-2.amazonaws.com/1.21.2/2021-07-05/bin/linux/amd64/kubectl
curl -o kubectl.sha256 https://amazon-eks.s3.us-west-2.amazonaws.com/1.21.2/2021-07-05/bin/linux/amd64/kubectl.sha256
openssl sha1 -sha256 kubectl
chmod +x ./kubectl
mkdir -p $HOME/bin && cp ./kubectl $HOME/bin/kubectl && export PATH=$PATH:$HOME/bin
echo 'export PATH=$PATH:$HOME/bin' >> ~/.bashrc
kubectl version --short --client

1. EKS Cluster、EKS Nodegroupを作成

注意:踏み台サーバ(EC2)上でeksctlを実行する、すなわち踏み台サーバがAWSリソースやEKS Cluster/Nodegroupを作成するので、踏み台サーバのIAMロールに権限を付与しておいてあげる必要がある。最小限の権限がわからなかったので(調べたら出てきたが試してないので省く)AdministratorAccessポリシーを踏み台サーバのIAMロールに割り当てた。

まずは踏み台サーバにeksctlをインストールする。

$ curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
$ sudo mv /tmp/eksctl /usr/local/bin
$ eksctl version

踏み台サーバからeksctl createでEKS Cluster, Nodegroupを作成する。sudoを抜くとエラーになるので注意。

$ sudo eksctl create cluster \
    --name ray-eks-cluster \
    --region us-west-2 \
    --nodegroup-name ray-nodegroup \
    --node-type t3.large \
    --nodes 3 \
    --nodes-min 2 \
    --nodes-max 4 \
    --managed

これで一気に各種AWSリソースとEKS Cluster/Nodegroupを作成してくれる。eksctlはCloud Formationを利用してこれらを作成するので、リソースの作成状況はCloud Formationで確認できる。

リソースの作成が完了したら、kubectlでEKS Clusterを操作するために、kubeconfigを作成する。

$ aws eks update-kubeconfig --region us-west-2 --name ray-eks-cluster

次のコマンドで以下の出力が得られればkubeconfigが正しく設定されている。

$ kubectl get svc
NAME             TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
svc/kubernetes   ClusterIP   10.100.0.1   <none>        443/TCP   1m

以下のコマンドで接続しているクラスタを確認できる。

$ kubectl config get-contexts

2. Rayクラスター作成

踏み台サーバ上にHelmをインストールする。helm versionでバージョンが確認できれば正常にインストールされている。

$ curl -O https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3
$ bash ./get-helm-3
$ helm version

次にRay用のHelm Chartをダウンロードし、Kubernetesクラスター上にKuberntesリソース(Ray cluster)をデプロイする。

$ sudo apt-get install git
$ git clone https://github.com/ray-project/ray.git
$ cd ray/deploy/charts
$ sudo helm -n ray install example-cluster --create-namespace ./ray

Kubernetes NodeやPodが確認できる。

$ sudo kubectl get nodes
$ sudo kubectl get pods
$ sudo kubectl get pods -n ray

3. Jupyter notebookへアクセス

Jupyter notebookをHead node上で起動する予定。なので、Head nodeへアクセスする必要がある。アクセスの方法はいろいろあると思うが、3通りの方法を記載する。

  1. 同じVPC内に踏み台サーバ設置
  2. 既存のServiceをLoadBalancerに変更して外部公開
  3. 新たにLoadBalancer Serviceを作成して外部公開

1.については、同じVPC内にあるAWSリソースからEKSのPodにアクセスできることを利用している。

3-1. 同じVPC内に踏み台サーバ(EC2)を設置

以下に概要のみ記す。まずEKSクラスタとして起動されたEC2がどのVPCに入っているかAWSコンソールから確認する。次に、同じVPC内のパブリックサブネット内に踏み台サーバとしてEC2を起動する。(※eksctlにより各アベイラビリティゾーン毎にパブリックサブネットとプライベートサブネットが1つずつ作成されているはず)。手順概要は以上。起動したEC2上でブラウザを開いてJupyter notebookを触るので、踏み台サーバはGUI化しておく必要がある(手順省略)

3-2. 既存のServiceをLoadBalancerに変更

デフォルトでは以下のClusterIP Serviceが作成される。これをLoadBalancerに変更して外部からアクセス可能なURLを生成する。

$ kubectl get svc -n ray
NAME                           TYPE           CLUSTER-IP       EXTERNAL-IP                                                               PORT(S)                                         AGE
example-cluster-ray-head       ClusterIP      10.100.231.189   <none>                                                                    10001/TCP,8265/TCP,8000/TCP                     74m

下記のコマンドでspec配下のtypeの値をLoadBalancerに変更する。

kubectl -n ray patch svc example-cluster-ray-head -p '{"spec": {"type": "LoadBalancer"}}'

再度Serviceを確認すると、EXTERNAL-IPが生成されていることがわかる。

$ kubectl get svc -n ray
NAME                           TYPE           CLUSTER-IP       EXTERNAL-IP                                                               PORT(S)                                         AGE
example-cluster-ray-head       LoadBalancer   10.100.231.189   a94bd10a573874295a1d41aa77f99957-1031258648.us-west-2.elb.amazonaws.com   10001:32634/TCP,8265:31708/TCP,8000:31710/TCP   76m

【!! 注意 !!】
EXTERNAL-IPが生成されても実際にルーティング処理できるようには結構時間がかかる気がする(全然数えてないけど10分くらい?)。

次に、example-cluster-ray-headのbashに入って(Head nodeに転送されるので実際にはHead nodeに入っている)、Jupyter notebookを起動する。

$ sudo kubectl -n ray exec -it service/example-cluster-ray-head -- bash
$ pip3 install notebook
$ jupyter notebook --ip=* --no-browser --port 8000

ブラウザでhttp://<EXTERNAL-IP>:8000にアクセスする。Jupyter notebook起動時に表示されたtokenを入力してJupyter notebookにログインする。あとはJupyter notebookを使ってRayを試す。

http://a94bd10a573874295a1d41aa77f99957-1031258648.us-west-2.elb.amazonaws.com:8000/

【!! 注意 !!】
kubectl get svc -n rayの結果では8000:31710/TCPとなっており8000番ポートを31710番に転送しているように見えるが、Jupyterを31710番ポートで起動してもなぜかアクセスできない(なにが原因なんだろ、、、)。8000番ポートで起動すればアクセスできる。

3-3. 新たにLoadBalancerを作成して外部公開

Jupyter notebookに外部からアクセスするためLoadBalancer Serviceを作成する。まずはLoadBalancer用のyamlを作成する。

既存のServiceを参考にするため既存のServiceをyamlで出力する。

$ sudo kubectl get service -o yaml -n ray

上記コマンドの出力結果を元にlb.yamlを作成する。重要な点は
selector:
cluster.ray.io/component: example-cluster-ray-head

として、LoadBalancerへのトラヒックがHead nodeにルーティングされるように設定しているところ。

lb.yaml
apiVersion: v1
kind: Service
metadata:
  name: example-cluster-ray-head-lb
  namespace: ray
spec:
  clusterIP: 10.100.231.167
  clusterIPs:
  - 10.100.231.167
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - name: client
    port: 10001
    protocol: TCP
    targetPort: 10001
  - name: dashboard
    port: 8265
    protocol: TCP
    targetPort: 8265
  - name: ray-serve
    port: 8000
    protocol: TCP
    targetPort: 8000
  selector:
    cluster.ray.io/component: example-cluster-ray-head
  sessionAffinity: None
  type: LoadBalancer

作成したlb.yamlをもとにLoad Balancerを作成する。

$ sudo kubectl create -f lb.yaml -n ray

Load Balancer serviceが作成されたことを確認する。

$ sudo kubectl get service -n ray
NAME                          TYPE           CLUSTER-IP       EXTERNAL-IP                                                               PORT(S)                                         AGE
example-cluster-ray-head      ClusterIP      10.100.150.175   <none>                                                                    10001/TCP,8265/TCP,8000/TCP                     142m
example-cluster-ray-head-lb   LoadBalancer   10.100.150.177   a932049cbef824477bfc553edba1d781-1349688053.us-west-2.elb.amazonaws.com   10001:31563/TCP,8265:31733/TCP,8000:30620/TCP   56s

【!! 注意 !!】
EXTERNAL-IPが生成されても実際にルーティング処理できるようには結構時間がかかる気がする(全然数えてないけど10分くらい?)。

example-cluster-ray-head (ClusterIP)のbashに入って、Jupyter notebookを起動する。指定するポートはexample-cluster-ray-head-lbの宛先ポート。

$ sudo kubectl -n ray exec -it service/example-cluster-ray-head -- bash
$ pip3 install notebook
$ jupyter notebook --ip=* --no-browser --port 8000

ブラウザでhttp://<EXTERNAL-IP>:8000にアクセスする。Jupyter notebook起動時に表示されたtokenを入力してJupyter notebookにログインする。あとはJupyter notebookを使ってRayを試す。

http://a932049cbef824477bfc553edba1d781-1349688053.us-west-2.elb.amazonaws.com:8000/

【!! 注意 !!】
kubectl get svc -n rayの結果では8000:31710/TCPとなっており8000番ポートを31710番に転送しているように見えるが、Jupyterを31710番ポートで起動してもなぜかアクセスできない(なにが原因なんだろ、、、)。8000番ポートで起動すればアクセスできる。

4. 削除

使い終わったら削除を忘れずに。

まずK8sリソースを削除。

# まずカスタムリソースrayClusterの「example-cluster」を削除
$ kubectl -n ray delete raycluster example-cluster

# 次に「example-cluster」をアンインストール
$ helm -n ray uninstall example-cluster
release "example-cluster" uninstalled

# 最後にネームスペースrayを削除
$ kubectl delete namespace ray
namespace "ray" deleted

さらにEKS clusterを削除。

$ sudo eksctl delete cluster \
    --name ray-eks-cluster \
    --wait

以上。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0