# Pod: Resources Management

In Kubernetes, we can specify CPU and memory requests and limits for each containers using the resources field in your Deployment or Pod specification.

## Why is it important?

If we don't specify a CPU and Memory resource limit, The Container has no upper bound on the resources it can use. The Container could use all of the CPU and Memory resources available on the Node where it is running.

If The Container is running in a namespace that has a default CPU or Memory limit. The Container is automatically assigned the default limit. Cluster administrators can use a `LimitRange` to specify a default value for the CPU and Memory limit.

Imagine that we have multiple services, and one of our service currently have DDoS attack. If we are not limiting the resources that service's pods will consume all available resource and disrupting other services that we have on that node.

## Enabling Metrics Server

First we need to enable minikube metric server by using this command.

```bash
➜ minikube addons enable metrics-server
💡  metrics-server is an addon maintained by Kubernetes. For any concerns contact minikube on GitHub.
You can view the list of minikube maintainers at: https://github.com/kubernetes/minikube/blob/master/OWNERS
    ▪ Using image registry.k8s.io/metrics-server/metrics-server:v0.7.2
🌟  The 'metrics-server' addon is enabled
```

Wait few second until the metrics data populated. We can check the pod resource used by using this command.

```bash
➜ kubectl top pod 
NAME                         CPU(cores)   MEMORY(bytes)   
simple-go-685974475c-7484x   1m           2Mi             
simple-go-685974475c-87ccm   1m           2Mi             
simple-go-685974475c-d2kdv   1m           2Mi
```

## Specify Resources Limit

You define resource requests and limits in the container spec within a Pod or Deployment. Let's open our deployment file `deployment.yaml`. Add resources section in containers `server` like this.

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: simple-go
  labels:
    app: simple-go
spec:
  replicas: 3
  selector:
    matchLabels:
      app: simple-go
  template:
    metadata:
      labels:
        app: simple-go
    spec:
      containers:
      - name: server
        image: simple-go:latest
        imagePullPolicy: Never
        resources:
          requests:
            memory: "16Mi" # Minimum memory guaranteed
            cpu: "10m" # Minimum CPU guaranteed
          limits:
            memory: "64Mi" # Maximum memory allowed
            cpu: "30m" # Maximum CPU allowed 
        ports:
        - containerPort: 8080
        env:
        - name: DEFAULT_MESSAGE
          valueFrom:
            configMapKeyRef:
              name: simple-go-config
              key: DEFAULT_MESSAGE
```

### `resources.requests`

* Kubernetes guarantees this amount of resources to the container.
* Used for Pod scheduling (i.e., to decide which node can run the Pod).

### `resources.limits`

* Defines the maximum resources the container can use.
* If the container tries to exceed these limits:
  * Memory: The container is terminated with an OutOfMemory (OOM) error.
  * CPU: The container is throttled (limited to the specified CPU).

### Apply and Validate

Let's apply our deployment again using `kubectl apply -f deployment.yaml`. New sets of pods should be running. An then we can validate if our pods has correct limit by using describe command.

```yaml
➜ kubectl describe pods simple-go-685974475c-7484x 
Name:             simple-go-685974475c-7484x
Namespace:        default
Priority:         0
Service Account:  default
Node:             minikube/192.168.49.2
Start Time:       Mon, 27 Jan 2025 21:41:50 +0700
Labels:           app=simple-go
                  pod-template-hash=685974475c
Annotations:      <none>
Status:           Running
IP:               10.244.0.35
IPs:
  IP:           10.244.0.35
Controlled By:  ReplicaSet/simple-go-685974475c
Containers:
  server:
    Container ID:   docker://abcf9833e078e1af850ffd2e26ffcc32edd42b48ba653fe0e9c0861b769a9f6b
    Image:          simple-go:latest
    Image ID:       docker://sha256:534128017b433fa09e637cb2d943f7057a809c244632390bc75378a32dc3b12e
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Mon, 27 Jan 2025 21:41:52 +0700
    Ready:          True
    Restart Count:  0
    Limits:
      cpu:     30m
      memory:  64Mi
    Requests:
      cpu:     10m
      memory:  16Mi
    Environment:
      DEFAULT_MESSAGE:  <set to the key 'DEFAULT_MESSAGE' of config map 'simple-go-config'>  Optional: false
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-rznfx (ro)
Conditions:
  Type                        Status
  PodReadyToStartContainers   True 
  Initialized                 True 
  Ready                       True 
  ContainersReady             True 
  PodScheduled                True 
Volumes:
  kube-api-access-rznfx:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   Burstable
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:                      <none>
```

We can see above that resources request and limit are properly set. Next we will learn about horizontal pod scaling (HPA) so our service can spin up new pods if we got increasing traffic that existing pod cannot handle.

## Pod Resource

In Kubernetes version `v1.32` (still in alpha) we can specify resource allocation in **Pod** level instead of **Container**. This is very useful if we have multiple containers, so we only need to specify resource allocation once on **Pod** level. You can read more about it [here](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#example-2).

## References

* <https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/>
* <https://kubernetes.io/docs/tasks/configure-pod-container/assign-cpu-resource/>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://bagus-cahyono.gitbook.io/programming-notes/cka/06_pod_resources.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
