Enterprise Kubernetes deployments require sophisticated storage node placement strategies that optimize performance, ensure data locality, and maintain operational efficiency across diverse infrastructure configurations. Longhorn storage systems, when properly configured with node placement controls, enable organizations to build highly available storage architectures that meet specific performance, compliance, and resource utilization requirements.

Understanding how to effectively restrict and manage Longhorn storage nodes through node selectors, taints and tolerations, and advanced configuration patterns is crucial for platform engineering teams responsible for large-scale production deployments. This comprehensive guide explores enterprise-grade approaches to storage node management that balance performance optimization with operational simplicity.

Executive Summary

Kubernetes Longhorn storage node placement requires strategic configuration of node selectors, resource constraints, and deployment patterns that align with enterprise infrastructure requirements. This guide provides comprehensive strategies for implementing advanced node placement controls, optimizing storage performance through intelligent resource allocation, and building production-ready storage architectures that scale efficiently across complex Kubernetes environments.

Longhorn Storage Architecture and Node Management

Understanding Storage Node Roles

Longhorn storage architecture involves multiple node types with specific roles and requirements:

# Comprehensive node role configuration for Longhorn storage
apiVersion: v1
kind: ConfigMap
metadata:
  name: longhorn-node-architecture
  namespace: longhorn-system
data:
  node-roles.yaml: |
    storage_nodes:
      purpose: "Primary storage nodes hosting volume replicas"
      requirements:
        cpu: "4 cores minimum"
        memory: "8Gi minimum"
        storage: "High-performance SSD or NVMe"
        network: "10Gbps+ recommended"
      labels:
        node_role: "storage"
        storage_tier: "high-performance"
        longhorn_storage: "enabled"

    compute_nodes:
      purpose: "Application workload nodes with storage access"
      requirements:
        cpu: "2 cores minimum"
        memory: "4Gi minimum"
        network: "1Gbps minimum"
      labels:
        node_role: "compute"
        longhorn_client: "enabled"

    management_nodes:
      purpose: "Longhorn manager and UI components"
      requirements:
        cpu: "2 cores minimum"
        memory: "2Gi minimum"
        high_availability: "required"
      labels:
        node_role: "management"
        longhorn_manager: "enabled"

    edge_nodes:
      purpose: "Edge storage nodes for local data access"
      requirements:
        local_storage: "required"
        network_latency: "low"
      labels:
        node_role: "edge"
        storage_tier: "edge"
        longhorn_edge: "enabled"

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: longhorn-deployment-patterns
  namespace: longhorn-system
data:
  patterns.yaml: |
    dedicated_storage_cluster:
      description: "Separate storage and compute nodes"
      benefits:
        - "Optimized resource allocation"
        - "Better performance isolation"
        - "Simplified capacity planning"
      use_cases:
        - "Large-scale production environments"
        - "High-performance workloads"
        - "Strict resource governance"

    converged_infrastructure:
      description: "Combined storage and compute on same nodes"
      benefits:
        - "Reduced infrastructure costs"
        - "Simplified deployment"
        - "Better resource utilization"
      use_cases:
        - "Small to medium deployments"
        - "Development environments"
        - "Edge computing scenarios"

    hybrid_deployment:
      description: "Mixed dedicated and converged nodes"
      benefits:
        - "Flexible resource allocation"
        - "Gradual scaling options"
        - "Workload-specific optimization"
      use_cases:
        - "Growing organizations"
        - "Multi-tenant environments"
        - "Diverse workload requirements"

Advanced Node Selection Strategies

Implement sophisticated node selection mechanisms for optimal storage placement:

# Advanced Longhorn node selection configuration
apiVersion: v1
kind: ConfigMap
metadata:
  name: longhorn-node-selection-config
  namespace: longhorn-system
data:
  node-selectors.yaml: |
    # Primary storage nodes configuration
    storage_nodes:
      nodeSelector:
        storage.company.com/tier: "high-performance"
        node.company.com/storage-enabled: "true"
        kubernetes.io/arch: "amd64"
      tolerations:
        - key: "storage.company.com/dedicated"
          operator: "Equal"
          value: "longhorn"
          effect: "NoSchedule"
        - key: "node.company.com/storage-only"
          operator: "Exists"
          effect: "NoExecute"

    # Management component nodes
    management_nodes:
      nodeSelector:
        node.company.com/role: "management"
        node.company.com/zone: "control-plane"
      tolerations:
        - key: "node-role.kubernetes.io/master"
          operator: "Exists"
          effect: "NoSchedule"

    # Edge storage nodes
    edge_nodes:
      nodeSelector:
        node.company.com/location: "edge"
        storage.company.com/local-storage: "available"
      tolerations:
        - key: "node.company.com/edge"
          operator: "Equal"
          value: "true"
          effect: "NoSchedule"

---
# Comprehensive Longhorn Helm values for node placement
apiVersion: v1
kind: ConfigMap
metadata:
  name: longhorn-helm-values
  namespace: longhorn-system
data:
  values.yaml: |
    # Image configuration
    image:
      longhorn:
        engine:
          repository: longhornio/longhorn-engine
          tag: v1.5.3
        manager:
          repository: longhornio/longhorn-manager
          tag: v1.5.3
        ui:
          repository: longhornio/longhorn-ui
          tag: v1.5.3
        instanceManager:
          repository: longhornio/longhorn-instance-manager
          tag: v1.5.3

    # Service configuration
    service:
      ui:
        type: ClusterIP
        nodePort: null
      manager:
        type: ClusterIP

    # Persistence configuration for management components
    persistence:
      defaultClass: true
      defaultClassReplicaCount: 3
      reclaimPolicy: Retain
      recurringJobs:
        enable: true

    # CSI driver configuration
    csi:
      kubeletRootDir: /var/lib/kubelet
      attacherReplicaCount: 3
      provisionerReplicaCount: 3
      resizerReplicaCount: 3
      snapshotterReplicaCount: 3

    # Longhorn Manager node placement
    longhornManager:
      priorityClass: "system-node-critical"
      tolerations:
        - key: "storage.company.com/dedicated"
          operator: "Equal"
          value: "longhorn"
          effect: "NoSchedule"
        - key: "node.company.com/storage-only"
          operator: "Exists"
          effect: "NoExecute"
      nodeSelector:
        storage.company.com/longhorn-manager: "enabled"
        node.company.com/zone: "storage"
      resources:
        limits:
          cpu: "1000m"
          memory: "2Gi"
        requests:
          cpu: "500m"
          memory: "1Gi"

    # Longhorn Driver node placement
    longhornDriver:
      priorityClass: "system-node-critical"
      tolerations:
        - key: "storage.company.com/dedicated"
          operator: "Equal"
          value: "longhorn"
          effect: "NoSchedule"
        - key: "node-role.kubernetes.io/master"
          operator: "Exists"
          effect: "NoSchedule"
        - key: "node.company.com/compute-only"
          operator: "Equal"
          value: "true"
          effect: "NoSchedule"
      nodeSelector:
        storage.company.com/csi-driver: "enabled"

    # Longhorn UI placement
    longhornUI:
      replicas: 2
      priorityClass: "system-cluster-critical"
      nodeSelector:
        node.company.com/role: "management"
        node.company.com/ui-enabled: "true"
      tolerations:
        - key: "node-role.kubernetes.io/master"
          operator: "Exists"
          effect: "NoSchedule"
      resources:
        limits:
          cpu: "500m"
          memory: "1Gi"
        requests:
          cpu: "100m"
          memory: "256Mi"

    # Default storage class configuration
    defaultSettings:
      backupstorePollInterval: 300
      backupTarget: "s3://longhorn-backups@us-east-1/"
      backupTargetCredentialSecret: "longhorn-backup-credentials"
      createDefaultDiskLabeledNodes: false
      defaultDataPath: "/var/lib/longhorn/"
      defaultDataLocality: "best-effort"
      replicaReplenishmentWaitInterval: 600
      concurrentReplicaRebuildPerNodeLimit: 3
      systemManagedPodsImagePullPolicy: "IfNotPresent"
      autoSalvage: true
      autoDeletePodWhenVolumeDetachedUnexpectedly: true
      disableSchedulingOnCordonedNode: true
      replicaZoneSoftAntiAffinity: true
      volumeAttachmentRecoveryPolicy: "wait"
      nodeDownPodDeletionPolicy: "delete-both-statefulset-and-deployment-pod"
      allowVolumeCreationWithDegradedAvailability: false
      mkfsExt4Parameters: "-O ^64bit,^metadata_csum"

---
# Node preparation automation
apiVersion: batch/v1
kind: Job
metadata:
  name: longhorn-node-preparation
  namespace: longhorn-system
spec:
  template:
    spec:
      restartPolicy: OnFailure
      hostNetwork: true
      hostPID: true
      serviceAccount: longhorn-node-preparation
      containers:
      - name: node-prep
        image: alpine:latest
        securityContext:
          privileged: true
        command: ["/bin/sh"]
        args:
        - -c
        - |
          set -euo pipefail

          echo "🔧 Preparing nodes for Longhorn storage"

          # Install required packages
          apk add --no-cache curl jq

          # Get node information
          NODE_NAME=${NODE_NAME:-$(hostname)}
          echo "Preparing node: $NODE_NAME"

          # Check for required kernel modules
          echo "📋 Checking kernel modules..."
          for module in iscsi_tcp target_core_mod; do
            if lsmod | grep -q "$module"; then
              echo "✅ Module $module is loaded"
            else
              echo "⚠️  Module $module is not loaded, attempting to load..."
              modprobe "$module" || echo "❌ Failed to load $module"
            fi
          done

          # Check disk configuration
          echo "💾 Analyzing disk configuration..."
          lsblk -f
          df -h

          # Validate network connectivity
          echo "🌐 Testing network connectivity..."
          ping -c 3 8.8.8.8 || echo "⚠️  Network connectivity issues detected"

          echo "✅ Node preparation completed for $NODE_NAME"
        env:
        - name: NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        volumeMounts:
        - name: host-root
          mountPath: /host
          mountPropagation: HostToContainer
        - name: host-sys
          mountPath: /sys
        - name: host-dev
          mountPath: /dev
      volumes:
      - name: host-root
        hostPath:
          path: /
      - name: host-sys
        hostPath:
          path: /sys
      - name: host-dev
        hostPath:
          path: /dev
      nodeSelector:
        storage.company.com/longhorn-candidate: "true"

Node Labeling and Preparation Automation

Comprehensive Node Management Scripts

Implement automated node preparation and labeling systems:

#!/bin/bash
# Script: longhorn-node-manager.sh
# Purpose: Comprehensive node management for Longhorn storage

set -euo pipefail

# Configuration
LABEL_PREFIX="storage.company.com"
NODE_CONFIG_FILE="/etc/longhorn/node-config.yaml"
LOG_FILE="/var/log/longhorn-node-management.log"

function log_message() {
    local level="$1"
    local message="$2"
    local timestamp=$(date -u +"%Y-%m-%d %H:%M:%S UTC")

    echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
}

function detect_node_capabilities() {
    local node_name="$1"

    log_message "INFO" "Detecting capabilities for node: $node_name"

    # Get node information
    local node_info=$(kubectl get node "$node_name" -o json)
    local cpu_capacity=$(echo "$node_info" | jq -r '.status.capacity.cpu')
    local memory_capacity=$(echo "$node_info" | jq -r '.status.capacity.memory' | numfmt --from=iec)
    local storage_capacity=$(echo "$node_info" | jq -r '.status.capacity."ephemeral-storage"' | numfmt --from=iec)

    # Convert memory to GB
    local memory_gb=$((memory_capacity / 1024 / 1024 / 1024))

    # Detect node role based on resources
    local node_role="unknown"
    local storage_tier="standard"

    if [[ $memory_gb -ge 32 && "$cpu_capacity" -ge 8 ]]; then
        node_role="storage-high-performance"
        storage_tier="high-performance"
    elif [[ $memory_gb -ge 16 && "$cpu_capacity" -ge 4 ]]; then
        node_role="storage-standard"
        storage_tier="standard"
    elif [[ $memory_gb -ge 8 && "$cpu_capacity" -ge 2 ]]; then
        node_role="compute"
        storage_tier="none"
    else
        node_role="edge"
        storage_tier="edge"
    fi

    # Detect storage devices
    local storage_devices=$(kubectl debug node/"$node_name" -it --image=alpine -- sh -c 'lsblk -d -o NAME,SIZE,TYPE | grep disk' 2>/dev/null | wc -l || echo "0")

    # Check for SSD/NVMe storage
    local has_ssd="false"
    if kubectl debug node/"$node_name" -it --image=alpine -- sh -c 'lsblk -d -o NAME,ROTA | grep -E "nvme|0$"' 2>/dev/null | grep -q .; then
        has_ssd="true"
    fi

    # Output capabilities
    cat <<EOF
{
  "node_name": "$node_name",
  "capabilities": {
    "cpu_cores": $cpu_capacity,
    "memory_gb": $memory_gb,
    "storage_gb": $((storage_capacity / 1024 / 1024 / 1024)),
    "storage_devices": $storage_devices,
    "has_ssd": $has_ssd,
    "recommended_role": "$node_role",
    "storage_tier": "$storage_tier"
  }
}
EOF
}

function prepare_storage_node() {
    local node_name="$1"
    local node_role="$2"

    log_message "INFO" "Preparing storage node: $node_name (role: $node_role)"

    # Check if node is ready
    local node_ready=$(kubectl get node "$node_name" -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}')
    if [[ "$node_ready" != "True" ]]; then
        log_message "ERROR" "Node $node_name is not ready"
        return 1
    fi

    # Install required packages via daemonset
    kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: longhorn-node-preparation-$node_name
  namespace: longhorn-system
spec:
  selector:
    matchLabels:
      app: longhorn-node-preparation
  template:
    metadata:
      labels:
        app: longhorn-node-preparation
    spec:
      hostNetwork: true
      hostPID: true
      containers:
      - name: node-prep
        image: alpine:latest
        securityContext:
          privileged: true
        command: ["/bin/sh"]
        args:
        - -c
        - |
          set -euo pipefail
          echo "Preparing Longhorn storage node"

          # Load kernel modules
          modprobe iscsi_tcp || echo "Failed to load iscsi_tcp"
          modprobe target_core_mod || echo "Failed to load target_core_mod"

          # Create longhorn directory
          mkdir -p /var/lib/longhorn

          # Set appropriate permissions
          chmod 755 /var/lib/longhorn

          echo "Node preparation completed"
          sleep infinity
        volumeMounts:
        - name: host-root
          mountPath: /host
          mountPropagation: HostToContainer
      volumes:
      - name: host-root
        hostPath:
          path: /
      nodeSelector:
        kubernetes.io/hostname: $node_name
      tolerations:
      - operator: Exists
EOF

    # Wait for preparation to complete
    sleep 30

    # Clean up preparation daemonset
    kubectl delete daemonset "longhorn-node-preparation-$node_name" -n longhorn-system || true

    log_message "INFO" "Node preparation completed for $node_name"
}

function apply_node_labels() {
    local node_name="$1"
    local capabilities="$2"

    log_message "INFO" "Applying labels to node: $node_name"

    # Parse capabilities
    local node_role=$(echo "$capabilities" | jq -r '.capabilities.recommended_role')
    local storage_tier=$(echo "$capabilities" | jq -r '.capabilities.storage_tier')
    local has_ssd=$(echo "$capabilities" | jq -r '.capabilities.has_ssd')
    local cpu_cores=$(echo "$capabilities" | jq -r '.capabilities.cpu_cores')
    local memory_gb=$(echo "$capabilities" | jq -r '.capabilities.memory_gb')

    # Apply base labels
    kubectl label node "$node_name" \
        "${LABEL_PREFIX}/node-role=$node_role" \
        "${LABEL_PREFIX}/storage-tier=$storage_tier" \
        "${LABEL_PREFIX}/has-ssd=$has_ssd" \
        "${LABEL_PREFIX}/cpu-cores=$cpu_cores" \
        "${LABEL_PREFIX}/memory-gb=$memory_gb" \
        --overwrite

    # Apply role-specific labels
    case "$node_role" in
        "storage-high-performance")
            kubectl label node "$node_name" \
                "${LABEL_PREFIX}/longhorn-storage=enabled" \
                "${LABEL_PREFIX}/longhorn-manager=enabled" \
                "${LABEL_PREFIX}/high-performance=true" \
                --overwrite
            ;;
        "storage-standard")
            kubectl label node "$node_name" \
                "${LABEL_PREFIX}/longhorn-storage=enabled" \
                "${LABEL_PREFIX}/longhorn-manager=enabled" \
                --overwrite
            ;;
        "compute")
            kubectl label node "$node_name" \
                "${LABEL_PREFIX}/longhorn-client=enabled" \
                "${LABEL_PREFIX}/csi-driver=enabled" \
                --overwrite
            ;;
        "edge")
            kubectl label node "$node_name" \
                "${LABEL_PREFIX}/longhorn-edge=enabled" \
                "${LABEL_PREFIX}/local-storage=preferred" \
                --overwrite
            ;;
    esac

    log_message "INFO" "Labels applied successfully to $node_name"
}

function apply_node_taints() {
    local node_name="$1"
    local node_role="$2"

    log_message "INFO" "Applying taints to node: $node_name (role: $node_role)"

    case "$node_role" in
        "storage-high-performance"|"storage-standard")
            # Taint storage nodes to prevent non-storage workloads
            kubectl taint node "$node_name" \
                "${LABEL_PREFIX}/dedicated=storage:NoSchedule" \
                --overwrite || true
            kubectl taint node "$node_name" \
                "${LABEL_PREFIX}/storage-only=true:NoExecute" \
                --overwrite || true
            ;;
        "edge")
            # Taint edge nodes for edge-specific workloads
            kubectl taint node "$node_name" \
                "${LABEL_PREFIX}/edge=true:NoSchedule" \
                --overwrite || true
            ;;
    esac

    log_message "INFO" "Taints applied successfully to $node_name"
}

function validate_node_configuration() {
    local node_name="$1"

    log_message "INFO" "Validating configuration for node: $node_name"

    # Check labels
    local labels=$(kubectl get node "$node_name" --show-labels | grep "$LABEL_PREFIX")
    if [[ -n "$labels" ]]; then
        log_message "INFO" "Labels validated for $node_name"
    else
        log_message "WARN" "No Longhorn labels found on $node_name"
        return 1
    fi

    # Check node readiness
    local ready=$(kubectl get node "$node_name" -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}')
    if [[ "$ready" == "True" ]]; then
        log_message "INFO" "Node $node_name is ready"
    else
        log_message "ERROR" "Node $node_name is not ready"
        return 1
    fi

    # Test scheduling capability
    local test_pod_name="node-validation-$node_name-$(date +%s)"

    kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: $test_pod_name
  namespace: default
spec:
  restartPolicy: Never
  nodeSelector:
    kubernetes.io/hostname: $node_name
  containers:
  - name: test
    image: alpine:latest
    command: ["sleep", "30"]
  tolerations:
  - operator: Exists
EOF

    # Wait for pod to schedule
    local timeout=60
    local count=0
    while [[ $count -lt $timeout ]]; do
        local pod_phase=$(kubectl get pod "$test_pod_name" -n default -o jsonpath='{.status.phase}' 2>/dev/null || echo "NotFound")

        if [[ "$pod_phase" == "Running" || "$pod_phase" == "Succeeded" ]]; then
            log_message "INFO" "Test pod scheduled successfully on $node_name"
            kubectl delete pod "$test_pod_name" -n default || true
            return 0
        fi

        sleep 2
        count=$((count + 2))
    done

    log_message "WARN" "Test pod failed to schedule on $node_name within timeout"
    kubectl delete pod "$test_pod_name" -n default || true
    return 1
}

function configure_all_nodes() {
    log_message "INFO" "Starting comprehensive node configuration"

    # Get all nodes
    local nodes=$(kubectl get nodes -o jsonpath='{.items[*].metadata.name}')

    for node in $nodes; do
        log_message "INFO" "Processing node: $node"

        # Detect capabilities
        local capabilities=$(detect_node_capabilities "$node")
        local node_role=$(echo "$capabilities" | jq -r '.capabilities.recommended_role')

        log_message "INFO" "Detected role for $node: $node_role"

        # Prepare node
        prepare_storage_node "$node" "$node_role"

        # Apply labels
        apply_node_labels "$node" "$capabilities"

        # Apply taints if needed
        apply_node_taints "$node" "$node_role"

        # Validate configuration
        validate_node_configuration "$node"

        log_message "INFO" "Configuration completed for node: $node"
    done

    log_message "INFO" "All nodes configured successfully"
}

function generate_node_report() {
    log_message "INFO" "Generating node configuration report"

    local report_file="/tmp/longhorn-node-report-$(date +%Y%m%d_%H%M%S).json"

    cat > "$report_file" <<EOF
{
  "report_timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "cluster_info": {
    "total_nodes": $(kubectl get nodes --no-headers | wc -l),
    "kubernetes_version": "$(kubectl version -o json | jq -r '.serverVersion.gitVersion')"
  },
  "nodes": [
EOF

    local nodes=$(kubectl get nodes -o jsonpath='{.items[*].metadata.name}')
    local first_node=true

    for node in $nodes; do
        if [[ "$first_node" == "true" ]]; then
            first_node=false
        else
            echo "," >> "$report_file"
        fi

        local capabilities=$(detect_node_capabilities "$node")
        echo "$capabilities" >> "$report_file"
    done

    cat >> "$report_file" <<EOF
  ],
  "summary": {
    "storage_nodes": $(kubectl get nodes -l "${LABEL_PREFIX}/longhorn-storage=enabled" --no-headers 2>/dev/null | wc -l),
    "compute_nodes": $(kubectl get nodes -l "${LABEL_PREFIX}/longhorn-client=enabled" --no-headers 2>/dev/null | wc -l),
    "edge_nodes": $(kubectl get nodes -l "${LABEL_PREFIX}/longhorn-edge=enabled" --no-headers 2>/dev/null | wc -l)
  }
}
EOF

    log_message "INFO" "Node report generated: $report_file"
    echo "📊 Node Configuration Report: $report_file"
    cat "$report_file" | jq .
}

# Main execution
case "${1:-help}" in
    "configure")
        configure_all_nodes
        ;;
    "detect")
        if [[ -n "${2:-}" ]]; then
            detect_node_capabilities "$2"
        else
            echo "Usage: $0 detect <node-name>"
        fi
        ;;
    "prepare")
        if [[ -n "${2:-}" && -n "${3:-}" ]]; then
            prepare_storage_node "$2" "$3"
        else
            echo "Usage: $0 prepare <node-name> <role>"
        fi
        ;;
    "label")
        if [[ -n "${2:-}" ]]; then
            local capabilities=$(detect_node_capabilities "$2")
            apply_node_labels "$2" "$capabilities"
        else
            echo "Usage: $0 label <node-name>"
        fi
        ;;
    "validate")
        if [[ -n "${2:-}" ]]; then
            validate_node_configuration "$2"
        else
            echo "Usage: $0 validate <node-name>"
        fi
        ;;
    "report")
        generate_node_report
        ;;
    *)
        echo "Longhorn Node Manager"
        echo "===================="
        echo ""
        echo "Usage: $0 {configure|detect|prepare|label|validate|report}"
        echo ""
        echo "Commands:"
        echo "  configure        - Configure all nodes automatically"
        echo "  detect <node>    - Detect node capabilities"
        echo "  prepare <node>   - Prepare node for Longhorn storage"
        echo "  label <node>     - Apply appropriate labels"
        echo "  validate <node>  - Validate node configuration"
        echo "  report           - Generate comprehensive node report"
        ;;
esac

Advanced Storage Tier Management

Multi-Tier Storage Architecture

Implement comprehensive storage tier management for different performance requirements:

# Multi-tier storage configuration for Longhorn
apiVersion: v1
kind: ConfigMap
metadata:
  name: longhorn-storage-tiers
  namespace: longhorn-system
data:
  storage-tiers.yaml: |
    tier_definitions:
      platinum:
        description: "Highest performance NVMe storage"
        node_requirements:
          cpu_cores: 16
          memory_gb: 64
          storage_type: "nvme"
          network_speed: "25Gbps"
        volume_characteristics:
          replicas: 3
          data_locality: "strict-local"
          performance_class: "ultra-high"
        use_cases:
          - "Database primary storage"
          - "High-frequency trading systems"
          - "Real-time analytics"

      gold:
        description: "High-performance SSD storage"
        node_requirements:
          cpu_cores: 8
          memory_gb: 32
          storage_type: "ssd"
          network_speed: "10Gbps"
        volume_characteristics:
          replicas: 3
          data_locality: "best-effort"
          performance_class: "high"
        use_cases:
          - "Application databases"
          - "Cache layers"
          - "Log aggregation"

      silver:
        description: "Standard performance storage"
        node_requirements:
          cpu_cores: 4
          memory_gb: 16
          storage_type: "ssd_hdd_mixed"
          network_speed: "1Gbps"
        volume_characteristics:
          replicas: 2
          data_locality: "disabled"
          performance_class: "standard"
        use_cases:
          - "General application storage"
          - "Development environments"
          - "Backup storage"

      bronze:
        description: "Cost-optimized storage"
        node_requirements:
          cpu_cores: 2
          memory_gb: 8
          storage_type: "hdd"
          network_speed: "1Gbps"
        volume_characteristics:
          replicas: 2
          data_locality: "disabled"
          performance_class: "basic"
        use_cases:
          - "Archive storage"
          - "Long-term backups"
          - "Infrequently accessed data"

---
# Storage class definitions for different tiers
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: longhorn-platinum
  annotations:
    storageclass.kubernetes.io/is-default-class: "false"
provisioner: driver.longhorn.io
allowVolumeExpansion: true
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer
parameters:
  numberOfReplicas: "3"
  staleReplicaTimeout: "2880"
  fromBackup: ""
  fsType: "ext4"
  dataLocality: "strict-local"
  replicaAutoBalance: "least-effort"
  diskSelector: "storage-tier,platinum"
  nodeSelector: "storage-tier,platinum"

---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: longhorn-gold
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: driver.longhorn.io
allowVolumeExpansion: true
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
parameters:
  numberOfReplicas: "3"
  staleReplicaTimeout: "2880"
  fromBackup: ""
  fsType: "ext4"
  dataLocality: "best-effort"
  replicaAutoBalance: "least-effort"
  diskSelector: "storage-tier,gold"
  nodeSelector: "storage-tier,gold"

---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: longhorn-silver
provisioner: driver.longhorn.io
allowVolumeExpansion: true
reclaimPolicy: Delete
volumeBindingMode: Immediate
parameters:
  numberOfReplicas: "2"
  staleReplicaTimeout: "2880"
  fromBackup: ""
  fsType: "ext4"
  dataLocality: "disabled"
  replicaAutoBalance: "least-effort"
  diskSelector: "storage-tier,silver"
  nodeSelector: "storage-tier,silver"

---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: longhorn-bronze
provisioner: driver.longhorn.io
allowVolumeExpansion: true
reclaimPolicy: Delete
volumeBindingMode: Immediate
parameters:
  numberOfReplicas: "2"
  staleReplicaTimeout: "2880"
  fromBackup: ""
  fsType: "ext4"
  dataLocality: "disabled"
  replicaAutoBalance: "disabled"
  diskSelector: "storage-tier,bronze"
  nodeSelector: "storage-tier,bronze"

---
# Automated storage tier assignment
apiVersion: batch/v1
kind: CronJob
metadata:
  name: storage-tier-optimizer
  namespace: longhorn-system
spec:
  schedule: "0 2 * * *"  # Run daily at 2 AM
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          serviceAccount: storage-tier-optimizer
          containers:
          - name: optimizer
            image: bitnami/kubectl:latest
            command: ["/bin/bash"]
            args:
            - -c
            - |
              set -euo pipefail

              echo "🔄 Starting storage tier optimization"

              # Get all nodes with storage capabilities
              nodes=$(kubectl get nodes -l "storage.company.com/longhorn-storage=enabled" -o jsonpath='{.items[*].metadata.name}')

              for node in $nodes; do
                echo "Analyzing node: $node"

                # Get node specifications
                cpu_cores=$(kubectl get node "$node" -o jsonpath='{.status.capacity.cpu}')
                memory_bytes=$(kubectl get node "$node" -o jsonpath='{.status.capacity.memory}' | numfmt --from=iec)
                memory_gb=$((memory_bytes / 1024 / 1024 / 1024))

                # Check for SSD/NVMe
                has_nvme="false"
                has_ssd="false"

                # Use node feature discovery if available
                storage_type=$(kubectl get node "$node" -o jsonpath='{.metadata.labels.feature\.node\.kubernetes\.io/storage-nonrotationaldisk}' 2>/dev/null || echo "unknown")

                if [[ "$storage_type" == "true" ]]; then
                  has_ssd="true"
                  # Check for NVMe specifically
                  nvme_info=$(kubectl get node "$node" -o jsonpath='{.metadata.labels.feature\.node\.kubernetes\.io/pci-0200_144d\.present}' 2>/dev/null || echo "false")
                  if [[ "$nvme_info" == "true" ]]; then
                    has_nvme="true"
                  fi
                fi

                # Determine tier based on specifications
                tier="bronze"
                if [[ $memory_gb -ge 64 && $cpu_cores -ge 16 && "$has_nvme" == "true" ]]; then
                  tier="platinum"
                elif [[ $memory_gb -ge 32 && $cpu_cores -ge 8 && "$has_ssd" == "true" ]]; then
                  tier="gold"
                elif [[ $memory_gb -ge 16 && $cpu_cores -ge 4 ]]; then
                  tier="silver"
                fi

                echo "Assigning tier '$tier' to node '$node'"

                # Apply tier labels
                kubectl label node "$node" \
                  "storage.company.com/storage-tier=$tier" \
                  "storage.company.com/tier-last-updated=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
                  --overwrite

                # Apply tier-specific disk labels
                kubectl annotate node "$node" \
                  "storage.company.com/tier-specifications={\"cpu\":$cpu_cores,\"memory_gb\":$memory_gb,\"has_ssd\":$has_ssd,\"has_nvme\":$has_nvme}" \
                  --overwrite
              done

              echo "✅ Storage tier optimization completed"

---
# Resource monitoring for storage tiers
apiVersion: v1
kind: ConfigMap
metadata:
  name: storage-tier-monitoring
  namespace: longhorn-system
data:
  monitoring-rules.yaml: |
    groups:
    - name: longhorn.storage.tiers
      rules:
      - alert: StorageTierPerformanceDegradation
        expr: |
          (
            rate(longhorn_volume_read_latency_seconds[5m]) > 0.1
            or
            rate(longhorn_volume_write_latency_seconds[5m]) > 0.1
          )
          and
          on(volume) label_replace(
            kube_persistentvolume_labels{label_storage_tier!=""},
            "volume", "$1", "persistentvolume", "(.+)"
          )
        for: 10m
        labels:
          severity: warning
          tier: "{{ $labels.label_storage_tier }}"
        annotations:
          summary: "Storage tier performance degradation"
          description: "Volume {{ $labels.volume }} in {{ $labels.label_storage_tier }} tier is experiencing high latency"

      - alert: StorageTierCapacityHigh
        expr: |
          (
            (longhorn_disk_capacity_bytes - longhorn_disk_usage_bytes) / longhorn_disk_capacity_bytes * 100 < 20
          )
          and
          on(node) label_replace(
            kube_node_labels{label_storage_company_com_storage_tier!=""},
            "node", "$1", "node", "(.+)"
          )
        for: 5m
        labels:
          severity: warning
          tier: "{{ $labels.label_storage_company_com_storage_tier }}"
        annotations:
          summary: "Storage tier capacity running low"
          description: "{{ $labels.label_storage_company_com_storage_tier }} tier node {{ $labels.node }} has less than 20% free space"

      - alert: StorageTierNodeUnavailable
        expr: |
          up{job="longhorn-manager"} == 0
          and
          on(node) label_replace(
            kube_node_labels{label_storage_company_com_storage_tier!=""},
            "node", "$1", "node", "(.+)"
          )
        for: 2m
        labels:
          severity: critical
          tier: "{{ $labels.label_storage_company_com_storage_tier }}"
        annotations:
          summary: "Storage tier node unavailable"
          description: "{{ $labels.label_storage_company_com_storage_tier }} tier node {{ $labels.node }} is unavailable"

Production Deployment Strategies

Rolling Deployment and Maintenance

Implement comprehensive deployment and maintenance procedures:

#!/bin/bash
# Script: longhorn-production-deployment.sh
# Purpose: Production deployment and maintenance procedures

set -euo pipefail

# Configuration
NAMESPACE="longhorn-system"
BACKUP_DIR="/var/backups/longhorn-production"
MAINTENANCE_LOG="/var/log/longhorn-maintenance-$(date +%Y%m%d_%H%M%S).log"

function log_deployment_step() {
    local level="$1"
    local message="$2"
    local timestamp=$(date -u +"%Y-%m-%d %H:%M:%S UTC")

    echo "[$timestamp] [$level] $message" | tee -a "$MAINTENANCE_LOG"
}

function create_pre_deployment_backup() {
    log_deployment_step "INFO" "Creating pre-deployment backup"

    local backup_timestamp=$(date +%Y%m%d_%H%M%S)
    local backup_path="$BACKUP_DIR/pre-deployment-$backup_timestamp"

    mkdir -p "$backup_path"

    # Backup Kubernetes resources
    kubectl get all,pv,pvc,sc,nodes.longhorn.io,volumes.longhorn.io,settings.longhorn.io -o yaml > "$backup_path/kubernetes-resources.yaml"

    # Backup Helm release information
    if command -v helm >/dev/null 2>&1; then
        helm get values longhorn -n "$NAMESPACE" > "$backup_path/helm-values.yaml"
        helm get manifest longhorn -n "$NAMESPACE" > "$backup_path/helm-manifest.yaml"
    fi

    # Create volume snapshot manifests
    kubectl get volumesnapshots --all-namespaces -o yaml > "$backup_path/volume-snapshots.yaml" 2>/dev/null || true

    log_deployment_step "INFO" "Pre-deployment backup completed: $backup_path"
}

function validate_cluster_readiness() {
    log_deployment_step "INFO" "Validating cluster readiness for deployment"

    # Check node health
    local unhealthy_nodes=$(kubectl get nodes -o json | jq '[.items[] | select(.status.conditions[] | select(.type=="Ready" and .status!="True"))] | length')

    if [[ $unhealthy_nodes -gt 0 ]]; then
        log_deployment_step "ERROR" "$unhealthy_nodes unhealthy nodes detected"
        return 1
    fi

    # Check existing Longhorn health
    local unhealthy_pods=$(kubectl get pods -n "$NAMESPACE" --no-headers | grep -v "Running\|Completed" | wc -l)

    if [[ $unhealthy_pods -gt 0 ]]; then
        log_deployment_step "WARN" "$unhealthy_pods unhealthy Longhorn pods detected"
        kubectl get pods -n "$NAMESPACE" | grep -v "Running\|Completed"
    fi

    # Check volume health
    local unhealthy_volumes=$(kubectl get volumes.longhorn.io -n "$NAMESPACE" -o json | jq '[.items[] | select(.status.state != "attached" and .status.state != "detached")] | length')

    if [[ $unhealthy_volumes -gt 0 ]]; then
        log_deployment_step "ERROR" "$unhealthy_volumes unhealthy volumes detected"
        return 1
    fi

    # Check resource availability
    local cpu_usage=$(kubectl top nodes --no-headers | awk '{print $3}' | sed 's/%//' | awk '{sum+=$1} END {print sum/NR}' || echo "0")
    local memory_usage=$(kubectl top nodes --no-headers | awk '{print $5}' | sed 's/%//' | awk '{sum+=$1} END {print sum/NR}' || echo "0")

    if (( $(echo "$cpu_usage > 80" | bc -l 2>/dev/null || echo "0") )); then
        log_deployment_step "WARN" "High CPU usage detected: ${cpu_usage}%"
    fi

    if (( $(echo "$memory_usage > 80" | bc -l 2>/dev/null || echo "0") )); then
        log_deployment_step "WARN" "High memory usage detected: ${memory_usage}%"
    fi

    log_deployment_step "INFO" "Cluster readiness validation completed"
}

function perform_rolling_deployment() {
    local deployment_strategy="$1"

    log_deployment_step "INFO" "Starting rolling deployment with strategy: $deployment_strategy"

    case "$deployment_strategy" in
        "conservative")
            perform_conservative_deployment
            ;;
        "balanced")
            perform_balanced_deployment
            ;;
        "aggressive")
            perform_aggressive_deployment
            ;;
        *)
            log_deployment_step "ERROR" "Unknown deployment strategy: $deployment_strategy"
            return 1
            ;;
    esac

    log_deployment_step "INFO" "Rolling deployment completed"
}

function perform_conservative_deployment() {
    log_deployment_step "INFO" "Performing conservative deployment"

    # Scale down non-critical workloads
    log_deployment_step "INFO" "Scaling down non-critical workloads"

    local non_critical_deployments=$(kubectl get deployments --all-namespaces -l "criticality!=critical" -o jsonpath='{range .items[*]}{.metadata.namespace}{","}{.metadata.name}{","}{.spec.replicas}{"\n"}{end}' 2>/dev/null || echo "")

    while IFS=',' read -r namespace name replicas; do
        if [[ -n "$namespace" && -n "$name" && -n "$replicas" ]]; then
            log_deployment_step "INFO" "Scaling down $namespace/$name from $replicas to 0"
            kubectl scale deployment "$name" --replicas=0 -n "$namespace" || true

            # Store original replica count
            kubectl annotate deployment "$name" -n "$namespace" \
                "longhorn.company.com/original-replicas=$replicas" \
                --overwrite || true
        fi
    done <<< "$non_critical_deployments"

    # Wait for workload termination
    sleep 60

    # Perform Helm upgrade with conservative settings
    log_deployment_step "INFO" "Performing Helm upgrade"
    helm upgrade longhorn longhorn/longhorn \
        --namespace "$NAMESPACE" \
        --wait \
        --timeout=30m \
        --set longhornManager.priorityClass=system-node-critical \
        --set longhornDriver.priorityClass=system-node-critical \
        --set defaultSettings.guaranteedEngineManagerCPU=5 \
        --set defaultSettings.guaranteedReplicaManagerCPU=5

    # Wait for system stabilization
    sleep 120

    # Restore non-critical workloads
    log_deployment_step "INFO" "Restoring non-critical workloads"

    while IFS=',' read -r namespace name replicas; do
        if [[ -n "$namespace" && -n "$name" ]]; then
            local original_replicas=$(kubectl get deployment "$name" -n "$namespace" -o jsonpath='{.metadata.annotations.longhorn\.company\.com/original-replicas}' 2>/dev/null || echo "$replicas")

            log_deployment_step "INFO" "Scaling up $namespace/$name to $original_replicas"
            kubectl scale deployment "$name" --replicas="$original_replicas" -n "$namespace" || true

            # Remove annotation
            kubectl annotate deployment "$name" -n "$namespace" \
                "longhorn.company.com/original-replicas-" || true
        fi
    done <<< "$non_critical_deployments"
}

function perform_balanced_deployment() {
    log_deployment_step "INFO" "Performing balanced deployment"

    # Perform Helm upgrade with standard settings
    helm upgrade longhorn longhorn/longhorn \
        --namespace "$NAMESPACE" \
        --wait \
        --timeout=20m \
        --set longhornManager.priorityClass=system-node-critical \
        --set longhornDriver.priorityClass=system-node-critical

    # Monitor deployment progress
    local timeout=1200
    local count=0

    while [[ $count -lt $timeout ]]; do
        local ready_pods=$(kubectl get pods -n "$NAMESPACE" --no-headers | grep "Running" | wc -l)
        local total_pods=$(kubectl get pods -n "$NAMESPACE" --no-headers | wc -l)

        log_deployment_step "INFO" "Deployment progress: $ready_pods/$total_pods pods running"

        if [[ $ready_pods -eq $total_pods ]]; then
            log_deployment_step "INFO" "All pods are running"
            break
        fi

        sleep 30
        count=$((count + 30))
    done

    if [[ $count -ge $timeout ]]; then
        log_deployment_step "WARN" "Deployment timeout reached, some pods may still be starting"
    fi
}

function perform_aggressive_deployment() {
    log_deployment_step "INFO" "Performing aggressive deployment"

    # Perform rapid Helm upgrade
    helm upgrade longhorn longhorn/longhorn \
        --namespace "$NAMESPACE" \
        --wait \
        --timeout=10m \
        --force

    # Quick validation
    sleep 60

    local running_pods=$(kubectl get pods -n "$NAMESPACE" --no-headers | grep "Running" | wc -l)
    log_deployment_step "INFO" "Rapid deployment completed with $running_pods running pods"
}

function validate_deployment_success() {
    log_deployment_step "INFO" "Validating deployment success"

    # Check pod health
    local unhealthy_pods=$(kubectl get pods -n "$NAMESPACE" --no-headers | grep -v "Running\|Completed" | wc -l)

    if [[ $unhealthy_pods -gt 0 ]]; then
        log_deployment_step "ERROR" "$unhealthy_pods unhealthy pods after deployment"
        kubectl get pods -n "$NAMESPACE" | grep -v "Running\|Completed"
        return 1
    fi

    # Test volume operations
    log_deployment_step "INFO" "Testing volume operations"

    local test_pvc_name="deployment-validation-$(date +%s)"

    kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: $test_pvc_name
  namespace: default
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: longhorn
  resources:
    requests:
      storage: 1Gi
EOF

    # Wait for PVC to be bound
    local timeout=300
    local count=0
    while [[ $count -lt $timeout ]]; do
        local pvc_status=$(kubectl get pvc "$test_pvc_name" -n default -o jsonpath='{.status.phase}' 2>/dev/null || echo "NotFound")

        if [[ "$pvc_status" == "Bound" ]]; then
            log_deployment_step "INFO" "Volume operation test successful"
            kubectl delete pvc "$test_pvc_name" -n default || true
            break
        fi

        sleep 5
        count=$((count + 5))
    done

    if [[ $count -ge $timeout ]]; then
        log_deployment_step "ERROR" "Volume operation test failed"
        kubectl delete pvc "$test_pvc_name" -n default || true
        return 1
    fi

    # Check system responsiveness
    log_deployment_step "INFO" "Checking system responsiveness"

    local api_response_time=$(time kubectl get nodes >/dev/null 2>&1 | grep real | awk '{print $2}' || echo "unknown")
    log_deployment_step "INFO" "API response time: $api_response_time"

    log_deployment_step "INFO" "Deployment validation completed successfully"
}

function generate_deployment_report() {
    log_deployment_step "INFO" "Generating deployment report"

    local report_file="/tmp/longhorn-deployment-report-$(date +%Y%m%d_%H%M%S).json"

    cat > "$report_file" <<EOF
{
  "deployment_info": {
    "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "cluster_context": "$(kubectl config current-context)",
    "longhorn_version": "$(kubectl get deployment longhorn-ui -n $NAMESPACE -o jsonpath='{.spec.template.spec.containers[0].image}' | cut -d':' -f2)",
    "kubernetes_version": "$(kubectl version -o json | jq -r '.serverVersion.gitVersion')"
  },
  "system_status": {
    "total_nodes": $(kubectl get nodes --no-headers | wc -l),
    "storage_nodes": $(kubectl get nodes -l "storage.company.com/longhorn-storage=enabled" --no-headers 2>/dev/null | wc -l || echo "0"),
    "running_pods": $(kubectl get pods -n $NAMESPACE --no-headers | grep "Running" | wc -l),
    "total_pods": $(kubectl get pods -n $NAMESPACE --no-headers | wc -l),
    "healthy_volumes": $(kubectl get volumes.longhorn.io -n $NAMESPACE -o json | jq '[.items[] | select(.status.state == "attached" or .status.state == "detached")] | length')
  },
  "performance_metrics": {
    "deployment_duration": "Measured during deployment",
    "system_responsiveness": "$(time kubectl get nodes >/dev/null 2>&1 | grep real | awk '{print $2}' || echo 'unknown')"
  }
}
EOF

    log_deployment_step "INFO" "Deployment report generated: $report_file"
    cat "$report_file" | jq .
}

function orchestrate_production_deployment() {
    local strategy="${1:-balanced}"

    log_deployment_step "INFO" "Starting production Longhorn deployment orchestration"

    # Pre-deployment activities
    create_pre_deployment_backup
    validate_cluster_readiness

    # Perform deployment
    perform_rolling_deployment "$strategy"

    # Post-deployment validation
    validate_deployment_success

    # Generate report
    generate_deployment_report

    log_deployment_step "INFO" "Production deployment orchestration completed"

    echo ""
    echo "🚀 Deployment Summary"
    echo "===================="
    echo "📄 Deployment log: $MAINTENANCE_LOG"
    echo "💾 Backup directory: $BACKUP_DIR"
    echo "📊 Deployment report: Generated above"
    echo ""
    echo "Next steps:"
    echo "1. Monitor system performance"
    echo "2. Update monitoring and alerting"
    echo "3. Document deployment outcomes"
    echo "4. Plan next maintenance window"
}

# Execution
case "${1:-help}" in
    "deploy")
        orchestrate_production_deployment "${2:-balanced}"
        ;;
    "conservative")
        orchestrate_production_deployment "conservative"
        ;;
    "balanced")
        orchestrate_production_deployment "balanced"
        ;;
    "aggressive")
        orchestrate_production_deployment "aggressive"
        ;;
    "validate")
        validate_cluster_readiness
        validate_deployment_success
        ;;
    "backup")
        create_pre_deployment_backup
        ;;
    "report")
        generate_deployment_report
        ;;
    *)
        echo "Longhorn Production Deployment Manager"
        echo "====================================="
        echo ""
        echo "Usage: $0 {deploy|conservative|balanced|aggressive|validate|backup|report}"
        echo ""
        echo "Commands:"
        echo "  deploy [strategy]  - Full deployment orchestration (default: balanced)"
        echo "  conservative       - Conservative deployment strategy"
        echo "  balanced          - Balanced deployment strategy"
        echo "  aggressive        - Aggressive deployment strategy"
        echo "  validate          - Validate system readiness and health"
        echo "  backup            - Create pre-deployment backup"
        echo "  report            - Generate deployment report"
        ;;
esac

Conclusion

Kubernetes Longhorn storage node placement requires sophisticated configuration strategies that optimize performance, ensure proper resource allocation, and maintain operational efficiency across complex enterprise environments. By implementing advanced node selection patterns, multi-tier storage architectures, and comprehensive deployment procedures, platform engineering teams can build highly available storage systems that meet diverse performance and compliance requirements.

The key to successful Longhorn node placement lies in understanding your infrastructure capabilities, implementing intelligent resource allocation strategies, and maintaining comprehensive monitoring and automation systems that ensure optimal storage performance at scale. As your Kubernetes infrastructure grows, these patterns provide a solid foundation for building enterprise-grade storage systems that adapt to evolving business requirements while maintaining reliability and performance.

Regular assessment, automated optimization, and continuous improvement based on performance metrics and operational experience ensure your Longhorn storage deployment remains efficient, scalable, and aligned with organizational objectives.