Easy Deploy Blog
Auto-scaling Best Practices for Production Workloads

Auto-scaling Best Practices for Production Workloads

March 12, 2024
12 min read
Farhaan Patel

Auto-scaling is crucial for maintaining optimal performance while controlling costs in production environments. This comprehensive guide covers the best practices for implementing effective auto-scaling strategies.

Understanding Auto-scaling Types

Horizontal Pod Autoscaler (HPA)

HPA scales the number of pod replicas based on observed metrics:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web-app
  minReplicas: 2
  maxReplicas: 50
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80

Vertical Pod Autoscaler (VPA)

VPA adjusts CPU and memory requests/limits for individual pods:

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: web-app-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web-app
  updatePolicy:
    updateMode: "Auto"
  resourcePolicy:
    containerPolicies:
    - containerName: web
      maxAllowed:
        cpu: 2
        memory: 4Gi
      minAllowed:
        cpu: 100m
        memory: 128Mi

Metric Selection Strategy

CPU-based Scaling

Best for CPU-intensive applications:

metrics:
- type: Resource
  resource:
    name: cpu
    target:
      type: Utilization
      averageUtilization: 70

Memory-based Scaling

Crucial for memory-intensive workloads:

metrics:
- type: Resource
  resource:
    name: memory
    target:
      type: Utilization
      averageUtilization: 80

Custom Metrics

For application-specific scaling decisions:

metrics:
- type: External
  external:
    metric:
      name: queue_depth
      selector:
        matchLabels:
          queue: "processing"
    target:
      type: AverageValue
      averageValue: "10"

Scaling Policies and Behavior

Prevent Thrashing

Configure scaling policies to avoid rapid fluctuations:

behavior:
  scaleDown:
    stabilizationWindowSeconds: 300
    policies:
    - type: Percent
      value: 10
      periodSeconds: 60
  scaleUp:
    stabilizationWindowSeconds: 60
    policies:
    - type: Percent
      value: 50
      periodSeconds: 60
    - type: Pods
      value: 4
      periodSeconds: 60
    selectPolicy: Max

Gradual Scaling

Implement gradual scaling for better stability:

behavior:
  scaleUp:
    policies:
    - type: Pods
      value: 2
      periodSeconds: 60
    - type: Percent
      value: 25
      periodSeconds: 60
    selectPolicy: Min

Production Considerations

Resource Requests and Limits

Properly set resource requests for accurate scaling:

resources:
  requests:
    cpu: 500m
    memory: 512Mi
  limits:
    cpu: 1
    memory: 1Gi

Readiness Probes

Ensure pods are ready before receiving traffic:

readinessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 10
  periodSeconds: 5
  timeoutSeconds: 3
  failureThreshold: 3

PodDisruptionBudgets

Maintain availability during scaling operations:

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web-app-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: web-app

Monitoring and Alerting

Key Metrics to Monitor

Setting Up Alerts

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: autoscaling-alerts
spec:
  groups:
  - name: autoscaling
    rules:
    - alert: HighScalingFrequency
      expr: increase(kube_hpa_status_current_replicas[5m]) > 5
      for: 2m
      labels:
        severity: warning
      annotations:
        summary: "HPA scaling too frequently"

Cost Optimization

Right-sizing Instances

Use appropriate instance types for your workload:

Spot Instances

Leverage spot instances for cost savings:

spec:
  template:
    spec:
      nodeSelector:
        node-type: spot
      tolerations:
      - key: spot-instance
        operator: Equal
        value: "true"
        effect: NoSchedule

Testing Auto-scaling

Load Testing

Simulate realistic traffic patterns:

# Using k6 for load testing
k6 run --vus 100 --duration 30m load-test.js

Chaos Engineering

Test scaling behavior under failure conditions:

apiVersion: litmuschaos.io/v1alpha1
kind: ChaosEngine
metadata:
  name: autoscaling-chaos
spec:
  chaosServiceAccount: litmus-admin
  experiments:
  - name: pod-cpu-hog
    spec:
      components:
        env:
        - name: CPU_CORES
          value: "2"

Common Pitfalls and Solutions

Problem: Scaling Too Aggressively

Solution: Implement gradual scaling policies

Problem: Insufficient Monitoring

Solution: Set up comprehensive metrics and alerting

Problem: Resource Conflicts

Solution: Use VPA and HPA together carefully

Problem: Cold Start Delays

Solution: Implement warm-up strategies and readiness probes

Advanced Patterns

Predictive Scaling

Use machine learning for proactive scaling:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: predictive-hpa
  annotations:
    predictive.autoscaling/enabled: "true"
    predictive.autoscaling/model: "linear-regression"

Multi-dimensional Scaling

Scale based on multiple metrics:

metrics:
- type: Resource
  resource:
    name: cpu
    target:
      type: Utilization
      averageUtilization: 70
- type: External
  external:
    metric:
      name: requests_per_second
    target:
      type: AverageValue
      averageValue: "1000"

Conclusion

Effective auto-scaling requires careful planning, proper monitoring, and continuous optimization. Start with simple CPU-based scaling and gradually add more sophisticated metrics and policies as your understanding of your application’s behavior improves.

Remember to always test your auto-scaling configuration in staging environments before deploying to production, and monitor the results closely to ensure optimal performance and cost efficiency.