Modul 5: Containerisering och orkestrering av ML-applikationer
Översikt
I denna modul fokuserar vi på hur containerteknologier och orkestreringsplattformar kan användas för att paketera, driftsätta och skala ML-modeller i produktionsmiljöer. Vi utforskar hur man kan bygga portabla, reproducerbara och skalbara ML-applikationer med hjälp av Docker och Kubernetes. Modulen behandlar även hur man kan hantera resursbehov, skalning och lastbalansering för prediktions-API:er och batchprocessering.
Lärandemål
Efter denna modul kommer du att:
- Förstå fördelarna med containerisering för ML-system
- Kunna bygga optimerade Docker-images för ML-modeller
- Behärska driftsättning av ML-modeller i Kubernetes
- Implementera skalningsstrategier för varierande belastning
- Hantera GPU-resurser i containeriserade miljöer
- Designa lösningar för både realtidsprediktioner och batchinferens
5.1 Introduktion till containerisering för ML
Varför containerisering för ML?
- Miljöisolering: Löser ”fungerar på min maskin”-problem
- Reproduktion: Säkerställer att modeller körs i identiska miljöer
- Portabilitet: Enkel förflyttning mellan utveckling, test och produktion
- Skalbarhet: Enkel skalning upp och ner baserat på belastning
- Versionering: Tydlig spårning av miljö och modellversioner
- Resurseffektivitet: Bättre resursutnyttjande än virtuella maskiner
Containerteknologier för ML
- Docker: De facto-standard för containerisering
- Singularity: Populärt för HPC (High-Performance Computing) och GPU-arbetslaster
- Containerd: Lättviktig container runtime
- Podman: Daemonless containerhantering
Grundläggande Docker-koncept för ML
- Images: Paketerad miljö för ML-modeller
- Containers: Körande instanser av images
- Dockerfile: Definition av en Docker-image
- Registry: Lagring och distribution av images (Docker Hub, ECR, etc.)
- Nätverk: Kommunikation mellan containers
- Volymer: Persistent datalagring
5.2 Containerisering av ML-modeller med Docker
Optimala Dockerfile-strategier för ML
- Base images: Val av lämpliga bas-images (TensorFlow, PyTorch, etc.)
- Multi-stage builds: Separera träning från inferens
- Layer-optimering: Minimera antalet lager och storleken
- Dependency management: Hantering av biblioteksberoenden
- Caching: Effektiv caching för snabbare byggen
Exempel på Dockerfile för ML-modell
# Multi-stage build för en ML-modell # Byggfas - använd officiell TensorFlow-image med GPU-stöd FROM tensorflow/tensorflow:2.9.0-gpu AS builder # Installera byggberoenden RUN apt-get update && apt-get install -y --no-install-recommends \ git \ && rm -rf /var/lib/apt/lists/* # Sätt arbetskatalog WORKDIR /build # Kopiera requirements först för bättre caching COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # Kopiera källkod COPY src/ ./src/ COPY models/ ./models/ COPY config.yaml . # Pakagera modellen för optimerad inferens RUN python src/optimize_model.py --model models/model.h5 --output models/optimized_model # Inferensfas - använd lightweight image för runtime FROM tensorflow/tensorflow:2.9.0 AS runtime # Installera produktionsberoenden COPY --from=builder /build/requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # Kopiera optimerad modell och kod WORKDIR /app COPY --from=builder /build/models/optimized_model ./models/ COPY --from=builder /build/src/inference.py ./ COPY --from=builder /build/config.yaml ./ # Exponera port för API EXPOSE 8501 # Definiera standardkommando CMD ["python", "inference.py", "--port", "8501"]
Optimering av Docker-images för ML
- Image-storlek: Minimera storleken genom att ta bort utvecklingsverktyg
- Startid: Optimera för snabb startup av containers
- Caching: Strukturera Dockerfile för optimal caching
- Lagerstruktur: Gruppera relaterade kommandon för att minimera antal lager
- Alpine-baserade images: För minimala produktionsimages
Best practices för containerisering av ML-modeller
- Separering av träning och inferens: Olika containers för olika ändamål
- Externalisera konfiguration: Använd environment-variabler eller config-filer
- Preload-modeller: Ladda modeller vid container-uppstart för att minimera kallstarttid
- Health checks: Implementera hälsokontroller för containerövervakning
- Lämplig loggning: Konfigurera loggning för effektiv felsökning
- Säkerhetsoptimering: Kör som non-root-användare, scanna för sårbarheter
5.3 Orkestrering med Kubernetes för ML-arbetsbelastningar
Introduktion till Kubernetes för ML
- Kubernetes-komponenter: Noder, Pods, Services, Deployments
- Kubernetes-arkitektur: Control plane och worker nodes
- Namespace-organisering: Logisk separation av miljöer och team
- ML-specifika överväganden: Resursbehov, specialiserad hårdvara
Kubernetes-resurser för ML-driftsättning
- Deployments: För stateless prediktions-API:er
- StatefulSets: För tillståndsbaserade ML-system
- Services: Exponera ML-endpoints
- ConfigMaps och Secrets: Hantera konfiguration och hemligheter
- Jobs och CronJobs: För batchträning och -inferens
- HPA (Horizontal Pod Autoscaler): Automatisk skalning baserat på belastning
Exempel på Kubernetes-manifest för ML-modellserving
# deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: ml-model-service labels: app: ml-model-service spec: replicas: 3 selector: matchLabels: app: ml-model-service template: metadata: labels: app: ml-model-service spec: containers: - name: model-server image: my-registry/ml-model:latest ports: - containerPort: 8501 resources: limits: cpu: "2" memory: "4Gi" nvidia.com/gpu: 1 requests: cpu: "1" memory: "2Gi" readinessProbe: httpGet: path: /health port: 8501 initialDelaySeconds: 10 periodSeconds: 5 livenessProbe: httpGet: path: /health port: 8501 initialDelaySeconds: 30 periodSeconds: 15 env: - name: MODEL_PATH value: "/app/models/optimized_model" - name: PREDICTION_TIMEOUT value: "5" volumeMounts: - name: model-storage mountPath: /app/models volumes: - name: model-storage persistentVolumeClaim: claimName: model-pvc --- # service.yaml apiVersion: v1 kind: Service metadata: name: ml-model-service spec: selector: app: ml-model-service ports: - port: 80 targetPort: 8501 type: ClusterIP --- # autoscaler.yaml apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: ml-model-service-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: ml-model-service minReplicas: 3 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70
Kubernetes-operatörer för ML
- KubeFlow Operator: Hantering av ML-arbetsflöden
- Seldon Core: Driftsättning av ML-modeller med komplex routning
- Feast Operator: Feature Store-hantering
- NVIDIA GPU Operator: GPU-resurshantering
5.4 Hantering av GPU-resurser i containeriserade miljöer
GPU-runtime för containers
- NVIDIA Docker: Docker med GPU-stöd
- Kubernetes Device Plugins: GPU-allokering i Kubernetes
- Multi-GPU-konfigurationer: Parallellisering över flera GPUs
GPU-specifika optimeringar
- Memory management: Optimalt utnyttjande av GPU-minne
- Batch sizing: Anpassade batchstorlekar för GPU
- Mixed precision: Användning av FP16 för snabbare inferens
- Kernel tuning: Optimering av CUDA-kernels
- GPU-delning: Dela en GPU mellan flera containers
Exempel på GPU-konfiguration i Kubernetes
# nvidia-device-plugin.yaml apiVersion: apps/v1 kind: DaemonSet metadata: name: nvidia-device-plugin-daemonset namespace: kube-system spec: selector: matchLabels: name: nvidia-device-plugin-ds template: metadata: labels: name: nvidia-device-plugin-ds spec: tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule containers: - name: nvidia-device-plugin-ctr image: nvidia/k8s-device-plugin:v0.12.2 securityContext: allowPrivilegeEscalation: false capabilities: drop: ["ALL"] volumeMounts: - name: device-plugin mountPath: /var/lib/kubelet/device-plugins volumes: - name: device-plugin hostPath: path: /var/lib/kubelet/device-plugins
5.5 Skalning och lastbalansering av ML-modeller
Skalningsstrategier för ML-tjänster
- Horisontell skalning: Öka antalet poddar baserat på belastning
- Vertikal skalning: Öka resurser per podd
- Autoskalning: Automatisk anpassning baserat på metrics
- Prediktiv skalning: Förutsägbara skalning baserat på historiska mönster
Lastbalanseringsmetoder
- Round-robin: Jämn fördelning av förfrågningar
- Sessionsstickyness: Håll användare till samma instans
- Modellshard: Dela upp modellen över flera instanser
- Specialisering: Olika modeller för olika typer av förfrågningar
Implementering av optimal inferens i en distribuerad miljö
- Modellparallellism: Dela upp stora modeller över flera GPUs/noder
- Batchprediktioner: Gruppera förfrågningar för bättre genomströmning
- Dataparallelism: Samma modell på flera noder för bättre genomströmning
- Adaptive batching: Dynamisk batchstorlek baserat på belastning
- Caching: Cacha vanliga förfrågningar för snabbare respons
Exempel på adaptive batching med TensorFlow Serving
import tensorflow as tf from tensorflow_serving.apis import predict_pb2 from tensorflow_serving.apis import prediction_service_pb2_grpc import grpc import numpy as np import time from concurrent import futures # Konfigurera gRPC-klient channel = grpc.insecure_channel('localhost:8500') stub = prediction_service_pb2_grpc.PredictionServiceStub(channel) # Batchsamlare class BatchCollector: def __init__(self, max_batch_size=32, timeout=0.1): self.max_batch_size = max_batch_size self.timeout = timeout self.batch = [] self.executor = futures.ThreadPoolExecutor(max_workers=1) self.future = None def add_request(self, image): # Skapa ett Future-object för resultatet result_future = futures.Future() # Lägg till request i batch self.batch.append((image, result_future)) # Starta batch-process om det är den första i batchen if len(self.batch) == 1: self.future = self.executor.submit(self._process_batch) # Processa omedelbart om batch är full if len(self.batch) >= self.max_batch_size: self.future.result() return result_future def _process_batch(self): # Vänta tills timeout eller maximal batchstorlek start_time = time.time() while len(self.batch) < self.max_batch_size and time.time() - start_time < self.timeout: time.sleep(0.001) # Skapa batch-request batch_size = len(self.batch) images = np.zeros((batch_size, 224, 224, 3), dtype=np.float32) futures = [] # Samla in data och futures for i, (image, future) in enumerate(self.batch): images[i] = image futures.append(future) # Töm batchen self.batch = [] # Skapa TF Serving-request request = predict_pb2.PredictRequest() request.model_spec.name = 'image_classifier' request.model_spec.signature_name = 'serving_default' request.inputs['input'].CopyFrom( tf.make_tensor_proto(images) ) # Gör prediktionen try: result = stub.Predict(request, timeout=5.0) predictions = tf.make_ndarray(result.outputs['output']) # Sätt resultat för varje future for i, future in enumerate(futures): future.set_result(predictions[i]) except Exception as e: # Sätt undantag för alla futures for future in futures: future.set_exception(e)
5.6 Design av ML-tjänster för olika användningsfall
Realtidsprediktioner
- API-design: RESTful eller gRPC-API för snabb inferens
- Latensoptimering: Minimera svarstid för realtidsapplikationer
- Stateless design: Stateless design för enkel skalning
- Caching-strategier: Cacha vanliga förfrågningar
- Felhantering: Robusta strategier för hantering av fel och timeout
Batchprediktioner
- Arbetsköer: Använd köer för att hantera stora batchjobb
- Schemaläggning: Schemalägg batchjobb under låg belastning
- Checkpointing: Spara tillstånd för att återuppta vid fel
- Parallellisering: Dela upp stora jobb i parallella arbetare
- Dataflödesoptimering: Optimera dataflöde för hög genomströmning
Online learning
- Inkrementell träning: Uppdatera modeller med nya data i realtid
- A/B-testmiljö: Testa modelluppdateringar i produktion
- Shadow deployment: Validera nya modeller utan att påverka användare
- Feedback loops: Samla in feedback för kontinuerlig förbättring
Exempel på ML-tjänstarkitektur för realtid- och batchprediktioner
# Real-time API service apiVersion: apps/v1 kind: Deployment metadata: name: realtime-prediction-api spec: replicas: 5 selector: matchLabels: app: realtime-prediction-api template: metadata: labels: app: realtime-prediction-api spec: containers: - name: api-server image: my-registry/ml-api:latest ports: - containerPort: 8000 resources: limits: nvidia.com/gpu: 1 --- # Batch prediction job apiVersion: batch/v1 kind: CronJob metadata: name: batch-prediction-job spec: schedule: "0 2 * * *" # Kör kl 02:00 varje dag jobTemplate: spec: parallelism: 5 # 5 parallella pods completions: 1 template: spec: containers: - name: batch-processor image: my-registry/ml-batch:latest resources: limits: nvidia.com/gpu: 1 volumeMounts: - name: data-volume mountPath: /data - name: output-volume mountPath: /output volumes: - name: data-volume persistentVolumeClaim: claimName: input-data-pvc - name: output-volume persistentVolumeClaim: claimName: output-data-pvc restartPolicy: Never
Praktiska övningar
1. Docker containerisering: Bygg en Docker-container för en tränad ML-modell 2. Kubernetes-driftsättning: Driftsätt en ML-modell på Kubernetes-kluster 3. Autoskalningskonfiguration: Implementera automatisk skalning baserat på trafikbelastning 4. GPU-optimering: Optimera en GPU-baserad inferensmiljö för maximal prestanda
Verktygsintroduktion
- Docker: Byggande och hantering av containers
- Kubernetes: Orkestrering av containers
- KubeFlow: ML-specifika tjänster för Kubernetes
- Seldon Core: Driftsättningsplattform för ML på Kubernetes
- TensorRT: NVIDIA SDK för optimerad inferens
Läsresurser
- ”Containerization of Machine Learning Models” - NVIDIA Developer Blog
- ”Kubernetes Patterns for ML Services” - Kubeflow Documentation
- ”Optimizing GPU Usage for Deep Learning Inference” - AWS ML Blog
- ”Distributed TensorFlow on Kubernetes” - Google Cloud Documentation
- ”High-Performance Inference with TensorRT” - NVIDIA Documentation
Nyckelinsikter
- Containerisering möjliggör portabel, reproducerbar ML-utveckling och -driftsättning
- Multi-stage Docker-byggen separerar utveckling från produktion för optimal effektivitet
- Kubernetes ger en robust plattform för att orkestreras ML-tjänster med komplex skalning
- GPU-hantering i containeriserade miljöer kräver speciella överväganden för optimal prestanda
- Skalnings- och lastbalanseringsstrategierna bör anpassas efter specifika ML-användningsfall
- Realtids- vs. batchprediktioner kräver olika arkitekturella mönster
Nästa steg
I nästa modul kommer vi att fokusera på modellövervakning och underhåll, där vi kommer att lära oss hur man övervakar modellprestanda i produktion, detekterar drift och implementerar automatiska omträningsstrategier.