背景#
Ray は、分散コンピューティングを可能にする統一フレームワークであり、単一のサーバーでは重い計算タスクを処理できない場合があります。この記事では、Ray の 2 つの重要な機能、すなわちマルチテナンシーとオートスケーリングについての詳細な分析を提供します。マルチテナンシーは、異なるユーザーに対して CPU やメモリなどの異なるリソースを割り当てることを可能にします。一方、オートスケーリングは、トラフィックや利用レベルに基づいてインスタンスの追加や削除を容易にします。
Kubernetes を選ぶ理由#
Ray はリソース要求に応じて Ray クラスターをスケールする公式のオートスケーリングソリューションを提供していますが、私たちの特定のシナリオではメモリ使用量に基づくオートスケーリングが必要です。その結果、私たちは 2 つの潜在的なソリューションを開発しました。最初のソリューションは、Ray リソースモニターを利用して各タスクとアクターのリソース使用量を監視することです。各ユーザーに異なるクォータを割り当てているため、各タスクとアクターのリソース使用量を集計する必要があります。さらに、メモリ使用量に基づいてオートスケーリングをトリガーするタイミングを決定するメカニズムを確立しなければなりません。2 番目のソリューションは、Kubernetes Horizontal Pod Autoscaler を利用してメモリ使用量に基づいてレプリカの数を自動的に調整することです。したがって、ここでは主に 2 番目のソリューションを選択します。
Ray クラスターの構築#
Kubernetes と Harbor 環境を既に設定していると仮定すると、次のステップは Ray クラスターをインストールすることです。特定の構成に合わせてイメージを変更する必要があることに注意してください。
# Rayヘッドノードサービス、ワーカーポッドがヘッドノードを発見して双方向通信を行うことを許可します。
# 詳細なコンテキストは[ポート構成ドキュメント](https://docs.ray.io/en/latest/ray-core/configure.html#ports-configurations)で確認できます。
apiVersion: v1
kind: Service
metadata:
name: service-ray-cluster
labels:
app: ray-cluster-head
spec:
clusterIP: None
ports:
- name: client
protocol: TCP
port: 10001
targetPort: 10001
- name: dashboard
protocol: TCP
port: 8265
targetPort: 8265
- name: gcs-server
protocol: TCP
port: 6380
targetPort: 6380
selector:
app: ray-cluster-head
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-ray-head
labels:
app: ray-cluster-head
spec:
# これを変更しないでください - Rayは現在、クラスターごとに1つのヘッドノードのみをサポートしています。
replicas: 1
selector:
matchLabels:
component: ray-head
type: ray
app: ray-cluster-head
template:
metadata:
labels:
component: ray-head
type: ray
app: ray-cluster-head
spec:
# ヘッドノードがダウンすると、クラスター全体(すべてのワーカーノードを含む)もダウンします。
# この場合、Kubernetesが新しいヘッドノードを立ち上げるようにしたい場合は、これを「Always」に設定し、そうでない場合は「Never」に設定します。
restartPolicy: Always
# このボリュームは、Rayがそのプラズマオブジェクトストアに使用するための共有メモリを割り当てます。
# これを提供しない場合、Rayは/tmpにフォールバックし、共有メモリボリュームでない場合は遅延が発生します。
# volumes:
# - name: dshm
# emptyDir:
# medium: Memory
containers:
- name: ray-head
image: rayproject/ray:2.3.0
imagePullPolicy: Always
command: [ "/bin/bash", "-c", "--" ]
# Redisにパスワードがない場合は、--redis-password=''を設定します
args:
- "ray start --head --port=6380 --num-cpus=$MY_CPU_REQUEST --dashboard-host=0.0.0.0 --object-manager-port=8076 --node-manager-port=8077 --dashboard-agent-grpc-port=8078 --dashboard-agent-listen-port=52365 --redis-password='123456' --block"
ports:
- containerPort: 6380 # GCSサーバー
- containerPort: 10001 # Rayクライアントによって使用される
- containerPort: 8265 # Rayダッシュボードによって使用される
# このボリュームは、Rayがそのプラズマオブジェクトストアに使用するための共有メモリを割り当てます。
# これを提供しない場合、Rayは/tmpにフォールバックし、共有メモリボリュームでない場合は遅延が発生します。
# volumeMounts:
# - mountPath: /dev/shm
# name: dshm
env:
# RAY_REDIS_ADDRESSは、Rayが外部Redisを使用して障害耐性を持つことを許可します
- name: RAY_REDIS_ADDRESS
value: redis:6379 # 外部RedisのIPアドレス、この例では「redis:6379」
# これはray startコマンドで使用され、Rayが正しい数のプロセスを生成できるようにします。
# これを省略すると、パフォーマンスが低下する可能性があります。
- name: MY_CPU_REQUEST
valueFrom:
resourceFieldRef:
resource: requests.cpu
resources:
limits:
cpu: "2"
memory: "5G"
requests:
# 生産用途の場合、整数のCPU要求と制限を指定することをお勧めします。
# また、CPUとメモリの両方の要求を制限と等しく設定することをお勧めします。
# この例では、KinDやminikubeなどのリソース制約のあるローカルKubernetesテスト環境に対応するために、500mのCPU要求を使用します。
cpu: "500m"
# Rayヘッドノードの残りの状態メモリ使用量は約1Gbです。Rayヘッドポッドに2Gb未満のメモリを割り当てることはお勧めしません。
# 生産用途の場合、各Rayコンテナに少なくとも8Gbのメモリを割り当てることをお勧めします。
memory: "2G"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-ray-worker
labels:
app: ray-cluster-worker
spec:
# Rayクラスターで開始されるワーカーノードの数をスケールするには、これを変更します。
selector:
matchLabels:
component: ray-worker
type: ray
app: ray-cluster-worker
template:
metadata:
labels:
component: ray-worker
type: ray
app: ray-cluster-worker
spec:
restartPolicy: Always
# volumes:
# - name: dshm
# emptyDir:
# medium: Memory
containers:
- name: ray-worker
image: rayproject/ray:2.3.0
imagePullPolicy: Always
command: ["/bin/bash", "-c", "--"]
args:
- "ray start --num-cpus=$MY_CPU_REQUEST --address=service-ray-cluster:6380 --object-manager-port=8076 --node-manager-port=8077 --dashboard-agent-grpc-port=8078 --dashboard-agent-listen-port=52365 --block"
# このボリュームは、Rayがそのプラズマオブジェクトストアに使用するための共有メモリを割り当てます。
# これを提供しない場合、Rayは/tmpにフォールバックし、共有メモリボリュームでない場合は遅延が発生します。
# volumeMounts:
# - mountPath: /dev/shm
# name: dshm
env:
# これはray startコマンドで使用され、Rayが正しい数のプロセスを生成できるようにします。
# これを省略すると、パフォーマンスが低下する可能性があります。
- name: MY_CPU_REQUEST
valueFrom:
resourceFieldRef:
resource: requests.cpu
# この設定のリソース要求と制限は、生産には小さすぎます!
# 多くの小さなRayポッドよりも、いくつかの大きなRayポッドを使用する方が良いです。
# 生産の場合、各RayポッドがスケジュールされたKubernetesノード全体を占有するのが理想的です。
resources:
limits:
cpu: "1"
memory: "1G"
# 生産用途の場合、整数のCPU要求と制限を指定することをお勧めします。
# また、CPUとメモリの両方の要求を制限と等しく設定することをお勧めします。
# この例では、KinDやminikubeなどのリソース制約のあるローカルKubernetesテスト環境に対応するために、500mのCPU要求を使用します。
requests:
cpu: "500m"
memory: "1G"
サーバー上にray-dev.yaml
ファイルを作成したら、Ray ヘッドとワーカーをインストールすることができます。ns
名前空間に Ray クラスターをインストールしたい場合は、次のコマンドを実行します。
kubectl apply -f ray-dev.yaml -n ns
サーバー上にray-dev.yaml
ファイルを作成し、Ray ヘッドとワーカーをインストールした後、次のステップはワーカーのために Horizontal Pod Autoscaling(HPA)を有効にすることです。
ワーカーの HPA を有効にするには、サーバー上にray-autoscaler.yaml
という別のファイルを作成する必要があります。このファイルには、CPU 利用率に基づいてワーカーポッドの数を自動的にスケールする Kubernetes HPA オブジェクトの設定が含まれます。以下はray-autoscaler.yaml
ファイルの例です。
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: ray-autoscaler
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: deployment-ray-worker
minReplicas: 1
maxReplicas: 2
targetCPUUtilizationPercentage: 60
この HPA は、指定されたデプロイメントのレプリカ数を CPU 利用率に基づいて自動的に調整し、最小 1 レプリカ、最大 2 レプリカで、CPU 利用率 60% を目指します。
この HPA をns
名前空間に適用するには、次のコマンドを実行します。
kubectl apply -f ray-autoscaler.yaml -n ns
監視と可視性#
次のステップは、クラスター監視を有効にすることです。Ray は、メトリクスエージェントのサービスディスカバリーを容易にするために、ヘッドノード上にprom_metrics_service_discovery.json
という Prometheus サービスディスカバリーファイルを自動生成します。Kubernetes のデフォルトの Prometheus を使用して Ray クラスターの監視を有効にするには、このファイルをマッピングし、Prometheus の設定に追加する必要があります。
ray-dev.yaml
設定ファイルを更新して、/tmp/ray
ディレクトリをマッピングするために永続ボリュームクレーム(PVC)を使用するようにします(詳細についてはドキュメントを参照してください)。これには、YAML ファイルにvolumes
とvolumeMounts
の設定を追加する必要があります。最後に、この PVC を Prometheus インスタンスに関連付けることができます。
spec:
volumes:
- name: ray-prom
persistentVolumeClaim:
claimName: ray-prom-pvc
containers:
- name: ray-head
volumeMounts:
- name: ray-prom
mountPath: /tmp/ray