Series MapLesson 25 / 60
Focus mode active/Press Alt+Shift+R to toggle/Esc to exit
Build CoreOrdered learning track

Resource Management

CPU request, CPU limit, memory request, memory limit, QoS class, OOMKilled, CPU throttling, eviction, node pressure, ephemeral storage, JVM sizing, resource quota, LimitRange, dan production review.

14 min read2699 words
PrevNext
Lesson 2560 lesson track12–33 Build Core
#kubernetes#resources#cpu#memory+4 more

Part 025 — Resource Management

Resource management adalah salah satu area Kubernetes yang paling sering diremehkan oleh backend engineer. Banyak engineer melihat resources.requests dan resources.limits sebagai angka administratif. Padahal angka ini menentukan:

  • apakah Pod bisa dijadwalkan,
  • node mana yang cukup kapasitasnya,
  • apakah JVM akan di-throttle,
  • apakah process akan dibunuh karena memory,
  • bagaimana cluster autoscaler mengambil keputusan,
  • bagaimana biaya cloud terbentuk,
  • bagaimana blast radius saat traffic naik,
  • apakah rollout bisa berjalan tanpa mengganggu workload lain.

Untuk Java/JAX-RS service, resource management lebih sensitif daripada aplikasi ringan karena JVM memiliki heap, metaspace, direct memory, thread stack, code cache, native memory, GC overhead, HTTP thread pool, connection pool, Kafka/RabbitMQ client thread, dan buffer internal.

CSG note: jangan mengasumsikan standar request/limit, JVM option, HPA metric, node type, node pool, quota, atau tuning rule di CSG. Angka-angka resource harus diverifikasi di manifest, Helm values, observability dashboard, autoscaling policy, incident notes, dan diskusi dengan platform/SRE/backend team.


1. Core Concept

Kubernetes resource management terutama berputar pada dua konsep:

request = kapasitas yang dipesan untuk scheduling
limit   = batas maksimum yang boleh dipakai runtime

Untuk CPU:

request.cpu = sinyal kebutuhan minimum untuk scheduler dan autoscaler
limit.cpu   = batas throttling CFS quota

Untuk memory:

request.memory = sinyal kebutuhan minimum untuk scheduler dan QoS
limit.memory   = batas keras; lewat batas dapat OOMKilled

Manifest sederhana:

resources:
  requests:
    cpu: "500m"
    memory: "768Mi"
  limits:
    cpu: "1"
    memory: "1Gi"

Mental model yang benar:

Kubernetes does not make your service efficient.
It only enforces boundaries and schedules based on declared assumptions.

Jika asumsi resource salah, Kubernetes akan menjalankan asumsi yang salah itu dengan sangat disiplin.


2. Why Resource Management Exists

Tanpa resource management, cluster akan berubah menjadi shared server liar:

  • satu service bisa menghabiskan CPU node,
  • satu memory leak bisa membunuh banyak workload,
  • scheduler tidak tahu kapasitas yang dibutuhkan Pod,
  • autoscaler tidak punya sinyal kapasitas,
  • cost attribution sulit,
  • production incident menjadi sulit diprediksi,
  • environment noisy-neighbor tidak terkendali.

Resource management memberi platform kemampuan untuk menjawab:

Can this Pod fit on a node?
How much capacity must be reserved?
Which workloads deserve guaranteed resources?
Which workloads may be evicted first?
When should the cluster add nodes?
Which team/service is consuming capacity?

Untuk senior backend engineer, ini bukan hanya urusan platform. Manifest resource yang buruk adalah bug arsitektural.


3. CPU Request

cpu request adalah jumlah CPU yang ingin dipesan oleh Pod untuk scheduling.

resources:
  requests:
    cpu: "500m"

500m artinya setengah vCPU.

Scheduler memakai request untuk menentukan apakah Pod bisa ditempatkan di node:

sum(request.cpu of scheduled Pods) <= allocatable CPU of node

CPU request tidak membatasi burst secara langsung. Jika tidak ada limit dan node punya idle CPU, container bisa memakai lebih dari request.

Practical implication:

request terlalu rendah  -> Pod mudah dijadwalkan tetapi bisa kekurangan CPU saat traffic naik.
request terlalu tinggi  -> capacity waste, bin packing buruk, node cost naik.

Untuk Java REST API, CPU request harus mempertimbangkan:

  • request rate normal,
  • p95/p99 latency target,
  • JSON serialization/deserialization,
  • TLS overhead jika ada,
  • DB/Kafka/RabbitMQ client work,
  • GC CPU overhead,
  • background thread,
  • startup/warmup CPU spike,
  • observability agent overhead.

4. CPU Limit

cpu limit membatasi CPU runtime menggunakan Linux CFS quota.

resources:
  limits:
    cpu: "1"

Jika container mencoba memakai lebih dari limit, process tidak dibunuh. Ia di-throttle.

CPU over limit -> throttling
Memory over limit -> potential OOMKilled

CPU throttling adalah silent latency killer.

Gejala umum:

  • p95/p99 latency naik,
  • request timeout meningkat,
  • GC pause tampak lebih mahal,
  • thread pool backlog naik,
  • Kafka/RabbitMQ consumer lag naik,
  • CPU usage terlihat "tidak 100%" tetapi aplikasi lambat,
  • container CPU throttled seconds meningkat.

Mental model penting:

A service can be CPU-throttled even when average CPU usage looks acceptable.

Karena throttling terjadi per enforcement period, workload bursty bisa terpukul keras walaupun rata-ratanya rendah.


5. CPU Limit and Java

JVM modern container-aware, tetapi CPU limit tetap berpengaruh pada keputusan internal JVM dan aplikasi.

Area yang terdampak:

  • GC thread count,
  • JIT compilation behavior,
  • ForkJoinPool parallelism,
  • HTTP server thread throughput,
  • Netty/worker event loop bila digunakan,
  • async executor,
  • Kafka consumer poll/processing,
  • RabbitMQ consumer processing,
  • database connection pool utilization,
  • batch job runtime.

Contoh failure:

Aplikasi diberi limit 500m.
Traffic naik.
GC butuh CPU untuk keep up.
CPU throttling terjadi.
GC makin tertunda.
Heap pressure naik.
Latency naik.
Readiness mulai gagal.
Pod restart atau rollout stuck.

Review rule:

Do not set CPU limit blindly on latency-sensitive Java services without checking throttling metrics.

Beberapa organisasi memilih:

  • set CPU request, tanpa CPU limit untuk service latency-sensitive,
  • set CPU limit untuk batch/noisy workload,
  • enforce policy berbeda per namespace/workload class.

Ini policy platform, bukan universal rule. Verifikasi internal.


6. Memory Request

memory request adalah memory yang dipesan untuk scheduling dan QoS.

resources:
  requests:
    memory: "768Mi"

Scheduler memakai request untuk menempatkan Pod di node.

Memory request juga berperan dalam eviction decision saat node pressure.

Jika request terlalu rendah:

  • Pod terlihat murah,
  • scheduler menempatkan terlalu banyak Pod di node,
  • node memory pressure meningkat,
  • Pod bisa dieviction lebih cepat,
  • autoscaler terlambat menambah node.

Jika request terlalu tinggi:

  • bin packing buruk,
  • node idle memory tinggi,
  • cost naik,
  • rollout lebih mudah Pending karena tidak ada node cukup besar.

Untuk Java, memory request harus dihitung dari total memory process, bukan heap saja.


7. Memory Limit

memory limit adalah batas keras memory container.

resources:
  limits:
    memory: "1Gi"

Jika process memakai memory melewati limit, Linux OOM killer dapat membunuh process. Kubernetes akan melaporkan status seperti:

Last State: Terminated
Reason: OOMKilled
Exit Code: 137

Memory limit berbeda dari heap limit.

container memory limit != JVM heap size

Container memory mencakup:

  • Java heap,
  • metaspace,
  • code cache,
  • direct buffer,
  • thread stacks,
  • GC native structures,
  • class metadata,
  • mmap files,
  • native libraries,
  • observability agent,
  • TLS buffers,
  • OS page cache contribution,
  • application native allocations.

Jika -Xmx terlalu dekat dengan container limit, OOMKilled sangat mungkin terjadi.


8. JVM Sizing Inside Kubernetes

Untuk Java 17+, pendekatan umum adalah memakai container-aware heap sizing:

-XX:MaxRAMPercentage=60
-XX:InitialRAMPercentage=30

Contoh:

env:
  - name: JAVA_TOOL_OPTIONS
    value: >-
      -XX:MaxRAMPercentage=60
      -XX:InitialRAMPercentage=30
      -XX:+ExitOnOutOfMemoryError

Jika container memory limit 1Gi dan MaxRAMPercentage=60, heap maksimum sekitar 614Mi.

Sisa memory harus cukup untuk:

  • metaspace,
  • direct memory,
  • thread stack,
  • native memory,
  • observability agent,
  • buffer client library.

Dangerous pattern:

memory limit: 1Gi
-Xmx: 1Gi

Ini hampir pasti menyisakan ruang native memory yang terlalu kecil.

Better mental model:

container limit = heap + non-heap + native + overhead + safety margin

9. Example Resource Sizing for Java/JAX-RS Service

Contoh awal, bukan angka universal:

resources:
  requests:
    cpu: "500m"
    memory: "768Mi"
  limits:
    cpu: "1"
    memory: "1Gi"
env:
  - name: JAVA_TOOL_OPTIONS
    value: >-
      -XX:MaxRAMPercentage=60
      -XX:InitialRAMPercentage=30
      -XX:+ExitOnOutOfMemoryError

Review pertanyaan:

  • Apakah traffic service CPU-bound atau IO-bound?
  • Apakah p95 latency stabil pada request CPU tersebut?
  • Apakah CPU throttling terjadi?
  • Berapa RSS process saat steady state?
  • Berapa memory setelah warmup?
  • Berapa memory saat traffic peak?
  • Apakah GC log menunjukkan pressure?
  • Apakah metaspace tumbuh?
  • Apakah direct memory digunakan oleh HTTP client/Kafka/RabbitMQ/Netty?
  • Apakah observability agent menambah overhead?

Production sizing harus berbasis observasi, bukan feeling.


10. QoS Class

Kubernetes menetapkan QoS class berdasarkan request/limit:

Guaranteed
Burstable
BestEffort

Guaranteed

Pod mendapat QoS Guaranteed jika setiap container punya CPU dan memory request/limit, dan request sama dengan limit.

resources:
  requests:
    cpu: "1"
    memory: "1Gi"
  limits:
    cpu: "1"
    memory: "1Gi"

Kelebihan:

  • eviction priority lebih baik,
  • capacity lebih deterministik.

Kekurangan:

  • CPU limit dapat menyebabkan throttling,
  • bin packing lebih kaku,
  • cost bisa lebih tinggi.

Burstable

Pod mendapat QoS Burstable jika request/limit ada tetapi tidak memenuhi syarat Guaranteed.

resources:
  requests:
    cpu: "500m"
    memory: "768Mi"
  limits:
    memory: "1Gi"

Ini umum untuk banyak service.

BestEffort

Pod mendapat QoS BestEffort jika tidak punya request/limit.

resources: {}

Ini biasanya buruk untuk production service.

BestEffort workload adalah kandidat eviction paling awal saat node pressure.


11. OOMKilled

OOMKilled berarti process dibunuh karena melewati memory boundary.

Typical signals:

kubectl describe pod <pod>
kubectl get pod <pod> -o jsonpath='{.status.containerStatuses[*].lastState.terminated.reason}'
kubectl logs <pod> --previous

Manifest symptom:

Reason: OOMKilled
Exit Code: 137

Common root causes:

  • heap terlalu besar,
  • memory limit terlalu kecil,
  • memory leak,
  • direct memory leak,
  • thread count terlalu banyak,
  • response/request payload terlalu besar,
  • caching tidak bounded,
  • observability agent overhead,
  • batch process membaca dataset besar sekaligus,
  • Kafka/RabbitMQ consumer prefetch/batch terlalu besar,
  • connection pool terlalu banyak,
  • native memory tidak terpantau.

Debugging path:

OOMKilled observed
  -> check last logs
  -> check memory usage before kill
  -> check JVM heap config
  -> check non-heap/native memory
  -> check traffic or batch size at time of kill
  -> check recent deployment/config change
  -> check node memory pressure
  -> decide: fix leak, tune heap, reduce batch, increase limit, or split workload

Do not fix every OOMKilled by simply raising memory limit. That can hide leaks and increase cost.


12. CPU Throttling

CPU throttling occurs when a container wants more CPU than its CPU quota allows.

Signals:

  • container_cpu_cfs_throttled_seconds_total,
  • container_cpu_cfs_throttled_periods_total,
  • latency p95/p99 spike,
  • queue lag,
  • rollout timeout,
  • health check timeout,
  • low throughput despite pending work.

Debugging path:

Latency spike or consumer lag
  -> check CPU usage
  -> check CPU throttling metrics
  -> check CPU limit
  -> check request/limit ratio
  -> check GC pause and CPU time
  -> check traffic spike
  -> tune CPU, thread pools, HPA, or remove inappropriate CPU limit

Important:

CPU usage alone is not enough.
You need throttling metrics.

13. Eviction

Eviction happens when node pressure forces kubelet to remove Pods.

Common pressure types:

  • memory pressure,
  • disk pressure,
  • PID pressure,
  • ephemeral storage pressure.

Eviction is not the same as OOMKilled.

OOMKilled: process exceeded container memory limit.
Evicted: kubelet removed Pod due to node pressure or resource pressure.

Debug commands:

kubectl describe pod <pod>
kubectl describe node <node>
kubectl get events --sort-by=.lastTimestamp

Possible root causes:

  • node overcommitted,
  • requests too low,
  • log volume too high,
  • emptyDir usage too large,
  • image garbage collection pressure,
  • runaway temporary files,
  • too many Pods per node,
  • burst workload consuming memory beyond request.

14. Node Pressure

Node pressure is a node-level condition that impacts scheduling and eviction.

Check node conditions:

kubectl describe node <node>

Look for:

MemoryPressure
DiskPressure
PIDPressure
Ready

Node pressure can create cascading symptoms:

DiskPressure
  -> image pulls fail
  -> logs cannot write
  -> Pods evicted
  -> rollout stuck
  -> service loses endpoints
  -> ingress returns 503

Backend engineers often debug only the service container and miss the node condition. Always check node state when Pod behavior looks inconsistent.


15. Ephemeral Storage

Ephemeral storage includes writable container layer, logs, emptyDir, and temporary files.

Manifest example:

resources:
  requests:
    ephemeral-storage: "512Mi"
  limits:
    ephemeral-storage: "1Gi"

Risky Java patterns:

  • writing large temp files to /tmp,
  • buffering upload/download locally,
  • generating large reports in filesystem,
  • unbounded log files inside container,
  • local cache without eviction,
  • heap dump written into container filesystem,
  • batch export to local disk before upload.

Production principle:

Container filesystem is not durable storage and not unlimited scratch space.

If workload needs temporary storage, make it explicit and bounded.


16. ResourceQuota

ResourceQuota limits aggregate resource usage in a namespace.

Example:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: team-quota
spec:
  hard:
    requests.cpu: "20"
    requests.memory: "40Gi"
    limits.cpu: "40"
    limits.memory: "80Gi"
    pods: "100"

Quota protects shared clusters from unlimited namespace growth.

Failure mode:

Deployment fails because namespace quota exceeded.

Debug:

kubectl describe quota -n <namespace>

Review questions:

  • Does the namespace quota match expected workload scale?
  • Will rollout with maxSurge exceed quota?
  • Will HPA scale be blocked by quota?
  • Are Jobs/CronJobs included in capacity planning?
  • Are dev/test namespaces constrained differently from prod?

17. LimitRange

LimitRange sets default/min/max request/limit rules inside a namespace.

Example:

apiVersion: v1
kind: LimitRange
metadata:
  name: default-limits
spec:
  limits:
    - type: Container
      defaultRequest:
        cpu: "250m"
        memory: "512Mi"
      default:
        cpu: "1"
        memory: "1Gi"
      min:
        cpu: "100m"
        memory: "128Mi"
      max:
        cpu: "2"
        memory: "4Gi"

LimitRange can silently add defaults if manifest omits resources.

Risk:

Developer thinks no CPU limit exists.
LimitRange injects CPU limit.
Service gets throttled.

Always inspect the effective Pod spec, not only source manifest.

kubectl get pod <pod> -o yaml

18. HPA Dependency on Requests

Horizontal Pod Autoscaler uses resource requests as denominator for utilization-based scaling.

Example:

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

If CPU request is 500m, 70% target means average 350m usage per Pod.

Bad request values distort HPA behavior:

request too low  -> HPA thinks utilization is high, scales too aggressively.
request too high -> HPA thinks utilization is low, scales too late.

Resource tuning and autoscaling cannot be separated.


19. Request Accuracy and Cost

Resource request drives reserved capacity. Reserved capacity drives node count. Node count drives cost.

Anti-patterns:

Everyone sets memory request to 2Gi because it is safe.
Cluster utilization drops.
Cost increases.
No one owns the waste.
Everyone sets request too low to save cost.
Node pressure rises.
Latency and eviction incidents increase.

Senior engineer stance:

Resource numbers are engineering claims. They must be backed by measurement.

Useful evidence:

  • p50/p95/p99 CPU usage,
  • p50/p95/p99 memory RSS,
  • throttling percentage,
  • GC metrics,
  • heap/non-heap metrics,
  • request rate,
  • queue lag,
  • restart/OOM history,
  • HPA scale events,
  • node utilization,
  • incident correlation.

20. Java Workload Type and Resource Profile

Different Java workload types need different resource assumptions.

REST API Service

Usually sensitive to:

  • CPU throttling,
  • p99 latency,
  • connection pool saturation,
  • GC pauses,
  • readiness timeout,
  • rolling update capacity.

Kafka/RabbitMQ Consumer

Usually sensitive to:

  • CPU per message,
  • batch size,
  • prefetch,
  • consumer lag,
  • graceful shutdown,
  • duplicate processing,
  • memory per batch.

Batch Job

Usually sensitive to:

  • memory spikes,
  • temporary storage,
  • timeout,
  • retry cost,
  • parallelism,
  • external API rate limits.

Camunda Worker / Workflow Worker

Usually sensitive to:

  • worker concurrency,
  • lock duration,
  • retry behavior,
  • long-running tasks,
  • idempotency,
  • graceful shutdown.

One-size-fits-all resource template is dangerous.


21. Resource Management and PostgreSQL/Kafka/RabbitMQ/Redis/Camunda

Resource settings of application Pods affect downstream dependencies.

PostgreSQL

If CPU limit is too low:

  • requests spend longer holding DB connections,
  • connection pool saturates,
  • transaction duration increases,
  • locks live longer,
  • DB sees more concurrent pressure.

If memory is too low:

  • large result processing can OOM,
  • retry storm can hit DB.

Kafka

If consumer CPU is throttled:

  • poll loop slows,
  • consumer lag increases,
  • rebalance risk increases,
  • duplicate processing risk may rise during unstable shutdown.

RabbitMQ

If consumer memory is too low:

  • high prefetch can accumulate messages,
  • OOMKilled can cause redelivery storm,
  • poison message handling may amplify load.

Redis

If app thread pool is throttled:

  • Redis calls queue up,
  • timeout/retry storm can amplify pressure,
  • cache stampede can occur.

Camunda

If workers are under-resourced:

  • job acquisition may lag,
  • lock duration may expire,
  • duplicate work/retry behavior can occur,
  • workflow SLA may be missed.

Resource management is not isolated to the Pod. It changes system-level behavior.


22. EKS, AKS, On-Prem, and Hybrid Considerations

EKS

Verify:

  • node instance type CPU/memory ratio,
  • VPC CNI IP capacity per node,
  • managed node group capacity,
  • Karpenter/Cluster Autoscaler behavior,
  • CloudWatch/Prometheus resource metrics,
  • pod density and ENI/IP limits,
  • spot node behavior if used.

AKS

Verify:

  • node pool VM SKU,
  • Azure CNI IP planning,
  • system vs user node pool,
  • Cluster Autoscaler config,
  • Azure Monitor metrics,
  • max pods per node,
  • spot/preemptible node usage.

On-Prem

Verify:

  • physical/VM node capacity,
  • overcommit policy,
  • storage pressure behavior,
  • monitoring fidelity,
  • upgrade/maintenance windows,
  • capacity procurement lead time.

Hybrid

Verify:

  • latency to downstream services,
  • retry behavior under throttling,
  • resource headroom during network degradation,
  • dependency timeout budget,
  • cross-site failover capacity.

23. Production Debugging Workflow

When a Java service is slow or unstable:

1. Check Pod status and restarts.
2. Check OOMKilled / Evicted / CrashLoopBackOff.
3. Check resource request/limit.
4. Check CPU usage and throttling.
5. Check memory RSS and limit proximity.
6. Check JVM heap/non-heap metrics.
7. Check GC pause and allocation rate.
8. Check thread pool and connection pool metrics.
9. Check HPA scale events.
10. Check node pressure.
11. Check downstream dependency latency.
12. Correlate with deployment/config/traffic change.

Useful commands:

kubectl top pod -n <namespace>
kubectl top node
kubectl describe pod <pod> -n <namespace>
kubectl describe node <node>
kubectl get events -n <namespace> --sort-by=.lastTimestamp
kubectl get quota -n <namespace>
kubectl describe limitrange -n <namespace>

Use dashboard metrics for historical analysis. kubectl top is only a snapshot.


24. Common Anti-Patterns

Anti-pattern: no requests/limits

resources: {}

Problems:

  • unpredictable scheduling,
  • BestEffort QoS,
  • eviction risk,
  • poor cost attribution.

Anti-pattern: copy-paste resource values

Every service uses 1 CPU / 2Gi memory.

Problems:

  • no workload-specific reasoning,
  • hidden cost waste,
  • poor autoscaling behavior.

Anti-pattern: Xmx equals memory limit

-Xmx1024m with memory limit 1Gi

Problems:

  • no native overhead room,
  • OOMKilled risk.

Anti-pattern: CPU limit too low for latency-sensitive service

Problems:

  • throttling,
  • p99 latency spike,
  • health probe failures.

Anti-pattern: fixing OOM by only increasing memory

Problems:

  • hides leak,
  • increases cost,
  • delays root cause analysis.

25. Correctness Concerns

Resource management affects correctness when timing matters.

Examples:

  • Kafka consumer exceeds max.poll.interval.ms because CPU is throttled.
  • RabbitMQ message processing is killed mid-flight due to OOM.
  • DB transaction stays open longer due to CPU starvation.
  • Camunda worker lock expires before completion.
  • CronJob overlaps because previous run was slowed by throttling.
  • Readiness fails during warmup because CPU is insufficient.

Correctness review must include resource review.


26. Performance Concerns

Performance signals to watch:

  • p95/p99 latency,
  • request throughput,
  • CPU throttling,
  • GC pause,
  • allocation rate,
  • heap usage,
  • RSS memory,
  • thread pool queue,
  • DB connection pool wait,
  • Kafka/RabbitMQ lag,
  • Redis timeout,
  • HPA scale lag.

Do not optimize based only on average CPU and memory.

Production incidents often live in tail behavior.


27. Security and Privacy Concerns

Resource settings can create security/privacy risks indirectly:

  • OOM heap dump may contain secrets/PII,
  • debug dump written to ephemeral storage may be collected by log agent,
  • crash loop may print sensitive env vars,
  • resource starvation can disable audit/log delivery,
  • noisy-neighbor behavior can become availability risk,
  • unbounded logs can fill node disk.

Review:

  • are heap dumps enabled?
  • where are dumps written?
  • are logs bounded?
  • are sensitive values logged during crash?
  • can one namespace exhaust shared capacity?

28. Cost Concerns

Cost drivers:

  • inflated memory requests,
  • unnecessary CPU requests,
  • low node utilization,
  • poor bin packing,
  • over-aggressive HPA,
  • oversized node pools,
  • multi-AZ overprovisioning,
  • large ephemeral storage,
  • excessive logs/metrics from crash loops,
  • NAT/LB cost amplified by retry storms.

Cost-aware does not mean underprovisioned. It means evidence-based capacity.


29. PR Review Checklist

When reviewing resource config:

  • Are CPU and memory requests defined?
  • Are CPU and memory limits defined intentionally?
  • Is CPU limit appropriate for latency-sensitive Java service?
  • Is memory limit compatible with JVM heap/non-heap/native overhead?
  • Is JAVA_TOOL_OPTIONS aligned with memory limit?
  • Is QoS class understood?
  • Is HPA denominator reasonable?
  • Are resources based on observed metrics?
  • Is startup/warmup considered?
  • Is peak traffic considered?
  • Are Kafka/RabbitMQ consumer batch/prefetch settings considered?
  • Is ephemeral storage bounded if used?
  • Could rollout maxSurge exceed quota/capacity?
  • Could HPA exceed namespace quota?
  • Is node pressure observable?
  • Are cost labels/ownership labels present?

30. Internal Verification Checklist

Verify internally:

  • standard resource request/limit policy,
  • whether CPU limits are required or optional,
  • Java heap sizing convention,
  • default JAVA_TOOL_OPTIONS,
  • namespace ResourceQuota,
  • namespace LimitRange,
  • HPA/VPA usage,
  • metrics source for CPU/memory/throttling,
  • dashboard for pod resource usage,
  • OOMKilled incident history,
  • CPU throttling incident history,
  • node pool capacity model,
  • autoscaler behavior,
  • spot/preemptible node usage,
  • resource review expectation in PR,
  • platform team guidance for Java services,
  • cost attribution labels,
  • escalation path for capacity issues.

31. Key Takeaways

Resource management is not decoration in Kubernetes manifest. It is the contract between application assumptions, scheduler behavior, node capacity, autoscaling, JVM runtime, production reliability, and cloud cost.

For Java/JAX-RS services:

memory limit must include heap + non-heap + native overhead
CPU settings must be validated against throttling and latency
requests must reflect real capacity needs
limits must be intentional, not copied blindly
HPA depends on request accuracy
OOMKilled and throttling must be treated as architecture signals

A senior engineer should be able to defend every resource number in a production manifest.

Lesson Recap

You just completed lesson 25 in build core. Use the series map if you want to review the broader track, or continue directly into the next lesson while the context is still warm.

Continue The Track

Keep the momentum while the lesson is still fresh. Move backward for review or continue forward into the next concept.