Kotaemon RAG 애플리케이션 완전 가이드: Kubernetes Helm 배포부터 운영까지
개요
Kotaemon은 22.5k 스타를 기록한 오픈소스 RAG 기반 문서 QA 애플리케이션입니다. 깔끔하고 사용자 친화적인 UI를 제공하며, 개발자와 최종 사용자 모두를 고려하여 설계되었습니다.
본 가이드에서는 Kotaemon을 Kubernetes Helm으로 배포하고 운영하는 전체 과정을 단계별로 설명합니다.
Kotaemon 주요 특징
최종 사용자를 위한 기능
- 깔끔하고 미니멀한 UI: RAG 기반 QA를 위한 사용자 친화적 인터페이스
- 다양한 LLM 지원: OpenAI, Azure OpenAI, Cohere 등 API 제공업체와 로컬 LLM(Ollama, llama-cpp-python) 호환
- 쉬운 설치: 빠른 시작을 위한 간단한 스크립트 제공
개발자를 위한 기능
- RAG 파이프라인 프레임워크: 자체 RAG 기반 문서 QA 파이프라인 구축 도구
- 커스터마이징 가능한 UI: Gradio로 구축된 UI를 통해 RAG 파이프라인 시각화
- Gradio 테마: Gradio 개발 시 사용할 수 있는 kotaemon-gradio-theme 제공
핵심 기능
- 멀티 사용자 문서 QA 웹 UI: 로그인 지원, 개인/공개 컬렉션 관리, 협업 및 공유 기능
- LLM 및 임베딩 모델 관리: 로컬 LLM과 인기 API 제공업체(OpenAI, Azure, Ollama, Groq) 지원
- 하이브리드 RAG 파이프라인: 전문 및 벡터 검색과 재순위화를 결합한 최적의 검색 품질
- 멀티모달 QA 지원: 도표와 표가 포함된 여러 문서에 대한 질의응답
- 고급 인용 및 문서 미리보기: 상세한 인용과 브라우저 내 PDF 뷰어 지원
- 복잡한 추론 방법: 질문 분해, ReAct, ReWOO 등 에이전트 기반 추론 지원
- 설정 가능한 UI: UI에서 검색 및 생성 프로세스의 중요한 측면 조정 가능
- 확장 가능: Gradio 기반으로 UI 요소 자유롭게 커스터마이징 가능
시스템 아키텍처
기본 아키텍처
graph TB
subgraph "Frontend Layer"
UI[Gradio Web UI]
API[REST API]
end
subgraph "Application Layer"
QA[QA Pipeline]
DOC[Document Processor]
CHAT[Chat Manager]
end
subgraph "Storage Layer"
VDB[(Vector Database)]
FDB[(File Database)]
MDB[(Metadata Store)]
end
subgraph "AI Services"
LLM[LLM Models]
EMB[Embedding Models]
end
UI --> QA
API --> QA
QA --> DOC
QA --> CHAT
DOC --> VDB
DOC --> FDB
CHAT --> MDB
QA --> LLM
DOC --> EMB
GraphRAG 통합 아키텍처
graph TB
subgraph "Document Processing"
PDF[PDF Files]
CHUNK[Text Chunking]
ENTITY[Entity Extraction]
GRAPH[Knowledge Graph]
end
subgraph "RAG Pipeline"
QUERY[User Query]
VECTOR[Vector Search]
GRAPH_SEARCH[Graph Search]
RERANK[Re-ranking]
GENERATE[Response Generation]
end
PDF --> CHUNK
CHUNK --> ENTITY
ENTITY --> GRAPH
QUERY --> VECTOR
QUERY --> GRAPH_SEARCH
VECTOR --> RERANK
GRAPH_SEARCH --> RERANK
RERANK --> GENERATE
사전 요구사항
시스템 요구사항
# 1. Python 3.10 이상
python --version
# 2. Docker (선택사항)
docker --version
# 3. Kubernetes 클러스터
kubectl cluster-info
# 4. Helm 3.x
helm version
Kubernetes 클러스터 준비
# 로컬 개발용 minikube 설정
minikube start --cpus=4 --memory=8192 --disk-size=50g
# 또는 GKE 클러스터 생성
gcloud container clusters create kotaemon-cluster \
--num-nodes=3 \
--machine-type=e2-standard-4 \
--zone=us-central1-a \
--enable-autoscaling \
--min-nodes=1 \
--max-nodes=5
Helm Chart 작성
1. Chart 구조 생성
# Helm Chart 디렉토리 생성
mkdir -p kotaemon-helm
cd kotaemon-helm
# Chart 구조 초기화
helm create kotaemon
cd kotaemon
2. Chart.yaml 설정
# Chart.yaml
apiVersion: v2
name: kotaemon
description: A Helm chart for Kotaemon RAG application
type: application
version: 1.0.0
appVersion: "latest"
keywords:
- rag
- ai
- document-qa
- gradio
home: https://github.com/Cinnamon/kotaemon
sources:
- https://github.com/Cinnamon/kotaemon
maintainers:
- name: Kotaemon Team
url: https://github.com/Cinnamon/kotaemon
3. values.yaml 설정
# values.yaml
replicaCount: 2
image:
repository: ghcr.io/cinnamon/kotaemon
pullPolicy: IfNotPresent
tag: "main-lite"
nameOverride: ""
fullnameOverride: ""
serviceAccount:
create: true
annotations: {}
name: ""
podAnnotations: {}
podSecurityContext:
fsGroup: 1000
securityContext:
capabilities:
drop:
- ALL
readOnlyRootFilesystem: false
runAsNonRoot: true
runAsUser: 1000
service:
type: LoadBalancer
port: 7860
targetPort: 7860
ingress:
enabled: false
className: ""
annotations: {}
hosts:
- host: kotaemon.local
paths:
- path: /
pathType: Prefix
tls: []
resources:
limits:
cpu: 2000m
memory: 4Gi
requests:
cpu: 1000m
memory: 2Gi
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 70
targetMemoryUtilizationPercentage: 80
nodeSelector: {}
tolerations: []
affinity: {}
# Kotaemon 특화 설정
kotaemon:
config:
# 문서 저장소 설정
docstore: "LanceDB" # Elasticsearch | LanceDB | SimpleFileDocumentStore
# 벡터 저장소 설정
vectorstore: "ChromaDB" # ChromaDB | LanceDB | InMemory | Milvus | Qdrant
# 멀티모달 QA 활성화
multimodal: true
# 추론 파이프라인
reasonings:
- "ktem.reasoning.simple.FullQAPipeline"
- "ktem.reasoning.simple.FullDecomposeQAPipeline"
- "ktem.reasoning.react.ReactAgentPipeline"
- "ktem.reasoning.rewoo.RewooAgentPipeline"
# 환경 변수
env:
GRADIO_SERVER_NAME: "0.0.0.0"
GRADIO_SERVER_PORT: "7860"
# GraphRAG 설정
USE_NANO_GRAPHRAG: "false"
USE_LIGHTRAG: "false"
USE_CUSTOMIZED_GRAPHRAG_SETTING: "false"
# OpenAI 설정 (선택사항)
OPENAI_API_BASE: "https://api.openai.com/v1"
OPENAI_CHAT_MODEL: "gpt-3.5-turbo"
OPENAI_EMBEDDINGS_MODEL: "text-embedding-ada-002"
# 데이터 지속성
persistence:
enabled: true
storageClass: ""
accessMode: ReadWriteOnce
size: 10Gi
mountPath: /app/ktem_app_data
# 벡터 데이터베이스 (ChromaDB)
chromadb:
enabled: true
image:
repository: chromadb/chroma
tag: "latest"
service:
port: 8000
persistence:
enabled: true
size: 20Gi
# PostgreSQL (메타데이터 저장용)
postgresql:
enabled: true
auth:
postgresPassword: "kotaemon123"
database: "kotaemon"
primary:
persistence:
enabled: true
size: 10Gi
4. Deployment 템플릿
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name:
labels:
spec:
replicas:
selector:
matchLabels:
template:
metadata:
annotations:
labels:
spec:
imagePullSecrets:
serviceAccountName:
securityContext:
containers:
- name:
securityContext:
image: ":"
imagePullPolicy:
ports:
- name: http
containerPort:
protocol: TCP
env:
- name:
value:
- name: CHROMA_HOST
value: "-chromadb"
- name: CHROMA_PORT
value: ""
- name: POSTGRES_HOST
value: "-postgresql"
- name: POSTGRES_DB
value:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: -postgresql
key: postgres-password
livenessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 60
periodSeconds: 30
readinessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 30
periodSeconds: 10
resources:
volumeMounts:
- name: data
mountPath:
volumes:
- name: data
persistentVolumeClaim:
claimName: -data
nodeSelector:
affinity:
tolerations:
5. Service 템플릿
# templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name:
labels:
spec:
type:
ports:
- port:
targetPort: http
protocol: TCP
name: http
selector:
6. PersistentVolumeClaim 템플릿
# templates/pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: -data
labels:
spec:
accessModes:
-
resources:
requests:
storage:
storageClassName:
7. ChromaDB 배포
# templates/chromadb-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: -chromadb
labels:
app.kubernetes.io/component: chromadb
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/component: chromadb
template:
metadata:
labels:
app.kubernetes.io/component: chromadb
spec:
containers:
- name: chromadb
image: ":"
ports:
- name: http
containerPort:
protocol: TCP
env:
- name: CHROMA_HOST
value: "0.0.0.0"
volumeMounts:
- name: data
mountPath: /chroma/chroma
volumes:
- name: data
persistentVolumeClaim:
claimName: -chromadb-data
---
apiVersion: v1
kind: Service
metadata:
name: -chromadb
labels:
app.kubernetes.io/component: chromadb
spec:
ports:
- port:
targetPort: http
protocol: TCP
name: http
selector:
app.kubernetes.io/component: chromadb
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: -chromadb-data
labels:
app.kubernetes.io/component: chromadb
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage:
배포 실행
1. Helm 저장소 추가 및 업데이트
# PostgreSQL Helm Chart 저장소 추가
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
2. 네임스페이스 생성
# 전용 네임스페이스 생성
kubectl create namespace kotaemon
# 네임스페이스를 기본값으로 설정
kubectl config set-context --current --namespace=kotaemon
3. Secret 생성 (API 키 등)
# OpenAI API 키 Secret 생성
kubectl create secret generic kotaemon-secrets \
--from-literal=openai-api-key="your-openai-api-key" \
--from-literal=azure-openai-api-key="your-azure-api-key" \
-n kotaemon
4. values.yaml 커스터마이징
# custom-values.yaml
image:
tag: "main-full" # 더 많은 파일 형식 지원
service:
type: LoadBalancer
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: nlb
ingress:
enabled: true
className: "nginx"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
hosts:
- host: kotaemon.yourdomain.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: kotaemon-tls
hosts:
- kotaemon.yourdomain.com
resources:
limits:
cpu: 4000m
memory: 8Gi
requests:
cpu: 2000m
memory: 4Gi
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 20
targetCPUUtilizationPercentage: 70
kotaemon:
env:
# GraphRAG 활성화
USE_NANO_GRAPHRAG: "true"
# OpenAI 설정
OPENAI_API_KEY:
valueFrom:
secretKeyRef:
name: kotaemon-secrets
key: openai-api-key
# 고성능 벡터 데이터베이스로 변경
chromadb:
enabled: false
# Qdrant 사용
qdrant:
enabled: true
image:
repository: qdrant/qdrant
tag: "latest"
service:
port: 6333
persistence:
enabled: true
size: 50Gi
5. Helm 설치 실행
# 의존성 업데이트
helm dependency update
# Dry-run으로 검증
helm install kotaemon . \
--namespace kotaemon \
--values custom-values.yaml \
--dry-run --debug
# 실제 배포
helm install kotaemon . \
--namespace kotaemon \
--values custom-values.yaml \
--timeout 10m
6. 배포 상태 확인
# Pod 상태 확인
kubectl get pods -n kotaemon
# 서비스 상태 확인
kubectl get svc -n kotaemon
# Ingress 확인
kubectl get ingress -n kotaemon
# 로그 확인
kubectl logs -f deployment/kotaemon -n kotaemon
운영 및 모니터링
1. 헬스 체크 설정
# templates/healthcheck.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: -healthcheck
data:
healthcheck.py: |
#!/usr/bin/env python3
import requests
import sys
import os
def check_health():
try:
# Kotaemon 애플리케이션 헬스 체크
response = requests.get(
f"http://localhost:{os.getenv('GRADIO_SERVER_PORT', '7860')}/",
timeout=30
)
if response.status_code == 200:
print("✅ Kotaemon is healthy")
return True
else:
print(f"❌ Kotaemon returned status {response.status_code}")
return False
except Exception as e:
print(f"❌ Health check failed: {e}")
return False
if __name__ == "__main__":
if check_health():
sys.exit(0)
else:
sys.exit(1)
2. 모니터링 대시보드
# monitoring/prometheus-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: kotaemon-prometheus-config
data:
prometheus.yml: |
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'kotaemon'
static_configs:
- targets: ['kotaemon:7860']
metrics_path: /metrics
scrape_interval: 30s
- job_name: 'chromadb'
static_configs:
- targets: ['kotaemon-chromadb:8000']
metrics_path: /metrics
scrape_interval: 30s
3. 로그 집계 설정
# logging/fluent-bit-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: kotaemon-fluent-bit-config
data:
fluent-bit.conf: |
[SERVICE]
Flush 1
Log_Level info
Daemon off
Parsers_File parsers.conf
[INPUT]
Name tail
Path /var/log/containers/kotaemon*.log
Parser docker
Tag kotaemon.*
Refresh_Interval 5
[FILTER]
Name kubernetes
Match kotaemon.*
Kube_URL https://kubernetes.default.svc:443
Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token
[OUTPUT]
Name es
Match kotaemon.*
Host elasticsearch.logging.svc.cluster.local
Port 9200
Index kotaemon-logs
4. 백업 및 복구 스크립트
#!/bin/bash
# backup-kotaemon.sh
set -e
NAMESPACE="kotaemon"
BACKUP_DIR="/backup/kotaemon/$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"
echo "🔄 Starting Kotaemon backup..."
# 1. 데이터베이스 백업
echo "📊 Backing up PostgreSQL..."
kubectl exec -n $NAMESPACE deployment/kotaemon-postgresql -- \
pg_dump -U postgres kotaemon > "$BACKUP_DIR/postgres_backup.sql"
# 2. 벡터 데이터베이스 백업
echo "🔍 Backing up ChromaDB..."
kubectl exec -n $NAMESPACE deployment/kotaemon-chromadb -- \
tar -czf - /chroma/chroma > "$BACKUP_DIR/chromadb_backup.tar.gz"
# 3. 애플리케이션 데이터 백업
echo "📁 Backing up application data..."
kubectl exec -n $NAMESPACE deployment/kotaemon -- \
tar -czf - /app/ktem_app_data > "$BACKUP_DIR/app_data_backup.tar.gz"
# 4. Kubernetes 리소스 백업
echo "⚙️ Backing up Kubernetes resources..."
kubectl get all,pvc,secrets,configmaps -n $NAMESPACE -o yaml > "$BACKUP_DIR/k8s_resources.yaml"
# 5. Helm values 백업
echo "📋 Backing up Helm values..."
helm get values kotaemon -n $NAMESPACE > "$BACKUP_DIR/helm_values.yaml"
echo "✅ Backup completed: $BACKUP_DIR"
5. 성능 최적화 설정
# performance/hpa-custom.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: kotaemon-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: kotaemon
minReplicas: 3
maxReplicas: 50
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
- type: Pods
pods:
metric:
name: requests_per_second
target:
type: AverageValue
averageValue: "100"
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 10
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 60
policies:
- type: Percent
value: 50
periodSeconds: 60
- type: Pods
value: 5
periodSeconds: 60
selectPolicy: Max
고급 설정
1. GraphRAG 활성화
# GraphRAG 의존성 설치
kubectl exec -it deployment/kotaemon -n kotaemon -- \
pip install nano-graphrag
# 환경 변수 업데이트
kubectl patch deployment kotaemon -n kotaemon -p='
{
"spec": {
"template": {
"spec": {
"containers": [
{
"name": "kotaemon",
"env": [
{
"name": "USE_NANO_GRAPHRAG",
"value": "true"
}
]
}
]
}
}
}
}'
2. 멀티모달 문서 파싱 설정
# values-multimodal.yaml
kotaemon:
env:
# Azure Document Intelligence
AZURE_DOC_INTELLIGENCE_ENDPOINT: "https://your-endpoint.cognitiveservices.azure.com/"
AZURE_DOC_INTELLIGENCE_KEY:
valueFrom:
secretKeyRef:
name: kotaemon-secrets
key: azure-doc-intelligence-key
# Docling (로컬 처리)
USE_DOCLING: "true"
# Docling 의존성 설치를 위한 initContainer
initContainers:
- name: install-docling
image: python:3.10
command: ['pip', 'install', 'docling']
volumeMounts:
- name: pip-cache
mountPath: /root/.cache/pip
3. 보안 강화 설정
# security/network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: kotaemon-network-policy
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: kotaemon
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
ports:
- protocol: TCP
port: 7860
- from:
- podSelector:
matchLabels:
app.kubernetes.io/name: kotaemon
ports:
- protocol: TCP
port: 7860
egress:
- to:
- podSelector:
matchLabels:
app.kubernetes.io/component: chromadb
ports:
- protocol: TCP
port: 8000
- to:
- podSelector:
matchLabels:
app.kubernetes.io/name: postgresql
ports:
- protocol: TCP
port: 5432
- to: []
ports:
- protocol: TCP
port: 443 # HTTPS for external APIs
- protocol: TCP
port: 53 # DNS
- protocol: UDP
port: 53 # DNS
트러블슈팅
1. 일반적인 문제 해결
# Pod가 시작되지 않는 경우
kubectl describe pod -l app.kubernetes.io/name=kotaemon -n kotaemon
# 메모리 부족 문제
kubectl top pods -n kotaemon
# 스토리지 문제 확인
kubectl get pvc -n kotaemon
kubectl describe pvc kotaemon-data -n kotaemon
# 네트워크 연결 문제
kubectl exec -it deployment/kotaemon -n kotaemon -- \
curl -v http://kotaemon-chromadb:8000/api/v1/heartbeat
2. 성능 문제 진단
# 애플리케이션 로그 분석
kubectl logs -f deployment/kotaemon -n kotaemon | grep -E "(ERROR|WARN|slow)"
# 리소스 사용량 모니터링
kubectl top pods -n kotaemon --containers
# HPA 상태 확인
kubectl get hpa -n kotaemon
kubectl describe hpa kotaemon-hpa -n kotaemon
3. 데이터베이스 연결 문제
# PostgreSQL 연결 테스트
kubectl exec -it deployment/kotaemon-postgresql -n kotaemon -- \
psql -U postgres -d kotaemon -c "SELECT version();"
# ChromaDB 연결 테스트
kubectl exec -it deployment/kotaemon-chromadb -n kotaemon -- \
curl http://localhost:8000/api/v1/heartbeat
업그레이드 및 롤백
1. 애플리케이션 업그레이드
# 새 버전으로 업그레이드
helm upgrade kotaemon . \
--namespace kotaemon \
--values custom-values.yaml \
--set image.tag=main-full-v2
# 업그레이드 상태 확인
helm status kotaemon -n kotaemon
# 롤링 업데이트 상태 확인
kubectl rollout status deployment/kotaemon -n kotaemon
2. 롤백 수행
# 이전 버전으로 롤백
helm rollback kotaemon 1 -n kotaemon
# 또는 Kubernetes 롤백
kubectl rollout undo deployment/kotaemon -n kotaemon
# 롤백 상태 확인
kubectl rollout status deployment/kotaemon -n kotaemon
정리 및 제거
# Helm 릴리스 제거
helm uninstall kotaemon -n kotaemon
# PVC 수동 삭제 (데이터 보존 필요시 백업 후)
kubectl delete pvc --all -n kotaemon
# 네임스페이스 제거
kubectl delete namespace kotaemon
# 로컬 Helm Chart 정리
rm -rf kotaemon-helm
결론
이 가이드를 통해 Kotaemon RAG 애플리케이션을 Kubernetes 환경에 성공적으로 배포하고 운영할 수 있습니다.
주요 성과
- 완전한 컨테이너화: Docker 기반 배포로 환경 일관성 보장
- 자동 확장: HPA를 통한 트래픽 기반 자동 스케일링
- 고가용성: 다중 복제본과 로드 밸런싱
- 데이터 지속성: PVC를 통한 데이터 보존
- 모니터링 및 로깅: 운영 가시성 확보
- 보안: NetworkPolicy와 RBAC을 통한 보안 강화
Kotaemon의 강력한 RAG 기능과 Kubernetes의 확장성을 결합하여 프로덕션 레벨의 문서 QA 시스템을 구축할 수 있습니다.