בדיקות ביצועים ב-Google Kubernetes Engine

כדי לבדוק את ביצועי הקריאה והכתיבה של עומס עבודה ב-Google Kubernetes Engine‏ (GKE) מכמה לקוחות GKE, אפשר להשתמש בכלי ההשוואה IOR. ההוראות הבאות מסבירות איך להפוך את הגדרת הלקוח לאוטומטית ולהשתמש ב-IOR עם mpirun באמצעות SSH ללא סיסמה בין פודים של Kubernetes כדי לבדוק את ה-I/O המצטבר.

דרישות מוקדמות

  • מכונה של Managed Lustre כבר הוקצתה.

  • סביבת Docker מקומית שמוגדרת ומאומתת כדי לשלוח ל-Google Artifact Registry או ל-Container Registry (ראו שיטות אימות).

  • מוודאים שהערך mtu של הרשת מוגדר ל-8896.

יצירת אשכול GKE

כדי לבדוק את הביצועים, צריך אשכול GKE עם מנהל התקן Managed Lustre CSI מופעל. כדי להשיג ביצועים גבוהים בעומסי עבודה של אחסון, צריך להגדיר את מאגרי הצמתים של GKE עם משפחות מכונות מותאמות לצריכת מעבד גבוהה (compute-optimized) (לדוגמה, c2 או c3) ועם TIER_1רשתות.

מריצים את הפקודה הבאה כדי ליצור אשכול GKE רגיל שעבר אופטימיזציה לבדיקות ביצועים:

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
  • מחליפים את ZONE ואת NETWORK בערכים הספציפיים של הפריסה. האשכול צריך להיות באותה רשת VPC כמו מכונת Managed Lustre.

  • בוחרים MACHINE_TYPE. במאמר שיקולים לגבי ביצועים יש מידע על בחירת סוגי מכונות כדי להשיג את התפוקה הטובה ביותר.

  • אם סוג המכונה לא תומך ברשת TIER_1, צריך למחוק את השורה --network-performance-configs מהפקודה.

  • מציינים את NUM_NODES. כדי להגיע לרוויה במערכת הקבצים, קיבולת הרשת הכוללת של האשכול צריכה להיות גדולה ב-20% בערך מהתפוקה שהוקצתה למערכת הקבצים.

    במכונות שבהן מופעלת רשת Tier 1, צומת יחיד יכול להעביר נתונים במהירות של 25‎ Gbps עד 200‎ Gbps (כ-3,000‎ MBps עד 25,000‎ MBps), בהתאם לסוג המכונה הווירטואלית ולמספר ליבות ה-CPU. במכונות רגילות, תעבורת נתונים יוצאת (egress) מוגבלת בדרך כלל ל-2Gbps לכל vCPU.

    לדוגמה, אם הקיבולת של מופע Managed Lustre שלכם מניבה 100,000MBps של תפוקה תיאורטית, אתם צריכים תעבורת נתונים יוצאת מצטברת של לקוח של 120,000MBps (100,000 * 1.2) כדי להגיע לניצול מלא:

    • במופעים רגילים: אם לכל צומת יש תעבורת נתונים יוצאת שפורסמה של 2,000MBps, צריך להקצות לפחות 60 צמתים (120,000 / 2,000).
    • עם רשת ברמה 1: אם לכל צומת יש תעבורת נתונים יוצאת שפורסמה של 10,000 מגה-בייט לשנייה (‎~80 Gbps), צריך להקצות לפחות 12 צמתים (120,000 / 10,000).

יצירת קובץ אימג' של Docker עבור IOR

יצירת קובץ אימג' של קונטיינר עם OpenMPI ו-IOR מותקנים. קומפילציה של IOR עם תמיכה ב-Asynchronous I/O (AIO) לשיפור הביצועים.

  1. יוצרים קובץ בשם 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. יוצרים את קובץ האימג' הזה ומעבירים אותו בדחיפה ל-Container Registry המועדף. ההוראות במסמך הזה מתייחסות ל-Artifact Registry.

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

יצירת מפתחות SSH ללא סיסמה עבור MPI

‫OpenMPI דורש תקשורת בין צמתים באמצעות SSH ללא סיסמה. יוצרים מפתח SSH ומאחסנים אותו ב-Kubernetes Secret.

  1. יוצרים את מפתחות ה-RSA:

    ssh-keygen -t rsa -b 4096 -C "mpi-user" -N '' -f "./id_rsa"
    
  2. יוצרים את הסוד של 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
    

יצירת נפח אחסון מתמיד ודרישה

מחברים את הפודים של GKE למופע של Managed Lustre באמצעות הקצאת משאבים סטטית.

  1. יוצרים קובץ בשם lustre-pv.yaml. מחליפים את מה שכתוב בשדות הבאים:

    • CAPACITY עם נפח האחסון של המופע ב-GiB.
    • EXTENDED_LUSTRE_ID עם המזהה של Managed Lustre, בפורמט PROJECT_ID/ZONE/INSTANCE_NAME. לדוגמה, project-123/us-west1-a/my-lustre-instance.
    • LUSTRE_IP בכתובת ה-IP של נקודת הגישה של המופע.
    • FS_NAME מחליפים בשם של מערכת הקבצים של המכונה.

    אפשר לאחזר את הערכים האלה באמצעות הפקודה 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: CAPACITYGi
    
  2. החלת המניפסט:

    kubectl apply -f lustre-pv.yaml
    

פריסת עובדי MPI

כדי לשנות את קנה המידה של משימות IOR בכמה צמתים, צריך לפרוס StatefulSet עם תמונת ההשוואה.

  1. יוצרים קובץ בשם mpi-workers.yaml. מציינים את PROJECT_ID, ומגדירים את NUM_NODES למספר הצמתים באשכול.

    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. החלת המניפסט:

    kubectl apply -f mpi-workers.yaml
    

הפעלת השוואה לשוק של IOR

מפעילים את ההשוואה מהפוד הראשון (mpi-worker-0) ומתייחסים אליו כאל צומת הראש.

  1. יוצרים קובץ מארח שמכיל את כתובות ה-IP הפנימיות של העובדים ומעתיקים אותו לצומת הראשי:

    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. פותחים סשן bash בתוך ה-pod הראשי:

    kubectl exec -it mpi-worker-0 -- /bin/bash
    
  3. בתוך ה-Pod, יוצרים ספריית בדיקה:

    mkdir -p /lustre/test
    
  4. מגדירים את משתני הבדיקה:

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

    כאשר:

    • NUM_NODES: המספר הכולל של פודי העובדים שמשתתפים בבדיקה.

    • PROCESSES_PER_NODE: מספר דרגות ה-MPI שיופעלו בכל קונטיינר. מומלץ להתחיל בהגדרה של הערך הזה כך שיתאים למספר הליבות הפיזיות (או למחצית ממספר המעבדים הווירטואליים) במכונות הלקוח. בדרך כלל, כדי להשיג את התפוקה הכי טובה ברשת במכונות עם ביצועים גבוהים, כדאי להגדיר את הערך הזה בין 8 ל-16.

  5. מריצים את פקודות ההשוואה:

    קצב העברת נתונים לכתיבה

    הפקודה הזו כותבת ברציפות במשך 60 שניות כדי לבדוק את קצב העברת הנתונים המקסימלי במצב יציב. גודל הקובץ לכל משימה מוגדר ל-50TiB, שהוא גודל גדול באופן שרירותי, כדי שהמשימות ימשיכו לכתוב עד שתם הזמן של 60 שניות.

    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

    קצב העברת נתונים לקריאה

    בשלב הזה, המערכת קוראת בחזרה בדיוק את כמות הנתונים שנכתבה בהצלחה במהלך בדיקת קצב העברת הנתונים של הכתיבה שנמשכת 60 שניות. למרות שגודל הקובץ לכל משימה (-b) מוגדר ל-50TiB כדי להתאים לגיאומטריה של שלב הכתיבה, הדגל -O stoneWallingWearOut=1 מורה ל-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" \
      --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) של כתיבה

    בבדיקה הזו נעשה שימוש בגדלי העברה קטנים של 4KiB ובגדלי קבצים של 8GiB לכל משימה כדי למדוד את מספר פעולות הקלט/פלט המקסימלי לשנייה (IOPS) שמערכת הקבצים יכולה לטפל בהן.

    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

    כדי למנוע קריאה מקובץ דליל, הבדיקה הזו משתמשת בשתי פקודות: פקודת כתיבה ליצירת קובץ מוצק בגודל העברה של 4MiB וגודל קובץ של 8GiB לכל משימה, ואחריה בדיקת IOPS של קריאה אקראית בגודל 4KiB.

    1. יוצרים את הקובץ לקריאה:

      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. מריצים את בדיקת הקריאה של 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

    התכונות הניסיוניות של mpirun הן:

    • --mca plm_rsh_no_tree_spawn 1: משבית את יצירת הדמונים על בסיס עץ כדי לשפר את אמינות ההפעלה בצמתים.
    • --mca opal_set_max_sys_limits 1: המערכת מנסה להגדיר באופן אוטומטי את המגבלות שלה (למשל, מספר הקבצים המקסימלי שאפשר לפתוח) לערכים המקסימליים המותרים.
    • --mca plm_rsh_num_concurrent: מגדיר את המספר המקסימלי של חיבורי SSH בו-זמניים ש-mpirun ישתמש בהם כשהוא מפעיל דימונים של עובדים.
    • --mca plm_rsh_args ...: עוקף את הבדיקה המחמירה של מפתח המארח כדי למנוע מצבים שבהם הנחיות אינטראקטיביות של SSH גורמות להשבתה של הפעלת תהליך MPI.
    • --prefix ...: מגדיר באופן מפורש את נתיב ההתקנה של OpenMPI עבור Rocky Linux ו-RHEL, כדי שצמתי העבודה יוכלו למצוא את הדמון הנדרש (orted).
    • --allow-run-as-root: מאפשר ל-mpirun לפעול כמשתמש root.
    • --oversubscribe: מאפשר ל-MPI לתזמן יותר תהליכים בצומת מאשר מספר הליבות הפיזיות הזמינות.
    • --map-by node: מפזר את תהליכי ה-MPI באופן שווה בין הצמתים הזמינים בשיטת round-robin.
    • --bind-to socket: קושר תהליכי MPI לשקעי CPU פיזיים כדי לייעל את הגישה לזיכרון ואת הביצועים של המטמון.
    • --npernode: מספר התהליכים לכל צומת.
    • --np: המספר הכולל של תהליכי MPI להפעלה.
    • --hostfile: מציין את הקובץ שמכיל את רשימת המארחים שבהם יופעל הסקריפט.

    התכונות הניסיוניות של ior הן:

    • -a AIO --posix.odirect: משתמש במנוע קלט/פלט אסינכרוני (AIO) בשילוב עם קלט/פלט ישיר של POSIX. הפעולה הזו מדלגת על מטמון הדפים ב-RAM בצד הלקוח ומכריחה כתיבות לא חוסמות בו-זמניות ישירות לשרתי האחסון, וכך מבטיחה שהמדד ימדוד את הביצועים האמיתיים של אחסון הרשת ולא את מאגרי הזיכרון.
    • --aio.max-pending=256: קובעת את המספר המקסימלי של פעולות קלט/פלט (I/O) אסינכרוניות בו-זמניות בתהליך.
    • -C: שינוי הסדר של המשימות כדי לשפר את ביצועי הקריאה.
    • -F: מצב קובץ לכל תהליך.
    • -g: שימוש במחסומים כדי להפריד בין שלבי הכתיבה והקריאה של הבדיקה.
    • -v: רישום מפורט ביומן הפלט.
    • -w / -r: מנחה את IOR להריץ את בדיקת הביצועים של כתיבה (-w) או קריאה (-r).
    • -k: מונע מ-IOR למחוק את קובץ הבדיקה אחרי הכתיבה, וכך הוא זמין לבדיקת הקריאה.
    • -e: מבצע fsync אחרי שלב הכתיבה כדי להבטיח שהנתונים יועברו לכונני האחסון.
    • -z: מורה ל-IOR לבצע קלט/פלט של גישה אקראית במקום גישה רציפה.
    • -s 1: מגדיר את מספר הפלחים ל-1.
    • -Q 1: מגדיר את ההיסט של המשימה לכל צומת, כך שהמשימות מיושרות ונקודת ההשוואה מתואמת בצורה נכונה בכל הצמתים.
    • -G 1745405099: מקודד את חותמת הזמן של הזרע האקראי כך שבשלב הקריאה ייווצרו בדיוק אותם היסטים אקראיים של קבצים ששימשו בשלב הכתיבה.
    • -t: הגדרת גודל ההעברה לכל פעולת קלט/פלט (לדוגמה, 4m לרוחב פס, 4k ל-IOPS).
    • -b: הגדרת גודל הבלוק המקסימלי לכל תהליך (לדוגמה, 50t לתפוקה, 8g ל-IOPS) כדי לוודא שבמהלך ההרצה המתוזמנת לא ייגמרו נתוני המטען הייעודי של הבדיקה.
    • -D: מגביל את משך זמן הריצה של הבדיקה למספר מסוים של שניות (למשל, 60 או 45). ההגבלה הזו מפסיקה את ההשוואה באופן שווה כדי לתעד מדידה אמיתית של מצב יציב.
    • -O stoneWallingWearOut=1: מאלץ את כל השרשורים המקבילים להמשיך ליצור עומס כתיבה רציף למשך כל משך הבדיקה, ומונע משרשורים מהירים יותר להשלים את הבדיקה מוקדם יותר ולהפחית את העומס הכולל על הרשת.
    • -O stoneWallingStatusFile=<path>: כותב קובץ לאימות המצב בסוף שלב הכתיבה. בשלב הקריאה הבא, המערכת משתמשת בקובץ הזה כדי לקרוא רק את הבלוקים שהועברו בהצלחה, וכך נמנעות שגיאות של מצביע null במהלך הקריאות.
    • -o: הנתיב לקובץ הבדיקה במערכת הקבצים של Managed Lustre.

צפייה בתוצאות

בסיום ההשוואה, מדדי הביצועים המצטברים מכל מכונות ה-VM או הפודים של הלקוח מוצגים ישירות בטרמינל. מחפשים את הטבלה Results בתחתית הפלט כדי למצוא את התפוקה המקסימלית או את IOPS.

מדדים מרכזיים

  • aggregate filesize: הכמות הכוללת של הנתונים שנכתבו או נקראו במהלך הבדיקה בכל הלקוחות המשתתפים.

  • bw(MiB/s) / Max Write / Max Read: המדד הכי חשוב לבדיקות רציפות. הערך הזה מייצג את רוחב הפס המצטבר שהושג על ידי מערכת הקבצים Managed Lustre.

  • IOPS: המדד הכי חשוב לבדיקות קלט/פלט אקראיות. העמודה הזו מציגה את מספר פעולות הקלט/פלט המקסימלי לשנייה.

ייצוא התוצאות לקובץ

אם רוצים לנתח את התוצאות באופן פרוגרמטי, להזין אותן למסד נתונים או לשמור אותן לניתוח מאוחר יותר, אפשר להגדיר ל-IOR לייצא את נתוני הסיכום בפורמטים JSON ו-CSV במקום רק להדפיס אותם על המסך.

כדי לעשות את זה, מוסיפים את הדגלים -O לסוף מחרוזת הפקודה ior:

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

ספריית הפלט צריכה להיות קיימת במערכת הקבצים לפני שמריצים את הבדיקה.

הביצועים הצפויים לעומת הביצועים בפועל

אתם יכולים לחשב את התפוקה המקסימלית המתמטית של מערכת הקבצים על סמך הקיבולת שהוקצתה לה ורמת הביצועים שלה. נפח האחסון מוקצה בגיביבייט (GiB) והרמות מדורגות בטביבייט (TiB), ולכן צריך קודם להמיר את הנפח:

(Capacity GiB / 1024) * Tier MBps = Theoretical Max MBps

לדוגמה, מופע של 216,000 GiB ברמה של 500 MBps לכל TiB מספק תפוקה של 105,469 MBps ((216000 / 1024) * 500).

התפוקה המקסימלית שנצפתה תמיד תהיה מוגבלת על ידי קיבולת התפוקה שהוקצתה למערכת הקבצים או על ידי מגבלות היציאה המשולבות מהרשת של מכונות הלקוח, לפי הנמוך מביניהם.

סיבות נפוצות לכך שמהירויות ההשוואה לא מגיעות למהירויות התיאורטיות:

  • תקורה של TCP/IP: הכמסה סטנדרטית של רשת וראשי חבילות צורכים בערך 5-10% מרוחב הפס הגולמי. הערך המקסימלי המתמטי כולל את התקורה הזו, אבל מדד ה-IOR בודק רק את המטען הייעודי (payload) הגולמי שנכתב בדיסק.

  • מגבלות ברשת הלקוח: למחשבי הלקוח יש מגבלות חמורות על רוחב הפס של התעבורה היוצאת. אם משתמשים במספר קטן של לקוחות או צמתים, או בסוגי מכונות בלי שהופעלה רשת Tier 1, הלקוחות יגבילו את הביצועים של הבדיקה לפני שמערכת הקבצים המנוהלת של Lustre תגיע למגבלה שלה.

  • החלפת הקשר של MPI: אם הערך של PROCESSES_PER_NODE גבוה ממספר הליבות הפיזיות במכונות הלקוח, התחרות על משאבי ה-CPU והתקורה של החלפת ההקשר יפגעו באופן מלאכותי בביצועי הקלט/פלט של הבדיקה.

  • חסר Direct I/O: אם לא מציינים את הדגל --posix.odirect, הנתונים עוברים דרך מטמון הדפים ב-RAM של הלקוח. הדבר יוצר צווארי בקבוק בזיכרון ותקורת מעבד שמסתירים את הביצועים האמיתיים של אחסון הרשת.

הסרת המשאבים

כדי לא לצבור חיובים בחשבון Google Cloud על המשאבים שבהם השתמשתם בדף הזה:

  1. מוחקים את קובצי הבדיקה מהנפח המנוהל של Lustre:

    kubectl exec mpi-worker-0 -- rm -rf /lustre/test
    
  2. מחיקת אשכול GKE:

    gcloud container clusters delete CLUSTER_NAME --zone=ZONE
    

    מחיקת האשכול תגרום גם למחיקה של קבוצות ה-Pod של GKE, של Kubernetes Secret ושל Persistent Volume Claim.

  3. אם דחפתם את קובץ האימג' של Docker של הערכת הביצועים וכבר לא צריך אותו, צריך למחוק את קובץ האימג' מהמאגר:

    gcloud container images delete gcr.io/PROJECT_ID/lustre-ior-benchmark:latest --force-delete-tags
    
  4. אם יצרתם את מכונת Managed Lustre במיוחד לבדיקה הזו וכבר אין לכם צורך בה, אתם יכולים למחוק אותה:

    gcloud lustre instances delete INSTANCE_ID --location=LOCATION
    

פתרון בעיות נפוצות שגורמות לצווארי בקבוק בהשוואה לשוק

אם תוצאות ההשוואה נמוכות משמעותית מרמת הביצועים הצפויה של האחסון, כדאי לעיין במאמר בנושא פתרון בעיות נפוצות שגורמות לצווארי בקבוק.