Belajar Kubernetes - Episode 29 - Pengenalan dan Penjelasan Computational Resources

Belajar Kubernetes - Episode 29 - Pengenalan dan Penjelasan Computational Resources

Di episode ini kita akan coba bahas Kubernetes computational resources management. Kita akan mempelajari kenapa kita harus selalu specify CPU dan memory request dan limit, bagaimana resource allocation work, dan best practice untuk resource management.

Arman Dwi Pangestu
Arman Dwi PangestuApril 4, 2026
0 views
9 min read

Pendahuluan

Catatan

Untuk kalian yang ingin membaca episode sebelumnya, bisa click thumbnail episode 28 di bawah ini

Episode 28Episode 28

Di episode sebelumnya kita sudah belajar tentang Kubernetes Dashboard untuk managing cluster melalui web interface. Selanjutnya di episode 29 kali ini, kita akan coba bahas Computational Resources, specifically CPU dan memory management - salah satu aspek paling critical untuk running production workload di Kubernetes.

Catatan: Disini saya akan menggunakan Kubernetes Cluster yang di install melalui K3s.

Memahami resource request dan limit essential untuk cluster stability, efficient resource utilization, dan preventing satu application dari starving yang lain. Tanpa proper resource management, cluster kalian bisa become unstable, unpredictable, dan expensive.

Apa Itu Computational Resources?

Computational Resources di Kubernetes refer ke CPU dan memory yang container bisa consume. Kubernetes allow kalian untuk specify berapa banyak resource ini yang container need (request) dan maximum yang bisa used (limit).

Bayangkan resource seperti restaurant reservation - request adalah guaranteed table kalian (minimum resource), sementara limit adalah maximum number orang yang bisa kalian bawa (maximum resource). Restaurant (node) need to know both untuk manage seating effectively.

Key resource type:

  • CPU - Measured in core (atau millicore)
  • Memory - Measured in byte (Ki, Mi, Gi)
  • Ephemeral Storage - Temporary disk space
  • Extended Resources - Custom resource (GPU, etc.)

Request vs Limit

Memahami difference crucial.

Request

Request define minimum amount resource guaranteed ke container.

  • Digunakan oleh scheduler untuk decide node mana yang bisa run Pod
  • Container guaranteed amount ini
  • Node harus punya available resource >= request
  • Digunakan untuk resource reservation
  • Affect Pod scheduling decision

Limit

Limit define maximum amount resource yang container bisa use.

  • Container tidak bisa exceed amount ini
  • Jika exceeded, container throttled (CPU) atau killed (memory)
  • Digunakan untuk resource protection
  • Prevent resource exhaustion
  • Affect runtime behavior

Relationship Antara Request dan Limit

Kubernetesyml
resources:
    requests:
        memory: "256Mi"  # Guaranteed minimum
        cpu: "250m"      # Guaranteed minimum
    limits:
        memory: "512Mi"  # Maximum allowed
        cpu: "500m"      # Maximum allowed

Rule:

  • Request ≤ Limit (always)
  • Request = what you need
  • Limit = what you might need at peak

Kenapa Harus Selalu Specify Resource?

Mari kita pahami kenapa resource specification critical.

Problem 1: Unpredictable Scheduling

Tanpa request:

Kubernetesyml
# Bad: No resource request
spec:
    containers:
        - name: app
          image: myapp:latest
          # No resources specified

Issue:

  • Scheduler tidak tahu Pod requirement
  • Mungkin schedule di overloaded node
  • Bisa cause node resource exhaustion
  • Unpredictable performance

Dengan request:

Kubernetesyml
# Good: Clear resource request
spec:
    containers:
        - name: app
          image: myapp:latest
          resources:
              requests:
                  memory: "256Mi"
                  cpu: "250m"

Benefit:

  • Scheduler make informed decision
  • Pod scheduled di appropriate node
  • Predictable resource availability
  • Better cluster utilization

Problem 2: Resource Starvation

Tanpa limit:

Kubernetesyml
# Bad: No resource limit
spec:
    containers:
        - name: memory-leak-app
          image: leaky:latest
          # No limit - bisa consume semua node memory

Issue:

  • Satu Pod bisa consume semua node resource
  • Pod lain starved of resource
  • Node become unstable
  • Cascading failure

Dengan limit:

Kubernetesyml
# Good: Resource limit protect node
spec:
    containers:
        - name: memory-leak-app
          image: leaky:latest
          resources:
              limits:
                  memory: "512Mi"
                  cpu: "500m"

Benefit:

  • Container tidak bisa exceed limit
  • Pod lain protected
  • Node remain stable
  • Predictable behavior

Problem 3: Cost Inefficiency

Tanpa proper resource:

  • Over-provisioning waste money
  • Under-provisioning cause failure
  • No visibility into actual usage
  • Difficult to optimize cost

Dengan proper resource:

  • Right-sized allocation
  • Efficient resource utilization
  • Clear cost attribution
  • Easy to optimize

Problem 4: Quality of Service (QoS)

Kubernetes assign QoS class based on resource:

Guaranteed (highest priority):

  • Request = Limit untuk semua container
  • Best performance guarantee
  • Last to be evicted

Burstable (medium priority):

  • Request < Limit
  • Bisa use extra resource ketika available
  • Evicted sebelum Guaranteed

BestEffort (lowest priority):

  • No request atau limit
  • Use whatever available
  • First to be evicted

Tanpa resource specification, Pod dapat BestEffort QoS - worst class.

CPU Resources

CPU measured in core atau millicore.

CPU Unit

Kubernetesyml
# 1 CPU core
cpu: "1"
cpu: "1000m"  # Same as 1 core
 
# Half CPU core
cpu: "0.5"
cpu: "500m"   # Same as 0.5 core
 
# Quarter CPU core
cpu: "0.25"
cpu: "250m"   # Same as 0.25 core
 
# 100 millicore (0.1 core)
cpu: "100m"

CPU Behavior

CPU is compressible:

  • Container bisa throttled jika exceeding limit
  • Container tidak killed untuk exceeding CPU limit
  • Performance degrade tapi container continue running

Contoh:

Kubernetescpu-example.yml
apiVersion: v1
kind: Pod
metadata:
    name: cpu-demo
spec:
    containers:
        - name: app
          image: nginx:1.25
          resources:
              requests:
                  cpu: "250m"    # Guaranteed 0.25 core
              limits:
                  cpu: "500m"    # Max 0.5 core

Behavior:

  • Guaranteed 250 millicore
  • Bisa burst up to 500 millicore
  • Jika trying to use lebih dari 500m, get throttled
  • Never killed untuk CPU usage

CPU Throttling

Ketika container exceed CPU limit:

Kubernetesbash
# Check CPU throttling
kubectl top pod cpu-demo
 
# View detailed metric
kubectl describe pod cpu-demo

Throttled container show:

  • High CPU usage (near limit)
  • Increased response time
  • Degraded performance

Memory Resources

Memory measured in byte dengan standard unit.

Memory Unit

Kubernetesyml
# Byte
memory: "134217728"   # 128 MiB in byte
 
# Kibibyte (1024 byte)
memory: "131072Ki"    # 128 MiB
 
# Mebibyte (1024 KiB)
memory: "128Mi"       # 128 MiB
 
# Gibibyte (1024 MiB)
memory: "1Gi"         # 1 GiB
 
# Decimal unit (less common)
memory: "128M"        # 128 MB (1000-based)
memory: "1G"          # 1 GB (1000-based)

Catatan

Gunakan binary unit (Ki, Mi, Gi) untuk consistency dengan bagaimana operating system report memory.

Memory Behavior

Memory is incompressible:

  • Container tidak bisa throttled untuk memory
  • Jika exceeding limit, container killed (OOMKilled)
  • Pod mungkin restarted depending on restart policy

Contoh:

Kubernetesmemory-example.yml
apiVersion: v1
kind: Pod
metadata:
    name: memory-demo
spec:
    containers:
        - name: app
          image: nginx:1.25
          resources:
              requests:
                  memory: "256Mi"   # Guaranteed 256 MiB
              limits:
                  memory: "512Mi"   # Max 512 MiB

Behavior:

  • Guaranteed 256 MiB
  • Bisa use up to 512 MiB
  • Jika trying to use lebih dari 512 MiB, get OOMKilled
  • Pod restarted jika restartPolicy allow

OOMKilled (Out of Memory Killed)

Ketika container exceed memory limit:

Kubernetesbash
# Check Pod status
kubectl get pod memory-demo
 
# Output show OOMKilled
NAME          READY   STATUS      RESTARTS   AGE
memory-demo   0/1     OOMKilled   3          2m
 
# View event
kubectl describe pod memory-demo
 
# Event show:
# Reason: OOMKilled
# Message: Container exceeded memory limit

Contoh Resource Specification

Basic Web Application

Kubernetesweb-app.yml
apiVersion: apps/v1
kind: Deployment
metadata:
    name: web-app
spec:
    replicas: 3
    selector:
        matchLabels:
            app: web
    template:
        metadata:
            labels:
                app: web
        spec:
            containers:
                - name: nginx
                  image: nginx:1.25
                  ports:
                      - containerPort: 80
                  resources:
                      requests:
                          memory: "128Mi"
                          cpu: "100m"
                      limits:
                          memory: "256Mi"
                          cpu: "200m"

Database Application

Kubernetesdatabase.yml
apiVersion: apps/v1
kind: StatefulSet
metadata:
    name: postgres
spec:
    serviceName: postgres
    replicas: 1
    selector:
        matchLabels:
            app: postgres
    template:
        metadata:
            labels:
                app: postgres
        spec:
            containers:
                - name: postgres
                  image: postgres:15
                  resources:
                      requests:
                          memory: "512Mi"
                          cpu: "500m"
                      limits:
                          memory: "1Gi"
                          cpu: "1000m"
                  env:
                      - name: POSTGRES_PASSWORD
                        value: "secretpassword"

Background Worker

Kubernetesworker.yml
apiVersion: apps/v1
kind: Deployment
metadata:
    name: worker
spec:
    replicas: 5
    selector:
        matchLabels:
            app: worker
    template:
        metadata:
            labels:
                app: worker
        spec:
            containers:
                - name: worker
                  image: myworker:latest
                  resources:
                      requests:
                          memory: "256Mi"
                          cpu: "250m"
                      limits:
                          memory: "512Mi"
                          cpu: "500m"

Microservice dengan Sidecar

Kubernetesmicroservice.yml
apiVersion: apps/v1
kind: Deployment
metadata:
    name: api-service
spec:
    replicas: 3
    selector:
        matchLabels:
            app: api
    template:
        metadata:
            labels:
                app: api
        spec:
            containers:
                # Main application
                - name: api
                  image: myapi:latest
                  resources:
                      requests:
                          memory: "256Mi"
                          cpu: "250m"
                      limits:
                          memory: "512Mi"
                          cpu: "500m"
                # Sidecar (logging agent)
                - name: log-agent
                  image: fluent/fluentd:v1.16
                  resources:
                      requests:
                          memory: "64Mi"
                          cpu: "50m"
                      limits:
                          memory: "128Mi"
                          cpu: "100m"

Quality of Service (QoS) Class

Kubernetes assign QoS class automatically based on resource specification.

Guaranteed QoS

Requirement:

  • Setiap container punya request dan limit
  • Request = Limit untuk CPU dan memory
Kubernetesguaranteed-qos.yml
apiVersion: v1
kind: Pod
metadata:
    name: guaranteed-pod
spec:
    containers:
        - name: app
          image: nginx:1.25
          resources:
              requests:
                  memory: "256Mi"
                  cpu: "250m"
              limits:
                  memory: "256Mi"  # Same as request
                  cpu: "250m"      # Same as request

Karakteristik:

  • Highest priority
  • Best performance guarantee
  • Last to be evicted under pressure
  • Predictable resource allocation

Burstable QoS

Requirement:

  • At least satu container punya request atau limit
  • Request < Limit (atau hanya satu specified)
Kubernetesburstable-qos.yml
apiVersion: v1
kind: Pod
metadata:
    name: burstable-pod
spec:
    containers:
        - name: app
          image: nginx:1.25
          resources:
              requests:
                  memory: "128Mi"
                  cpu: "100m"
              limits:
                  memory: "256Mi"  # Higher than request
                  cpu: "200m"      # Higher than request

Karakteristik:

  • Medium priority
  • Bisa burst above request ketika resource available
  • Evicted sebelum Guaranteed, setelah BestEffort
  • Flexible resource usage

BestEffort QoS

Requirement:

  • No request atau limit specified
Kubernetesbesteffort-qos.yml
apiVersion: v1
kind: Pod
metadata:
    name: besteffort-pod
spec:
    containers:
        - name: app
          image: nginx:1.25
          # No resources specified

Karakteristik:

  • Lowest priority
  • No resource guarantee
  • First to be evicted under pressure
  • Unpredictable performance

Warning

Peringatan: Hindari BestEffort QoS di production. Selalu specify at least request untuk predictable behavior.

Checking QoS Class

Kubernetesbash
kubectl get pod guaranteed-pod -o jsonpath="{.status.qosClass}"
# Output: Guaranteed
 
kubectl get pod burstable-pod -o jsonpath="{.status.qosClass}"
# Output: Burstable
 
kubectl get pod besteffort-pod -o jsonpath="{.status.qosClass}"
# Output: BestEffort

Resource Quota

Limit total resource di namespace.

Membuat Resource Quota

Kubernetesresource-quota.yml
apiVersion: v1
kind: ResourceQuota
metadata:
    name: compute-quota
    namespace: development
spec:
    hard:
        requests.cpu: "10"        # Total CPU request
        requests.memory: "20Gi"   # Total memory request
        limits.cpu: "20"          # Total CPU limit
        limits.memory: "40Gi"     # Total memory limit
        pods: "50"                # Max number Pod

Apply quota:

Kubernetesbash
kubectl apply -f resource-quota.yml

Check quota usage:

Kubernetesbash
kubectl describe resourcequota compute-quota -n development

Output:

Kubernetesbash
Name:            compute-quota
Namespace:       development
Resource         Used   Hard
--------         ----   ----
limits.cpu       5      20
limits.memory    10Gi   40Gi
pods             15     50
requests.cpu     2.5    10
requests.memory  5Gi    20Gi

Quota Enforcement

Ketika quota exceeded:

Kubernetesbash
kubectl apply -f deployment.yml -n development
 
# Error: exceeded quota
Error from server (Forbidden): error when creating "deployment.yml": 
pods "app-xyz" is forbidden: exceeded quota: compute-quota, 
requested: requests.memory=1Gi, used: requests.memory=19.5Gi, 
limited: requests.memory=20Gi

Limit Range

Set default dan min/max resource untuk container.

Membuat Limit Range

Kuberneteslimit-range.yml
apiVersion: v1
kind: LimitRange
metadata:
    name: resource-limits
    namespace: development
spec:
    limits:
        # Container limit
        - type: Container
          default:
              memory: "512Mi"   # Default limit
              cpu: "500m"
          defaultRequest:
              memory: "256Mi"   # Default request
              cpu: "250m"
          max:
              memory: "2Gi"     # Maximum limit
              cpu: "2000m"
          min:
              memory: "64Mi"    # Minimum request
              cpu: "50m"
        # Pod limit
        - type: Pod
          max:
              memory: "4Gi"
              cpu: "4000m"

Apply limit range:

Kubernetesbash
kubectl apply -f limit-range.yml

Limit Range Behavior

Tanpa resource specified:

Kubernetesyml
# Pod definition tanpa resource
spec:
    containers:
        - name: app
          image: nginx:1.25
          # No resources specified

Kubernetes apply default:

Kubernetesyml
# Automatically applied oleh LimitRange
spec:
    containers:
        - name: app
          image: nginx:1.25
          resources:
              requests:
                  memory: "256Mi"  # From defaultRequest
                  cpu: "250m"
              limits:
                  memory: "512Mi"  # From default
                  cpu: "500m"

Monitoring Resource Usage

Menggunakan kubectl top

View node resource:

Kubernetesbash
kubectl top nodes

Output:

Kubernetesbash
NAME       CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
node-1     850m         42%    3.2Gi           40%
node-2     1200m        60%    4.5Gi           56%

View Pod resource:

Kubernetesbash
kubectl top pods

Output:

Kubernetesbash
NAME                    CPU(cores)   MEMORY(bytes)
web-app-abc123-xyz      150m         180Mi
database-def456-uvw     450m         850Mi
worker-ghi789-rst       200m         320Mi

View Pod resource di namespace:

Kubernetesbash
kubectl top pods -n production

Menggunakan Metrics Server

Metrics Server harus installed:

Kubernetesbash
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

Verify Metrics Server:

Kubernetesbash
kubectl get deployment metrics-server -n kube-system

Viewing Resource Allocation

Check node allocatable resource:

Kubernetesbash
kubectl describe node node-1

Output show:

Kubernetesbash
Capacity:
  cpu:                4
  memory:             8Gi
Allocatable:
  cpu:                3800m
  memory:             7.5Gi
Allocated resources:
  Resource           Requests      Limits
  --------           --------      ------
  cpu                2500m (65%)   5000m (131%)
  memory             4Gi (53%)     8Gi (106%)

Kesalahan Umum dan Pitfall

Kesalahan 1: No Resource Specification

Problem: Pod tanpa resource dapat BestEffort QoS.

Solusi: Selalu specify at least request:

Kubernetesyml
resources:
    requests:
        memory: "256Mi"
        cpu: "250m"

Kesalahan 2: Limit Terlalu Rendah

Problem: Container frequently OOMKilled atau throttled.

Solusi: Monitor actual usage dan adjust:

Kubernetesbash
# Monitor usage
kubectl top pod myapp
 
# Adjust limit based on actual usage
resources:
    limits:
        memory: "512Mi"  # Increased dari 256Mi

Kesalahan 3: Request Terlalu Tinggi

Problem: Pod tidak bisa scheduled karena over-requesting.

Solusi: Set request based on actual minimum need:

Kubernetesyml
resources:
    requests:
        memory: "128Mi"  # Reduced dari 512Mi
        cpu: "100m"      # Reduced dari 500m

Kesalahan 4: Request = Limit Always

Problem: Waste resource, prevent bursting.

Solusi: Allow bursting untuk variable workload:

Kubernetesyml
resources:
    requests:
        memory: "256Mi"  # Baseline
        cpu: "250m"
    limits:
        memory: "512Mi"  # Bisa burst 2x
        cpu: "500m"

Kesalahan 5: Ignore Multi-Container Pod

Problem: Lupa set resource untuk semua container.

Solusi: Specify resource untuk setiap container:

Kubernetesyml
containers:
    - name: app
      resources:
          requests:
              memory: "256Mi"
              cpu: "250m"
    - name: sidecar
      resources:
          requests:
              memory: "64Mi"   # Jangan lupa sidecar
              cpu: "50m"

Best Practice

Start dengan Monitoring

Sebelum set resource:

  1. Deploy tanpa limit initially (dengan request)
  2. Monitor actual usage untuk 1-2 minggu
  3. Set limit based on observed peak usage + buffer
  4. Continue monitoring dan adjust

Gunakan Appropriate Ratio

CPU:

  • Request: baseline usage
  • Limit: 2-3x request untuk burstable workload
  • Limit: 1x request untuk consistent workload

Memory:

  • Request: minimum needed
  • Limit: 1.5-2x request (smaller buffer daripada CPU)
  • Memory leak bisa cause OOMKill

Set Namespace Default

Gunakan LimitRange untuk consistent default:

Kubernetesyml
apiVersion: v1
kind: LimitRange
metadata:
    name: defaults
spec:
    limits:
        - type: Container
          defaultRequest:
              memory: "128Mi"
              cpu: "100m"
          default:
              memory: "256Mi"
              cpu: "200m"

Gunakan Resource Quota

Prevent namespace resource exhaustion:

Kubernetesyml
apiVersion: v1
kind: ResourceQuota
metadata:
    name: namespace-quota
spec:
    hard:
        requests.cpu: "10"
        requests.memory: "20Gi"
        limits.cpu: "20"
        limits.memory: "40Gi"

Different Resource untuk Different Workload

Web server:

Kubernetesyml
resources:
    requests:
        memory: "128Mi"
        cpu: "100m"
    limits:
        memory: "256Mi"
        cpu: "200m"

Database:

Kubernetesyml
resources:
    requests:
        memory: "1Gi"
        cpu: "500m"
    limits:
        memory: "2Gi"
        cpu: "1000m"

Batch job:

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

Document Resource Decision

Add annotation explaining resource choice:

Kubernetesyml
metadata:
    annotations:
        resources.note: "Based on 2-week monitoring, peak usage 180Mi/150m"
spec:
    containers:
        - name: app
          resources:
              requests:
                  memory: "256Mi"
                  cpu: "200m"
              limits:
                  memory: "512Mi"
                  cpu: "400m"

Troubleshooting Resource Issue

Pod Pending Karena Insufficient Resource

Kubernetesbash
kubectl describe pod myapp
 
# Event show:
# Warning  FailedScheduling  pod has unbound immediate PersistentVolumeClaims
# 0/3 nodes are available: 3 Insufficient cpu.

Solusi:

  1. Reduce resource request
  2. Add more node
  3. Delete unused Pod
  4. Scale down workload lain

Pod OOMKilled

Kubernetesbash
kubectl get pod myapp
# STATUS: OOMKilled
 
kubectl describe pod myapp
# Reason: OOMKilled
# Exit Code: 137

Solusi:

  1. Increase memory limit
  2. Fix memory leak di application
  3. Optimize application memory usage
  4. Gunakan memory profiling tool

CPU Throttling

Kubernetesbash
kubectl top pod myapp
# CPU usage at atau near limit
 
# Check throttling metric
kubectl describe pod myapp

Solusi:

  1. Increase CPU limit
  2. Optimize application CPU usage
  3. Scale horizontally (more replica)
  4. Profile application untuk CPU hotspot

Node Resource Pressure

Kubernetesbash
kubectl describe node node-1
# Conditions:
#   MemoryPressure   True
#   DiskPressure     False

Solusi:

  1. Evict BestEffort Pod
  2. Add more node
  3. Reduce resource request
  4. Implement resource quota

Penutup

Pada episode 29 ini, kita telah membahas Computational Resources di Kubernetes secara mendalam. Kita sudah belajar kenapa resource request dan limit critical, bagaimana mereka affect scheduling dan runtime behavior, dan best practice untuk resource management.

Key takeaway:

  • Selalu specify resource untuk predictable behavior
  • Request guarantee minimum resource untuk scheduling
  • Limit prevent resource exhaustion dan protect node
  • CPU is compressible - throttled ketika exceeded
  • Memory is incompressible - OOMKilled ketika exceeded
  • QoS class determine eviction priority
  • Guaranteed QoS require request = limit
  • Burstable QoS allow flexible resource usage
  • BestEffort QoS should be avoided di production
  • Resource Quota limit namespace resource usage
  • Limit Range set default dan boundary
  • Monitor actual usage sebelum set limit
  • Different workload need different resource profile
  • Request affect scheduling, limit affect runtime
  • Gunakan kubectl top untuk monitor resource usage

Proper resource management fundamental untuk running stable, efficient Kubernetes cluster. Dengan memahami dan implementing resource request dan limit, kalian ensure predictable application behavior, efficient resource utilization, dan cluster stability.

Bagaimana, makin jelas kan tentang Computational Resources di Kubernetes? Jadi, pastikan tetap semangat belajar dan nantikan episode selanjutnya!

Catatan

Untuk kalian yang ingin melanjutkan ke episode selanjutnya, bisa click thumbnail episode 30 di bawah ini

Episode 30Episode 30

Related Posts