Skip to content

Rightsizing: Machine Type Selection, VPA Recommendations, Insights

Rightsizing là tối ưu hóa hiệu quả chi phí bằng cách chọn machine type phù hợp với actual usage. Một VM chạy n2-standard-32 (32 vCPU, 128 GB) nhưng chỉ dùng 2 vCPU + 8 GB memory là sử dụng tài nguyên tồi.

Rightsizing có thể cắt giảm 20–50% chi phí mà không ảnh hưởng performance — nó là low-hanging fruit của cost optimization.


Understanding Utilization Patterns

Metrics to Track

CPU utilization = (actual_cpu_used / requested_cpu) × 100%
Memory utilization = (actual_memory_used / requested_memory) × 100%

GCP Insights tracks:
  - P50, P95, P99 utilization over last 30 days
  - Peak utilization
  - Average utilization

Example Analysis

VM: n2-standard-16 (16 vCPU, 64 GB memory)
Actual usage (30-day analysis):
  - CPU p95: 2 vCPU (87.5% unutilized)
  - Memory p95: 12 GB (81% unutilized)

Recommendation:
  → Resize to n2-standard-4 (4 vCPU, 16 GB)
  → Cost reduction: 75% (from $1000 to $250/month)

VPA: Vertical Pod Autoscaler

VPA automatically right-size Kubernetes pod resources (CPU/memory requests/limits) based on actual usage.

How VPA Works

  1. Monitoring phase:

    • Observes actual CPU/memory usage per pod
    • Collects metrics over 1–7 days
  2. Recommendation phase:

    • Calculates recommended CPU/memory requests
    • Formula: recommended = p95_usage × safety_margin (1.5x)
  3. Update phase (optional):

    • Recreates pod with new requests
    • Requires pod restart (causes temporary unavailability)

VPA Modes

1. "Off": Only recommend, don't act
   → Safe, good for testing

2. "Initial": Only apply on pod creation
   → Good for stateless services

3. "Recreate": Recreate pod when recommendation differs
   → Production use with PDB (Pod Disruption Budget)

4. "Auto": Dynamically update running pods (most aggressive)
   → Risky, can cause spikes in unavailability

VPA Configuration

yaml
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: my-app-vpa
spec:
  targetRef:
    apiVersion: "apps/v1"
    kind: Deployment
    name: my-app
  
  updatePolicy:
    updateMode: "Auto"  # or "Off", "Initial", "Recreate"
  
  resourcePolicy:
    containerPolicies:
    - containerName: app
      minAllowed:
        cpu: "100m"
        memory: "128Mi"
      maxAllowed:
        cpu: "4"
        memory: "4Gi"
      controlledResources: ["cpu", "memory"]

VPA Recommendation Process

Example pod:
  - Requested: 4 vCPU, 4 Gi memory
  - Actual p95 usage: 1 vCPU, 500 Mi memory

VPA recommendation:
  - CPU: 1 vCPU × 1.5 safety margin = 1500m (1.5 vCPU)
  - Memory: 500 Mi × 1.5 = 750 Mi

Updated pod will request 1.5 vCPU + 750 Mi
Cost impact: Roughly 40–50% reduction per pod

Recommender API: Machine Type Recommendations

GCP Recommender API provides machine type recommendations based on actual usage:

Getting Recommendations

bash
gcloud recommender recommendations list \
  --recommender=compute.rightsizingRecommender \
  --zone=us-central1-a

Output:

NAME: projects/.../recommendations/resize-instance-abc123
RECOMMENDATION: Resize to n2-standard-4
ESTIMATED_COST_REDUCTION: $500/month (50%)
PRIORITY: High
ACCEPTED_COUNT: 0

Implementation

bash
# Accept recommendation (creates compute instance change)
gcloud recommender recommendations mark-accepted \
  --recommender=compute.rightsizingRecommender \
  --zone=us-central1-a \
  --name=resize-instance-abc123

Machine Type Selection Strategy

Choosing Right Machine Type

Factors:

  1. CPU requirement (actual p95): Choose vCPU ≥ p95 usage
  2. Memory requirement (actual p95): Choose memory ≥ p95 usage
  3. Cost per vCPU/GB: Some series cheaper than others
  4. Regional availability: Some machine types unavailable in some regions
  5. Custom vs pre-defined: Custom machines (custom-N-M) finer grain but more overhead

Cost-Per-Resource Comparison

Machine Type     | vCPU | Memory | Cost/month | Cost/vCPU | Cost/GB
n2-standard-4    | 4    | 16 GB  | $190       | $47.5     | $11.9
n2-standard-8    | 8    | 32 GB  | $380       | $47.5     | $11.9  ← same ratio
c2-standard-4    | 4    | 16 GB  | $170       | $42.5     | $10.6  ← cheaper per resource
e2-standard-4    | 4    | 16 GB  | $100       | $25.0     | $6.2   ← lowest cost

Decision:
  - If need 3 vCPU + 12 GB: Choose e2-standard-4 (overkill but cheapest)
  - If need 6 vCPU + 24 GB: Choose n2-standard-8 (exact fit)
  - If need 2 vCPU + 8 GB: Choose e2-standard-2 (if exists) or custom-2-8192

Series Comparison

Series | Use Case              | Cost | Performance
N2     | General-purpose       | Mid  | Standard
E2     | Cost-sensitive        | Low  | Acceptable
C2     | Compute-optimized     | High | High CPU density
M2     | Memory-optimized      | High | High memory density

Rule of thumb:

  • 80% of workload = E2 (cost-conscious)
  • 15% of workload = N2 (balanced)
  • 5% of workload = C2/M2 (specialized)

Operational Patterns

Pattern 1: Right-Size on Renewal

Timeline:
  Month 1: Deploy app with conservative requests (4 vCPU, 4 Gi)
  Month 2–3: Monitor actual usage, receive recommendations
  Month 4: Resize, receive discount benefit
  
Trigger: Commit renewal (CUD expiry, annual review)

Pattern 2: Continuous VPA Monitoring

Setup:
  1. Deploy VPA in "Off" mode
  2. Monthly review recommendations
  3. For production, update via canary:
     - 10% pods new request → 90% old request
     - Monitor SLA (p99 latency, error rate)
     - If good, expand to 100%

Pattern 3: Batch Right-Sizing (one-time)

Process:
  1. Audit all instances (gcloud compute instances list)
  2. Get recommendations for each
  3. Batch apply low-risk ones (e.g., dev/test instances)
  4. Gradual prod instances (monitor SLA)
  
Result: 20–40% cost reduction in 1–2 weeks

Risks & Constraints

Risk 1: Oversizing (Still Happens)

Scenario: Recommendation says resize to n2-standard-4, but you choose n2-standard-8 "for headroom".

Impact: Lose 50% of potential savings.

Mitigation: Trust Recommender (VPA safety margin), document decision if override.

Risk 2: Undersizing Performance Degradation

Scenario: Right-size from n2-standard-16 to n2-standard-4, but p99 latency increases 2x.

Impact: User-facing SLA violation.

Mitigation:

  • Test in staging first
  • Monitor p99 latency during rollout
  • Have rollback plan (revert to previous size)

Risk 3: Memory Leaks Not Detected

Scenario: App has memory leak, grows from 2 GB/day to 20 GB over week. VPA recommendations based on p95, miss the leak.

Impact: VPA right-sizes to insufficient memory, app crashes during peak.

Mitigation:

  • Monitor memory trend (OOM incidents increase?) via alerting
  • Use VPA + manual cap: maxAllowed: 4Gi to prevent undersizing

Constraint: Regional Machine Type Availability

Not all machine types available in all regions:

us-central1: All types
asia-south1: Limited (E2 only, maybe N2)
europe-west1: Most types

If app must stay in specific region, right-sizing options limited.


VPA Edge Cases

Edge Case 1: High Variance Workload

Workload usage: [500m, 1.5, 4.8, 200m, 600m] vCPU

VPA p95: ~4.5 vCPU

Problem: Recommends 6.75 vCPU (4.5 × 1.5 safety), but average is 1.7. Oversizing again.

Fix: Use VPA + HPA (Horizontal Pod Autoscaler):

  • HPA scale pod count by load
  • VPA right-size each pod

Rightsizing at Scale

Automated Right-Sizing (Infrastructure as Code)

python
# Python script to auto-apply recommendations
import google.cloud.recommender_v1
import subprocess

client = google.cloud.recommender_v1.RecommenderClient()

for recommendation in client.list_recommendations(...):
    if recommendation.priority == "High":
        # Check if cost savings > threshold
        if estimated_savings > $100/month:
            # Accept recommendation
            client.mark_recommendation_claimed(...)
            # Trigger infrastructure update (Terraform, etc)
            subprocess.run(["terraform", "apply", ...])

Monthly Cost Savings Report

sql
SELECT
  DATE_TRUNC(usage_start_time, MONTH) as month,
  SUM(cost) as total_cost,
  LAG(SUM(cost)) OVER (ORDER BY DATE_TRUNC(usage_start_time, MONTH)) as prev_month,
  (LAG(SUM(cost)) - SUM(cost)) / LAG(SUM(cost)) * 100 as percent_reduction
FROM `project.billing_dataset.gcp_billing_export_v1`
WHERE service.description = 'Compute Engine'
GROUP BY month
ORDER BY month DESC;

References