Untuk menguji performa baca dan tulis workload Google Kubernetes Engine (GKE) dari beberapa klien GKE, gunakan alat benchmark IOR. Petunjuk berikut menunjukkan cara mengotomatiskan penyiapan klien dan menggunakan IOR dengan mpirun melalui SSH tanpa sandi antara Pod Kubernetes untuk menguji I/O gabungan.
Prasyarat
Instance Managed Lustre sudah disediakan.
Lingkungan Docker lokal dikonfigurasi dan diautentikasi untuk mengirim ke Google Artifact Registry atau Container Registry (lihat Metode autentikasi).
Pastikan nilai
mtujaringan Anda ditetapkan ke8896.
Membuat cluster GKE
Untuk menguji performa, Anda memerlukan cluster GKE dengan driver CSI Managed Lustre diaktifkan. Untuk workload penyimpanan berperforma tinggi, konfigurasi node pool GKE Anda dengan kelompok mesin yang dioptimalkan untuk komputasi (misalnya, c2 atau c3) dan jaringan TIER_1.
Jalankan perintah berikut untuk membuat cluster GKE Standar yang dioptimalkan untuk pengujian performa:
gcloud container clusters create CLUSTER_NAME \
--zone=ZONE \
--machine-type=MACHINE_TYPE \
--addons=LustreCsiDriver \
--network-performance-configs=total-egress-bandwidth-tier=TIER_1 \
--network=NETWORK \
--num-nodes=NUM_NODES
Ganti ZONE dan NETWORK dengan nilai deployment spesifik Anda. Cluster harus berada di jaringan VPC yang sama dengan instance Managed Lustre Anda.
Pilih MACHINE_TYPE. Lihat Pertimbangan performa untuk mengetahui informasi tentang memilih jenis mesin guna mendapatkan throughput terbaik.
Jika jenis mesin Anda tidak mendukung jaringan TIER_1, hapus baris
--network-performance-configsdari perintah.Tentukan NUM_NODES. Untuk memenuhi sistem file Anda, kapasitas jaringan gabungan cluster Anda harus melebihi throughput yang disediakan sistem file Anda sebesar ~20%.
Untuk mesin dengan jaringan Tingkat 1 diaktifkan, satu node dapat mengirim antara 25 Gbps–200 Gbps (~3.000–25.000 MBps), bergantung pada kelompok VM dan jumlah CPU. Untuk instance standar, traffic keluar biasanya dibatasi sekitar 2 Gbps per vCPU.
Misalnya, jika kapasitas instance Managed Lustre Anda menghasilkan throughput teoretis sebesar 100.000 MBps, Anda memerlukan traffic keluar klien gabungan sebesar 120.000 MBps (
100,000 * 1.2) untuk memenuhinya:- Dengan instance standar: Jika setiap node memiliki traffic keluar yang dipublikasikan sebesar
2.000 MBps, Anda harus menyediakan setidaknya 60 node (
120,000 / 2,000). - Dengan jaringan Tingkat 1: Jika setiap node memiliki traffic keluar yang dipublikasikan sebesar
10.000 MBps (~80 Gbps), Anda harus menyediakan setidaknya 12 node
(
120,000 / 10,000).
- Dengan instance standar: Jika setiap node memiliki traffic keluar yang dipublikasikan sebesar
2.000 MBps, Anda harus menyediakan setidaknya 60 node (
Membuat Image Docker IOR
Buat image container dengan OpenMPI dan IOR terinstal. Kompilasi IOR dengan dukungan I/O Asinkron (AIO) untuk performa yang lebih baik.
Buat file bernama
Dockerfilesecara lokal:FROM ubuntu:22.04 # Prevent interactive prompts during installation ENV DEBIAN_FRONTEND=noninteractive # Install dependencies, SSH, and required Autotools packages RUN apt-get update && apt-get install -y \ openssh-server \ openmpi-bin \ libopenmpi-dev \ wget \ git \ make \ gcc \ g++ \ automake \ autoconf \ libtool \ pkg-config \ libaio-dev \ sudo \ && rm -rf /var/lib/apt/lists/* # Build IOR from source (version 4.0.0) with Asynchronous I/O (AIO) support RUN git clone -b 4.0.0 https://github.com/hpc/ior /tmp/ior \ && cd /tmp/ior \ && ./bootstrap \ && ./configure --disable-dependency-tracking --with-aio \ && make -j"$(nproc)" \ && make install \ && rm -rf /tmp/ior # Configure SSH for OpenMPI passwordless communication RUN mkdir /var/run/sshd RUN echo 'root:root' | chpasswd RUN sed -i 's/^#PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config RUN sed -i 's/^#PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config # SSH login fix so user isn't kicked out after container initialization RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd EXPOSE 22 CMD ["/usr/sbin/sshd", "-D"]Bangun dan kirim image ini ke container registry pilihan Anda. Petunjuk dalam dokumen ini menggunakan Artifact Registry.
export IMAGE_TAG="gcr.io/PROJECT_ID/lustre-ior-benchmark:latest" docker build -t $IMAGE_TAG . docker push $IMAGE_TAG
Membuat Kunci SSH Tanpa Sandi untuk MPI
OpenMPI memerlukan komunikasi antar-node menggunakan SSH tanpa sandi. Buat kunci SSH dan simpan di Secret Kubernetes.
Buat kunci RSA:
ssh-keygen -t rsa -b 4096 -C "mpi-user" -N '' -f "./id_rsa"Buat Secret Kubernetes:
kubectl create secret generic mpi-ssh-secret \ --from-file=id_rsa=./id_rsa \ --from-file=id_rsa.pub=./id_rsa.pub \ --from-file=authorized_keys=./id_rsa.pub
Membuat Volume dan Klaim Persisten
Hubungkan pod GKE Anda ke instance Managed Lustre menggunakan penyediaan statis.
Buat file bernama
lustre-pv.yaml. Ganti kode berikut:- CAPACITY dengan kapasitas penyimpanan instance Anda dalam GiB.
- EXTENDED_LUSTRE_ID dengan ID Managed Lustre
Anda, dalam format PROJECT_ID/ZONE/INSTANCE_NAME.
Misalnya,
project-123/us-west1-a/my-lustre-instance. - LUSTRE_IP dengan alamat IP pemasangan instance Anda.
- FS_NAME dengan nama sistem file instance.
Nilai ini dapat diambil dengan perintah
gcloud lustre instances describe.apiVersion: v1 kind: PersistentVolume metadata: name: my-lustre-pv spec: storageClassName: "" claimRef: name: my-lustre-pvc namespace: default accessModes: - ReadWriteMany capacity: storage: CAPACITYGi # retain `Gi` suffix persistentVolumeReclaimPolicy: Retain volumeMode: Filesystem csi: driver: lustre.csi.storage.gke.io volumeHandle: EXTENDED_LUSTRE_ID # project-name/zone/instance-name volumeAttributes: ip: LUSTRE_IP filesystem: FS_NAME --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-lustre-pvc spec: storageClassName: "" volumeName: my-lustre-pv accessModes: - ReadWriteMany resources: requests: storage: CAPACITYGiTerapkan manifes:
kubectl apply -f lustre-pv.yaml
Men-deploy Pekerja MPI
Untuk menskalakan tugas IOR di beberapa node, deploy a
StatefulSet dengan
image benchmark Anda.
Buat file bernama
mpi-workers.yaml. Tentukan PROJECT_ID, dan tetapkan NUM_NODES ke jumlah node di cluster Anda.apiVersion: v1 kind: Service metadata: name: mpi-workers labels: app: mpi-worker spec: clusterIP: None selector: app: mpi-worker ports: - port: 22 name: ssh --- apiVersion: apps/v1 kind: StatefulSet metadata: name: mpi-worker spec: serviceName: "mpi-workers" replicas: NUM_NODES selector: matchLabels: app: mpi-worker template: metadata: labels: app: mpi-worker spec: tolerations: - operator: "Exists" containers: - name: mpi-worker image: gcr.io/PROJECT_ID/lustre-ior-benchmark:latest command: ["/bin/sh", "-c"] args: - >- mkdir -p /var/run/sshd && ssh-keygen -A && mkdir -p /root/.ssh && echo "Host *" > /root/.ssh/config && echo " StrictHostKeyChecking no" >> /root/.ssh/config && echo " UserKnownHostsFile=/dev/null" >> /root/.ssh/config && cp /mnt/mpi-ssh-keys/id_rsa /root/.ssh/id_rsa && cp /mnt/mpi-ssh-keys/id_rsa.pub /root/.ssh/id_rsa.pub && cp /mnt/mpi-ssh-keys/authorized_keys /root/.ssh/authorized_keys && chmod 700 /root/.ssh && chmod 600 /root/.ssh/* && exec /usr/sbin/sshd -D ports: - containerPort: 22 volumeMounts: - name: lustre-mount mountPath: /lustre - name: ssh-key-secret mountPath: /mnt/mpi-ssh-keys readOnly: true volumes: - name: lustre-mount persistentVolumeClaim: claimName: my-lustre-pvc - name: ssh-key-secret secret: secretName: mpi-ssh-secretTerapkan manifes:
kubectl apply -f mpi-workers.yaml
Menjalankan Benchmark IOR
Mulai benchmark dari pod pertama (mpi-worker-0), dan perlakukan sebagai node utama.
Buat file host yang berisi alamat IP internal pekerja dan salin ke node utama:
kubectl get pods -l app=mpi-worker -o jsonpath='{range .items[*]}{.status.podIP}{"\n"}{end}' > hosts.txt kubectl cp hosts.txt mpi-worker-0:/root/hostfileBuka sesi bash di dalam pod utama Anda:
kubectl exec -it mpi-worker-0 -- /bin/bashDi dalam pod, buat direktori pengujian:
mkdir -p /lustre/testTentukan variabel pengujian:
export NUM_NODES="NUM_NODES" export PROCESSES_PER_NODE="PROCESSES_PER_NODE" export NUM_PROCESSES=$(( NUM_NODES * PROCESSES_PER_NODE ))Dengan:
NUM_NODES: Jumlah total Pod pekerja yang berpartisipasi dalam pengujian.
PROCESSES_PER_NODE: Jumlah peringkat MPI yang akan dijalankan di setiap container. Sebaiknya mulai dengan menetapkan nilai ini agar sesuai dengan jumlah core fisik (atau setengah jumlah vCPU) di mesin klien Anda. Untuk jenis mesin berperforma tinggi, menetapkan nilai ini antara
8dan16biasanya menghasilkan throughput jaringan terbaik.
Jalankan perintah benchmark:
Throughput tulis
Perintah ini menulis secara terus-menerus selama 60 detik untuk menguji throughput kondisi stabil puncak. Ukuran file per tugas ditetapkan ke batas 50 TiB yang sangat besar untuk membuat tugas tetap menulis hingga waktu 60 detik berakhir.
mpirun \ --allow-run-as-root \ --mca plm_rsh_no_tree_spawn 1 \ --mca opal_set_max_sys_limits 1 \ --mca plm_rsh_num_concurrent ${NUM_NODES} \ --mca plm_rsh_args "-o StrictHostKeyChecking=no" \ --npernode ${PROCESSES_PER_NODE} \ --np ${NUM_PROCESSES} \ --hostfile ~/hostfile \ /usr/local/bin/ior \ -a AIO \ --posix.odirect \ -F -g -v -w -k \ -t 4m -b 50t \ -D 60 \ -O stoneWallingWearOut=1 \ -O stoneWallingStatusFile=/lustre/test/ior-easy.stonewall \ -o /lustre/test/ior_file
Throughput baca
Fase ini membaca kembali jumlah data yang berhasil ditulis selama pengujian throughput tulis 60 detik. Meskipun ukuran file per tugas (
-b) ditetapkan ke 50 TiB agar sesuai dengan geometri fase tulis, tanda-O stoneWallingWearOut=1menginstruksikan IOR untuk berhenti membaca segera setelah mencapai batas data yang tepat yang tercatat dalam file status stonewall.mpirun \ --allow-run-as-root \ --mca plm_rsh_no_tree_spawn 1 \ --mca opal_set_max_sys_limits 1 \ --mca plm_rsh_num_concurrent ${NUM_NODES} \ --mca plm_rsh_args "-o StrictHostKeyChecking=no" \ --npernode ${PROCESSES_PER_NODE} \ --np ${NUM_PROCESSES} \ --hostfile ~/hostfile \ /usr/local/bin/ior \ -a AIO \ --posix.odirect \ -F -g -v -r -k \ -t 4m -b 50t \ -D 60 \ -O stoneWallingWearOut=1 \ -O stoneWallingStatusFile=/lustre/test/ior-easy.stonewall \ -o /lustre/test/ior_file
IOPS tulis
Pengujian ini menggunakan ukuran transfer kecil 4 KiB dan ukuran file per tugas 8 GiB untuk mengukur Operasi Input/Output Per Detik (IOPS) maksimum yang dapat ditangani sistem file.
mpirun \ --allow-run-as-root \ --mca plm_rsh_no_tree_spawn 1 \ --mca opal_set_max_sys_limits 1 \ --mca plm_rsh_num_concurrent ${NUM_NODES} \ --mca plm_rsh_args "-o StrictHostKeyChecking=no" \ --np ${NUM_PROCESSES} \ --oversubscribe \ --map-by node \ --bind-to socket \ --hostfile ~/hostfile \ /usr/local/bin/ior \ -e \ -t 4k \ -b 8g \ -s 1 \ -a AIO \ --posix.odirect \ --aio.max-pending=256 \ -w \ -F \ -z \ -Q 1 \ -G 1745405099 \ -D 45 \ -O stoneWallingWearOut=1 \ -o /lustre/test/ior-random
IOPS baca
Untuk mencegah pembacaan dari file jarang, pengujian ini menggunakan dua perintah: tulis untuk membuat file solid menggunakan ukuran transfer 4 MiB dan ukuran file per tugas 8 GiB, diikuti dengan pengujian IOPS baca acak 4 KiB yang sebenarnya.
Buat file yang akan dibaca:
mpirun \ --allow-run-as-root \ --mca plm_rsh_no_tree_spawn 1 \ --mca opal_set_max_sys_limits 1 \ --mca plm_rsh_num_concurrent ${NUM_NODES} \ --mca plm_rsh_args "-o StrictHostKeyChecking=no" \ --npernode ${PROCESSES_PER_NODE} \ --np ${NUM_PROCESSES} \ --oversubscribe \ --map-by node \ --bind-to socket \ --hostfile ~/hostfile \ /usr/local/bin/ior \ -a AIO \ --posix.odirect \ -w \ -F \ -k \ -t 4m \ -b 8g \ -s 1 \ -Q 1 \ -G 1745405099 \ -o /lustre/test/ior_rand_read
Jalankan pengujian baca IOR:
mpirun \ --allow-run-as-root \ --mca plm_rsh_no_tree_spawn 1 \ --mca opal_set_max_sys_limits 1 \ --mca plm_rsh_num_concurrent ${NUM_NODES} \ --mca plm_rsh_args "-o StrictHostKeyChecking=no" \ --oversubscribe \ --map-by node \ --bind-to socket \ --npernode ${PROCESSES_PER_NODE} \ --np ${NUM_PROCESSES} \ --hostfile ~/hostfile \ /usr/local/bin/ior \ -a AIO \ --posix.odirect \ --aio.max-pending 256 \ -r \ -F \ -z \ -t 4k \ -b 8g \ -s 1 \ -Q 1 \ -G 1745405099 \ -D 45 \ -O stoneWallingWearOut=1 \ -o /lustre/test/ior_rand_read
Tanda
mpirunadalah:--mca plm_rsh_no_tree_spawn 1: Menonaktifkan pembuatan daemon berbasis pohon untuk meningkatkan keandalan peluncuran di seluruh node.--mca opal_set_max_sys_limits 1: Otomatis mencoba menetapkan batas sistem batas (seperti file terbuka maks) ke nilai tertinggi yang diizinkan.--mca plm_rsh_num_concurrent: Menetapkan jumlah maksimum koneksi SSH serentakmpirunyang akan digunakan saat meluncurkan daemon pekerja.--mca plm_rsh_args ...: Melewati pemeriksaan kunci host yang ketat untuk mencegah perintah SSH interaktif menggantung peluncuran proses MPI.--prefix ...: Menentukan jalur penginstalan OpenMPI secara eksplisit untuk Rocky Linux dan RHEL sehingga node pekerja dapat menemukan daemon yang diperlukan (orted).--allow-run-as-root: Mengizinkanmpirununtuk dieksekusi sebagai pengguna root.--oversubscribe: Mengizinkan MPI menjadwalkan lebih banyak proses pada node daripada core fisik yang tersedia.--map-by node: Mendistribusikan proses MPI secara round-robin secara merata di seluruh node yang tersedia.--bind-to socket: Mengikat proses MPI ke soket CPU fisik untuk mengoptimalkan akses memori dan performa cache.--npernode: Jumlah proses per node.--np: Jumlah total proses MPI yang akan diluncurkan.--hostfile: Menentukan file yang berisi daftar host yang akan dijalankan.
Tanda
ioradalah:-a AIO --posix.odirect: Menggunakan mesin I/O Asinkron (AIO) yang dikombinasikan dengan I/O Langsung POSIX. Tindakan ini melewati cache halaman RAM sisi klien dan memaksa penulisan non-blocking serentak langsung ke server penyimpanan, sehingga memastikan benchmark mengukur performa penyimpanan jaringan yang sebenarnya, bukan buffer memori.--aio.max-pending=256: Menentukan jumlah maksimum operasi I/O Asinkron serentak yang sedang berlangsung per proses.-C: Mengurutkan ulang tugas untuk performa baca yang optimal.-F: Mode file per proses.-g: Menggunakan penghalang untuk memisahkan fase tulis dan baca pengujian.-v: Menghasilkan logging panjang.-w/-r: Menginstruksikan IOR untuk menjalankan pengujian performa tulis (-w) atau baca (-r) .-k: Mencegah IOR menghapus file pengujian setelah menulis, sehingga tersedia untuk pengujian baca.-e: Melakukanfsyncsetelah fase tulis untuk menjamin bahwa data diterapkan ke drive penyimpanan.-z: Menginstruksikan IOR untuk melakukan I/O akses acak, bukan akses berurutan.-s 1: Menetapkan jumlah segmen ke 1.-Q 1: Menetapkan offset tugas per node, menyelaraskan tugas sehingga benchmark berkoordinasi dengan benar di semua node.-G 1745405099: Mengodekan stempel waktu seed acak sehingga fase baca menghasilkan offset file acak yang sama persis dengan yang digunakan fase tulis.-t: Menetapkan ukuran transfer untuk setiap operasi I/O (misalnya,4muntuk throughput,4kuntuk IOPS).-b: Menetapkan ukuran blok target per proses (misalnya,50tuntuk throughput,8guntuk IOPS) guna memastikan pengujian tidak kehabisan data payload selama pengujian berjangka waktu.-D: Membatasi durasi runtime pengujian ke jumlah detik tertentu (misalnya,60atau45). "Stonewalling" ini menghentikan benchmark secara merata untuk mendapatkan pengukuran kondisi stabil yang sebenarnya.-O stoneWallingWearOut=1: Memaksa semua thread serentak untuk terus menghasilkan beban tulis berkelanjutan selama durasi penuh, sehingga mencegah thread yang lebih cepat selesai lebih awal dan menurunkan tekanan jaringan secara keseluruhan.-O stoneWallingStatusFile=<path>: Menulis file verifikasi status di akhir fase tulis. Fase baca berikutnya menggunakan file ini untuk membaca hanya blok yang berhasil diterapkan, sehingga mencegah error pointer null selama pembacaan.-o: Jalur ke file pengujian di sistem file Managed Lustre file system.
Melihat hasil
Setelah benchmark selesai, benchmark akan menampilkan metrik performa gabungan dari semua VM atau pod klien langsung di terminal Anda. Cari tabel Results di bagian bawah output untuk menemukan throughput atau IOPS maksimum Anda.
Metrik utama
aggregate filesize: Jumlah total data yang ditulis atau dibaca selama pengujian di semua klien yang berpartisipasi.bw(MiB/s)/Max Write/Max Read: Metrik terpenting untuk pengujian berurutan. Metrik ini menunjukkan bandwidth gabungan yang dicapai oleh sistem file Managed Lustre.IOPS: Metrik terpenting untuk pengujian I/O acak. Metrik ini menunjukkan Operasi Input/Output Per Detik maksimum.
Mengekspor hasil ke file
Jika ingin mengurai hasil secara terprogram, memasukkannya ke dalam database, atau menyimpannya untuk analisis nanti, Anda dapat menginstruksikan IOR untuk mengekspor data ringkasan dalam format JSON dan CSV, bukan hanya mencetaknya ke layar.
Untuk melakukannya, tambahkan tanda -O ke akhir string perintah ior Anda:
-O summaryFormat=JSON \
-O summaryFile=/lustre/test/perf-results/summary.json \
-O saveRankPerformanceDetailsCSV=/lustre/test/perf-results/details.csv
Direktori output harus ada di sistem file sebelum menjalankan benchmark.
Performa yang diharapkan versus performa di dunia nyata
Anda dapat menghitung throughput maksimum matematis sistem file berdasarkan kapasitas yang disediakan dan tingkat performa. Karena kapasitas penyimpanan disediakan dalam gibibyte (GiB) dan tingkat dinilai dalam tebibyte (TiB), Anda harus mengonversi kapasitas terlebih dahulu:
(Capacity GiB / 1024) * Tier MBps = MBps Maksimum Teoretis
Misalnya, instance 216.000 GiB di tingkat 500 MBps per TiB secara matematis memberikan throughput 105.469 MBps ((216000 / 1024) * 500).
Throughput maksimum yang diamati akan selalu dibatasi oleh kapasitas throughput yang disediakan sistem file Anda atau batas traffic keluar jaringan gabungan mesin klien Anda, mana pun yang lebih rendah.
Alasan umum mengapa angka benchmark Anda mungkin tidak mencapai kecepatan teoretis mencakup:
Overhead TCP/IP: Enkapsulasi jaringan standar dan header paket menggunakan sekitar 5-10% bandwidth mentah. Maksimum matematis Anda mencakup overhead ini, tetapi benchmark IOR hanya mengukur payload mentah yang ditulis ke disk.
Batas jaringan klien: Mesin klien memiliki batas bandwidth traffic keluar yang ketat. Jika Anda menggunakan sejumlah kecil klien atau node, atau jenis mesin tanpa jaringan Tingkat 1 diaktifkan, klien akan membatasi benchmark sebelum sistem file Managed Lustre mencapai batasnya.
Pengalihan konteks MPI: Jika
PROCESSES_PER_NODEditetapkan lebih tinggi dari jumlah core fisik di mesin klien Anda, pertentangan CPU dan overhead pengalihan konteks akan menurunkan performa I/O benchmark secara artifisial.I/O Langsung tidak ada: Jika tanda
--posix.odirectdihilangkan, data akan diteruskan melalui cache halaman RAM klien. Hal ini menyebabkan bottleneck memori dan overhead CPU yang menutupi performa penyimpanan jaringan yang sebenarnya.
Pembersihan
Agar akun Anda tidak dikenai biaya untuk resource yang digunakan pada halaman ini, ikuti langkah-langkah berikut: Google Cloud
Hapus file pengujian dari volume Managed Lustre:
kubectl exec mpi-worker-0 -- rm -rf /lustre/testHapus cluster GKE:
gcloud container clusters delete CLUSTER_NAME --zone=ZONEMenghapus cluster juga akan menghapus pod GKE, Secret Kubernetes, dan Klaim Volume Persisten.
Jika Anda mengirim image Docker benchmark dan tidak memerlukannya lagi, hapus image dari repositori Anda:
gcloud container images delete gcr.io/PROJECT_ID/lustre-ior-benchmark:latest --force-delete-tagsJika Anda membuat instance Managed Lustre khusus untuk pengujian ini dan tidak memerlukannya lagi, hapus instance tersebut:
gcloud lustre instances delete INSTANCE_ID --location=LOCATION
Memecahkan masalah bottleneck benchmark umum
Jika hasil benchmark Anda jauh lebih rendah dari tingkat performa penyimpanan yang diharapkan, lihat Memecahkan masalah bottleneck umum.