ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [AEWS 3기] 11주차 - ML Infra(GPU) on EKS
    AWS 2025. 4. 20. 01:35
      1. Configure Storgae - Host model data on Amazon FSx for Lustre
    3.1. 실습 소개

    이 워크숍에서는 Mistral-7B-Instruct 모델이 Amazon S3 Bucket에 저장되어 있으며, 이 버킷은 Amazon FSx for Lustre File System과 연결되어 있습니다. vLLM Container는 이를 활용하여 Generative AI ChatBot Application을 실행합니다.

    이 모듈에서는 Amazon FSx for Lustre 인스턴스를 배포하고 이를 Amazon EKS Cluster와 통합하여 Generative AI Application을 호스팅하는 방법을 학습합니다. 또한 Kubernetes 스토리지 개념, 예를 들어 CSI Driver, Persistent Volumes, StorageClass, 그리고 Static ProvisioningDynamic Provisioning의 차이점을 알아봅니다. 이 모듈의 인프라는 Amazon EKS Cluster(2개의 EC2 Worker Nodes 포함), Amazon FSx for Lustre File System, 그리고 Amazon S3 Bucket으로 구성됩니다.

     

    Amazon FSx for Lustre

    Amazon FSx for Lustre는 완전 관리형 서비스로, 속도가 중요한 워크로드(예: Machine Learning, Analytics, High Performance Compute)를 위한 고성능 병렬 파일 시스템을 제공합니다. FSx for Lustre는 밀리초 미만의 지연 시간(sub-millisecond latency)으로 데이터에 접근할 수 있으며, 테라바이트 단위의 처리량(TB/s of throughput)과 수백만 IOPS로 확장 가능합니다. 또한 Amazon S3와 통합되어 클라우드 데이터를 Lustre 고성능 파일 시스템으로 쉽게 저장, 접근, 처리할 수 있습니다. S3 Bucket과 연결될 경우, FSx for Lustre File SystemS3 Objects를 파일로 투명하게 표시하며, 파일이 추가, 수정, 삭제될 때 연결된 S3 Bucket의 내용을 자동으로 업데이트합니다.

     

    Kubernetes 스토리지 개념 및 FSx for Lustre 통합

    CSI Driver

    • Container Storage Interface (CSI)는 Kubernetes와 같은 컨테이너 오케스트레이션 시스템에서 블록 및 파일 스토리지 시스템을 노출하기 위한 표준입니다. 이를 통해 Kubernetes는 컨테이너화된 애플리케이션에 대해 영구 스토리지를 기본적으로 관리할 수 있습니다.

    FSx for Lustre CSI DriverAmazon EKS ClusterFSx for Lustre File System 기반의 Persistent Volumes의 라이프사이클을 관리할 수 있도록 CSI Interface를 제공합니다. 이 드라이버를 사용하면 고성능, 저지연(low-latency) 영구 스토리지를 컨테이너 워크로드에 빠르고 쉽게 통합할 수 있습니다.

    StorageClass

    StorageClassEKS 관리자가 제공하는 스토리지의 "클래스"를 정의하는 방법입니다. 서로 다른 StorageClass는 다양한 스토리지 유형(예: Amazon FSx, Amazon EBS, Amazon EFS) 또는 백업 정책에 매핑될 수 있습니다. Kubernetes는 이러한 StorageClass가 무엇을 나타내는지에 대해 특정한 제약을 두지 않습니다.

    Persistent Volume (PV)

    • Persistent Volume (PV)는 EKS Cluster에 매핑된, 관리자가 이미 프로비저닝한 스토리지 볼륨입니다. PV의 라이프사이클은 Pod의 수명을 초월하므로, 공유 데이터에 접근해야 하며 Pod의 수명을 넘어 지속되어야 하는 데이터에 이상적인 선택입니다.

    Persistent Volume Claim (PVC)

    • Persistent Volume Claim (PVC)는 사용자가 스토리지 볼륨을 요청하는 것입니다. PVC는 특정 크기와 접근 모드(예: ReadWriteOnce, ReadOnlyMany, ReadWriteMany)를 요청할 수 있습니다.

    Static Provisioning vs Dynamic Provisioning

    • Static Provisioning: 스토리지를 생성하고 사용하는 두 단계 프로세스입니다.
      1. 관리자가 스토리지 인스턴스(예: 새로운 FSx for Lustre 인스턴스)에 백엔드 스토리지 볼륨을 생성한 후, Kubernetes Cluster에서 해당 FSx for Lustre Instance에 대한 Persistent Volume (PV) 정의를 생성합니다.
      2. 애플리케이션 개발자가 PVC 요청을 제출하여 Persistent VolumePod에서 사용합니다.
    • Dynamic Provisioning: 관리자가 EKS Cluster에 스토리지를 미리 프로비저닝할 필요를 없애줍니다. 사용자는 필요에 따라 영구 스토리지를 요청할 수 있으며, PVC 요청이 발생하면 Persistent Volume과 관련된 FSx for Lustre Instance가 자동으로 프로비저닝됩니다.
     
    3.2. Deploy CSI Driver

    이 섹션에서는 환경 변수를 설정하고, 서비스 계정을 생성하며, EKS 클러스터에서 FSx for Lustre용 CSI 드라이버를 배포하기 위해 IAM 정책을 생성하고 연결하는 단계를 안내합니다.

     

    3.2.1. 전제 조건 - account-id 환경 변수 설정

    Cloud9 터미널에 다음 명령어를 복사하여 붙여넣습니다.

    ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)
      • 참고

    AWS 주최 워크숍의 경우, 보안 그룹(Security Group)과 S3 버킷은 이미 사전에 생성되어 있습니다.

    FSx Lustre 보안 그룹에 필요한 규칙에 대한 자세한 정보는 official document 를 참조하세요.

     

    3.2.2. CSI 드라이버가 AWS API 호출을 수행할 수 있도록 IAM 정책 및 서비스 계정 생성

    아래 명령어를 복사하여 실행하여 fsx-csi-driver.json 파일을 생성합니다.

    cat << EOF > fsx-csi-driver.json
    {
        "Version":"2012-10-17",
        "Statement":[
            {
                "Effect":"Allow",
                "Action":[
                    "iam:CreateServiceLinkedRole",
                    "iam:AttachRolePolicy",
                    "iam:PutRolePolicy"
                ],
                "Resource":"arn:aws:iam::*:role/aws-service-role/s3.data-source.lustre.fsx.amazonaws.com/*"
            },
            {
                "Action":"iam:CreateServiceLinkedRole",
                "Effect":"Allow",
                "Resource":"*",
                "Condition":{
                    "StringLike":{
                        "iam:AWSServiceName":[
                            "fsx.amazonaws.com"
                        ]
                    }
                }
            },
            {
                "Effect":"Allow",
                "Action":[
                    "s3:ListBucket",
                    "fsx:CreateFileSystem",
                    "fsx:DeleteFileSystem",
                    "fsx:DescribeFileSystems",
                    "fsx:TagResource"
                ],
                "Resource":[
                    "*"
                ]
            }
        ]
    }
    EOF
     

    3.2.3. IAM 정책 생성

    다음 명령어를 복사하여 실행하여 IAM 정책을 생성합니다.

    aws iam create-policy \
            --policy-name Amazon_FSx_Lustre_CSI_Driver \
            --policy-document file://fsx-csi-driver.json
     

    3.2.4. 드라이버용 Kubernetes 서비스 계정 생성 및 정책 연결

    아래 명령어를 복사하여 실행하여 서비스 계정을 생성하고, 3단계에서 생성한 IAM 정책을 연결합니다.

    eksctl create iamserviceaccount \
        --region $AWS_REGION \
        --name fsx-csi-controller-sa \
        --namespace kube-system \
        --cluster $CLUSTER_NAME \
        --attach-policy-arn arn:aws:iam::$ACCOUNT_ID:policy/Amazon_FSx_Lustre_CSI_Driver \
        --approve
        
    2025-04-19 14:08:38 [ℹ]  1 iamserviceaccount (kube-system/fsx-csi-controller-sa) was included (based on the include/exclude rules)
    2025-04-19 14:08:38 [!]  serviceaccounts that exist in Kubernetes will be excluded, use --override-existing-serviceaccounts to override
    2025-04-19 14:08:38 [ℹ]  1 task: { 
        2 sequential sub-tasks: { 
            create IAM role for serviceaccount "kube-system/fsx-csi-controller-sa",
            create serviceaccount "kube-system/fsx-csi-controller-sa",
        } }2025-04-19 14:08:38 [ℹ]  building iamserviceaccount stack "eksctl-eksworkshop-addon-iamserviceaccount-kube-system-fsx-csi-controller-sa"
    2025-04-19 14:08:38 [ℹ]  deploying stack "eksctl-eksworkshop-addon-iamserviceaccount-kube-system-fsx-csi-controller-sa"
    2025-04-19 14:08:38 [ℹ]  waiting for CloudFormation stack "eksctl-eksworkshop-addon-iamserviceaccount-kube-system-fsx-csi-controller-sa"
    ....
      • 참고: 위 명령은 완료까지 30~60초 정도 소요됩니다.

    서비스 계정이 생성되는 동안 여러 줄의 출력이 표시됩니다. 마지막 출력은 아래와 유사합니다.

    2023-09-29 07:40:56 [ℹ]  created serviceaccount "kube-system/fsx-csi-controller-sa"
     

    3.2.5. 생성된 역할 ARN을 변수로 저장

    아래 명령어를 복사하여 실행하여 역할 ARN을 저장합니다.

    export ROLE_ARN=$(aws cloudformation describe-stacks --stack-name "eksctl-${CLUSTER_NAME}-addon-iamserviceaccount-kube-system-fsx-csi-controller-sa" --query "Stacks[0].Outputs[0].OutputValue"  --region $AWS_REGION --output text)
     

    ROLE_ARN의 출력 값을 메모장에 복사합니다.

    echo $ROLE_ARN
    
    arn:aws:iam::576809327369:role/eksctl-eksworkshop-addon-iamserviceaccount-ku-Role1-RX4wBEdHMjfD
     

    3.2.6. FSx for Lustre용 CSI 드라이버 배포

    다음 명령어를 복사하여 실행하여 FSx for Lustre용 CSI 드라이버를 배포합니다.

    kubectl apply -k "github.com/kubernetes-sigs/aws-fsx-csi-driver/deploy/kubernetes/overlays/stable/?ref=release-1.2"
    ...
    serviceaccount/fsx-csi-controller-sa configured
    serviceaccount/fsx-csi-node-sa created
    clusterrole.rbac.authorization.k8s.io/fsx-csi-external-provisioner-role created
    clusterrole.rbac.authorization.k8s.io/fsx-csi-node-role created
    clusterrole.rbac.authorization.k8s.io/fsx-external-resizer-role created
    clusterrolebinding.rbac.authorization.k8s.io/fsx-csi-external-provisioner-binding created
    clusterrolebinding.rbac.authorization.k8s.io/fsx-csi-node-getter-binding created
    clusterrolebinding.rbac.authorization.k8s.io/fsx-csi-resizer-binding created
    deployment.apps/fsx-csi-controller created
    daemonset.apps/fsx-csi-node created
    csidriver.storage.k8s.io/fsx.csi.aws.com created
     

    CSI 드라이버가 성공적으로 설치되었는지 확인하려면 다음 명령어를 실행합니다.

    결과는 아래와 같이 출력된어야 합니다.

    kubectl get pods -n kube-system -l app.kubernetes.io/name=aws-fsx-csi-driver
    NAME                                  READY   STATUS    RESTARTS   AGE
    fsx-csi-controller-6f4c577bd4-nm8nh   4/4     Running   0          30s
    fsx-csi-controller-6f4c577bd4-vg2vx   4/4     Running   0          30s
    fsx-csi-node-jf5fg                    3/3     Running   0          30s
    fsx-csi-node-jrnsj                    3/3     Running   0          30
     

    3.2.7. 위에서 생성한 서비스 계정(SA)에 주석 추가

    다음 명령어를 복사하여 실행하여 서비스 계정에 IAM 역할을 추가합니다.

    kubectl annotate serviceaccount -n kube-system fsx-csi-controller-sa \
     eks.amazonaws.com/role-arn=$ROLE_ARN --overwrite=true
     

    성공 여부를 확인하려면 다음 명령어로 서비스 계정 내용을 확인합니다.

     

    서비스 계정에 방금 생성한 IAM 역할에 대한 주석이 추가된 것을 확인할 수 있습니다.

    kubectl get sa/fsx-csi-controller-sa -n kube-system -o yaml
    
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      annotations:
        eks.amazonaws.com/role-arn: arn:aws:iam::576809327369:role/eksctl-eksworkshop-addon-iamserviceaccount-ku-Role1-RX4wBEdHMjfD
        kubectl.kubernetes.io/last-applied-configuration: |
          {"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"labels":{"app.kubernetes.io/name":"aws-fsx-csi-driver"},"name":"fsx-csi-controller-sa","namespace":"kube-system"}}
      creationTimestamp: "2025-04-19T14:09:08Z"
      labels:
        app.kubernetes.io/managed-by: eksctl
        app.kubernetes.io/name: aws-fsx-csi-driver
      name: fsx-csi-controller-sa
      namespace: kube-system
      resourceVersion: "1075584"
      uid: 7d3a14a1-3113-485a-8fd6-a61ffc9c4b38
     

    3.2.8. 요약

    이 섹션에서는 환경 변수 설정, 적절한 IAM 정책 및 역할 ARN을 포함한 서비스 계정 생성, 그리고 FSx for Lustre용 CSI 드라이버 배포를 완료했습니다. 다음 섹션에서는 FSx for Lustre용 Persistent Volume(PV), Persistent Volume Claim(PVC), 및 StorageClass를 생성할 것입니다.

    3.3. EKS Cluster에 PV 생성하기

    3.3.1. Persistent Volumes 생성을 위한 두 가지 방법

    1. Static Provisioning (정적 프로비저닝)
      • 관리자가 백엔드 스토리지 엔터티를 생성하고, Persistent Volume (PV, 영구 볼륨)을 생성합니다. 이후 사용자는 이 PV를 자신의 Pod(파드)에서 사용하기 위해 Persistent Volume Claim (PVC, 영구 볼륨 클레임)을 생성합니다.
    2. Dynamic Provisioning (동적 프로비저닝)
      • 사용자가 PVC를 요청하면, 사용자의 요구사항에 따라 CSI 드라이버가 자동으로 PV와 해당 백엔드 스토리지 엔터티를 생성합니다. 이 방법은 관리자가 미리 PV를 생성할 필요가 없는 방식입니다.
     

    3.3.2. 실습 - Static Provisioning을 사용한 Persistent Volume 생성

    이 실습에서는 Static Provisioning (정적 프로비저닝) 방법을 사용하여 Persistent Volume (PV)을 생성합니다. 이미 프로비저닝된 FSx for Lustre 인스턴스를 사용하며, 이 인스턴스는 Amazon S3 버킷에 연결되어 Mistral-7B 모델을 저장하고 있습니다. 여기서는 Persistent Volume 정의를 생성하고 Persistent Volume Claim을 만들어, vLLM Pod에서 Mistral-7B 모델 데이터를 사용할 수 있도록 설정합니다.

     

    3.3.3. 준비 - 작업 디렉토리 이동 및 환경 변수 설정

      1. 작업 디렉토리로 이동:
    cd /home/ec2-user/environment/eks/FSxL
      1. FSx for Lustre 인스턴스 세부 정보를 환경 변수에 설정:
    FSXL_VOLUME_ID=$(aws fsx describe-file-systems --query 'FileSystems[].FileSystemId' --output text)
    DNS_NAME=$(aws fsx describe-file-systems --query 'FileSystems[].DNSName' --output text)
    MOUNT_NAME=$(aws fsx describe-file-systems --query 'FileSystems[].LustreConfiguration.MountName' --output text)
     

    3.3.3. Step 1: Persistent Volume (PV, 영구 볼륨) 생성

      1. Persistent Volume 정의 파일 확인

    아래는 FSx for Lustre 인스턴스를 위한 Persistent Volume 정의 파일(fsxL-persistent-volume.yaml)입니다. 이 파일은 1200GiB FSx for Lustre 인스턴스를 EKS 클러스터 리소스로 등록하며, 이름은 fsx-pv로 지정됩니다.

    # fsxL-persistent-volume.yaml
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: fsx-pv
    spec:
      persistentVolumeReclaimPolicy: Retain
      capacity:
        storage: 1200Gi
      volumeMode: Filesystem
      accessModes:
        - ReadWriteMany
      mountOptions:
        - flock
      csi:
        driver: fsx.csi.aws.com
        volumeHandle: FSXL_VOLUME_ID
        volumeAttributes:
          dnsname: DNS_NAME
          mountname: MOUNT_NAME
      1. 환경 변수로 값 치환

    FSx for Lustre 인스턴스의 실제 값으로 FSXL_VOLUME_ID, DNS_NAME, MOUNT_NAME을 치환합니다:

    sed -i'' -e "s/FSXL_VOLUME_ID/$FSXL_VOLUME_ID/g" fsxL-persistent-volume.yaml
    sed -i'' -e "s/DNS_NAME/$DNS_NAME/g" fsxL-persistent-volume.yaml
    sed -i'' -e "s/MOUNT_NAME/$MOUNT_NAME/g" fsxL-persistent-volume.yaml
      1. Persistent Volume 정의 파일 확인

    치환된 Persistent Volume 정의 파일을 확인합니다:

    cat fsxL-persistent-volume.yaml
    
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: fsx-pv
    spec:
      persistentVolumeReclaimPolicy: Retain
      capacity:
        storage: 1200Gi
      volumeMode: Filesystem
      accessModes:
        - ReadWriteMany
      mountOptions:
        - flock
      csi:
        driver: fsx.csi.aws.com
        volumeHandle: fs-04cfba6267f7c90e9
        volumeAttributes:
          dnsname: fs-04cfba6267f7c90e9.fsx.us-west-2.amazonaws.com
          mountname: bietbb4v
      1. Persistent Volume 배포

    EKS 클러스터에 Persistent Volume을 배포합니다:

    kubectl apply -f fsxL-persistent-volume.yaml
      1. Persistent Volume 생성 확인

    fsx-pv라는 이름의 PV가 생성되었는지 확인합니다:

    kubectl get pv
     

    3.3.4. Step 2: Persistent Volume Claim (PVC, 영구 볼륨 클레임) 생성

      1. Persistent Volume Claim 정의 파일 확인

    아래는 Persistent Volume Claim 정의 파일(fsxL-claim.yaml)입니다. 이 파일은 이전 단계에서 생성한 fsx-pv라는 Persistent Volume과 바인딩됩니다.

    # fsxL-claim.yaml
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: fsx-lustre-claim
    spec:
      accessModes:
        - ReadWriteMany
      storageClassName: ""
      resources:
        requests:
          storage: 1200Gi
      volumeName: fsx-pv
      1. Persistent Volume Claim 배포

    EKS 클러스터에 Persistent Volume Claim을 배포합니다:

    kubectl apply -f fsxL-claim.yaml
      1. Persistent Volume Claim 바인딩 확인

    Persistent Volume Claim(fsx-lustre-claim)이 Persistent Volume(fsx-pv)에 바인딩되었는지 확인합니다:

    kubectl get pv,pvc
    
    NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                                                      STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
    persistentvolume/fsx-pv                                     1200Gi     RWX            Retain           Bound    default/fsx-lustre-claim                                                                  <unset>                          12s
    persistentvolume/pvc-290eab08-4727-4a78-8cc6-7ca2020bb730   50Gi       RWO            Delete           Bound    kube-prometheus-stack/data-prometheus-kube-prometheus-stack-prometheus-0   gp3            <unset>                          2d11h
    
    NAME                                     STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
    persistentvolumeclaim/fsx-lustre-claim   Pending   fsx-pv   0                                        <unset>                 7m7s
     

    3.3.5. 요약

    이 실습에서 **Persistent Volume (PV)**을 성공적으로 설정하고, **Persistent Volume Claim (PVC)**을 생성하여 vLLM Pod에서 Mistral-7B 모델 데이터를 사용할 수 있도록 준비했습니다.

    3.4. FSx 콘솔에서 내용 확인하기

    이전 단계에서 이 랩에서 미리 프로비저닝된 FSx for Lustre를 사용하여 Persistent Volume(PV)을 설정했습니다. 이제 FSx for Lustre 인스턴스의 설정과 옵션을 살펴보겠습니다.

    • 참고: 이 워크숍의 후속 섹션에서 EKS 클러스터와 함께 FSx for Lustre 인스턴스를 직접 배포하고 설정할 기회가 있을 것입니다.
     

    1. Amazon FSx 콘솔로 이동

      1. Amazon FSx 콘솔로 이동합니다.
      2. 오른쪽 상단에서 이 랩에서 제공된 AWS 리전(aws_region)을 선택합니다.
     
     

    2. FSx 인스턴스 목록 확인

    FSx 콘솔에서 FSx 인스턴스 목록을 확인할 수 있습니다. 여기에는 랩에서 미리 프로비저닝된 FSx for Lustre 인스턴스의 세부 정보가 포함되어 있으며, 이는 EKS 클러스터에서 Persistent Volume으로 설정한 인스턴스입니다.

     
     

    3. 새로운 FSx for Lustre 인스턴스 배포 옵션 확인

      1. 오른쪽 상단의 Create file system(파일 시스템 생성) 버튼을 클릭합니다.
      2. Amazon FSx for Lustre를 선택하고 Next(다음)를 클릭합니다.

    다음 화면에서 FSx for Lustre의 배포 옵션을 확인할 수 있습니다:

        1. 스토리지 유형: PERSISTENT-SSD 또는 Scratch 스토리지
        2. 스토리지 단위당 처리량(Throughput per unit of storage): 원하는 처리량 설정 가능
        3. 메타데이터 IOPS 성능(Metadata IOPS performance): 메타데이터 성능 설정 가능
        4. 압축(Compression): 데이터 압축 옵션 설정 가능
        5. 데이터 리포지토리 가져오기/내보내기(Data Repository Import/Export): S3 연동 버킷을 통해 자동 데이터 가져오기/내보내기 설정 가능
     
    1. 화면을 종료하려면 Cancel(취소) 버튼을 클릭하여 FSx 콘솔로 돌아갑니다.
     

    4. 기존 FSx for Lustre 인스턴스 세부 정보 확인

    FSx 콘솔에서 이미 프로비저닝된 1200GiB FSx for Lustre 인스턴스를 확인할 수 있습니다. 이 인스턴스는 다음과 같은 설정을 갖추고 있습니다:

    • 스토리지 유형: Persistent-SSD
    • 스토리지 단위당 처리량: 250MB/s
      1. File system ID(파일 시스템 ID)를 클릭하여 FSx for Lustre 인스턴스의 세부 정보를 확인합니다.
      2. 세부 정보 화면에서 다음을 확인할 수 있습니다:
        • FSx 인스턴스의 상세 설정
        • 온라인으로 업데이트 가능한 항목:
          • Storage Capacity(스토리지 용량) 업데이트
          • Throughput per unit of storage(스토리지 단위당 처리량) 업데이트

    참고:

        • FSx for Lustre 인스턴스의 스토리지 용량을 증가시키면 스토리지 단위당 처리량 성능도 증가합니다.
        • 스토리지 용량을 늘리지 않고도 Throughput Capacity(처리량 용량)를 독립적으로 증가시킬 수 있습니다(예: 추가 스토리지 없이 더 높은 처리량 성능이 필요한 경우).
      1. 화면 하단으로 스크롤하여 Monitoring & performance(모니터링 및 성능) 탭을 클릭합니다. 여기에서 다양한 차원의 성능 메트릭을 확인할 수 있습니다:
        • 요약 메트릭(Summary Metrics): 용량(Capacity), 처리량(Throughput), IOPS
        • 세부 성능 메트릭(Detailed Performance Metrics): 메타데이터 성능(Metadata Performance), 네트워크(Network) 등
     
     

    5. 요약

    이 모듈을 통해 다음을 학습했습니다:

    • FSx for Lustre의 다양한 배포 옵션 (PERSISTENT-SSD, Scratch 스토리지, 처리량, 메타데이터 IOPS 등)
    • 기존 FSx 인스턴스의 스토리지 용량(Storage Capacity), 처리량 용량(Throughput Capacity), **메타데이터 IOPS 성능(Metadata IOPS performance)**을 온라인으로 증가시킬 수 있는 기능
     
      1. Deploy Generative AI Chat application
    4.1. 실습 소개

    이 실습에서는 Kubernetes 상에서 Generative AI 챗봇 애플리케이션을 구성하고 배포합니다. 이를 위해 Amazon EKS 클러스터vLLM PodWebUI Pod를 배포하고, Mistral-7B 모델Amazon FSx for LustreAmazon S3를 사용해 저장 및 접근하며, AWS Inferentia AcceleratorsGenerative AI 워크로드의 가속 컴퓨팅으로 활용합니다.

     
      • Generative AI와 Machine Learning

    Generative AI와 Machine Learning (ML)은 비즈니스가 운영 및 혁신 방식을 변화시키는 데 도움을 줍니다. Generative AI는 Large Language Models (LLM)을 활용해 텍스트, 이미지, 오디오, 소프트웨어 코드와 같은 새로운 콘텐츠를 프롬프트(prompt)로부터 생성하는 인공지능(AI) 클래스입니다.

     
      • Large Language Model (LLM)이란?

    Large Language Models (LLM)은 방대한 텍스트 데이터로 훈련되어 자연어의 패턴과 구조를 학습하는 Machine Learning 모델입니다. 이러한 모델은 텍스트 생성, 질문 답변, 언어 번역 등 다양한 Natural Language Processing (NLP) 작업에 사용됩니다. 이 워크숍에서는 7 billion parameters를 가진 오픈소스 모델인 Mistral-7B-Instruct를 사용합니다. 여기서 "Instruct"는 이 모델이 텍스트 생성뿐만 아니라 다양한 작업을 수행하고 지침을 따르도록 훈련되었음을 의미하며, 이는 Chat Applications에 적합합니다.

     
    • vLLM이란?
      • vLLM (Virtual Large Language Model)은 LLM의 추론(inference) 및 서빙(serving)을 위한 오픈소스 라이브러리로, 사용이 간편합니다. 이 프레임워크는 Mistral-7B-Instruct와 같은 LLM 모델을 배포해 텍스트 생성 추론을 제공하며, OpenAI API와 호환되는 API를 제공하여 LLM 애플리케이션 통합을 용이하게 합니다.
      • vLLM의 특징:
      • 고속 성능:
        • 최첨단 서빙 처리량(state-of-the-art serving throughput)
        • PagedAttention을 통한 효율적인 Attention Key/Value Memory 관리
        • 연속적인 요청 배치 처리(continuous batching)
        • CUDA/HIP Graph를 활용한 빠른 모델 실행
      • 유연성과 사용 편의성:
        • HuggingFace 모델과의 원활한 통합
        • OpenAI-compatible API Server
        • Prefix Caching 지원
        • AWS NeuronNVIDIA GPUs 등 다양한 칩셋 지원
     
      • Amazon EKS에서 vLLM을 사용해 Mistral-7B-Instruct 배포

    OpenAI-compatible Endpoint로 텍스트 생성 추론 기능을 제공하기 위해 Amazon Elastic Kubernetes Service (EKS)에서 vLLM 프레임워크를 사용해 Mistral-7B-Instruct 모델을 배포합니다. Karpenter를 활용해 AWS Inferentia2 EC2 노드 (Generative AI용 가속 컴퓨팅)를 생성하고, Container Image에서 vLLM Pod를 실행합니다.

     
      • AWS Inferentia Accelerators

    AWS InferentiaAWS가 설계한 Machine Learning 칩으로, Deep LearningGenerative AI 추론 애플리케이션을 가속화합니다. AWS Inferentia AcceleratorsAmazon EC2에서 높은 성능과 최저 비용을 제공하며, TensorFlow, PyTorch, MXNet과 같은 인기 있는 Machine Learning Frameworks를 지원합니다. 특히 Inferentia2 Accelerators는 대규모 Deep Learning 모델 실행에 최적화되어 있으며, Large Language Models (LLM)Latent Diffusion Models과 같은 복잡한 모델 배포에 적합합니다.

    AWS InferentiaMachine Learning추론(inference) 단계를 가속화합니다. 추론은 훈련된 모델을 사용해 새로운 데이터에 대한 예측이나 결정을 내리는 과정으로, 낮은 지연 시간(low latency)과 높은 처리량(high throughput)이 요구되는 실시간 애플리케이션에 중요합니다. AWS Inferentia2는 높은 처리량과 낮은 지연 시간을 제공하며, 각 Inferentia2 Accelerator는 두 개의 Second-generation NeuronCores를 포함하고, 최대 12개의 Inferentia2 AcceleratorsEC2 Inf2 Instance에 탑재할 수 있습니다. 각 Inferentia2 Accelerator190 TFLOPSFP16 성능을 지원하며, 32 GB HBM을 제공해 Inferentia1 대비 메모리는 4배, 메모리 대역폭은 10배 증가했습니다.

     
      • AWS Neuron SDK - ML Frameworks에 대한 네이티브 지원

    AWS Neuron SDK는 고성능 및 비용 효율적인 Deep Learning (DL) 가속화를 가능하게 하는 컴파일러, 런타임, 프로파일링 도구를 포함한 SDK입니다. AWS Neuron SDKPyTorch, TensorFlow와 같은 인기 있는 ML Frameworks와 네이티브로 통합되며, AWS Inferentia Accelerators에서 Deep Learning 모델을 최적으로 배포할 수 있도록 최소한의 코드 변경과 벤더별 솔루션에 대한 의존성을 줄입니다. NeuronNatural Language Processing (NLP), 언어 번역, 텍스트 요약, 비디오 및 이미지 생성, 음성 인식, 개인화, 사기 탐지 등 다양한 추론 애플리케이션Inferentia Accelerators에서 실행할 수 있도록 지원합니다.

    4.2. Deploy vLLM on AWS Inferentia nodes for model Inference

    4.2.1. AWS Inferentia 가속기를 위한 Karpenter NodePool 및 EC2 NodeClass 생성

    Karpenter 설정은 NodePool Custom Resource (CR) 형태로 제공됩니다. NodePool은 Karpenter가 생성할 수 있는 노드와 해당 노드에서 실행될 수 있는 Pod에 대한 제약 조건을 설정합니다. 예를 들어, NodePool은 노드 생성을 특정 컴퓨터 아키텍처로 제한하거나 여러 아키텍처를 유연하게 사용할 수 있도록 설정할 수 있습니다. 단일 Karpenter NodePool은 다양한 Pod 형태를 처리할 수 있습니다. Karpenter는 Pod의 속성(예: Label, Affinity)을 기반으로 스케줄링 및 프로비저닝 결정을 내립니다. 클러스터는 여러 NodePool을 가질 수 있지만, 이번에는 Inferentia NodePool을 추가로 선언하겠습니다.

      • Karpenter NodePool은 Karpenter가 생성할 수 있는 노드와 해당 노드에서 실행될 수 있는 Pod에 대한 제약 조건을 설정합니다. AWS 관련 설정은 NodeClass를 통해 구성할 수 있습니다. 여러 NodePool이 동일한 EC2NodeClass를 참조할 수 있습니다.
      • Cloud9 터미널에서 작업 디렉토리로 이동
    cd /home/ec2-user/environment/eks/genai
      • 배포할 Karpenter NodePool 정의 확인 AWS Inferentia INF2 Accelerated Compute 노드용 NodePool을 생성하여 Generative AI 애플리케이션(vLLM Pod)을 구동합니다.
    cat inferentia_nodepool.yaml
      • AWS Inferentia INF2 Accelerated Compute 노드용 Karpenter NodePool 정의 배포
    kubectl apply -f inferentia_nodepool.yaml
      • NodePool 및 EC2NodeClass 확인
    kubectl get nodepool,ec2nodeclass inferentia
    
    NAME                               NODECLASS    NODES   READY   AGE
    nodepool.karpenter.sh/inferentia   inferentia   0       True    7s
    
    NAME                                        READY   AGE
    ec2nodeclass.karpenter.k8s.aws/inferentia   True    6s
     
     

    4.2.2. Neuron Device Plugin 및 Scheduler 설치

    중요: 워크샵 시간을 절약하기 위해 Mistral-7B 모델은 이미 AWS Neuron SDK를 사용해 다운로드 및 컴파일된 상태입니다. 이를 AWS Inferentia Accelerated Compute 노드에 배포할 수 있습니다.

    이제 EKS 클러스터에 Neuron Device PluginNeuron Scheduler를 설치해야 합니다.

      • Neuron Device Plugin

    Neuron Device PluginNeuron Core 및 디바이스를 Kubernetes 리소스로 노출합니다.

    다음 명령어를 실행하여 Neuron Device Plugin을 설치합니다 (kubectl 경고는 무시하세요):

    kubectl apply -f https://raw.githubusercontent.com/aws-neuron/aws-neuron-sdk/master/src/k8/k8s-neuron-device-plugin-rbac.yml
    kubectl apply -f https://raw.githubusercontent.com/aws-neuron/aws-neuron-sdk/master/src/k8/k8s-neuron-device-plugin.yml
      • Neuron Scheduler

    Neuron Scheduler 확장은 여러 Neuron Core 또는 디바이스 리소스를 요구하는 Pod 스케줄링에 필요합니다. 이 확장은 비연속적인 코어/디바이스 ID를 가진 노드를 필터링하고, 연속적인 코어/디바이스 ID를 요구하는 Pod에 이를 강제 할당합니다.

    다음 명령어를 실행하여 Neuron Scheduler를 설치합니다:

    kubectl apply -f https://raw.githubusercontent.com/aws-neuron/aws-neuron-sdk/master/src/k8/k8s-neuron-scheduler-eks.yml
    kubectl apply -f https://raw.githubusercontent.com/aws-neuron/aws-neuron-sdk/master/src/k8/my-scheduler.yml
     

    4.2.3. vLLM 애플리케이션 Pod 배포

    이제 모델 서빙 및 추론 엔드포인트를 제공할 vLLM Pod를 배포합니다. vLLM Pod가 온라인 상태가 되면 Mistral-7B 모델(29GB)을 FSx for Lustre 기반 Persistent Volume에서 메모리로 로드하여 사용 준비를 마칩니다.

      • vLLM Pod 배포

    다음 명령어를 실행하여 vLLM Pod를 배포합니다:

    kubectl apply -f mistral-fsxl.yaml
    참고: vLLM 배포는 약 7~8분이 소요됩니다. (다음 단계로 진행할 수 있으며, 이 단계가 완료될 때까지 기다릴 필요는 없습니다.)
      • vLLM의 mistral-fsxl.yaml 배포 파일 확인

    다음 명령어를 실행하여 배포 파일을 확인합니다:

    cat mistral-fsxl.yaml
    
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: vllm-mistral-inf2-deployment
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: vllm-mistral-inf2-server
      template:
        metadata:
          labels:
            app: vllm-mistral-inf2-server
        spec:
          tolerations:
          - key: "aws.amazon.com/neuron"
            operator: "Exists"
            effect: "NoSchedule"
          containers:
          - name: inference-server
            image: public.ecr.aws/u3r1l1j7/eks-genai:neuronrayvllm-100G-root
            resources:
              requests:
                aws.amazon.com/neuron: 1
              limits:
                aws.amazon.com/neuron: 1
            args:
            - --model=$(MODEL_ID)
            - --enforce-eager
            - --gpu-memory-utilization=0.96
            - --device=neuron
            - --max-num-seqs=4
            - --tensor-parallel-size=2
            - --max-model-len=10240
            - --served-model-name=mistralai/Mistral-7B-Instruct-v0.2-neuron
            env:
            - name: MODEL_ID
              value: /work-dir/Mistral-7B-Instruct-v0.2/
            - name: NEURON_COMPILE_CACHE_URL
              value: /work-dir/Mistral-7B-Instruct-v0.2/neuron-cache/
            - name: PORT
              value: "8000"
            volumeMounts:
            - name: persistent-storage
              mountPath: "/work-dir"
          volumes:
          - name: persistent-storage
            persistentVolumeClaim:
              claimName: fsx-lustre-claim
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: vllm-mistral7b-service
    spec:
      selector:
        app: vllm-mistral-inf2-server
      ports:
      - protocol: TCP
        port: 80
        targetPort: 8000
    참고: 단일 Pod 배포 요청이 포함되어 있으며, AWS Inferentia Neuron Core 요청, 이전에 생성한 PVC(FSx for Lustre, fsx-lustre-claim)를 사용한 영구 스토리지, 그리고 모델 파라미터가 포함되어 있습니다.
      • vLLM Pod 생성 모니터링

    다음 명령어를 주기적으로 실행하여 Pod 상태가 Running으로 전환되는지 확인합니다:

    kubectl get po
    NAME                                            READY   STATUS              RESTARTS   AGE
    kube-ops-view-5d9d967b77-tttmp                  1/1     Running             0          2d11h
    vllm-mistral-inf2-deployment-7d886c8cc8-7fsv7   0/1     ContainerCreating   0          20m
    
    # karpenter에 의해서 node가 생성되고 static provisioning된 pv가 pvc에 의해 할당한다
    kubectl describ po vllm-mistral-inf2-deployment-7d886c8cc8-7fsv7
    ...
    Events:
      Type     Reason            Age                  From               Message
      ----     ------            ----                 ----               -------
      Normal   Nominated         36s                  karpenter          Pod should schedule on: nodeclaim/inferentia-cn67p
      Warning  FailedScheduling  19s (x5 over 7m27s)  default-scheduler  0/2 nodes are available: pod has unbound immediate PersistentVolumeClaims. preemption: 0/2 nodes are available: 2 Preemption is not helpful for scheduling.
      Warning  FailedScheduling  9s                   default-scheduler  0/3 nodes are available: 1 node(s) had untolerated taint {node.kubernetes.io/not-ready: }, 2 Insufficient aws.amazon.com/neuron. preemption: 0/3 nodes are available: 1 Preemption is not helpful for scheduling, 2 No preemption victims found for incoming pod
     
      • Amazon EKS 클러스터 콘솔 탐색
        1. Amazon EKS 클러스터 콘솔로 이동합니다.
        2. 클러스터 이름(예: eksworkshop)을 클릭합니다.
        3. Compute 탭에서 새로운 AWS Inferentia inf2.xlarge 컴퓨트 노드가 생성된 것을 확인합니다.
        4. 노드 이름을 클릭하면 inf2.xlarge 컴퓨트 노드의 용량 할당 및 Pod 세부 정보를 확인할 수 있습니다.
     
      • 요약

    이제 vLLM Pod를 성공적으로 배포했습니다. 다음 랩 섹션으로 진행하여 WebUI Pod를 배포하고, Mistral-7B 모델을 vLLM(모델 서빙 및 추론)을 통해 상호작용할 수 있도록 설정하세요.

    4.3. Deploy WebUI chat application to interact with model

    4.3.1. 추론 서비스(Inference Service) 사용 방법

    Open WebUI 애플리케이션을 사용하여 추론 서비스(Inference Service)에 연결할 수 있습니다. 이 애플리케이션은 워크숍에서 배포할 vLLM-hosted Mistral-7B-Instruct 모델이 제공하는 OpenAI-compatible endpoint를 소비하도록 설계되었습니다. Open WebUI는 채팅 기반 인터페이스를 통해 사용자가 LLM(Large Language Model)과 상호작용할 수 있게 해줍니다. Open WebUI 애플리케이션을 사용하려면, 애플리케이션 컨테이너를 배포하고 제공된 WebUI URL에 연결하여 LLM과 채팅을 시작하면 됩니다. WebUI 애플리케이션은 vLLM-hosted Mistral-7B-Instruct 모델과의 통신을 처리하여 원활한 사용자 경험을 제공합니다.

     

    4.3.2. Open WebUI Pod 배포 및 로드 밸런서 설정

    아래 명령어를 실행하여 Open WebUI 애플리케이션 Pod를 배포하세요. 이를 통해 이전 단계에서 배포한 vLLM Mistral 모델과 상호작용할 수 있습니다. 이 명령은 또한 Application Load Balancer를 배포하여 Open WebUI Chat 사용자 인터페이스를 제공합니다.

    kubectl apply -f open-webui.yaml
     

    4.3.3. Open WebUI Chat 인터페이스의 URL 주소 확인

    아래 명령어를 실행하여 Open WebUI Chat 인터페이스의 URL 주소를 확인하세요.

    kubectl get ing
    
    NAME                 CLASS   HOSTS   ADDRESS                                                     PORTS   AGE
    open-webui-ingress   alb     *       open-webui-ingress-1989187441.us-west-2.elb.amazonaws.com   80      22s

    1~2분 정도 기다린 후( Open WebUI 배포가 완료될 때까지), 위에서 확인한 URL 주소를 복사하여 웹 브라우저에 붙여넣으세요. 그러면 Open WebUI 채팅 클라이언트 인터페이스가 열립니다.

     

    4.3.4. WebUI 인터페이스 사용

    WebUI 인터페이스 상단 메뉴 바에 있는 드롭다운 메뉴에서 모델을 선택할 수 있습니다. 드롭다운 메뉴에서 Mistral-7B 모델을 선택한 후, 새로 배포한 Generative AI Chat 애플리케이션과 채팅을 시작하세요.

    만약 Mistral-7B 모델이 보이지 않는다면, 상단 드롭다운 선택 메뉴에 모델이 나타날 때까지 WebUI 페이지를 새로고침하세요. (이전 랩 모듈에서 언급했듯이, vLLM Pod와 모델이 메모리에 로드되는 데 약 7~8분이 소요됩니다.)

     

    4.3.5. 완료

    이제 Amazon EKS에서 컨테이너화된 Generative AI Chatbot 애플리케이션을 성공적으로 배포했습니다. 이 애플리케이션은 Amazon FSx Lustre에 캐싱된 Mistral-7B 모델을 사용하며, AWS Inferentia Accelerators로 구동됩니다.

     
      1. Inspect Mistral-7B data, and share & replicate generated data assets
    5.1. 실습 소개

    이 실습에서는 vLLM Pod에 로그인하여 Persistent Volume에 저장된 Mistral 모델 데이터 구조를 확인합니다.

    vLLM Pod에 로그인함으로써 FSx Lustre 파일 시스템으로 지원되는 Persistent Volume을 통해 S3 버킷에 저장된 모든 데이터에 접근하고 확인하는 방법을 알 수 있습니다.

    모델이나 훈련 데이터(Training Data)를 S3 버킷에 저장하고 이를 다른 지역(예: 재해 복구(DR) 또는 다른 팀의 분산 액세스)에 있는 EKS 클러스터와 공유하거나, Pod에서 생성된 자산(Generated Assets)을 공유해야 하는 시나리오를 상상해 보세요.

    이 랩 섹션에서는 EKS Pod의 Persistent Volume(FSx for Lustre로 지원됨)에 테스트 파일을 생성하고, 이 파일이 S3 버킷으로 자동으로 내보내지는 과정을 확인합니다. 또한, 설정할 S3 복제(S3 Replication)를 통해 테스트 파일이 우리가 제공한 다른 대상 AWS 리전(us-east-2)의 S3 버킷으로 자동으로 복제되는 모습을 볼 수 있습니다.

      • 정보
        • 하나의 Persistent Volume Claim을 여러 Pod와 공유한다!!

    수많은 AI 모델이나 방대한 훈련 데이터 세트(Training Data-Sets)를 호스팅해야 하며, 이를 워크로드의 수많은 Pod에서 액세스해야 하는 시나리오를 상상해 보세요. 이러한 데이터를 FSx for Lustre로 지원되는 단일 Persistent Volume(PV)과 Persistent Volume Claim(PVC)에 저장할 수 있습니다. 이를 통해 각 Pod마다 개별 로컬 스토리지 볼륨(Local Storage Volumes)을 생성하는 대신, 중앙 집중식 고성능 모델/데이터 캐시 위치(Centralized High-Performance Model/Data Cache Location)를 만들어 애플리케이션 Pod에 서비스를 제공할 수 있습니다. 이는 로컬 볼륨 간 데이터 중복의 비효율성을 제거하고, 새로운 Pod를 시작할 때 데이터를 각 로컬 볼륨으로 복사하는 데 따른 대기 시간을 줄이는 데 도움이 됩니다.

    5.2. Configure S3 Cross-Region Replication for your S3-linked FSx for Lustre Instance

    여기서는 Amazon S3 Cross Region Replication 설정 한다!!

    5.2.1. Amazon S3 콘솔로 이동

      • Amazon S3 콘솔을 엽니다.
      • 사용자의 리전에서 생성된 S3 버킷(예: fsx-lustre-bucket-xxxx)을 선택합니다. 주의: 이름에 2ndregion이 포함된 버킷(예: fsx-lustre-bucket-2ndregion-xxxx)은 선택하지 마세요.
     

    5.2.2. Replication Rule 생성

      • 선택한 S3 버킷 페이지에서 Management 탭으로 이동합니다.
      • Replication rules 섹션으로 스크롤하여 Create replication rule 버튼을 클릭합니다.
     

    5.2.3. Bucket Versioning 활성화 및 Rule 설정

      • 화면 상단의 빨간색 팝업 창에서 Enable Bucket Versioning을 클릭하여 버킷 버전 관리를 활성화합니다.
      • Rule name 필드에 나중에 식별할 수 있는 이름을 입력합니다(예: my-replication-rule).
      • Status는 기본적으로 Enabled로 설정되어 있는지 확인합니다.
     

    5.2.4. Source Bucket 설정

      • Source bucket 섹션에서 Limit the scope of this rule using one or more filters 옵션을 선택합니다.
      • 필터 값으로 test/를 입력하여 해당 접두사를 가진 객체에만 복제를 적용합니다.
     

    5.2.5. Destination Bucket 설정

      • Destination 섹션에서 Browse S3를 클릭합니다.
      • 대상 리전(us-east-2)에 생성된 S3 버킷(예: fsx-lustre-bucket-2ndregion-xxxx)을 선택한 후 Choose path를 클릭합니다.
      • 대상 버킷에서도 빨간색 팝업 창이 나타나면 Enable Bucket Versioning을 클릭하여 버전 관리를 활성화합니다.
     

    5.2.6. IAM Role 설정

      • Amazon S3가 객체를 복제할 수 있도록 IAM Role을 설정합니다.
      • 미리 생성된 역할(이름이 s3-cross-region-replication-role로 시작)을 선택합니다.
     

    5.2.7. Encryption 설정

      • Encryption 섹션에서 Replicate objects encrypted with AWS KMS를 선택합니다.
      • Available AWS KMS keys에서 표시된 유일한 KMS 키를 선택합니다.
     

    5.2.8. 설정 저장

      • 나머지 옵션은 기본값으로 유지합니다.
      • Save 버튼을 클릭하여 설정을 저장합니다.
     

    5.2.9. 기존 객체 복제 여부 선택

      • 기존 객체 복제 여부를 묻는 팝업이 나타나면 No, do not replicate existing objects를 선택하고 Submit을 클릭합니다.
     

    5.2.10. 설정 확인

    • 설정이 완료되면 S3 replication rules 페이지로 돌아갑니다.
    • 새로 생성된 복제 규칙이 성공적으로 표시되는지 확인합니다.
     

    요약

    이 과정을 통해 두 개의 S3 버킷 간 Cross Region Replication 규칙을 성공적으로 설정했습니다. 다음 단계에서는 Persistent Volume에 마운트된 Pod에서 테스트 데이터를 생성하고, 생성된 데이터가 대상 S3 버킷으로 원활하게 복사되는 과정을 확인할 수 있습니다. Amazon S3의 네이티브 복제 기능은 데이터 공유 및 컨테이너화된 워크로드의 DR/BCP(재해 복구/비즈니스 연속성 계획) 전략에 유용하게 활용될 수 있습니다.

    5.3. Inspect Mistral-7B data, generate test file in Pod to enable auto-export and replication of data

    이 섹션에서는 Pod에 로그인하여 Mistral-7B 모델 데이터를 검사하고, 공유 및 복제될 테스트 파일을 생성합니다.

     

    5.3.1. Pod에 로그인, 모델 데이터 검사, 복제용 테스트 파일 생성

    Cloud9 터미널로 돌아가 작업 디렉토리로 이동합니다.

    cd /home/ec2-user/environment/eks/FSxL

    이제 vLLM Pod에 로그인합니다. 먼저 아래 명령어를 실행하여 Pod 이름을 확인합니다.

    kubectl get pods
    NAME                                            READY   STATUS    RESTARTS   AGE
    kube-ops-view-5d9d967b77-tttmp                  1/1     Running   0          2d12h
    open-webui-deployment-5d7ff94bc9-kf6jk          1/1     Running   0          40m
    vllm-mistral-inf2-deployment-7d886c8cc8-7fsv7   1/1     Running   0          66m

    출력 결과에서 환경에 표시된 vLLM으로 시작하는 이름을 복사합니다. 복사한 값을 사용하여 아래 명령어를 실행하여 vLLM Pod에 로그인합니다.

    kubectl exec -it <YOUR-vLLM-POD-NAME> -- bash

    다음 명령어를 실행합니다.

    oot@vllm-mistral-inf2-deployment-7d886c8cc8-7fsv7:~# df -h
    Filesystem                 Size  Used Avail Use% Mounted on
    overlay                    100G   23G   78G  23% /
    tmpfs                       64M     0   64M   0% /dev
    tmpfs                      7.7G     0  7.7G   0% /sys/fs/cgroup
    10.0.58.250@tcp:/bietbb4v  1.2T   28G  1.1T   3% /work-dir
    /dev/nvme0n1p1             100G   23G   78G  23% /etc/hosts
    shm                         64M     0   64M   0% /dev/shm
    tmpfs                       15G   12K   15G   1% /run/secrets/kubernetes.io/serviceaccount
    tmpfs                      7.7G     0  7.7G   0% /proc/acpi
    tmpfs                      7.7G     0  7.7G   0% /sys/firmware

    work-dir은 Persistent Volume Claim(FSx for Lustre 파일 시스템으로 지원됨)의 마운트 위치입니다.

    이 Persistent Volume에 저장된 내용을 검사해봅시다.

    cd /work-dir/
    ls -ll
    total 297
    drwxr-xr-x 5 root root  33280 Apr 16 20:07 Mistral-7B-Instruct-v0.2
    -rw-r--r-- 1 root root 147482 Apr 16 20:09 sysprep

    Mistral-7B 모델이 여기에 저장되어 있음을 확인할 수 있습니다. 모델 데이터 구조를 살펴봅시다.

    cd Mistral-7B-Instruct-v0.2/
    ls -ll
    total 2550
    drwxr-xr-x 3 root root   33280 Apr 16 20:07 -split
    -rwxr-xr-x 1 root root    5471 Apr 16 19:42 README.md
    -rwxr-xr-x 1 root root     596 Apr 16 19:42 config.json
    -rwxr-xr-x 1 root root     111 Apr 16 19:42 generation_config.json
    -rwxr-xr-x 1 root root   25125 Apr 16 19:42 model.safetensors.index.json
    drwxr-xr-x 3 root root   33280 Apr 16 20:07 neuron-cache
    -rwxr-xr-x 1 root root   23950 Apr 16 19:42 pytorch_model.bin.index.json
    -rwxr-xr-x 1 root root     414 Apr 16 19:42 special_tokens_map.json
    -rwxr-xr-x 1 root root 1795188 Apr 16 19:42 tokenizer.json
    -rwxr-xr-x 1 root root  493443 Apr 16 19:42 tokenizer.model
    -rwxr-xr-x 1 root root    2103 Apr 16 19:42 tokenizer_config.json

    다음으로, Persistent Volume(FSx for Lustre로 지원됨)에 테스트 파일을 생성합니다. 여기서 FSx for Lustre의 새로운/변경된 파일을 Amazon S3로 자동 내보내기 기능과 S3 버킷 간 복제를 확인할 수 있습니다. vLLM Pod에서 생성한 파일은 us-east-2 지역의 대상 S3 버킷으로 원활하게 복사됩니다. 이 데이터는 기존 환경에서 사용하거나 DR(재해 복구) 시나리오에서 Amazon EKS 클러스터, Pod, FSx Lustre 인스턴스를 자동으로 실행하여 복제된 데이터를 소비하는 데 사용할 수 있습니다.

    test라는 새 폴더 아래 testfile이라는 테스트 파일을 생성하여 FSx 인스턴스와 연결된 S3 버킷으로 테스트 파일의 내보내기를 트리거하고, S3 Replication을 통해 us-east-2 지역의 대상 S3 버킷으로 테스트 파일을 복제합니다.

    cd /work-dir
    mkdir test
    cd test
    cp /work-dir/Mistral-7B-Instruct-v0.2/README.md /work-dir/test/testfile
    ls -ll /work-dir/test
     

    5.3.2. S3 버킷으로 데이터 내보내기 및 지역 간 복제 확인

    Amazon S3 Console 페이지로 이동합니다: Amazon S3 console

    사용자의 지역에 있는 S3 버킷(FSx 인스턴스와 연결된 버킷)을 클릭합니다. 이름에 2ndregion이 포함된 S3 버킷은 클릭하지 마세요.

     

    test 폴더가 존재함을 확인할 수 있습니다. test 폴더를 클릭하면 Pod의 Persistent Volume에서 생성한 testfile이 FSx for Lustre 파일 시스템에서 S3 버킷으로 자동 내보내기된 것을 볼 수 있습니다.

     

    이제 다른 AWS 지역(us-east-2)에 있는 대상 S3 버킷으로 이동하여 이 testfile이 자동으로 복제되었는지 확인합니다.

    창 상단의 Buckets 하이퍼링크를 클릭합니다.

    이름에 2ndregion이 포함된 S3 버킷을 클릭합니다. 이 버킷은 us-east-2에 위치하며, test 폴더와 testfile이 S3 Replication에 의해 자동으로 복제되었음을 확인할 수 있습니다.

     
     

    5.3.3. 요약

    이 섹션에서는 FSx for Lustre와 Amazon S3로의 자동 가져오기/내보내기 기능을 사용하여 Pod 내에서 생성된 데이터를 공유하고 복제하는 방법을 확인했습니다. 또한 S3 Replication을 통해 S3 버킷 간 데이터를 원활하게 복제하는 방법도 확인했습니다. 이는 분산 데이터 요구사항이나 DR(재해 복구) 시나리오에 유용합니다. 예를 들어, 보조 지역(DR)에 기존 EKS 클러스터가 있는 경우, 복제된 S3 버킷의 데이터를 활용하여 FSx for Lustre 인스턴스를 생성하고, FSx 인스턴스를 사용한 Persistent Volume을 생성한 후, 애플리케이션 Pod를 실행하여 다른 AWS 지역에서 데이터를 원활하게 소비할 수 있습니다.

      • 정보

    많은 AI 모델이나 대량의 훈련 데이터셋을 호스팅해야 하며, 이를 수백 개의 Pod에서 액세스해야 하는 시나리오를 상상해보세요. 이 데이터를 FSx for Lustre로 지원되는 단일 Persistent Volume(PV)에 저장할 수 있습니다. 이를 통해 각 Pod에 개별 로컬 스토리지 볼륨을 생성하여 데이터가 중복되거나, Pod가 데이터를 액세스하기 전에 로컬 볼륨으로 데이터를 복사하는 대기 시간이 발생하는 대신, 중앙 집중식 고성능 모델/데이터 캐시 위치를 제공하여 애플리케이션 Pod를 효율적으로 서비스할 수 있습니다.

     
      1. Create your own environment for testing Data layer
    6.1. 실습 소개

    이전 모듈에서 관리자가 미리 생성한 기존 스토리지 인스턴스를 사용하여 정적 프로비저닝(Static Provisioning)을 통해 EKS 클러스터에서 퍼시스턴트 볼륨(Persistent Volume, PV)과 퍼시스턴트 볼륨 클레임(Persistent Volume Claim, PVC)을 생성하는 방법을 배웠습니다. 이 섹션에서는 테스트 환경을 직접 구성하여 포드(Pod)를 배포하고, 사용자가 동적 프로비저닝(Dynamic Provisioning) 기능을 사용하여 주문형 퍼시스턴트 볼륨(PV)과 퍼시스턴트 볼륨 클레임(PVC)을 배포하는 방법을 배웁니다. 이를 통해 백엔드에서 FSx Lustre 인스턴스가 자동으로 생성되며, 관리자의 사전 프로비저닝이 필요 없습니다. 이후 해당 PVC를 포드에 마운트하여 이 랩 섹션에서 테스트를 진행합니다.

    6.2. Use Dynamic Provisioning to deploy a new PV and FSx Lustre instance for testing

    ⇒ 동적 프로비저닝(Dynamic Provisioning)을 사용한 FSx for Lustre 스토리지 설정

    이 섹션에서는 CSI 드라이버의 Dynamic Provisioning 기능을 사용하여 온디맨드 방식으로 Persistent Volume(PV) 및 Persistent Volume Claim(PVC)을 생성하는 방법을 학습합니다. 이를 통해 백엔드에서 FSx for Lustre 인스턴스를 자동으로 생성하며, 관리자의 사전 프로비저닝 없이 작업이 가능합니다. StorageClass, PersistentVolume, PersistentVolumeClaim 정의를 생성하여 Static Provisioning과의 차이점을 확인하고, 이 PV를 테스트에 사용합니다.

     

    6.2.1. StorageClass 정의

      1. 환경 변수 설정

    아래 명령어를 Cloud9 터미널에 입력하여 VPC, 서브넷, 보안 그룹 ID를 설정합니다:

    VPC_ID=$(aws eks describe-cluster --name $CLUSTER_NAME --region $AWS_REGION --query "cluster.resourcesVpcConfig.vpcId" --output text)
    SUBNET_ID=$(aws eks describe-cluster --name $CLUSTER_NAME --region $AWS_REGION --query "cluster.resourcesVpcConfig.subnetIds[0]" --output text)
    SECURITY_GROUP_ID=$(aws ec2 describe-security-groups --filters Name=vpc-id,Values=${VPC_ID} Name=group-name,Values="FSxLSecurityGroup01" --query "SecurityGroups[*].GroupId" --output text)
      1. 환경 변수 확인

    아래 명령어로 서브넷 ID와 보안 그룹 ID를 확인합니다:

    echo $SUBNET_ID
    echo $SECURITY_GROUP_ID
      1. 작업 디렉토리 이동
    cd /home/ec2-user/environment/eks/FSxL
      1. StorageClass 정의 파일(fsxL-storage-class.yaml)

    이 파일은 CSI 드라이버가 FSx for Lustre를 동적으로 프로비저닝하기 위한 StorageClass를 정의합니다.

    주요 파라미터는 다음과 같습니다:

        1. subnetId – The subnet ID that the Amazon FSx for Lustre file system should be created in. Amazon FSx for Lustre is not supported in all Availability Zones. Open the Amazon FSx for Lustre console at https://console.aws.amazon.com/fsx/ to confirm that the subnet that you want to use is in a supported Availability Zone. The subnet can include your nodes, or can be a different subnet or VPC. If the subnet that you specify is not the same subnet that you have nodes in, then your VPCs must be connected, and you must ensure that you have the necessary ports open in your security groups.
        2. securityGroupIds – The security group ID for your nodes.
        3. s3ImportPath – The Amazon Simple Storage Service data repository that you want to copy data from to the persistent volume.
        4. s3ExportPath – The Amazon S3 data repository that you want to export new or modified files to.
        5. deploymentType – The file system deployment type. Valid values are SCRATCH_1, SCRATCH_2, and PERSISTENT_1. For more information about deployment types, see Create your Amazon FSx for Lustre file system.
        6. autoImportPolicy - the policy FSx will follow that determines how the filesystem is automatically updated with changes made in the linked data repository. For a list of acceptable policies, please view the official FSx for Lustre documentation
        7. perUnitStorageThroughput - for deployment type PERSISTENT_1, customer can specify the storage throughput. Default: "200". Note that customer has to specify as a string here like "200" or "100" etc.
     

    여기서 설정한 파라미터는 아래와 같습니다:

        1. provisioner: fsx.csi.aws.com
        2. subnetId: FSx 인스턴스가 배포될 서브넷
        3. securityGroupIds: FSx 인스턴스에 적용될 보안 그룹
        4. deploymentType: SCRATCH_2 (임시 데이터용 고성능 파일 시스템)
        5. fileSystemTypeVersion: 2.15 (FSx 파일 시스템 버전)
        6. mountOptions: flock (파일 잠금 옵션)
    kind: StorageClass
    apiVersion: storage.k8s.io/v1
    metadata:
      name: fsx-lustre-sc
    provisioner: fsx.csi.aws.com
    parameters:
      subnetId: SUBNET_ID
      securityGroupIds: SECURITY_GROUP_ID
      deploymentType: SCRATCH_2
      fileSystemTypeVersion: "2.15"
    mountOptions:
      - flock
      1. 환경 변수로 값 치환

    아래 명령어로 SUBNET_ID와 SECURITY_GROUP_ID를 실제 값으로 치환합니다:

    sed -i'' -e "s/SUBNET_ID/$SUBNET_ID/g" fsxL-storage-class.yaml
    sed -i'' -e "s/SECURITY_GROUP_ID/$SECURITY_GROUP_ID/g" fsxL-storage-class.yaml
      1. 파일 확인

    치환된 값을 확인합니다:

    cat fsxL-storage-class.yaml

    참고: s3ImportPath와 s3ExportPath는 동일한 S3 버킷을 사용해야 하며, s3ImportPath만 지정할 경우 랜덤 경로가 생성됩니다.

     

    6.2.2. StorageClass 생성

      1. StorageClass 적용 아래 명령어로 정의된 StorageClass를 생성합니다:
    kubectl apply -f fsxL-storage-class.yaml
      1. StorageClass 확인 생성된 StorageClass를 확인합니다:
    kubectl get sc
    
    NAME            PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
    fsx-lustre-sc   fsx.csi.aws.com         Delete          Immediate              false                  5s
    gp2             kubernetes.io/aws-ebs   Delete          WaitForFirstConsumer   false                  2d13h
    gp3 (default)   ebs.csi.aws.com         Delete          WaitForFirstConsumer   true                   2d13h
     

    6.2.3. Persistent Volume Claim(PVC) 생성

      1. PVC 정의 파일(fsxL-dynamic-claim.yaml)

    이 파일은 1200GiB 용량의 PVC를 요청하며, 앞서 생성한 fsx-lustre-sc StorageClass를 참조합니다:

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: fsx-lustre-dynamic-claim
    spec:
      accessModes:
        - ReadWriteMany
      storageClassName: fsx-lustre-sc
      resources:
        requests:
          storage: 1200Gi
      1. PVC 생성

    아래 명령어로 PVC를 생성합니다:

    kubectl apply -f fsxL-dynamic-claim.yaml
      1. PVC 상태 확인

    아래 명령어로 PVC 상태를 확인합니다:

    kubectl get pvc

    참고: FSx for Lustre 인스턴스 생성은 약 15분이 소요되며, 이 기간 동안 PVC 상태는 Pending으로 표시됩니다. 상태가 Bound로 변경될 때까지 기다려야 합니다.

     

    6.2.4. FSx for Lustre 인스턴스 및 PVC 상태 확인

      1. PVC 상태 확인

    약 15분 후, 아래 명령어로 PVCBound 상태인지 확인합니다:

    kubectl get pvc
    
    NAME                       STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS    VOLUMEATTRIBUTESCLASS   AGE
    fsx-lustre-claim           Bound     fsx-pv   1200Gi     RWX                            <unset>                 90m
    fsx-lustre-dynamic-claim   Pending                                      fsx-lustre-sc   <unset>                 9s
      1. 문제 해결

    ProvisioningFailed 경고가 표시되면 FSx 파일 시스템 생성이 진행 중일 가능성이 높습니다. Amazon FSx 콘솔에서 상태를 확인할 수 있습니다(상태가 Creating에서 Available로 변경됨).

     

    6.2.5. 요약

    이 섹션에서는 Dynamic Provisioning을 사용하여 StorageClassPVC를 정의하고, S3 버킷과 연결된 FSx for Lustre 파일 시스템 및 PV를 성공적으로 생성했습니다. 다음 섹션에서는 이 PV를 활용하여 새로운 Pod를 배포하고 FSx for Lustre의 성능 테스트를 수행합니다.

    6.3. Performance testing

    이 섹션에서는 FSx for Lustre 파일 시스템의 스토리지 성능과 관련된 중요한 매개변수인 IOPS, throughput, 그리고 latency를 살펴봅니다. 이를 위해 FIO (Flexible I/O)라는 널리 사용되는 스토리지 벤치마킹 도구와 IOping이라는 실시간 I/O 지연 시간 모니터링 도구를 사용하여 CSI driver를 통해 프로비저닝된 FSx for Lustre 드라이브의 성능을 테스트합니다. 테스트는 EKS Pod에서 수행됩니다.

     

    6.3.1. Pod 프로비저닝 및 FSx for Lustre에 10GB 스토리지 설정

    테스트용 PodYAML 파일을 사용하여 프로비저닝하고, FSx for Lustre에 10GB 스토리지를 설정합니다.

      1. 작업 디렉토리로 이동
    cd /home/ec2-user/environment/eks/FSxL
      1. 아래 명령어를 실행하여 FSx for Lustre 인스턴스의 Availability Zone (예: "us-west-2c")을 확인하고 출력된 값을 기록합니다.
    aws ec2 describe-subnets --subnet-id $SUBNET_ID --region $AWS_REGION | jq .Subnets[0].AvailabilityZone
      1. Pod 배포 설정 파일 수정
    vi pod_performance.yaml
        1. 중요

    아래 단계는 성능 테스트에 매우 중요합니다. PodFSx for Lustre 파일 시스템과 동일한 Availability Zone에 배포되도록 보장합니다.

          1. vi 편집기에서 “i”를 눌러 편집 모드로 전환합니다.
          2. nodeSelectortopology.kubernetes.io/zone으로 시작하는 마지막 두 줄의 주석 (#)을 제거하여 활성화합니다.
          3. 이전 단계에서 기록한 Availability Zone (예: us-east-2c)을 해당 줄에 반영합니다.
          4. 편집을 완료한 후 ESC를 누르고 :wq를 입력한 뒤 Enter를 눌러 저장하고 종료합니다.
     
      1. 아래 명령어를 복사하여 실행해 성능 테스트용 Pod를 프로비저닝합니다.
    kubectl apply -f pod_performance.yaml
      1. 아래 명령어를 실행하여 Pod의 상태를 확인합니다. PodRUNNING 상태로 전환되는 데 약 1분이 걸립니다.
    kubectl get pods
        1. 중요

    Pod 이벤트에 아래와 같은 메시지가 표시된다면, FSx for Lustre 파일 시스템 프로비저닝이 아직 완료되지 않은 것입니다.

    Events:
      Type     Reason            Age   From               Message
      ----     ------            ----  ----               -------
      Warning  FailedScheduling  25s   default-scheduler  0/2 nodes are available: 2 pod has unbound immediate PersistentVolumeClaims. preemption: 0/2 nodes are available: 2 Preemption is not helpful for scheduling.

    이 경우 PVC fsx-lustre-claimPending 상태인지 확인하고, 최대 15분까지 기다립니다. PVC fsx-lustre-claimBound 상태로 전환되면 PodRUNNING 상태로 변경됩니다.

     

    6.3.2. Container에 로그인하여 FIO 및 IOping 테스트 수행

    이 단계에서는 FIOIOping 유틸리티를 설치하고, 성능 부하 테스트를 실행하여 IOPSthroughput를 관찰합니다.

      1. 아래 명령어를 사용하여 Container에 로그인합니다.
    kubectl exec -it fsxl-performance  -- bash
      1. FIOIOping 설치
    apt-get update
    apt-get install fio ioping -y
      1. 아래 IOping 명령어를 실행하여 FSx for Lustre 파일 시스템의 latency를 테스트합니다.
    ioping -c 20 .

    평균 latency 값을 기록합니다. 일반적으로 0.5ms (500us) 미만으로, FSx for Lustre 파일 시스템의 낮은 지연 시간과 높은 성능을 보여줍니다.

     
      1. 아래 명령어와 FIO 명령어를 실행하여 부하 테스트를 수행하고, Throughput 값을 기록합니다.
    mkdir -p /data/performance
    cd /data/performance
    fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=fiotest --filename=testfio8gb --bs=1MB --iodepth=64 --size=8G --readwrite=randrw --rwmixread=50 --numjobs=8 --group_reporting --runtime=10
        1. 중요

    이번 실습에서는 가장 작은 FSx for Lustre 구성인 1.2TiB를 배포했으며, 이는 240MB/s의 기본 throughput을 제공합니다. FSx for Lustre 파일 시스템의 크기를 늘리면 기본 throughput도 증가합니다. FIO 테스트 결과에서 빨간색으로 강조된 부분은 평균 읽기 및 쓰기 throughput을 보여줍니다.

    FIO 테스트에서는 1MB의 큰 블록 크기를 사용하여 throughput을 테스트하며, 작은 EKS Container 환경에서 50% 읽기/쓰기 혼합, 랜덤 읽기-쓰기 패턴, 8개의 동시 작업을 시뮬레이션합니다.

     
      1. Pod에서 로그아웃합니다.
    exit
     

    6.3.3. 성능 요약

    워크로드가 FSx for Lustre 파일 시스템에서 얻을 수 있는 throughputIOPS의 구체적인 양은 파일 시스템의 throughput capacity, storage capacity 구성, 그리고 워크로드의 특성에 따라 달라집니다. Amazon FSx for Lustre 성능에 대한 자세한 정보는 다음 링크를 참조하세요:

    Amazon FSx for Lustre performance chart

     

    6.3.4. 요약

    FIOIOping 도구를 사용하여 Amazon FSx for Lustre 파일 시스템의 성능 테스트를 성공적으로 완료했습니다. EKS Pod에서 FSx for Lustre에 부하를 가하며 높은 throughput과 밀리초 미만의 latency를 관찰했습니다.

Designed by Tistory.