Cấu hình Horizontal Pod Autoscaler (HPA) dựa trên GPU Usage
Để hệ thống tự động mở rộng số lượng pod vLLM khi tải GPU tăng cao, chúng ta cần triển khai Metrics Server và cấu hình HPA sử dụng metric GPU custom.
Trước tiên, đảm bảo Metrics Server đã chạy trên cluster Kubernetes của bạn. Nếu chưa có, hãy deploy nó bằng command sau:
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
Kết quả mong đợi: Pod metrics-server hiện trong namespace kube-system và kubectl top nodes trả về dữ liệu.
Tiếp theo, vì HPA mặc định chỉ hỗ trợ CPU/RAM, chúng ta cần thêm adapter để đọc metric GPU từ device plugin (NVIDIA GPU Operator hoặc DaemonSet). Ở đây, giả định bạn đã cài NVIDIA Device Plugin.
Tạo file cấu hình HPA tại đường dẫn /etc/k8s/autoscaling/vllm-hpa.yaml với nội dung hoàn chỉnh:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: vllm-hpa
namespace: llm-platform
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: vllm-deployment
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: nvidia.com/gpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 80
File này cấu hình HPA mở rộng tối đa 10 pod khi GPU sử dụng trên 70% hoặc CPU trên 80%. Tham số averageUtilization là ngưỡng kích hoạt scaling.
Áp dụng cấu hình vào cluster:
kubectl apply -f /etc/k8s/autoscaling/vllm-hpa.yaml
Kết quả mong đợi: HPA được tạo thành công và hiển thị trạng thái "Conditions: ScalingActive".
Để verify kết quả, chạy lệnh sau để kiểm tra trạng thái HPA:
kubectl get hpa vllm-hpa -n llm-platform -w
Khi bạn tạo load test (ví dụ dùng locust hoặc curl) gửi nhiều request, bạn sẽ thấy REPLICAS tăng lên và MEMORY/CPU hoặc GPU percentage vượt ngưỡng 70%.
Tối ưu hóa Pipeline RAG: Caching và Giảm độ trễ
Pipeline RAG thường gặp độ trễ cao do quá trình embedding và tìm kiếm vector lặp lại cho các câu hỏi tương tự. Chúng ta sẽ tích hợp Redis làm layer caching cho kết quả vector search.
Đầu tiên, triển khai Redis trên Kubernetes để lưu cache. Tạo file /etc/k8s/cache/redis-deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-cache
namespace: llm-platform
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7-alpine
ports:
- containerPort: 6379
resources:
limits:
memory: 2Gi
cpu: 1000m
Deploy Redis:
kubectl apply -f /etc/k8s/cache/redis-deployment.yaml
Kết quả mong đợi: Pod redis-cache chạy ổn định và expose port 6379.
Trong code Backend RAG (Python), chúng ta cần thêm logic kiểm tra cache trước khi gọi VectorDB. Giả sử file code backend nằm tại /app/rag_service/service.py, hãy cập nhật hàm retrieve_context như sau:
import redis
import json
import hashlib
from datetime import datetime
# Kết nối Redis
REDIS_HOST = "redis-cache.llm-platform.svc.cluster.local"
REDIS_CLIENT = redis.Redis(host=REDIS_HOST, port=6379, db=0)
CACHE_TTL = 3600 # Cache sống 1 giờ
def get_cache_key(query: str) -> str:
"""Tạo key hash cho query để lưu cache"""
return hashlib.md5(query.encode()).hexdigest()
async def retrieve_context(query: str, vector_db_client) -> list:
cache_key = get_cache_key(query)
# Bước 1: Kiểm tra cache Redis
cached_result = REDIS_CLIENT.get(cache_key)
if cached_result:
print(f"Cache hit for query: {query}")
return json.loads(cached_result.decode())
# Bước 2: Nếu không có cache, gọi VectorDB (Milvus/Chroma)
print(f"Cache miss, querying VectorDB for: {query}")
results = await vector_db_client.search(query, top_k=5)
# Bước 3: Lưu kết quả vào Redis
redis_data = json.dumps(results)
REDIS_CLIENT.setex(cache_key, CACHE_TTL, redis_data)
return results
Logic này giảm tải cho VectorDB và giảm latency xuống mức gần như không đáng kể cho các câu hỏi lặp lại.
Để verify hiệu quả caching, thực hiện 2 lần query cùng một câu hỏi và đo thời gian:
time curl -X POST http://rag-backend:8000/query -d '{"question": "Cách tối ưu vLLM trên GPU A100?"}'
Kết quả mong đợi: Lần chạy đầu tiên mất khoảng 500-800ms (bao gồm VectorDB), lần chạy thứ hai (cache hit) chỉ mất 10-20ms.
Để kiểm tra cache trong Redis:
kubectl exec -it redis-cache-xxxxx -n llm-platform -- redis-cli keys "*"
Bạn sẽ thấy các key hash tương ứng với các câu hỏi đã query.
Tinh chỉnh tham số vLLM để tăng Throughput
vLLM có nhiều tham số quan trọng ảnh hưởng trực tiếp đến throughput (số token/giây) và latency. Chúng ta sẽ tinh chỉnh max-num-batched-tokens, max-num-seqs và enforce-eager.
Trước hết, xác định tài nguyên GPU hiện có. Nếu dùng GPU A100 80GB, chúng ta có thể tăng kích thước batch lên đáng kể. Cập nhật file Deployment vLLM tại /etc/k8s/deployment/vllm-deployment.yaml.
Sửa phần command hoặc args của container vLLM như sau:
apiVersion: apps/v1
kind: Deployment
metadata:
name: vllm-deployment
namespace: llm-platform
spec:
replicas: 1
selector:
matchLabels:
app: vllm
template:
metadata:
labels:
app: vllm
spec:
containers:
- name: vllm
image: vllm/vllm-openai:latest
args:
- --model=/data/models/Llama-3-70B-Instruct
- --tensor-parallel-size=8
- --max-num-batched-tokens=32768
- --max-num-seqs=256
- --max-model-len=8192
- --enforce-eager
- --gpu-memory-utilization=0.95
- --served-model-name=llama-3-70b
- --api-key=sk-vllm-secure-key-12345
resources:
limits:
nvidia.com/gpu: 8
ports:
- containerPort: 8000
volumeMounts:
- name: model-storage
mountPath: /data/models
volumes:
- name: model-storage
hostPath:
path: /mnt/nvme/models
Giải thích các tham số tối ưu:
--max-num-batched-tokens=32768: Tăng giới hạn tổng số tokens trong một batch lên 32k, giúp GPU hoạt động hết công suất khi có nhiều request ngắn.
--max-num-seqs=256: Tăng số lượng request đồng thời tối đa lên 256, cho phép xử lý nhiều người dùng cùng lúc.
--gpu-memory-utilization=0.95: Dành 95% VRAM cho model và context, tăng kích thước context window có thể phục vụ.
--enforce-eager: Bắt buộc sử dụng chế độ eager execution, giúp giảm độ trễ (latency) cho các request nhỏ, dù có thể giảm nhẹ throughput cho request rất lớn.
Áp dụng lại cấu hình:
kubectl apply -f /etc/k8s/deployment/vllm-deployment.yaml
Kết quả mong đợi: Pod vLLM sẽ restart và khởi động lại với các tham số mới. Kiểm tra log để đảm bảo không có lỗi OOM (Out Of Memory).
kubectl logs -f deployment/vllm-deployment -n llm-platform | grep "Starting engine"
Để verify throughput tăng lên, chạy test load với nhiều request đồng thời (concurrency) và so sánh tổng tokens/giây:
locust --host=http://vllm-service.llm-platform.svc.cluster.local:8000 --users=50 --spawn-rate=5 --run-time=60s --headless -f locustfile.py
Tại đây, locustfile.py là file script chứa logic gửi request sinh văn bản. Sau khi chạy xong, kiểm tra số liệu Requests/s và Total Tokens trong report của Locust.
So sánh kết quả với cấu hình mặc định, bạn sẽ thấy throughput tăng rõ rệt, đặc biệt trong trường hợp nhiều user truy cập cùng lúc.
Điều hướng series:
Mục lục: Series: Xây dựng nền tảng Private LLM với vLLM, RAG và VectorDB trên hạ tầng Kubernetes
« Phần 7: Tích hợp Frontend và API Gateway cho trải nghiệm người dùng
Phần 9: Bảo mật, giám sát và xử lý sự cố (Troubleshooting) cho hệ thống »