1. Xử lý lỗi thường gặp khi sync dữ liệu giữa DVC và Git
1.1. Khắc phục lỗi "Git index dirty" khi commit dữ liệu lớn
Nếu bạn gặp lỗi Git index dirty khi chạy dvc push hoặc git commit, nguyên nhân là Git đang cố theo dõi các file dữ liệu thực tế thay vì file manifest .dvc.
Để sửa, ta cần xóa file dữ liệu khỏi Git index nhưng giữ nguyên trên disk, sau đó thêm lại vào .gitignore.
git rm --cached data/raw/dataset_v1.parquet
git commit -m "Remove raw data from Git index"
echo "data/raw/dataset_v1.parquet" >> .gitignore
git commit -m "Add data file to gitignore"
Kết quả mong đợi: Lỗi "dirty index" biến mất, Git chỉ theo dõi file dataset_v1.parquet.dvc.
1.2. Xử lý lỗi kết nối S3/Remote Storage trong DVC
Lỗi Connection error hoặc Permission denied thường xảy ra khi biến môi trường (Environment Variables) không được truyền đúng vào container hoặc máy chủ.
Kiểm tra cấu hình remote trong file .dvc/config và đảm bảo AWS credentials đã được export.
Đường dẫn file: /.dvc/config (hoặc ./.dvc/config trong repo).
[core]
remote = s3-remote
[remote "s3-remote"]
url = s3://my-bucket-name/data-ops-ml
config = aws_access_key_id=AKIAIOSFODNN7EXAMPLE
config = aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
config = region=us-east-1
Để verify, chạy lệnh test kết nối:
export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
dvc remote show default
Kết quả mong đợi: In ra thông tin remote đã cấu hình mà không có lỗi connection.
1.3. Xử lý lỗi hash không khớp (Hash mismatch)
Khi dvc pull báo lỗi hash mismatch, có nghĩa là file trên remote đã bị thay đổi so với hash trong file .dvc.
Để reset và đồng bộ lại, ta cần xóa file local (nếu cần) và pull lại từ remote.
dvc checkout --force
dvc pull
Kết quả mong đợi: File dữ liệu được tải lại từ remote, hash trong file .dvc khớp với file thực tế.
2. Khắc phục sự cố kết nối giữa MLflow client và server
2.1. Xử lý lỗi Connection Refused khi truy cập MLflow
Lỗi Connection refused thường xảy ra khi Client không thể tìm thấy Service của MLflow trong Kubernetes hoặc Port không được expose.
Trước tiên, kiểm tra trạng thái Pod và Service của MLflow.
kubectl get pods -n mlflow
kubectl get svc -n mlflow
Kết quả mong đợi: Pod ở trạng thái Running và Service có EXTERNAL-IP (nếu là LoadBalancer) hoặc ClusterIP.
2.2. Cấu hình biến môi trường MLFLOW_TRACKING_URI trong Docker
Nếu code Python bị lỗi MLflowException: Unable to connect to tracking server, nguyên nhân là biến MLFLOW_TRACKING_URI chưa được set đúng.
Trong file Dockerfile hoặc docker-compose.yml, ta cần set biến này trỏ vào Service URL.
Đường dẫn file: ./Dockerfile (cho training container).
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
ENV MLFLOW_TRACKING_URI=http://mlflow-tracking-service:5000
CMD ["python", "train.py"]
Kết quả mong đợi: Script train.py chạy trong container có thể gọi mlflow.set_tracking_uri() thành công mà không cần hardcode URL.
2.3. Debug lỗi CORS hoặc Authentication trong MLflow
Nếu truy cập qua browser bị chặn (CORS) hoặc 401 Unauthorized, cần kiểm tra config của mlflow server.
Tạo file config mlflow_config.yaml để enable CORS và disable auth (nếu đang dev) hoặc cấu hình auth đúng.
Đường dẫn file: ./mlflow_config.yaml.
tracking:
uri: dbfs://default/mlflow-tracking
artifact_location: dbfs://default/mlflow-artifacts
server:
host: 0.0.0.0
port: 5000
cors_allow_origins: "*"
cors_allow_credentials: true
Chạy server với config file:
mlflow server --backend-store-uri postgresql://user:pass@host:5432/mlflow --default-artifact-root s3://my-bucket/mlflow-artifacts --config-file mlflow_config.yaml
Kết quả mong đợi: Browser truy cập vào MLflow UI thành công, không bị lỗi CORS.
3. Tối ưu tốc độ build image Docker cho training/inference
3.1. Sử dụng Multi-stage builds để giảm kích thước image
Image training thường rất nặng do chứa thư viện phát triển (dev dependencies). Để deploy inference nhẹ, ta dùng Multi-stage builds.
Giai đoạn 1: Install dependencies và build code. Giai đoạn 2: Copy chỉ file cần thiết vào image runtime nhẹ (như python:3.9-slim).
Đường dẫn file: ./Dockerfile.
FROM python:3.9-slim as builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --user -r requirements.txt
COPY . .
RUN python -m compileall .
FROM python:3.9-slim as runtime
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY --from=builder /app .
ENV PATH=/root/.local/bin:$PATH
CMD ["python", "inference.py"]
Kết quả mong đợi: Image runtime chỉ ~150MB thay vì ~2GB, tốc độ pull và start pod nhanh hơn đáng kể.
3.2. Tối ưu Cache Layer trong Docker
Để tăng tốc build khi code chưa đổi, hãy đặt lệnh COPY requirements.txt và pip install trước lệnh COPY . ..
Điều này giúp Docker cache lại layer dependencies, chỉ rebuild layer code khi file code thay đổi.
FROM python:3.9-slim
WORKDIR /app
# Copy requirements trước để tận dụng cache
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy source code sau
COPY . .
CMD ["python", "train.py"]
Kết quả mong đợi: Chạy docker build lần thứ 2 (chỉ sửa code logic) sẽ gần như tức thì (vài giây) thay vì vài phút.
3.3. Sử dụng BuildKit để tăng tốc build
Trên Kubernetes hoặc CI/CD, kích hoạt BuildKit giúp parallel build và cache tốt hơn.
Set biến môi trường DOCKER_BUILDKIT=1 trước khi chạy lệnh build.
export DOCKER_BUILDKIT=1
docker build -t my-ml-model:v1 .
Kết quả mong đợi: Log build hiển thị tiến trình song song (parallel), tổng thời gian build giảm 20-30%.
4. Các best practices để bảo trì hệ thống DataOps lâu dài
4.1. Chiến lược làm sạch artifact và model cũ
Storage S3 hoặc Disk sẽ đầy nhanh chóng nếu không xóa các model/data cũ. Cần thiết lập quy trình tự động.
Sử dụng script Python để xóa artifact của các run đã quá 30 ngày hoặc model chưa được staging/production.
Đường dẫn file: ./scripts/cleanup_mlflow_artifacts.py.
import mlflow
from datetime import datetime, timedelta
import os
mlflow.set_tracking_uri("http://mlflow-tracking-service:5000")
client = mlflow.tracking.MlflowClient()
# Lấy tất cả runs
runs = client.search_runs(experiment_ids=["0"])
cutoff_date = datetime.now() - timedelta(days=30)
for run in runs:
run_time = datetime.fromtimestamp(run.info.start_time / 1000)
if run_time < cutoff_date and run.info.status != "FINISHED":
# Xóa artifact nếu run quá cũ và không thành công
try:
client.delete_run(run.info.run_id)
print(f"Deleted old run: {run.info.run_id}")
except Exception as e:
print(f"Error deleting run {run.info.run_id}: {e}")
Chạy script này qua CronJob trong Kubernetes mỗi đêm.
Kết quả mong đợi: Dung lượng storage được giải phóng, chỉ giữ lại các model/run mới và quan trọng.
4.2. Monitoring tài nguyên và cảnh báo sớm
Đừng đợi hệ thống sập mới kiểm tra. Cần set alert cho CPU/RAM của Pod training và Pod inference.
Cấu hình ResourceQuota và LimitRange trong Kubernetes để tránh một job ăn hết tài nguyên cluster.
Đường dẫn file: ./k8s/resource-quota.yaml.
apiVersion: v1
kind: ResourceQuota
metadata:
name: ml-training-quota
namespace: mlflow
spec:
hard:
requests.cpu: "20"
requests.memory: "64Gi"
limits.cpu: "40"
limits.memory: "128Gi"
persistentvolumeclaims: "10"
Kết quả mong đợi: Kubernetes từ chối deploy các Pod vượt quá giới hạn, bảo vệ tính ổn định của cluster.
4.3. Versioning cho Config và Pipeline
Không chỉ version data và model, cần version cả config (hyperparameters, pipeline steps).
Đưa file config (yaml/json) vào Git và tham chiếu trong DVC/MLflow. Sử dụng mlflow.log_params để ghi lại tham số vào run.
import yaml
import mlflow
with open('config.yaml', 'r') as f:
config = yaml.safe_load(f)
mlflow.log_params(config['training'])
mlflow.log_artifact('config.yaml')
Kết quả mong đợi: Khi xem MLflow UI, bạn có thể thấy rõ phiên bản config nào tạo ra model đó, dễ dàng reproduce kết quả.
4.4. Backup và Disaster Recovery
Luôn có bản backup cho Database metadata (Postgres/MySQL) của MLflow và bucket artifact.
Sử dụng pg_dump cho database và aws s3 sync với lifecycle policy cho backup S3.
pg_dump -h db-host -U mlflow_user mlflow_db > /backup/mlflow_metadata_$(date +%F).sql
aws s3 sync /backup s3://my-bucket-backup/mlflow-metadata --delete
Kết quả mong đợi: Có thể khôi phục toàn bộ hệ thống MLflow từ backup nếu server bị mất hoặc lỗi database.
Điều hướng series:
Mục lục: Series: Xây dựng nền tảng DataOps với DVC, MLflow và Kubernetes cho vòng đời AI
« Phần 9: Chiến lược mở rộng (Scaling) và bảo mật nâng cao
Phần 10: Troubleshooting và các mẹo tối ưu hiệu suất »