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.