Google Kubernetes Engine에서 성능 테스트

여러 GKE 클라이언트에서 Google Kubernetes Engine (GKE) 워크로드의 읽기 및 쓰기 성능을 테스트하려면 IOR 벤치마크 도구를 사용하세요. 다음 안내에서는 클라이언트 설정을 자동화하고 Kubernetes 포드 간에 비밀번호가 없는 SSH를 통해 mpirun으로 IOR을 사용하여 집계 I/O를 테스트하는 방법을 보여줍니다.

기본 요건

GKE 클러스터 만들기

성능을 테스트하려면 Managed Lustre CSI 드라이버가 사용 설정된 GKE 클러스터가 필요합니다. 고성능 스토리지 워크로드의 경우 컴퓨팅 최적화 머신 계열 (예: c2 또는 c3) 및 TIER_1 네트워킹으로 GKE 노드 풀을 구성합니다.

다음 명령어를 실행하여 성능 테스트에 최적화된 표준 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
  • ZONENETWORK를 특정 배포 값으로 바꿉니다. 클러스터는 Managed Lustre 인스턴스와 동일한 VPC 네트워크에 있어야 합니다.

  • MACHINE_TYPE을 선택합니다. 최고의 처리량을 얻기 위해 머신 유형을 선택하는 방법에 대한 자세한 내용은 성능 고려사항 을 참고하세요.

  • 머신 유형이 TIER_1 네트워킹을 지원하지 않으면 명령어에서 --network-performance-configs 행을 삭제합니다.

  • NUM_NODES를 지정합니다. 파일 시스템을 포화시키려면 클러스터의 집계 네트워크 용량이 파일 시스템의 프로비저닝된 처리량을 ~20% 초과해야 합니다.

    Tier 1 네트워킹이 사용 설정된 머신의 경우 VM 계열 및 CPU 수에 따라 단일 노드가 25~200Gbps (~3,000~25,000MBps)를 푸시할 수 있습니다. 표준 인스턴스의 경우 이그레스는 일반적으로 vCPU당 약 2Gbps로 제한됩니다.

    예를 들어 Managed Lustre 인스턴스 용량이 이론적 처리량 100,000MBps를 생성하는 경우 이를 포화시키려면 집계 클라이언트 이그레스가 120,000MBps (100,000 * 1.2)여야 합니다.

    • 표준 인스턴스 사용: 각 노드의 게시된 이그레스가 2,000MBps인 경우 노드를 60개 이상 프로비저닝해야 합니다 (120,000 / 2,000).
    • Tier 1 네트워킹 사용: 각 노드의 게시된 이그레스가 10,000MBps (~80Gbps)인 경우 노드를 12개 이상 프로비저닝해야 합니다(120,000 / 10,000).

IOR Docker 이미지 만들기

OpenMPI 및 IOR이 설치된 컨테이너 이미지를 빌드합니다. 더 나은 성능을 위해 비동기 I/O (AIO) 지원으로 IOR을 컴파일합니다.

  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. 이 이미지를 원하는 컨테이너 레지스트리에 빌드하고 푸시합니다. 이 문서의 안내에서는 Artifact Registry를 사용합니다.

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

MPI용 비밀번호가 없는 SSH 키 생성

OpenMPI에는 비밀번호가 없는 SSH를 사용한 노드 간 통신이 필요합니다. SSH 키를 만들고 Kubernetes 보안 비밀에 저장합니다.

  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_IDPROJECT_ID/ZONE/INSTANCE_NAME 형식의 Managed Lustre 식별자로 바꿉니다. 예를 들어 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 세션을 엽니다.

    kubectl exec -it mpi-worker-0 -- /bin/bash
    
  3. 포드 내에서 테스트 디렉터리를 만듭니다.

    mkdir -p /lustre/test
    
  4. 테스트 변수를 정의합니다.

    export