Leistungstests in Google Kubernetes Engine

Mit dem IOR-Benchmarktool können Sie die Lese- und Schreibleistung einer Google Kubernetes Engine-Arbeitslast (GKE) von mehreren GKE-Clients aus testen. Die folgende Anleitung zeigt, wie Sie die Clienteinrichtung automatisieren und IOR mit mpirun über passwortloses SSH zwischen Kubernetes-Pods verwenden, um die aggregierte E/A zu testen.

Vorbereitung

  • Eine Managed Lustre-Instanz ist bereits bereitgestellt.

  • Eine lokale Docker-Umgebung ist konfiguriert und authentifiziert, um Daten in Google Artifact Registry oder Container Registry zu übertragen (siehe Authentifizierungsmethoden).

  • Stellen Sie sicher, dass der Wert für mtu Ihres Netzwerks auf festgelegt ist8896.

GKE-Cluster erstellen

Zum Testen der Leistung benötigen Sie einen GKE-Cluster, in dem der Managed Lustre-CSI-Treiber aktiviert ist. Konfigurieren Sie für speicherintensive Arbeitslasten mit hoher Leistung Ihre GKE-Knotenpools mit computing-optimierten Maschinenfamilien (z.B. c2 oder c3) und TIER_1-Netzwerken.

Führen Sie den folgenden Befehl aus, um einen Standard-GKE-Cluster zu erstellen, der für Leistungstests optimiert ist:

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
  • Ersetzen Sie ZONE und NETWORK durch die spezifischen Bereitstellung werte. Der Cluster muss sich im selben VPC-Netzwerk wie Ihre Managed Lustre-Instanz befinden.

  • Wählen Sie einen MACHINE_TYPE aus. Informationen zur Auswahl von Maschinentypen für den besten Durchsatz finden Sie unter Überlegungen zur Leistung.

  • Wenn Ihr Maschinentyp das TIER_1-Netzwerk nicht unterstützt, löschen Sie die Zeile --network-performance-configs aus dem Befehl.

  • Geben Sie die NUM_NODES an. Um Ihr Dateisystem zu sättigen, sollte die aggregierte Netzwerkkapazität Ihres Clusters den bereitgestellten Durchsatz Ihres Dateisystems um etwa 20 % übersteigen.

    Bei Maschinen mit aktiviertem Tier 1-Netzwerk kann ein einzelner Knoten je nach VM-Familie und Anzahl der CPUs zwischen 25 Gbit/s und 200 Gbit/s (~3.000–25.000 MB/s) übertragen. Bei Standardinstanzen ist der ausgehende Traffic in der Regel auf etwa 2 Gbit/s pro vCPU begrenzt.

    Wenn die Kapazität Ihrer Managed Lustre-Instanz beispielsweise einen theoretischen Durchsatz von 100.000 MB/s ergibt, benötigen Sie einen aggregierten ausgehenden Client-Traffic von 120.000 MB/s (100,000 * 1.2), um ihn zu sättigen:

    • Mit Standardinstanzen: Wenn jeder Knoten einen veröffentlichten ausgehenden Traffic von 2.000 MB/s hat, sollten Sie mindestens 60 Knoten bereitstellen (120,000 / 2,000).
    • Mit Tier 1-Netzwerk: Wenn jeder Knoten einen veröffentlichten ausgehenden Traffic von 10.000 MB/s (~80 Gbit/s) hat, sollten Sie mindestens 12 Knoten bereitstellen (120,000 / 10,000).

IOR-Docker-Image erstellen

Erstellen Sie ein Container-Image mit installiertem OpenMPI und IOR. Kompilieren Sie IOR mit Unterstützung für asynchrone E/A (AIO), um eine bessere Leistung zu erzielen.

  1. Erstellen Sie lokal eine Datei mit dem Namen Dockerfile:

    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"]
    
  2. Erstellen Sie dieses Image und übertragen Sie es in die gewünschte Container Registry. In dieser Anleitung wird Artifact Registry verwendet.

    export IMAGE_TAG="gcr.io/PROJECT_ID/lustre-ior-benchmark:latest"
    docker build -t $IMAGE_TAG .
    docker push $IMAGE_TAG
    

Passwortlose SSH-Schlüssel für MPI generieren

OpenMPI erfordert die Kommunikation zwischen Knoten über passwortloses SSH. Erstellen Sie einen SSH-Schlüssel und speichern Sie ihn in einem Kubernetes-Secret.

  1. Generieren Sie die RSA-Schlüssel:

    ssh-keygen -t rsa -b 4096 -C "mpi-user" -N '' -f "./id_rsa"
    
  2. Erstellen Sie das Kubernetes-Secret:

    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
    

Nichtflüchtiges Volume und Anspruch erstellen

Verbinden Sie Ihre GKE-Pods über die statische Bereitstellung mit der Managed Lustre Instanz .

  1. Erstellen Sie eine Datei mit dem Namen lustre-pv.yaml. Ersetzen Sie Folgendes:

    • CAPACITY durch die Speicherkapazität Ihrer Instanz in GiB.
    • EXTENDED_LUSTRE_ID durch die Managed Lustre -ID im Format PROJECT_ID/ZONE/INSTANCE_NAME. Beispiel: project-123/us-west1-a/my-lustre-instance.
    • LUSTRE_IP durch die Bereitstellungs-IP-Adresse Ihrer Instanz.
    • FS_NAME durch den Dateisystemnamen der Instanz.

    Diese Werte können mit dem gcloud lustre instances describe Befehl abgerufen werden.

    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: CAPACITYGi
    
  2. Wenden Sie das Manifest an:

    kubectl apply -f lustre-pv.yaml
    

MPI-Worker bereitstellen

Wenn Sie IOR-Aufgaben auf mehrere Knoten skalieren möchten, stellen Sie ein StatefulSet mit Ihrem Benchmark-Image bereit.

  1. Erstellen Sie eine Datei mit dem Namen mpi-workers.yaml. Geben Sie Ihre PROJECT_ID an und legen Sie NUM_NODES auf die Anzahl der Knoten in Ihrem Cluster fest.

    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-secret
    
  2. Wenden Sie das Manifest an:

    kubectl apply -f mpi-workers.yaml
    

IOR-Benchmark ausführen

Starten Sie den Benchmark vom ersten Pod (mpi-worker-0) aus und behandeln Sie ihn als Hauptknoten.

  1. Generieren Sie eine Hostdatei mit den internen IP-Adressen der Worker und kopieren Sie sie auf den Hauptknoten:

    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/hostfile
    
  2. Öffnen Sie eine Bash-Sitzung in Ihrem Haupt-Pod:

    kubectl exec -it mpi-worker-0 -- /bin/bash
    
  3. Erstellen Sie im Pod ein Testverzeichnis:

    mkdir -p /lustre/test
    
  4. Definieren Sie Testvariablen:

    export NUM_NODES="NUM_NODES"
    export PROCESSES_PER_NODE="PROCESSES_PER_NODE"
    export NUM_PROCESSES=$(( NUM_NODES * PROCESSES_PER_NODE ))
    

    Wobei:

    • NUM_NODES: Die Gesamtzahl der Worker-Pods, die am Test teilnehmen.

    • PROCESSES_PER_NODE: Die Anzahl der MPI-Ränge, die in jedem Container ausgeführt werden sollen. Legen Sie diesen Wert am besten so fest, dass er der Anzahl der physischen Kerne (oder der Hälfte der Anzahl der vCPUs) auf Ihren Clientcomputern entspricht. Bei leistungsstarken Maschinentypen ergibt eine Einstellung zwischen 8 und 16 in der Regel den besten Netzwerkdurchsatz.

  5. Führen Sie die Benchmark-Befehle aus:

    Durchsatz für Schreibvorgänge

    Dieser Befehl schreibt 60 Sekunden lang kontinuierlich, um den maximalen stationären Durchsatz zu testen. Die Dateigröße pro Aufgabe ist auf ein beliebig großes Limit von 50 TiB festgelegt, damit Aufgaben so lange geschrieben werden, bis das 60-Sekunden-Limit erreicht ist.

    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

    Durchsatz für Lesevorgänge

    In dieser Phase wird genau die Datenmenge zurückgelesen, die während des 60-sekündigen Durchsatztests für Schreibvorgänge erfolgreich geschrieben wurde. Obwohl die Dateigröße pro Aufgabe (-b) auf 50 TiB festgelegt ist, um der Geometrie der Schreibphase zu entsprechen, weist das Flag -O stoneWallingWearOut=1 IOR an, das Lesen zu beenden, sobald die genaue Datengrenze erreicht ist, die in der Statusdatei für die Blockierung aufgezeichnet wurde.

    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

    Schreib-IOPS

    Bei diesem Test werden kleine Übertragungsgrößen von 4 KiB und Dateigrößen von 8 GiB pro Aufgabe verwendet, um die maximale Anzahl von Eingabe-/Ausgabevorgängen pro Sekunde (IOPS) zu messen, die das Dateisystem verarbeiten kann.

    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

    Lese-IOPS

    Um zu verhindern, dass aus einer spärlichen Datei gelesen wird, werden bei diesem Test zwei Befehle verwendet: Ein Schreibvorgang zum Erstellen einer soliden Datei mit Übertragungsgrößen von 4 MiB und Dateigrößen von 8 GiB pro Aufgabe, gefolgt vom eigentlichen 4-KiB-Test für zufällige Lese-IOPS.

    1. Erstellen Sie die zu lesende Datei:

      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
    2. Führen Sie den IOR-Lesetest aus:

      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

    Die mpirun-Flags sind:

    • --mca plm_rsh_no_tree_spawn 1: Deaktiviert die baumbasierte Daemon-Erstellung, um die Zuverlässigkeit des Starts auf mehreren Knoten zu verbessern.
    • --mca opal_set_max_sys_limits 1: Versucht automatisch, System limits (z. B. die maximale Anzahl offener Dateien) auf die höchstzulässigen Werte festzulegen.
    • --mca plm_rsh_num_concurrent: Legt die maximale Anzahl gleichzeitiger SSH Verbindungen fest, die mpirun beim Starten von Worker-Daemons verwendet.
    • --mca plm_rsh_args ...: Umgeht die strenge Hostschlüsselprüfung, um zu verhindern, dass interaktive SSH-Aufforderungen den Start des MPI-Prozesses blockieren.
    • --prefix ...: Definiert explizit den OpenMPI-Installationspfad für Rocky Linux und RHEL, damit Worker-Knoten den erforderlichen Daemon (orted) finden können.
    • --allow-run-as-root: Ermöglicht die Ausführung von mpirun als Root-Nutzer.
    • --oversubscribe: Ermöglicht MPI, mehr Prozesse auf einem Knoten zu planen, als physische Kerne verfügbar sind.
    • --map-by node: Verteilt MPI-Prozesse im Round-Robin-Verfahren gleichmäßig auf die verfügbaren Knoten.
    • --bind-to socket: Bindet MPI-Prozesse an physische CPU-Sockets, um den Speicherzugriff und die Cacheleistung zu optimieren.
    • --npernode: Die Anzahl der Prozesse pro Knoten.
    • --np: Die Gesamtzahl der zu startenden MPI-Prozesse.
    • --hostfile: Gibt die Datei mit der Liste der Hosts an, auf denen der Test ausgeführt werden soll.

    Die ior-Flags sind:

    • -a AIO --posix.odirect: Verwendet die asynchrone E/A-Engine (AIO) in Kombination mit POSIX Direct I/O. Dadurch wird der RAM-Seitencache auf Clientseite umgangen und gleichzeitige nicht blockierende Schreibvorgänge werden direkt auf die Speicherserver erzwungen. So wird sichergestellt, dass der Benchmark die tatsächliche Leistung des Netzwerkspeichers und nicht die Speicherpuffer misst.
    • --aio.max-pending=256: Bestimmt die maximale Anzahl gleichzeitiger asynchroner E/A-Vorgänge pro Prozess.
    • -C: Ordnet Aufgaben neu an, um die Lesegeschwindigkeit zu optimieren.
    • -F: Modus „Datei pro Prozess“.
    • -g: Verwendet Barrieren, um die Schreib- und Lesevorgänge des Tests zu trennen.
    • -v: Gibt ausführliche Protokollierung aus.
    • -w / -r: Weist IOR an, den Leistungstest für Schreibvorgänge (-w) oder Lesevorgänge (-r) auszuführen.
    • -k: Verhindert, dass IOR die Testdatei nach dem Schreiben löscht, sodass sie für den Lesetest verfügbar ist.
    • -e: Führt nach der Schreibphase einen fsync-Vorgang aus, um sicherzustellen, dass die Daten auf die Speicherlaufwerke übertragen werden.
    • -z: Weist IOR an, zufällige E/A-Zugriffe anstelle von sequenziellen Zugriffen auszuführen.
    • -s 1: Legt die Anzahl der Segmente auf 1 fest.
    • -Q 1: Legt den Offset für die Aufgabe pro Knoten fest und richtet die Aufgaben so aus, dass der Benchmark auf allen Knoten korrekt koordiniert wird.
    • -G 1745405099: Codiert den Zeitstempel für den Zufallssamen fest, sodass die Lesevorgänge genau dieselben zufälligen Dateioffsets generieren, die in der Schreibphase verwendet wurden.
    • -t: Legt die Übertragungsgröße für jeden E/A-Vorgang fest (z.B. 4m für den Durchsatz, 4k für IOPS).
    • -b: Legt die Zielblockgröße pro Prozess fest (z.B. 50t für den Durchsatz, 8g für IOPS), um sicherzustellen, dass während der zeitgesteuerten Ausführung nicht die Nutzlastdaten ausgehen.
    • -D: Beschränkt die Laufzeit des Tests auf eine bestimmte Anzahl von Sekunden (z.B. 60 oder 45). Diese "Blockierung" beendet den Benchmark gleichmäßig um eine echte stationäre Messung zu erfassen.
    • -O stoneWallingWearOut=1: Erzwingt, dass alle gleichzeitigen Threads die gesamte Dauer über kontinuierlich Schreiblast generieren, wodurch verhindert wird, dass schnellere Threads frühzeitig abgeschlossen werden und der Gesamtdruck auf das Netzwerk sinkt.
    • -O stoneWallingStatusFile=<path>: Schreibt am Ende der Schreibphase eine Statusprüfungsdatei. In der nachfolgenden Lesevorgangsphase werden mit dieser Datei nur die Blöcke gelesen, die erfolgreich übertragen wurden, wodurch Nullzeigerfehler bei Lesevorgängen verhindert werden.
    • -o: Der Pfad zur Testdatei im Managed Lustre Dateisystem.

Ergebnisse aufrufen

Nach Abschluss des Benchmarks werden die aggregierten Leistungsmesswerte aller Client-VMs oder -Pods direkt im Terminal angezeigt. Suchen Sie unten in der Ausgabe nach der Tabelle Results (Ergebnisse), um den maximalen Durchsatz oder die maximale Anzahl von IOPS zu finden.

Wichtige Messwerte

  • aggregate filesize: Die Gesamtmenge der Daten, die während des Tests auf allen teilnehmenden Clients geschrieben oder gelesen wurden.

  • bw(MiB/s) / Max Write / Max Read: Der wichtigste Messwert für sequenzielle Tests. Er zeigt die aggregierte Bandbreite, die vom Managed Lustre-Dateisystem erreicht wurde.

  • IOPS: Der wichtigste Messwert für zufällige E/A-Tests. Er zeigt die maximale Anzahl von Eingabe-/Ausgabevorgängen pro Sekunde.

Ergebnisse in eine Datei exportieren

Wenn Sie Ihre Ergebnisse programmatisch parsen, in eine Datenbank einfügen oder für eine spätere Analyse speichern möchten, können Sie IOR anweisen, die Zusammenfassungsdaten im JSON- und CSV-Format zu exportieren, anstatt sie nur auf dem Bildschirm auszugeben.

Hängen Sie dazu die -O-Flags an das Ende der ior-Befehlszeile an:

-O summaryFormat=JSON \
-O summaryFile=/lustre/test/perf-results/summary.json \
-O saveRankPerformanceDetailsCSV=/lustre/test/perf-results/details.csv

Das Ausgabeverzeichnis muss im Dateisystem vorhanden sein, bevor Sie den Benchmark ausführen.

Erwartete Leistung im Vergleich zur tatsächlichen Leistung

Sie können den mathematischen maximalen Durchsatz Ihres Dateisystems anhand der bereitgestellten Kapazität und der Leistungsstufe berechnen. Da die Speicherkapazität in Gibibyte (GiB) bereitgestellt wird und die Stufen in Tebibyte (TiB) bewertet werden, müssen Sie zuerst die Kapazität umrechnen:

(Capacity GiB / 1024) * Tier MBps = Theoretisches Maximum in MB/s

Eine 216.000 GiB -Instanz in der Stufe 500 MB/s pro TiB bietet mathematisch beispielsweise einen Durchsatz von 105.469 MB/s ((216000 / 1024) * 500).

Der maximal beobachtete Durchsatz ist immer durch die bereitgestellte Durchsatzkapazität Ihres Dateisystems oder die kombinierten Limits für ausgehenden Traffic Ihrer Clientcomputer begrenzt, je nachdem, welcher Wert niedriger ist.

Häufige Gründe dafür, dass Ihre Benchmark-Zahlen nicht die theoretischen Geschwindigkeiten erreichen:

  • TCP/IP-Overhead:Die Standardnetzwerk-Kapselung und Paketheader verbrauchen etwa 5–10% der Rohbandbreite. Ihr mathematisches Maximum umfasst diesen Overhead, aber der IOR-Benchmark misst nur die Rohdaten, die auf das Laufwerk geschrieben wurden.

  • Netzwerklimitierungen des Clients:Clientcomputer haben strenge Limits für die Bandbreite des ausgehenden Traffics. Wenn Sie eine kleine Anzahl von Clients oder Knoten oder Maschinentypen ohne aktiviertes Tier 1-Netzwerk verwenden, drosseln die Clients den Benchmark, bevor das Managed Lustre-Dateisystem sein Limit erreicht.

  • MPI-Kontextwechsel:Wenn PROCESSES_PER_NODE höher als die Anzahl der physischen Kerne auf Ihren Clientcomputern festgelegt ist, verschlechtern CPU-Konflikte und der Overhead durch Kontextwechsel die E/A-Leistung des Benchmarks künstlich.

  • Fehlende direkte E/A:Wenn das Flag --posix.odirect weggelassen wird, werden Daten über den RAM-Seitencache des Clients übertragen. Dies führt zu Speicherengpässen und CPU-Overhead, die die tatsächliche Leistung des Netzwerkspeichers verschleiern.

Bereinigen

Mit den folgenden Schritten vermeiden Sie, dass Ihrem Google Cloud Konto die auf dieser Seite verwendeten Ressourcen in Rechnung gestellt werden:

  1. Löschen Sie die Testdateien aus dem Managed Lustre-Volume:

    kubectl exec mpi-worker-0 -- rm -rf /lustre/test
    
  2. Löschen Sie den GKE-Cluster:

    gcloud container clusters delete CLUSTER_NAME --zone=ZONE
    

    Wenn Sie den Cluster löschen, werden auch die GKE-Pods, das Kubernetes-Secret und der Anspruch auf ein nichtflüchtiges Volume gelöscht.

  3. Wenn Sie das Benchmark-Docker-Image übertragen haben und es nicht mehr benötigen, löschen Sie es aus Ihrem Repository:

    gcloud container images delete gcr.io/PROJECT_ID/lustre-ior-benchmark:latest --force-delete-tags
    
  4. Wenn Sie die Managed Lustre-Instanz speziell für diesen Test erstellt haben und sie nicht mehr benötigen, löschen Sie sie:

    gcloud lustre instances delete INSTANCE_ID --location=LOCATION
    

Häufige Engpässe bei Benchmarks beheben

Wenn Ihre Benchmark-Ergebnisse deutlich niedriger als die erwartete Speicherleistungsstufe sind, lesen Sie den Artikel Häufige Engpässe beheben.