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