데보션앱 소개페이지 바로가기
로그인 선택

신고하기

CLOSE
신고사유 (대표 사유 1개)
상세내용 (선택)
0/200
  • 신고한 게시글은 더 이상 보이지 않습니다.
  • 이용약관과 운영정책에 따라 신고사유에 해당하는지 검토 후 조치됩니다.
  • 허위 신고인 경우, 신고자의 서비스 이용이 제한될 수 있으니 유의하시어 신중하게 신고해 주세요.
(이 회원이 작성한 모든 댓글과 커뮤니티 게시물이 보이지 않고, 알림도 오지 않습니다.)

미리보기

커뮤니티

      1,234

      badge 23.06.15

      글 등록

      카테고리를 선택해주세요.

      DEVOTEE를 활성화 시키면
      지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.

      버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.

      임시저장함에 저장되었습니다. 저장일시 : 2022.5.17 14:29:08

      임시저장함

      제목을 선택하시면 이어서 작성이 가능하며,
      최대 20건까지 저장합니다.
      컨텐츠 유형, 제목, 저장일시, 삭제로 이뤄진 임시저장 목록
      컨텐츠 유형 제목 저장일 삭제

      데보션 블로그 게재 요청

      CLOSE
      • *
      • *

      본인인증

      효율적인 데보션 서비스 이용 및
      고객님의 소중한 개인정보보호를 위해
      본인인증을 진행해주세요. 본인인증 미 진행 시 로그인이 제한됩니다.
      본인인증 실패

      본인인증 로그인에 실패하였습니다.
      회원이 아니시거나 본인인증 등록이
      완료되지 않은 사용자입니다.

      회원정보 연결

      kubernetes에서 Local LLM 편리하게 사용하기

      sungil 24.12.30
      6,666 10 1
      DEVOTEE 요약
      현대의 LLM 시대에서는 Kubernetes에서 ML/DL 모델을 운영할 수 있는 다양한 방법이 있습니다. Ollama나 LM Studio 등을 이용하여 신속히 모델을 질의하고 응답할 수 있도록 구축할 수 있으며, Kserve와 KubeAI 같은 플랫폼을 활용해 복잡한 인프라 관리나 자동화된 로드 밸런싱 등의 기능을 통해 확장성과 고가용성을 제공받을 수 있습니다. 이러한 플랫폼을 활용하면 고가용성 및 확장성을 유지하면서도 다양한 ML/DL 모델을 잘 관리하고 서빙할 수 있습니다.
      DEVOTEE 추천 블로그

      바야흐로 LLM 전성시대를 지나가고 있다.

      (일부 캐즘에 왔다는 의견도 있지만) ollama를 활용하면 쉽게 hugging face에 공개된 모델이나 자신이 갖고 있는 모델을 사용하여 질의하고 응답을 받을 수 있다.

      LM Studio와 같은 툴을 사용하면 훨씬더 쉽고 강력하게 모델을 사용할 수 있다.


      kubernetes에서도 이러한 ML/DL 모델들을 운영하고 활용하는 방법들이 있어 이 글을 통해 정리하고자 한다.

      직접 POD로 만들어 띄우기

      ollama나 vllm, sglang등 라이브러리를 활용하여 프로그램을 구동하는 pod를 만드는 것이다.

      다음은 ollama를 사용하여 llm 모델을 올리고 이를 활용하는 예시이다.

      1. ollama를 올리기 위한 pod와 서비스를 준비한다. ollama 이미지를 사용하고 기본포트인 11434 포트에 접근가능하도록 해주는 것이 포인트이다.

        apiVersion: v1
        kind: Pod
        metadata:
          name: ollama
          labels:
            app.kubernetes.io/name: ollama
        spec:
          containers:
          - name: ollama
            image: ollama/ollama:0.5.0
            ports:
            - containerPort: 11434
        ---
        apiVersion: v1
        kind: Service
        metadata:
          name: llm-service
        spec:
          selector:
            app.kubernetes.io/name: ollama
          ports:
          - port: 11434
            targetPort: 11434
            nodePort: 31434
          type: NodePort
        ---
      2. 준비한 yaml을 배포한다

        $ kubectl apply -f ollama.pod.yaml                                                                                                                                  
        pod/ollama created                                                                     
        service/llm-service created 
      3. 배포된 workload에서 모델을 다운로드 받는다.

        $ kubectl exec -it ollama bash
        kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
        root@ollama:/# ollama list
        NAME    ID    SIZE    MODIFIED 
        root@ollama:/# ollama run gemma2:2b
        pulling manifest 
        pulling 7462734796d6... 100% ▕███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ 1.6 GB                         
        pulling e0a42594d802... 100% ▕███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏  358 B                         
        pulling 097a36493f71... 100% ▕███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ 8.4 KB                         
        pulling 2490e7468436... 100% ▕███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏   65 B                         
        pulling e18ad7af7efb... 100% ▕███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏  487 B                         
        verifying sha256 digest 
        writing manifest 
        success 
        >>> Send a message (/? for help)
      4. 서비스로 열어놓은 노트포트를 통해 외부에서 문장생성을 요청할 수 있다.

        $ curl http://siim-dev:31434/api/generate -d '{
            "model": "gemma2:2b",
            "prompt": "오늘 하루의 응원 문구를 하나 추천해줘"
            }'
        {"model":"gemma2:2b","created_at":"2024-12-06T22:45:38.149942565Z","response":"##","done":false}
        {"model":"gemma2:2b","created_at":"2024-12-06T22:45:38.200397257Z","response":" 오","done":false}
        {"model":"gemma2:2b","created_at":"2024-12-06T22:45:38.252816111Z","response":"늘","done":false}
        {"model":"gemma2:2b","created_at":"2024-12-06T22:45:38.304500496Z","response":" 하","done":false}
        {"model":"gemma2:2b","created_at":"2024-12-06T22:45:38.357209239Z","response":"루","done":false}
        ... <중략> ...
        {"model":"gemma2:2b","created_at":"2024-12-06T22:45:49.083443124Z","response":" 있습니다","done":false}
        {"model":"gemma2:2b","created_at":"2024-12-06T22:45:49.13733027Z","response":"!","done":false}
        {"model":"gemma2:2b","created_at":"2024-12-06T22:45:49.191131037Z","response":" 🎉","done":false}
        {"model":"gemma2:2b","created_at":"2024-12-06T22:45:49.246082586Z","response":"  ","done":false}
        {"model":"gemma2:2b","created_at":"2024-12-06T22:45:49.299441352Z","response":"**","done":false}
        {"model":"gemma2:2b","created_at":"2024-12-06T22:45:49.352740658Z","response":"\n\n\n","done":false}
        {"model":"gemma2:2b","created_at":"2024-12-06T22:45:49.406885585Z","response":"","done":true,"done_reason":"stop","context":[106,1645,108,237410,240703,30181,238949,236137,224047,237399,45980,237302,236791,113859,75943,239250,237138,244669,107,108,106,2516,108,1620,44245,240703,30181,238949,224047,237399,75630,236569,236183,235292,235248,119607,109,688,235281,
        237410,240703,236840,105560,239205,48060,235269,235248,244328,237589,30181,238949,29283,238151,96673,235341,44416,236309,139,237602,239079,244801,231124,32929,134660,99091,237047,206716,105560,238138,236392,174538,237036,96673,235341,139,239208,239553,235281,5231,110,235832,45980,237302,236214,115049,237233,132929,60318,239158,236392,128753,236464,55496,235265
        ,109,235287,5231,246133,236864,237603,224907,103293,242508,236511,70754,237601,236386,95573,664,238356,239205,48060,235269,235248,244328,237589,30181,238949,29283,238151,96673,4496,80564,81673,235832,235248,242991,236648,100280,238513,26291,28693,238304,231124,216702,245461,236392,31087,239522,43395,235265,108,235287,5231,236666,237047,237889,240090,236179,143
        636,240449,90621,197054,156610,75630,236569,236183,95573,139,235281,237602,239079,244801,231124,32929,134660,99091,237047,206716,105560,238138,236392,174538,237036,96673,4496,79871,236214,45980,237199,236648,32929,237047,50390,240090,125507,22803,38585,237410,236214,32048,238780,236511,36203,240054,236179,99797,237545,153728,236345,153145,179694,235265,235248,
        109,688,235832,224047,237399,75630,236569,194255,49532,236589,236137,36203,240054,237233,41645,238036,236179,207221,237458,42916,240046,238080,22618,55496,235341,160588,139,688,110],"total_duration":14312477982,"load_duration":2752779534,"prompt_eval_count":24,"prompt_eval_duration":293000000,"eval_count":211,"eval_duration":11264000000}
      5. (옵션) 더 실질적인 활용을 위해 kubectl의 ai 플러그인을 통해 사용하여 다양한 리소스에 대한 yaml을 만드는데 사용할 수 있다. (https://github.com/sozercan/kubectl-ai)

        $ export OPENAI_ENDPOINT="http://siim-dev:31434/v1"
        $ export OPENAI_DEPLOYMENT_NAME="gemma2:2b"
        $ export OPENAI_API_KEY="n/a"
        $ kubectl ai "create an nginx deployment with 3 replicas"
        
          ✨ Attempting to apply the following manifest:                              
        
            apiVersion: apps/v1                                                       
            kind: Deployment                                                          
            metadata:                                                                 
              name: nginx-deployment                                                  
            spec:                                                                     
              replicas: 3                                                             
              selector:                                                               
                matchLabels:                                                          
                  app: nginx                                                          
              template:                                                               
                metadata:                                                             
                  labels:                                                             
                    app: nginx                                                        
                spec:                                                                 
                  containers:                                                         
                  - name: nginx                                                       
                    image: docker.io/nginx:latest                                     
                    ports:                                                            
                      - containerPort: 80                                             
        
        Use the arrow keys to navigate: ↓ ↑ → ← 
        ? (context: kubernetes-admin@siim-dev) Would you like to apply this? [Reprompt/Apply/Don't Apply]: 
        +   Reprompt
          ▸ Apply
            Don't Apply

      이 방법은 단순하고 직관적이지만 k8s의 여러가지 이점들을 이용하는데는 한계가 있다.

      개별 자원들을 모두 만들어줘야하고 모니터링등을 하기위해서는 별로의 장치를 추가하는 것들이 수동으로 진행되어야 한다.

      고가용성을 지원하기 위한 구조등을 위한 여러가지 고민도 필요하므로 상용에는 적합하지 않는 방법이다.

      AI 서빙 지원을 위한 플랫폼 활용하기

      ML/DL 모델을 지원하기 위한 플랫폼들이 있다.

      첫번쨰는 kubeflow 진영에서 분리되어 나온 kserve이다. 두번쨰는 open-webui라는 모듈을 활용하여 나온 kubeai이다. 각각을 살펴보면 다음과 같다.

      Kserve

      kserve는 쿠버네티스 환경에서 ML 모델을 효율적으로 서빙하고 관리할 수 있게 해주는 도구이다. 

      복잡한 인프라 관리 없이도 모델을 서빙하고 확장성 있게 운영할 수 있다.

      주요 기능

      이를 위해 자동 로드밸런싱을 제공하고 모델버전을 관리해주고 장애 복구기능도 내장하고 있다. 이를 통해 확장성과 고가용성을 제공한다.

      다양한 프레임워크로 만든 모델을 지원하고 실시간 예측 API 구축이 가능하고 트래픽의 분산을 지원하고 A/B테스트나 카나리 배포등 다양한 전략을 지원하여 배포 유연성도 확보가능하다.

      설치하기

      공식 사이트에서는 설치스크립트를 제공하고 있다.

      스크립트의 내용 중 oci 방식으로 ghcr에서 helm chart를 가져오는 부분이 있으므로 github에 적적한 권한을 갖은 토큰으로 로그인하는 것이 필수이다.

      curl -s "https://raw.githubusercontent.com/kserve/kserve/release-0.14/hack/quick_install.sh" | bash

      스크립트는 다음과 같이 2가지 종류의 설치(서버리스와 디플로이)와 삭제기능을 제공한다.

      서버리스를 선택해서 설치하면 kNative를 함께 구성하고 활용하도록 배포된다.

      $ ./quick_install.sh -h
      KServe quick install script.
      
      Syntax: [-s|-r]
      options:
      s Serverless Mode.
      r RawDeployment Mode.
      u Uninstall.
      d Install only dependencies.

      서버리스 모드로 설치하면 다음과 같은 과정을 통해 필요한 모듈들이 설치된다.

      $ ./quick_install.sh -s
      "istio" has been added to your repositories 
      NAME: istio-base                                                               
      LAST DEPLOYED: Sat Dec  7 14:22:50 2024
      NAMESPACE: istio-system                
      STATUS: deployed 
      REVISION: 1     
      TEST SUITE: None
      NOTES:          
      Istio base successfully installed!
      
      To learn more about the release, try:                       
        $ helm status istio-base                                   
        $ helm get all istio-base                                
      NAME: istiod                                                  
      LAST DEPLOYED: Sat Dec  7 14:23:03 2024          
      NAMESPACE: istio-system                           
      STATUS: deployed                                               
      REVISION: 1          
      TEST SUITE: None
      NOTES:                                         
      "istiod" successfully installed!                
      
      To learn more about the release, try:                                   
        $ helm status istiod                                    
        $ helm get all istiod                             
      
      Next steps:                                                          
        * Deploy a Gateway: https://istio.io/latest/docs/setup/additional-setup/gateway/
        * Try out our tasks to get started on common configurations: 
          * https://istio.io/latest/docs/tasks/traffic-management
          * https://istio.io/latest/docs/tasks/security/            
          * https://istio.io/latest/docs/tasks/policy-enforcement/    
        * Review the list of actively supported releases, CVE publications and our hardening guide:                                                                                        
          * https://istio.io/latest/docs/releases/supported-releases/ 
          * https://istio.io/latest/news/security/        
          * https://istio.io/latest/docs/ops/best-practices/security/
      
      For further documentation see https://istio.io website       
      NAME: istio-ingressgateway                                 
      LAST DEPLOYED: Sat Dec  7 14:23:34 2024                       
      NAMESPACE: istio-system                          
      STATUS: deployed                                  
      REVISION: 1                                                    
      TEST SUITE: None           
      NOTES:
      "istio-ingressgateway" successfully installed!
      
      To learn more about the release, try:
        $ helm status istio-ingressgateway
        $ helm get all istio-ingressgateway
      
      Next steps:
        * Deploy an HTTP Gateway: https://istio.io/latest/docs/tasks/traffic-management/ingress/ingress-control/                                                                           
        * Deploy an HTTPS Gateway: https://istio.io/latest/docs/tasks/traffic-management/ingress/secure-ingress/                                                                           
      pod/istio-ingressgateway-5758d9fbb9-hsbtx condition met
      😀 Successfully installed Istio                  
      "jetstack" has been added to your repositories
      NAME: cert-manager                                                                                                                                                                                                                                                                                                                                                        
      LAST DEPLOYED: Sat Dec  7 14:24:01 2024      
      NAMESPACE: cert-manager               
      STATUS: deployed                           
      REVISION: 1                                                          
      TEST SUITE: None                        
      NOTES:                      
      cert-manager v1.15.1 has been deployed successfully!                                      
      
      In order to begin issuing certificates, you will need to set up a ClusterIssuer
      or Issuer resource (for example, by creating a 'letsencrypt-staging' issuer).
      
      More information on the different types of issuers and how to configure them
      can be found in our documentation:
      
      https://cert-manager.io/docs/configuration/
      
      For information on how to configure cert-manager to automatically provision
      Certificates for Ingress resources, take a look at the `ingress-shim`
      documentation:                                               
      
      https://cert-manager.io/docs/usage/ingress/
      😀 Successfully installed Cert Manager    
      NAME: knative-operator
      LAST DEPLOYED: Sat Dec  7 14:26:28 2024
      NAMESPACE: knative-serving
      STATUS: deployed
      REVISION: 1
      TEST SUITE: None
      knativeserving.operator.knative.dev/knative-serving created
      😀 Successfully installed Knative
      ./quick_install.sh: line 133: [: =: unary operator expected
      Pulled: ghcr.io/kserve/charts/kserve-crd:v0.14.0
      Digest: sha256:6ae5af970d9a9400e8456ad1dbc86360d03f4b6bb00be4f16c48bc0542283d42           
      NAME: kserve-crd
      LAST DEPLOYED: Sat Dec  7 14:28:27 2024
      NAMESPACE: kserve
      STATUS: deployed
      REVISION: 1
      TEST SUITE: None
      Pulled: ghcr.io/kserve/charts/kserve:v0.14.0
      Digest: sha256:25129d39a4aa85f96159db6933729ea9f35e9d0f7f7cac7918c0a8013672eccb
      NAME: kserve
      LAST DEPLOYED: Sat Dec  7 14:29:16 2024
      NAMESPACE: kserve
      STATUS: deployed
      REVISION: 1
      TEST SUITE: None
      😀 Successfully installed KServe 

      가이드에서 나오는 내역과 설치해주는 버전에서의 사용자 자원이 달라서 진행이 안되는 문제가 있었다.

      이에 따라 다음과 같이 스크립트의 내부에서 knative의 버전을 변경하여 설치하였다.

      export KNATIVE_OPERATOR_VERSION=v1.14.5
      export KNATIVE_SERVING_VERSION=1.13.1
      -->
      export KNATIVE_OPERATOR_VERSION=v1.16.0
      export KNATIVE_SERVING_VERSION=1.16.0

      사용해보기

      https://kserve.github.io/website/latest/get_started/first_isvc/


      추론서비스를 정의하여 모델을 사용할 수 있다.

      1. 테스트용 네임스페이스 생성

        kubectl create namespace kserve-test
      2. 추론서비스 생성

        kubectl apply -n kserve-test -f - <<EOF
        apiVersion: "serving.kserve.io/v1beta1"
        kind: "InferenceService"
        metadata:
          name: "sklearn-iris"
        spec:
          predictor:
            model:
              modelFormat:
                name: sklearn
              storageUri: "gs://kfserving-examples/models/sklearn/1.0/model"
        EOF
      3. 서비스가 올라오는 내역을 확인 (아래와 같이 할수 있으나 외부 dns 연결 등 여러가지 상황으로 ready가 표시되지 않을수 있다.)

        siim@adm:~/my/abc$ kubectl get inferenceservices -n kserve-test sklearn-iris 
        NAME           URL   READY     PREV   LATEST   PREVROLLEDOUTREVISION   LATESTREADYREVISION   AGE
        sklearn-iris         Unknown                                                                 45s

        이에 따라 다음과 같이 pod를 직접확인하자

        siim@adm:~/my/abc$ kubectl get po -n kserve-test
        NAME                                                       READY   STATUS    RESTARTS   AGE
        sklearn-iris-predictor-00001-deployment-7dd975bd86-gbtr5   2/2     Running   0          26m
      4. 만들어진 추론 파드에 포트포워딩 한 후 테스트 해볼수 있다.

        $ kubectl port-forward -n kserve-test sklearn-iris-predictor-00001-deployment-7dd975bd86-gbtr5 8080:8080                                                                                                                            
        Forwarding from 127.0.0.1:8080 -> 8080
        Forwarding from [::1]:8080 -> 8080

        새로운 창을 만들어 추론서비스로 요청해 볼 수 있다.

        siim@adm:~/my/abc$ cat <<EOF > "./iris-input.json"
        {
          "instances": [
            [6.8,  2.8,  4.8,  1.4],
            [6.0,  3.4,  4.5,  1.6]
          ]
        }
        EOF
        siim@adm:~/my/abc$ curl -v -H "Content-Type: application/json" http://localhost:8080/v1/models/sklearn-iris:predict -d @./iris-input.json                                                                                                          
        *   Trying 127.0.0.1:8080...
        * Connected to localhost (127.0.0.1) port 8080 (#0)
        > POST /v1/models/sklearn-iris:predict HTTP/1.1
        > Host: localhost:8080
        > User-Agent: curl/7.81.0
        > Accept: */*
        > Content-Type: application/json
        > Content-Length: 76
        > 
        * Mark bundle as not supporting multiuse
        < HTTP/1.1 200 OK
        < date: Sat, 07 Dec 2024 22:13:06 GMT
        < server: uvicorn
        < content-length: 21
        < content-type: application/json
        < 
        * Connection #0 to host localhost left intact
        {"predictions":[1,1]}
      5. (옵션) llm 서비스를 올려서 사용해보기

        $ kubectl apply -f - <<EOF                                                                                                                                                                                                                                                                
        apiVersion: v1                                                                                                                                                                                                                                                                                      
        kind: Secret                                                                                                                                                                                                                                                                                        
        metadata:                                                                                                                                                                                                                                                                                           
            name: hf-secret                                                                                                                                                                                                                                                                                 
        type: Opaque                                                                                                                                                                                                                                                                                        
        stringData:                                                                                                                                                                                                                                                                                         
            HF_TOKEN: hf_your_huggingface_token                                                                                                                                                                                                                                                
        EOF                                                                                                                                                                                                                                                                                                 
        secret/hf-secret configured 
        
        $ kubectl apply -f - <<EOF
        apiVersion: serving.kserve.io/v1beta1
        kind: InferenceService
        metadata:
          name: huggingface-qwen
        spec:
          predictor:
            model:
              modelFormat:
                name: huggingface
              args:
                - --model_name=qwen
                - --model_id=Qwen/Qwen2.5-Coder-32B-Instruct
              env:
                - name: HF_TOKEN
                  valueFrom:
                    secretKeyRef:
                      name: hf-secret
                      key: HF_TOKEN
                      optional: false
              resources:
                limits:
                  cpu: "6"
                  memory: 24Gi
                requests:            
                  cpu: "6"
                  memory: 24Gi
        EOF
        inferenceservice.serving.kserve.io/huggingface-llama3 created

      위 방식으로 시도했으나 현재 갖고 있는 환경의 문제인지 정확하게 huggingface 서버가 동작하지 않는 문제가 있었다.

      최신 GPU를 사용하면 잘 될지 모르겠으나 구형 GPU, 또는 CPU 모드로 사용할 수 없어서 여기까지만 진행하였다.

      cpu 모드로 구동하기 위해서는 아래와 같은 환경변수를 추가해서 추론서버를 올리면 된다.

              - name: VLLM_TARGET_DEVICE
                value: "cpu"

      사족: kserve를 redhat에서 적극도입하여 사용하고 있다는 사실을 알고 잘 될꺼라 믿으면서 진행했는데

      redhat도 kserve + knative 방식이 아닌 자신들의 서버리스용 오퍼레이터(OpenShift Serverless)를 따로 만들어 사용하는 것 같다.

      혹시 llm 올리시는데 성공하신 분이 있다면 제보해주시기 바란다.

      참고: https://www.redhat.com/ko/blog/fine-tuning-and-serving-open-source-foundation-model-red-hat-openshift-ai

      KubeAI

      kubernetes에서 LM Studio처럼 쉽게 llm을 올려보고 사용할 순 없을까 하다가 찾았던 프로젝트로 open-webui(https://docs.openwebui.com/)라는 것을 발견했다.

      이 프로젝트는 웹앱을 띄워주는데 해당 웹엡에서 모델들을 로딩할 수 있고 모델에 채팅할 수 있는 창도 제공하고 RestAPI도 제공하는 등의 기능이 있었다.


      kubeai 는 이 open webui를 기본 엔진으로 사용하고 있으며 여러가지 부가기능을 추가한 오픈소스 프로젝트이다.

      image

      블로그 등의 내용을 토대로 생각해보면 dewu라는 회사에서 만들어 오픈한 것으로 보여지는데 전체시스템 중의 일부(모델을 서비스하는 부분)만을 공개한 것으로 생각된다.

      아래 그림은 dewu에서 자신들의 시스템을 설명하는 블로그의 그림이고 이를 보면 데이터에 대한 보관 및 전달, 모델의 학습, 배포하는 컴포넌트등 광범위한 AI 지원 컴포넌트들을 포함하는 것으로 기술되어있다.

      자세한 설명과 내용은 알리바바 블로그로 공개된 내역을 확인하자.


      image

      출처: https://www.alibabacloud.com/blog/implementation-and-practice-of-kubeai-a-cloud-native-ai-platform-of-dewu_600192


      실제 오픈소스의 메인페이지는 https://www.kubeai.org/ 이고 이곳에서 보여지는 아래그림이 오픈소스의 내역을 더 정확히 알려준다.

      KubeAI는 외부 시스템에 다양한 인터페이스를 제공하고 내부적으로 vllm, ollama 서버들을 관리하는 것이다.

      image

      KubeAI를 설치하면 open-webui가 설치되고 추가적으로 model 이라는 사용자 자원과 이를 처리하는 오퍼레이터가 생성된다.

      설치하기

      helm 을 사용하면 간단하게 하나의 차트를 통해 설치할 수 있다. (서브챠트를 통해 다른 컴포넌트들도 포함된 하나의 챠트)

      1. helm repo 등록

        helm repo add kubeai https://www.kubeai.org
        helm repo update
      2. kubeai (operator) 설치

        helm install kubeai kubeai/kubeai --wait --timeout 10m

      설치하고나면 2개의 파드가 실행되고 있는 것을 확인할 수 있는데 kubeai는 오퍼레이터, openwebui는 chatgpt와 유사한 웹UI이다. openwebui라는 서비스를 통해 웹앱에 접근할 수 있다.

      $ kubectl get po 
      NAME                                   READY   STATUS    RESTARTS       AGE
      kubeai-5c99b99b85-9m8kr                1/1     Running   1 (5h5m ago)   7d2h
      openwebui-55d54bd69-b9ztb              1/1     Running   0              7d2h

      image

      모델추가

      모델을 생성하기위한 별도의 챠트(models)를 제공하고 있으며 이 챠트를 통해 앞에서 설치한 오퍼레이터의 사용자 자원인 model을 만들수 있다.

      아래 예시는 공식 사이트에 있는 것으로 카탈로그에 다른 모델들을 추가할 수 있다. 추가가능한 리스트는 링크를 참조하면 된다.

      cat <<EOF > kubeai-models.yaml
      catalog:
        gemma2-2b-cpu:
          enabled: true
          minReplicas: 1
        qwen2-500m-cpu:
          enabled: true
        nomic-embed-text-cpu:
          enabled: true
        llama-3.1-70b-instruct-fp8-gh200:
      		enabled: true
      EOF
      
      helm install kubeai-models kubeai/models -f ./kubeai-models.yaml

      모델이 적용되면 모델에 맵핑되는 pod가 생성되고 요청의 양에 따라 그 크기가 조정된다고 한다.

      위 예시에서는 4개의 모델을 추가하고 있는데 그중 gemma2 모델에 붙어있는 ‘minReplicas: 1’ 설정을 했으므로 요청이 없는 경우에도 최소한의 파드는 유지된다.

      따라서 배포된 네임스페이스에서 파드를 검색해보면 gemma2에 대한 파드만 동작하고 있는 것을 확인할 수 있다.

      나머지 3개의 모델의 경우는 호출이 들어오면 파드가 생성된다.


      웹앱을 통해 들어가보면 지정한 모델들이 모두 보여지고 gemma2 모델을 선택하면 즉각적인 채팅이 가능하다.

      그외 모델을 선택하고 채팅을 시도하면 이때 선택된 모델과 관련한 model 파드가 생성되며 완료 이 후 채팅이 가능해 진다.

      최소 수~수십GB의 모델파일을 적재해 구동해야하는 llm 모델의 특성상 replica 설정을 하지 않은 경우 최초 요청에서 답변이 나오는 시간까지 매우 오랜 대기가 발생할 수 있다.

      $ kubectl get model
      NAME                               AGE
      gemma2-2b-cpu                      7d2h
      llama-3.1-70b-instruct-fp8-gh200   7d2h
      nomic-embed-text-cpu               7d2h
      qwen2-500m-cpu                     7d2h
      
      $ kubectl get po 
      NAME                                   READY   STATUS    RESTARTS       AGE
      kubeai-5c99b99b85-9m8kr                1/1     Running   1 (5h5m ago)   7d2h
      model-gemma2-2b-cpu-557968f69b-qttpk   1/1     Running   0              7d2h
      openwebui-55d54bd69-b9ztb              1/1     Running   0              7d2h

      image

      사용하기

      일반적으로 두가지 방식의 사용법이 존재한다. chatgpt가 인도해준 사실상 표준이 되어가고 있는 두 가지이다.

      하나는 채팅창을 통해 모델을 사용하는 것이고 두번째는 api 호출을 통해 활용하는 것이다.

      1. 채팅창을 통한 접근: 웹앱을 통해 채팅할수 있다.

        image

      2. api 호출을 통한 접근: 앞의 예시와 동일하게 kubectl ai 플러그인을 통해 활용할 수 있다.

        앞의 과정을 따라했다면 생성한 모델중 minreplica를 설정한 gemma2만 워크로드가 올라와 있는 것을 확인할 수 있고 이 워크로드에 포트포워딩 접근을 통해 사용하면 된다.

        $ kubectl get po 
        NAME                                   READY   STATUS    RESTARTS         AGE
        kubeai-5c99b99b85-9m8kr                1/1     Running   25 (7h22m ago)   8d
        model-gemma2-2b-cpu-557968f69b-qttpk   1/1     Running   0                8d
        openwebui-55d54bd69-b9ztb              1/1     Running   0                8d
        
        $ kubectl port-forward model-gemma2-2b-cpu-557968f69b-qttpk 30080:8000
        Forwarding from 127.0.0.1:30080 -> 8000
        Forwarding from [::1]:30080 -> 8000
        Handling connection for 30080
        Handling connection for 30080
        $ export OPENAI_ENDPOINT="http://localhost:30080/v1"
        $ export OPENAI_DEPLOYMENT_NAME="gemma2-2b-cpu:latest"
        $ export OPENAI_API_KEY="n/a"
        $ kubectl ai "create an nginx deployment with 3 replicas"
        
          ✨ Attempting to apply the following manifest:                              
        
            apiVersion: apps/v1                                                       
            kind: Deployment                                                          
            metadata:                                                                 
            #  spec.template.spec is a part of a deployment                           
              name: nginx-deployment                                                  
              labels:                                                                 
                app: nginx-deployment                                                 
            spec:                                                                     
              replicas: 3                                                             
              selector:                                                               
                matchLabels:                                                          
                  app: nginx                                                          
              template:                                                               
                metadata:                                                             
                  labels:                                                             
                    app: nginx                                                        
                Spec:                                                                 
                 containers:                                                          
                    - name: nginx                                                     
                      image: nginx:latest                                             
                      ports:                                                          
                        - containerPort: 80                                           
        
        Use the arrow keys to navigate: ↓ ↑ → ← 
        ? (context: kubernetes-admin@siim-dev) Would you like to apply this? [Reprompt/Apply/Don't Apply]: 
        +   Reprompt
          ▸ Apply
            Don't Apply

      두가지 플랫폼의 비교

      KubeAI는 단순하고 가벼운 구조로 설계되었고 외부 의존성이 없으므로(Istio, Knative 등 불필요) 유지보수에 유리함이 있다.


      KServe는 Knative 기반으로 충실한 서버리스를 갖고 있지만 kubernetes의 여러 오픈소소들을 활용하는 아키텍쳐로 매우 복잡하므로 유지보수함에 어려움이 예상된다.

      하지만 다양한 ML 프레임워크 지원 (TensorFlow, PyTorch, XGBoost 등)과 kubernetes의 강점을 활용하는데는 더욱 유리한 것도 사실이다.

      image

      맺으며

      이 글에서는 kubernetes에서 AI를 지원하기 위한 방법들을 살펴보았다.

      간단하게 ollama또는 vllm을 띄우는 파드를 만들수도 있으나 k8s의 다양한 기능들을 활용하기에는 불현한 것은 사실이고 상용으로 운영한다하면 선택지는 아닐것이다.

      k8s에서 AI 지원을 위한 플랫폼이 거의 kubeflow를 기반으로 확장되어 있지만 학습등의 영역을 사용하지 않는다면 너무 무거운 시스템인 것도 사실이다.

      이에 따라 추론서비스만을 위한 두가지의 플랫폼을 살펴보았다.

      댓글 0

      DEVOTEE를 활성화 시키면
      지금 작성한 댓글에 AI가 댓글을 달아줍니다.

      sungil 님의 최신 블로그

      더보기

      DEVOTEE 추천 블로그

      동영상 기고하기