ローカルディスクを使用したMilvus QueryNodeの設定
Milvus QueryNodeでローカルディスクを使用するための設定方法について説明します。
概要
MilvusはAIに特化したベクトルデータベースであり、膨大なベクトルデータの効率的な保存と検索が可能です。画像・動画解析、自然言語処理、推薦システムなどのタスクに最適です。最適なパフォーマンスを確保するには、ディスクの読み取りレイテンシを最小限に抑えることが極めて重要です。遅延を防ぎ、システムの安定性を維持するためには、ローカルのNVMe SSDを使用することが強く推奨されます。
ローカル・ディスク・ストレージが活躍する主な機能は以下のとおりです:
- チャンク・キャッシュ:データをローカル・ディスク・キャッシュにプリロードし、検索を高速化します。
- MMap:ファイルの内容を直接メモリにマップし、メモリ効率を向上させます。
- DiskANNインデックス:効率的なインデックス管理のためにディスク・ストレージを必要とする。
本記事では、Milvus Distributedをクラウドプラットフォームにデプロイし、NVMeディスクストレージを使用するようにQueryNodeを設定する方法に焦点を当てます。以下の表は、様々なクラウドプロバイダーの推奨マシンタイプの一覧です。
クラウドプロバイダ | マシンタイプ |
---|---|
AWS | R6idシリーズ |
GCP | N2シリーズ |
アジュール | Lsv3シリーズ |
アリババクラウド | i3シリーズ |
テンセントクラウド | IT5シリーズ |
これらのマシンタイプはNVMeディスクストレージを提供する。これらのマシンタイプのインスタンスでlsblk
コマンドを使用して、NVMe ディスクストレージがあるかどうかを確認できます。もしあれば、次のステップに進むことができる。
$ lsblk | grep nvme
nvme0n1 259:0 0 250.0G 0 disk
nvme1n1 259:1 0 250.0G 0 disk
ローカルディスクを使用するようにKubernetesを設定する
Milvus DistributedのQueryNodeがNVMeディスクストレージを使用するように設定するには、対象のKubernetesクラスタのワーカーノードがコンテナとイメージをNVMeディスクに保存するように設定する必要があります。この手順はクラウドプロバイダによって異なる。
AWS
Amazon EKSを使用する場合、ノードグループの構成設定を指定できるローンチテンプレートを使用して管理ノードをカスタマイズできます。以下は、Amazon EKSクラスタのワーカーノードにNVMeディスクをマウントする方法の例です:
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="==MYBOUNDARY=="
--==MYBOUNDARY==
Content-Type: text/x-shellscript; charset="us-ascii"
#!/bin/bash
echo "Running custom user data script"
if ( lsblk | fgrep -q nvme1n1 ); then
mkdir -p /mnt/data /var/lib/kubelet /var/lib/docker
mkfs.xfs /dev/nvme1n1
mount /dev/nvme1n1 /mnt/data
chmod 0755 /mnt/data
mv /var/lib/kubelet /mnt/data/
mv /var/lib/docker /mnt/data/
ln -sf /mnt/data/kubelet /var/lib/kubelet
ln -sf /mnt/data/docker /var/lib/docker
UUID=$(lsblk -f | grep nvme1n1 | awk '{print $3}')
echo "UUID=$UUID /mnt/data xfs defaults,noatime 1 1" >> /etc/fstab
fi
echo 10485760 > /proc/sys/fs/aio-max-nr
--==MYBOUNDARY==--
上記の例では、NVMe ディスクは/dev/nvme1n1
であると仮定しています。特定の構成に合わせてスクリプトを変更する必要があります。
詳細については、起動テンプレートを使用した管理ノードのカスタマイズを参照してください。
GCP
Google Kubernetes Engine(GKE)クラスタ上でLocal SSDストレージをプロビジョニングし、クラスタ内のノードに接続されたLocal SSDでバックアップされたエフェメラルストレージからデータを消費するようにワークロードを設定するには、次のコマンドを実行します:
gcloud container node-pools create ${POOL_NAME} \
--cluster=${CLUSTER_NAME} \
--ephemeral-storage-local-ssd count=${NUMBER_OF_DISKS} \
--machine-type=${MACHINE_TYPE}
詳細については、GKEでのLocal SSDストレージのプロビジョニングを参照してください。
アジュール
ローカルNVMeディスクストレージを持つ仮想マシンスケールセット(VMSS)を作成するには、VMインスタンスにカスタムデータを渡す必要があります。以下は、VMSS内のVMインスタンスにNVMeディスクをアタッチする方法の例です:
mdadm -Cv /dev/md0 -l0 -n2 /dev/nvme0n1 /dev/nvme1n1
mdadm -Ds > /etc/mdadm/mdadm.conf
update-initramfs -u
mkfs.xfs /dev/md0
mkdir -p /var/lib/kubelet
echo '/dev/md0 /var/lib/kubelet xfs defaults 0 0' >> /etc/fstab
mount -a
上記の例では、NVMe ディスクは/dev/nvme0n1
と/dev/nvme1n1
であると仮定しています。特定の構成に合わせてスクリプトを変更する必要があります。
AlibabaクラウドとTecentCloud
ローカルSSDボリュームを使用するノードプールを作成するには、カスタムデータを渡す必要があります。以下はカスタムデータの例です。
#!/bin/bash
echo "nvme init start..."
mkfs.xfs /dev/nvme0n1
mkdir -p /mnt/data
echo '/dev/nvme0n1 /mnt/data/ xfs defaults 0 0' >> /etc/fstab
mount -a
mkdir -p /mnt/data/kubelet /mnt/data/containerd /mnt/data/log/pods
mkdir -p /var/lib/kubelet /var/lib/containerd /var/log/pods
echo '/mnt/data/kubelet /var/lib/kubelet none defaults,bind 0 0' >> /etc/fstab
echo '/mnt/data/containerd /var/lib/containerd none defaults,bind 0 0' >> /etc/fstab
echo '/mnt/data/log/pods /var/log/pods none defaults,bind 0 0' >> /etc/fstab
mount -a
echo "nvme init end..."
上記の例では、NVMeディスクを/dev/nvme0n1
と仮定しています。特定の構成に合わせてスクリプトを修正する必要があります。
独自の IDC
独自のIDCを実行しており、コンテナがcontainerdでデフォルトで新しくマウントされたNVMeディスク上のファイルシステムを使用するように設定したい場合は、以下の手順に従ってください:
NVMe ディスクをマウントする。
NVMeディスクがホストマシンに正しくマウントされていることを確認します。お好みのディレクトリにマウントできます。例えば、
/mnt/nvme
にマウントする場合、それが正しく設定され、lsblk
またはdf -h
を実行して/mnt/nvme
で利用可能なディスクを確認できることを確認する。containerd 構成を更新する。
コンテナ・ストレージのルート・ディレクトリとして新しいマウントを使用するように、containerd 構成を修正します。
sudo mkdir -p /mnt/nvme/containerd /mnt/nvme/containerd/state sudo vim /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".containerd]
セクションを探し、snapshotter
とroot
の設定を以下のように修正する。[plugins."io.containerd.grpc.v1.cri".containerd] snapshotter = "overlayfs" root = "/mnt/nvme/containerd" state = "/mnt/nvme/containerd/state"
containerd を再起動する。
containerd サービスを再起動して、変更を適用する。
sudo systemctl restart containerd
ディスク・パフォーマンスの検証
ディスク性能をベンチマークするための一般的なツールであるFio を使用して、ディスク性能を検証することを推奨する。以下は、ディスク性能をテストするために Fio を実行する方法の例である。
NVMe ディスクのあるノードにテストポッドをデプロイします。
kubectl create -f ubuntu.yaml
ubuntu.yaml
ファイルは以下のとおりです:apiVersion: v1 kind: Pod metadata: name: ubuntu spec: containers: - name: ubuntu image: ubuntu:latest command: ["sleep", "86400"] volumeMounts: - name: data-volume mountPath: /data volumes: - name: data-volume emptyDir: {}
Fio を実行してディスク性能をテストします。
# enter the container kubectl exec pod/ubuntu -it bash # in container apt-get update apt-get install fio -y # change to the mounted dir cd /data # write 10GB fio -direct=1 -iodepth=128 -rw=randwrite -ioengine=libaio -bs=4K -size=10G -numjobs=10 -runtime=600 -group_reporting -filename=test -name=Rand_Write_IOPS_Test # verify the read speed # compare with the disk performance indicators provided by various cloud providers. fio --filename=test --direct=1 --rw=randread --bs=4k --ioengine=libaio --iodepth=64 --runtime=120 --numjobs=128 --time_based --group_reporting --name=iops-test-job --eta-newline=1 --readonly
そして、出力は以下のようになるはずです:
Jobs: 128 (f=128): [r(128)][100.0%][r=1458MiB/s][r=373k IOPS][eta 00m:00s] iops-test-job: (groupid=0, jobs=128): err= 0: pid=768: Mon Jun 24 09:35:06 2024 read: IOPS=349k, BW=1364MiB/s (1430MB/s)(160GiB/120067msec) slat (nsec): min=765, max=530621k, avg=365836.09, stdev=4765464.96 clat (usec): min=35, max=1476.0k, avg=23096.78, stdev=45409.13 lat (usec): min=36, max=1571.6k, avg=23462.62, stdev=46296.74 clat percentiles (usec): | 1.00th=[ 69], 5.00th=[ 79], 10.00th=[ 85], 20.00th=[ 95], | 30.00th=[ 106], 40.00th=[ 123], 50.00th=[ 149], 60.00th=[ 11469], | 70.00th=[ 23462], 80.00th=[ 39584], 90.00th=[ 70779], 95.00th=[103285], | 99.00th=[189793], 99.50th=[244319], 99.90th=[497026], 99.95th=[591397], | 99.99th=[767558] bw ( MiB/s): min= 236, max= 4439, per=100.00%, avg=1365.82, stdev= 5.02, samples=30591 iops : min=60447, max=1136488, avg=349640.62, stdev=1284.65, samples=30591 lat (usec) : 50=0.01%, 100=24.90%, 250=30.47%, 500=0.09%, 750=0.31% lat (usec) : 1000=0.08% lat (msec) : 2=0.32%, 4=0.59%, 10=1.86%, 20=8.20%, 50=17.29% lat (msec) : 100=10.62%, 250=4.80%, 500=0.38%, 750=0.09%, 1000=0.01% lat (msec) : 2000=0.01% cpu : usr=0.20%, sys=0.48%, ctx=838085, majf=0, minf=9665 IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.0% submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0% complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0% issued rwts: total=41910256,0,0,0 short=0,0,0,0 dropped=0,0,0,0 latency : target=0, window=0, percentile=100.00%, depth=64
Milvus Distributedをデプロイします。
検証結果が満足のいくものであれば、以下の手順でMilvus Distributedをデプロイすることができる:
Helmを使用してMilvus Distributedをデプロイするためのヒント
QueryNodeポッドはデフォルトでNVMeディスクをEmptyDirボリュームとして使用します。最適なパフォーマンスを確保するために、NVMeディスクをQueryNodeポッド内の/var/lib/milvus/data
。
Helmを使用したMilvus Distributedのデプロイ方法の詳細については、「Run Milvus in Kubernetes with Helm」を参照してください。
Milvus Operatorを使用してMilvus Distributedをデプロイするためのヒント
Milvus Operatorは、NVMeディスクをEmptyDirボリュームとして使用するようにQueryNodeポッドを自動的に設定します。MilvusCluster
カスタムリソースに以下の設定を追加することをお勧めします:
...
spec:
components:
queryNode:
volumeMounts:
- mountPath: /var/lib/milvus/data
name: data
volumes:
- emptyDir:
name: data
これにより、QueryNodeポッドがNVMeディスクをデータボリュームとして使用するようになります。Milvus Operatorを使用してMilvus Distributedをデプロイする方法の詳細については、Milvus Operatorを使用してKubernetesでMilvusを実行するを参照してください。