23.06.15
DEVOTEE를 활성화 시키면
지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.
버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.
| 컨텐츠 유형 | 제목 | 저장일 | 삭제 |
|---|
본인인증 로그인에 실패하였습니다.
회원이 아니시거나 본인인증 등록이
완료되지 않은 사용자입니다.
바야흐로 LLM 전성시대를 지나가고 있다.
(일부 캐즘에 왔다는 의견도 있지만) ollama를 활용하면 쉽게 hugging face에 공개된 모델이나 자신이 갖고 있는 모델을 사용하여 질의하고 응답을 받을 수 있다.
LM Studio와 같은 툴을 사용하면 훨씬더 쉽고 강력하게 모델을 사용할 수 있다.
kubernetes에서도 이러한 ML/DL 모델들을 운영하고 활용하는 방법들이 있어 이 글을 통해 정리하고자 한다.
ollama나 vllm, sglang등 라이브러리를 활용하여 프로그램을 구동하는 pod를 만드는 것이다.
다음은 ollama를 사용하여 llm 모델을 올리고 이를 활용하는 예시이다.
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
---준비한 yaml을 배포한다
$ kubectl apply -f ollama.pod.yaml
pod/ollama created
service/llm-service created 배포된 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)서비스로 열어놓은 노트포트를 통해 외부에서 문장생성을 요청할 수 있다.
$ 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}(옵션) 더 실질적인 활용을 위해 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의 여러가지 이점들을 이용하는데는 한계가 있다.
개별 자원들을 모두 만들어줘야하고 모니터링등을 하기위해서는 별로의 장치를 추가하는 것들이 수동으로 진행되어야 한다.
고가용성을 지원하기 위한 구조등을 위한 여러가지 고민도 필요하므로 상용에는 적합하지 않는 방법이다.
ML/DL 모델을 지원하기 위한 플랫폼들이 있다.
첫번쨰는 kubeflow 진영에서 분리되어 나온 kserve이다. 두번쨰는 open-webui라는 모듈을 활용하여 나온 kubeai이다. 각각을 살펴보면 다음과 같다.
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.0https://kserve.github.io/website/latest/get_started/first_isvc/
추론서비스를 정의하여 모델을 사용할 수 있다.
테스트용 네임스페이스 생성
kubectl create namespace kserve-test추론서비스 생성
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서비스가 올라오는 내역을 확인 (아래와 같이 할수 있으나 외부 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만들어진 추론 파드에 포트포워딩 한 후 테스트 해볼수 있다.
$ 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]}(옵션) 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 올리시는데 성공하신 분이 있다면 제보해주시기 바란다.
kubernetes에서 LM Studio처럼 쉽게 llm을 올려보고 사용할 순 없을까 하다가 찾았던 프로젝트로 open-webui(https://docs.openwebui.com/)라는 것을 발견했다.
이 프로젝트는 웹앱을 띄워주는데 해당 웹엡에서 모델들을 로딩할 수 있고 모델에 채팅할 수 있는 창도 제공하고 RestAPI도 제공하는 등의 기능이 있었다.
kubeai 는 이 open webui를 기본 엔진으로 사용하고 있으며 여러가지 부가기능을 추가한 오픈소스 프로젝트이다.

블로그 등의 내용을 토대로 생각해보면 dewu라는 회사에서 만들어 오픈한 것으로 보여지는데 전체시스템 중의 일부(모델을 서비스하는 부분)만을 공개한 것으로 생각된다.
아래 그림은 dewu에서 자신들의 시스템을 설명하는 블로그의 그림이고 이를 보면 데이터에 대한 보관 및 전달, 모델의 학습, 배포하는 컴포넌트등 광범위한 AI 지원 컴포넌트들을 포함하는 것으로 기술되어있다.
자세한 설명과 내용은 알리바바 블로그로 공개된 내역을 확인하자.

실제 오픈소스의 메인페이지는 https://www.kubeai.org/ 이고 이곳에서 보여지는 아래그림이 오픈소스의 내역을 더 정확히 알려준다.
KubeAI는 외부 시스템에 다양한 인터페이스를 제공하고 내부적으로 vllm, ollama 서버들을 관리하는 것이다.

KubeAI를 설치하면 open-webui가 설치되고 추가적으로 model 이라는 사용자 자원과 이를 처리하는 오퍼레이터가 생성된다.
helm 을 사용하면 간단하게 하나의 차트를 통해 설치할 수 있다. (서브챠트를 통해 다른 컴포넌트들도 포함된 하나의 챠트)
helm repo 등록
helm repo add kubeai https://www.kubeai.org
helm repo updatekubeai (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
모델을 생성하기위한 별도의 챠트(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
일반적으로 두가지 방식의 사용법이 존재한다. chatgpt가 인도해준 사실상 표준이 되어가고 있는 두 가지이다.
하나는 채팅창을 통해 모델을 사용하는 것이고 두번째는 api 호출을 통해 활용하는 것이다.
채팅창을 통한 접근: 웹앱을 통해 채팅할수 있다.

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 ApplyKubeAI는 단순하고 가벼운 구조로 설계되었고 외부 의존성이 없으므로(Istio, Knative 등 불필요) 유지보수에 유리함이 있다.
KServe는 Knative 기반으로 충실한 서버리스를 갖고 있지만 kubernetes의 여러 오픈소소들을 활용하는 아키텍쳐로 매우 복잡하므로 유지보수함에 어려움이 예상된다.
하지만 다양한 ML 프레임워크 지원 (TensorFlow, PyTorch, XGBoost 등)과 kubernetes의 강점을 활용하는데는 더욱 유리한 것도 사실이다.

이 글에서는 kubernetes에서 AI를 지원하기 위한 방법들을 살펴보았다.
간단하게 ollama또는 vllm을 띄우는 파드를 만들수도 있으나 k8s의 다양한 기능들을 활용하기에는 불현한 것은 사실이고 상용으로 운영한다하면 선택지는 아닐것이다.
k8s에서 AI 지원을 위한 플랫폼이 거의 kubeflow를 기반으로 확장되어 있지만 학습등의 영역을 사용하지 않는다면 너무 무거운 시스템인 것도 사실이다.
이에 따라 추론서비스만을 위한 두가지의 플랫폼을 살펴보았다.
DEVOTEE를 활성화 시키면
지금 작성한 댓글에 AI가 댓글을 달아줍니다.