deployment.yaml#

# Title: Weather ML Application Deployment
# Purpose: Defines the main FastAPI application for weather forecasting MLOps platform
# Owner: MLOps Team
# Source: k8s/deployment.yaml
# Last-Reviewed: 2025-08-24
# Depends-On: k8s/pvc.yaml, k8s/service.yaml, docker-compose.yml
# Change-Log:
#   2025-08-24: Updated comments and documentation structure
#   2024-01-01: Initial deployment configuration
# Links: https://github.com/user/weather-ml-platform

# WHY: Core API configuration establishes deployment type and Kubernetes compatibility
apiVersion: apps/v1              # Kubernetes API version for Deployment resources
kind: Deployment                 # Defines this as a Deployment resource type

# WHY: Metadata uniquely identifies this deployment and enables service discovery
metadata:
  name: weather-ml-app           # Unique name for this deployment within namespace
  labels:
    app: weather-ml-app          # Labels enable service discovery and pod selection

# WHY: Spec defines deployment behavior, scaling, and pod template
spec:
  replicas: 1                    # Single replica simplifies demo, enables scaling
  selector:                      # Selector identifies pods managed by this deployment
    matchLabels:
      app: weather-ml-app        # Must match labels in pod template below for association

  # WHY: Template defines blueprint for pods created by this deployment
  template:
    metadata:
      labels:
        app: weather-ml-app      # Labels must match selector for pod association
    spec:
      # WHY: Init containers ensure dependencies are ready before main containers start
      initContainers:
      - name: wait-for-postgres   # Unique identifier for this init container
        image: busybox:1.36      # Minimal networking tools image
        command: ['sh', '-c', 'until nc -zv postgres 5432; do echo "Waiting for postgres..."; sleep 2; done;']
        # WHY: Ensures PostgreSQL availability before FastAPI starts, preventing race conditions

      # WHY: Main container runs the FastAPI application with all required dependencies
      containers:
      - name: weather-ml-container    # Unique container identifier within pod
        image: ml-weather-app:latest  # Local Docker image for development
        imagePullPolicy: Never        # Use local image in development environment

        # WHY: Network configuration exposes FastAPI service internally
        ports:
        - containerPort: 8000       # Internal FastAPI listening port

        # WHY: Environment variables loaded from ConfigMap for configuration
        envFrom:
        - configMapRef:
            name: app-config       # External ConfigMap provides environment variables

        # WHY: Persistent volume for model artifacts and shared application data
        volumeMounts:
        - name: data-storage       # References persistent volume definition
          mountPath: /data         # Mount point for data access
          readOnly: false          # Enable write access for model storage
          # WHY: Write access needed for ML models and data files

        # WHY: Resource allocation ensures predictable performance and prevents overconsumption
        resources:
          # WHY: Minimum guaranteed resources for pod scheduling
          requests:
            cpu: "250m"            # 25% of CPU core minimum
            memory: "128Mi"        # 128 MB RAM minimum
          # WHY: Hard limits prevent resource exhaustion
          limits:
            cpu: "1"               # 100% of CPU core maximum
            memory: "512Mi"        # 512 MB RAM maximum

        # WHY: Security hardening prevents common container vulnerabilities
        securityContext:
          runAsNonRoot: true         # Security: run as non-root user
          runAsUser: 1000            # Specific user ID from Dockerfile
          allowPrivilegeEscalation: false  # Security: prevent privilege escalation
          capabilities:              # Security: manage Linux capabilities
            drop: ["ALL"]            # Security: drop all capabilities by default
          readOnlyRootFilesystem: false  # Allow writes for temporary files

        # WHY: Health checks enable automated monitoring and self-healing
        readinessProbe:              # Determines when pod can receive traffic
          httpGet:
            path: /docs             # FastAPI endpoint for health verification
            port: 8000              # Container internal port
          initialDelaySeconds: 15   # Initial delay before first probe
          periodSeconds: 10         # Time between probe attempts
          timeoutSeconds: 5         # Maximum response time
          failureThreshold: 6       # Failures before marking unready
          successThreshold: 1       # Successes to mark ready

        livenessProbe:               # Determines when pod should restart
          httpGet:
            path: /docs             # Consistent endpoint with readiness
            port: 8000
          initialDelaySeconds: 30   # Longer delay for startup time
          periodSeconds: 20         # Less frequent than readiness checks
          timeoutSeconds: 5
          failureThreshold: 3       # Restart after fewer failures
          successThreshold: 1

      # WHY: Persistent volume provides durable storage for ML models and application data
      volumes:
      - name: data-storage           # Referenced by volumeMounts above
        persistentVolumeClaim:       # Use PVC for dynamic volume provisioning
          claimName: data-pvc        # References PVC defined in k8s/pvc.yaml