Xây dựng Docker Image tích hợp PyTorch và TensorRT
Bước đầu tiên là đóng gói mô hình AI vào container. Chúng ta sẽ sử dụng Dockerfile dựa trên image L4T (L4T JetPack) chính chủ của NVIDIA để đảm bảo tính tương thích phần cứng, sau đó cài đặt PyTorch và TensorRT để chuyển đổi mô hình sang định dạng tối ưu cho Jetson.
Tại thư mục chứa dự án trên host Proxmox hoặc Jetson, tạo file Dockerfile với nội dung sau. Lưu ý: Thay thế jetson-image:latest bằng version L4T cụ thể đã chuẩn bị ở phần 3 (ví dụ: nvcr.io/nvidia/l4t-jetson:35.1.0).
FROM nvcr.io/nvidia/l4t-jetson:35.1.0
# Cài đặt các dependency cần thiết
RUN apt-get update && apt-get install -y \
python3-pip \
python3-venv \
&& rm -rf /var/lib/apt/lists/*
# Tạo môi trường ảo Python để tránh xung đột với hệ thống
RUN python3 -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
# Cài đặt PyTorch và TensorRT cho Jetson
# Lưu ý: Sử dụng wheel file hoặc pip install từ repo NVIDIA cho Jetson
RUN pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/jetson \
&& pip install tensorrt
# Copy mã nguồn và mô hình vào container
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY model.pt .
COPY inference.py .
# Chạy script inference
CMD ["python3", "inference.py"]
Kết quả mong đợi: File Dockerfile được tạo thành công, sẵn sàng để build. Image này sẽ chứa đầy đủ runtime PyTorch và thư viện TensorRT cần thiết để chạy inference trên GPU Jetson.
Build image Docker với tag rõ ràng để quản lý version. Thực hiện lệnh này trên Jetson hoặc host Proxmox nếu đã cấu hình Docker daemon remote.
docker build -t jetson-ai-inference:v1.0 .
Kết quả mong đợi: Docker hoàn tất quá trình build và hiển thị dòng Successfully tagged jetson-ai-inference:v1.0. Kiểm tra bằng lệnh docker images để xác nhận image tồn tại.
Cấu hình GPU Resource Quota trong Kubernetes
Để Kubernetes (K3s) nhận diện và phân bổ GPU của Jetson cho các container, cần đảm bảo driver NVIDIA Container Runtime đã được kích hoạt. Nếu chưa cấu hình ở Phần 4, cần thêm file config cho containerd để K3s có thể map GPU vào pod.
Tạo file cấu hình /etc/containerd/config.toml (hoặc thêm vào file có sẵn) để enable GPU support. Dấu hiệu nhận biết là phần [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc] phải có tham số runtime_type và privileged_without_host_devices được cấu hình đúng để NVIDIA Container Toolkit hoạt động.
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
runtime_type = "io.containerd.runc.v2"
privileged_without_host_devices = false
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia]
runtime_type = "io.containerd.nvidia.v2"
privileged_without_host_devices = false
binary_name = "nvidia-container-runtime"
[plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime]
runtime_type = "io.containerd.nvidia.v2"
Kết quả mong đợi: Containerd đã được cấu hình để nhận diện runtime NVIDIA. Cần restart containerd để áp dụng: systemctl restart containerd.
Sau đó, khởi động lại K3s để nó nhận diện GPU device. Lệnh này sẽ đảm bảo K3s agent trên Jetson đăng ký node với label nvidia.com/gpu.
systemctl restart k3s
Kiểm tra xem node Jetson có hiển thị tài nguyên GPU hay không bằng lệnh kubectl describe node <jetson-node-name>. Trong phần Allocated resources, bạn cần thấy dòng nvidia.com/gpu với giá trị > 0.
kubectl get nodes --show-labels
Kết quả mong đợi: Node Jetson có label feature.nvidia.com/gpu=true hoặc tương tự. Nếu không thấy, kiểm tra lại driver NVIDIA và NVIDIA Container Toolkit trên host Jetson.
Tạo Deployment và Service cho ứng dụng Edge AI
Bây giờ chúng ta sẽ viết manifest Kubernetes để deploy container AI. File YAML này sẽ chỉ định số lượng GPU cần dùng (limits) và yêu cầu node có GPU (tolerations/affinity).
Tạo file /root/edge-ai-deployment.yaml với nội dung hoàn chỉnh sau. Lưu ý phần resources.limits.nvidia.com/gpu là điểm mấu chốt để container truy cập vào GPU vật lý.
apiVersion: apps/v1
kind: Deployment
metadata:
name: jetson-ai-inference
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: ai-inference
template:
metadata:
labels:
app: ai-inference
spec:
tolerations:
- key: nvidia.com/gpu
operator: Exists
effect: NoSchedule
containers:
- name: inference-container
image: jetson-ai-inference:v1.0
imagePullPolicy: IfNotPresent
resources:
limits:
nvidia.com/gpu: 1
ports:
- containerPort: 8000
env:
- name: NVIDIA_VISIBLE_DEVICES
value: all
---
apiVersion: v1
kind: Service
metadata:
name: ai-inference-service
spec:
selector:
app: ai-inference
ports:
- protocol: TCP
port: 8000
targetPort: 8000
type: LoadBalancer
Kết quả mong đợi: File YAML được tạo sẵn sàng để apply. Cấu hình này yêu cầu pod chỉ chạy trên node có GPU và cấp phép 1 GPU cho container.
Áp dụng cấu hình vào cluster K3s. Lệnh này sẽ tạo Pod và Service, K3s scheduler sẽ tự động đặt Pod lên node Jetson do yêu cầu GPU.
kubectl apply -f /root/edge-ai-deployment.yaml
Kiểm tra trạng thái Pod. Trạng thái mong đợi là Running sau vài phút. Nếu thấy Pending hoặc CrashLoopBackOff, hãy kiểm tra logs bằng kubectl logs -f <pod-name>.
kubectl get pods -o wide
Kết quả mong đợi: Pod jetson-ai-inference-xxxxx đang chạy trên node Jetson (IP nội bộ của Jetson). Service ai-inference-service đã được tạo và cấp IP ClusterIP hoặc LoadBalancer.
Kiểm tra hiệu năng Inference và sử dụng GPU
Cuối cùng, cần xác minh rằng container đang thực sự sử dụng GPU để chạy mô hình chứ không phải CPU. Chúng ta sẽ dùng công cụ nvtop hoặc nvidia-smi bên trong container hoặc từ host.
Chạy lệnh nvidia-smi trên host Jetson để xem danh sách các process đang sử dụng GPU. Bạn cần thấy tên container (ví dụ: inference-container hoặc hash của container) trong cột Process Name với trạng thái Running.
nvidia-smi
Kết quả mong đợi: Bảng hiển thị GPU 0 đang được sử dụng bởi một process Docker. Cột Used-Mem tăng lên khi inference chạy, và Utilization nhảy lên cao khi có request.
Để kiểm tra trực tiếp từ bên trong container, execute shell vào pod đang chạy và chạy nvidia-smi ngay trong đó. Điều này xác nhận context GPU đã được map đúng vào container.
kubectl exec -it deployment/jetson-ai-inference -- nvidia-smi
Kết quả mong đợi: Trong terminal của pod, lệnh nvidia-smi chạy thành công và hiển thị thông tin GPU tương tự như trên host. Nếu lệnh báo lỗi "command not found", có thể driver chưa được map đúng hoặc image chưa chứa nvidia-smi (cần thêm vào Dockerfile).
Thực hiện một request giả lập để đo độ trễ (latency). Sử dụng curl để gọi endpoint inference của Service và đo thời gian phản hồi.
time curl http://ai-inference-service:8000/predict
Kết quả mong đợi: Thời gian phản hồi (real time) phải nhanh hơn đáng kể so với chạy trên CPU (ví dụ: < 50ms cho model nhỏ). Nếu thời gian quá lâu (>1s) và GPU utilization không tăng, mô hình đang chạy trên CPU do lỗi cấu hình.
Đ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 5: Tích hợp hệ thống quản lý thiết bị biên (Device Management)
Phần 7: Tối ưu hóa hiệu năng và cân bằng tải cho Edge AI »