Cấu hình cân bằng tải dựa trên tải GPU với Metrics Server
Bước đầu tiên để tự động mở rộng (scale) các Pod AI là đảm bảo Kubernetes có thể đọc được chỉ số sử dụng GPU từ driver NVIDIA.
Trên Jetson, K3s mặc định không có Metrics Server hỗ trợ GPU. Bạn cần cài đặt NVIDIA GPU Operator hoặc cấu hình Metrics Server thủ công để thu thập dữ liệu từ `dcgm-exporter`.
Chúng ta sẽ cài đặt Metrics Server và cấu hình để nó đọc dữ liệu từ DCGM (Data Center GPU Manager) có sẵn trên Jetson.
Thực thi lệnh sau để thêm repository và cài đặt Metrics Server tương thích với K3s:
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
Đợi khoảng 30 giây để Pod `metrics-server` trong namespace `kube-system` chuyển sang trạng thái `Running`.
Verify kết quả bằng lệnh:
kubectl get pods -n kube-system | grep metrics-server
Kết quả mong đợi: Trạng thái `STATUS` là `Running`.
Cấu hình Custom Metrics Adapter cho GPU
Metrics Server mặc định chỉ đo CPU/RAM. Để HPA dựa trên GPU, bạn cần Custom Metrics Adapter (thường là `external-metrics-adapter` hoặc `prometheus-adapter` tích hợp với DCGM).
Trong môi trường Jetson đơn giản, ta sẽ sử dụng `dcgm-exporter` để xuất metric và cấu hình `external-metrics-adapter` để HPA đọc được metric `gpu_utilization_percent`.
Tạo file cấu hình `dcgm-exporter-deployment.yaml` tại đường dẫn `/opt/jetson/k8s/dcgm-exporter.yaml` với nội dung:
apiVersion: apps/v1
kind: Deployment
metadata:
name: dcgm-exporter
namespace: monitoring
spec:
replicas: 1
selector:
matchLabels:
app: dcgm-exporter
template:
metadata:
labels:
app: dcgm-exporter
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9400"
spec:
containers:
- name: dcgm-exporter
image: nvcr.io/nvidia/dcgm-exporter:2.0.0
ports:
- containerPort: 9400
name: metrics
env:
- name: DEFAULT_METRICS_EXPORT_FREQ
value: "10s"
- name: DEFAULT_METRICS_SETS
value: "default,gpu"
resources:
limits:
nvidia.com/gpu: 1
requests:
nvidia.com/gpu: 1
nodeSelector:
nvidia.com/gpu: "true"
Chạy lệnh tạo namespace và áp dụng cấu hình:
kubectl create namespace monitoring
kubectl apply -f /opt/jetson/k8s/dcgm-exporter.yaml
Verify kết quả: Kiểm tra xem DCGM Exporter đã chạy và xuất metric chưa.
kubectl logs -n monitoring -l app=dcgm-exporter | grep "Exporting metrics"
Kết quả mong đợi: Dòng log xác nhận việc xuất metric thành công.
Cấu hình Horizontal Pod Autoscaler (HPA) dựa trên GPU
Sau khi có metric, ta tạo HPA để tự động tăng/giảm số lượng Pod inference khi tải GPU vượt ngưỡng.
Tạo file `hpa-gpu.yaml` tại `/opt/jetson/k8s/hpa-gpu.yaml` với nội dung:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: ai-inference-hpa
namespace: default
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: ai-inference-deployment
minReplicas: 1
maxReplicas: 4
metrics:
- type: External
external:
metric:
name: gpu_utilization_percent
target:
type: AverageValue
averageValue: "70"
Áp dụng cấu hình HPA:
kubectl apply -f /opt/jetson/k8s/hpa-gpu.yaml
Verify kết quả: Kiểm tra trạng thái HPA và giá trị metric hiện tại.
kubectl get hpa ai-inference-hpa -o wide
Kết quả mong đợi: Cột `CURRENT METRICS` hiển thị giá trị phần trăm GPU thực tế (ví dụ: `0%/70%` nếu chưa có load).
Tối ưu hóa mạng nội bộ giữa Jetson và Cloud
Trong môi trường Edge, băng thông và độ trễ là yếu tố sống còn. Ta cần tối ưu đường truyền giữa Jetson (Edge) và Server trung tâm (Cloud/On-prem).
Chúng ta sẽ cấu hình QoS (Quality of Service) cho traffic AI và sử dụng `iptables` để ưu tiên gói tin inference.
Trên node Jetson, tạo script cấu hình mạng `/opt/jetson/scripts/edge-network-optim.sh` với nội dung:
#!/bin/bash
# Cấu hình TC (Traffic Control) để ưu tiên traffic trên port 8080 (Inference API)
INTERFACE="eth0" # Thay đổi nếu Jetson dùng interface khác
PORT=8080
# Xóa cấu hình cũ
tc qdisc del dev $INTERFACE root 2>/dev/null
# Tạo qdisc HTB (Hierarchical Token Bucket)
tc qdisc add dev $INTERFACE root handle 1 htb default 30
# Tạo lớp ưu tiên cao (Class 10) cho traffic AI
tc class add dev $INTERFACE parent 1: classid 1:10 htb rate 100mbit ceil 100mbit prio 1
# Tạo lớp mặc định (Class 30) cho traffic thường
tc class add dev $INTERFACE parent 1: classid 1:30 htb rate 50mbit ceil 100mbit prio 2
# Filter: Ưu tiên traffic TCP đến cổng 8080 vào class 1:10
tc filter add dev $INTERFACE protocol ip parent 1:0 prio 1 u32 match ip dport $PORT 0xffff flowid 1:10
# Filter: Ưu tiên traffic TCP từ cổng 8080 (response) vào class 1:10
tc filter add dev $INTERFACE protocol ip parent 1:0 prio 1 u32 match ip sport $PORT 0xffff flowid 1:10
echo "Network QoS configured for port $PORT on $INTERFACE"
Chạy script với quyền root:
chmod +x /opt/jetson/scripts/edge-network-optim.sh
/opt/jetson/scripts/edge-network-optim.sh
Verify kết quả: Kiểm tra cấu hình TC đang chạy.
tc qdisc show dev eth0
Kết quả mong đợi: Hiển thị cấu hình HTB với các class 1:10 và 1:30.
Cấu hình Network Policy để hạn chế traffic không cần thiết
Để giảm tải cho CPU Jetson, ta chặn traffic không liên quan đến AI tại tầng Kubernetes.
Tạo file `network-policy-edge.yaml` tại `/opt/jetson/k8s/network-policy-edge.yaml`:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ai-traffic-only
namespace: default
spec:
podSelector:
matchLabels:
app: ai-inference
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: monitoring
- podSelector:
matchLabels:
app: loadbalancer
ports:
- protocol: TCP
port: 8080
egress:
- to:
- ipBlock:
cidr: 192.168.1.0/24 # Mạng nội bộ Proxmox/Cloud
ports:
- protocol: TCP
port: 443
- protocol: TCP
port: 6379 # Redis cache nếu cần
Áp dụng chính sách:
kubectl apply -f /opt/jetson/k8s/network-policy-edge.yaml
Verify kết quả: Kiểm tra Pod có thể truy cập cổng 8080 từ namespace monitoring nhưng bị chặn từ bên ngoài.
kubectl run test-pod --rm -it --image=busybox --restart=Never -- wget -qO- http://ai-inference-deployment:8080
Kết quả mong đợi: Kết nối thành công nếu chạy từ namespace được phép, timeout nếu chạy từ namespace lạ.
Sử dụng Local Persistent Volume cho dữ liệu cache
Dữ liệu cache mô hình AI (model weights, embeddings) cần tốc độ đọc ghi cực cao. Sử dụng `hostPath` hoặc `Local PV` giúp giảm độ trễ so với mạng.
Trên Jetson, ta sẽ tạo một Local PV trỏ vào thư mục `nvme` hoặc `ssd` tốc độ cao (nếu có) hoặc `rootfs` tối ưu.
Tạo file `local-pv-cache.yaml` tại `/opt/jetson/k8s/local-pv-cache.yaml`:
apiVersion: v1
kind: PersistentVolume
metadata:
name: local-pv-cache-jetson
labels:
type: local
app: ai-cache
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: local-storage
local:
path: /mnt/data/ai-cache
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- jetson-edge-node-01
Tạo thư mục vật lý trên Jetson (chạy trên host, không qua kubectl):
mkdir -p /mnt/data/ai-cache
chown -R 1000:1000 /mnt/data/ai-cache # UID/GID của user chạy container
Áp dụng Local PV:
kubectl apply -f /opt/jetson/k8s/local-pv-cache.yaml
Tiếp theo, cập nhật Deployment AI để mount volume này. Tạo file `deployment-ai-cache.yaml` tại `/opt/jetson/k8s/deployment-ai-cache.yaml`:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ai-inference-deployment
spec:
replicas: 1
selector:
matchLabels:
app: ai-inference
template:
metadata:
labels:
app: ai-inference
spec:
containers:
- name: ai-inference
image: nvcr.io/nvidia/l4t-ai-inference:latest
volumeMounts:
- name: cache-storage
mountPath: /app/cache
volumes:
- name: cache-storage
persistentVolumeClaim:
claimName: local-pvc-cache
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: nvidia.com/gpu
operator: In
values:
- "true"
Tạo PVC để bind với Local PV:
cat
Verify kết quả: Kiểm tra trạng thái PVC và Pod đã bind volume chưa.
kubectl get pvc local-pvc-cache
kubectl get pod -l app=ai-inference -o jsonpath='{.spec.volumes[*].name}'
Kết quả mong đợi: PVC có trạng thái `Bound`, Pod hiển thị volume `cache-storage`.
Cấu hình Node Affinity để phân phối workload đúng thiết bị
Trong cụm Edge có nhiều Jetson với cấu hình khác nhau (Nano, Xavier, Orin), ta cần đảm bảo Pod AI chỉ chạy trên node có GPU mạnh.
Sử dụng `Node Affinity` với label `nvidia.com/gpu` hoặc label custom về model Jetson.
Đầu tiên, gán label cho node Jetson có GPU (nếu chưa có sẵn):
kubectl label nodes jetson-edge-node-01 nvidia.com/gpu=true model=jetson-orin
Cập nhật Deployment (đã có sẵn trong file `deployment-ai-cache.yaml` ở mục trên, nhưng ta tách riêng để làm rõ logic):
Tạo file `node-affinity-config.yaml` tại `/opt/jetson/k8s/node-affinity-config.yaml`:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ai-inference-deployment
spec:
template:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: nvidia.com/gpu
operator: In
values:
- "true"
- key: model
operator: In
values:
- "jetson-orin" # Chỉ chạy trên Orin, không chạy trên Nano
tolerations:
- key: nvidia.com/gpu
operator: Exists
Áp dụng cấu hình affinity:
kubectl apply -f /opt/jetson/k8s/node-affinity-config.yaml
Verify kết quả: Kiểm tra Pod đang chạy trên node nào.
kubectl get pod -l app=ai-inference -o wide
Kết quả mong đợi: Cột `NODE` hiển thị `jetson-edge-node-01` (hoặc node có label tương ứng). Nếu node không có GPU, Pod sẽ ở trạng thái `Pending`.
Test cân bằng tải và Affinity
Tạo tải giả lập để kích hoạt HPA và kiểm tra Affinity.
Sử dụng `hey` hoặc `ab` để tạo request vào endpoint inference:
hey -z 1m -c 50 http://:8080/infer
Quan sát số lượng Pod và CPU/GPU usage:
kubectl get hpa ai-inference-hpa -w
Kết quả mong đợi: Khi load tăng, số lượng Pod tăng lên (tối đa 4), và tất cả Pod đều được schedule vào node có GPU.
Điều hướng series:
Mục lục: Series: Series: Xây dựng nền tảng Edge AI với NVIDIA Jetson, Kubernetes K3s và hệ thống quản lý thiết bị biên trên hạ tầng Proxmox
« Phần 6: Triển khai mô hình AI và container GPU trên Jetson
Phần 8: Giám sát, Logging và bảo mật cho hệ thống Edge »