Modul 5: Containerisering och orkestrering av ML-applikationer

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.

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
  • 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
  • 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
  • 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
  • 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
# 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"]
  • 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
  • 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
  • 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
  • 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
# 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
  • 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
  • NVIDIA Docker: Docker med GPU-stöd
  • Kubernetes Device Plugins: GPU-allokering i Kubernetes
  • Multi-GPU-konfigurationer: Parallellisering över flera GPUs
  • 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
# 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
  • 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
  • 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
  • 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
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)
  • 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
  • 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
  • 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
# 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

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

  • 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
  • ”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
  • 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

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.