Default로는 container는 리소스 할당에 대한 제한이 없다.
No limit, No request : 하나의 파드가 모든 리소스를 사용할 수 있고, 2번째 Pod가 필요한 리소스를 할당받는데 방해한다.
Resource Request
- 어느 노드가 실행해주면 좋을 지를 scheduler가 판단한다.
- 컨테이너가 실행되기 위해 최소한으로 필요한 메모리의 양을 정의한다.
- Kubernetes 스케줄러는 이 값을 기반으로 Pod을 스케줄링할 노드를 결정합니다.
- Request는 보장된 자원으로, 다른 컨테이너가 이 메모리를 빼앗아 사용할 수 없습니다.
- Pod이 실행되려면 노드에 Request 값 이상의 사용 가능한 메모리가 있어야 함.
- 노드가 과부하 상태가 되면, Request가 낮은 Pod이 우선적으로 제거될 수 있음(Eviction).
Resource Limit
- 컨테이너가 사용할 수 있는 최대 리소스 양(메모리 상한선)을 정의한다.
- 컨테이너가 이 값을 초과하여 메모리를 사용하려고 하면 OOM(Out Of Memory) 오류가 발생하며, 해당 컨테이너가 재시작될 수 있다.
- OOM Kill: Pod Limit을 초과한 메모리를 사용 -> Limit 값을 더 높이기
- Limit을 설정하지 않으면 컨테이너는 필요한 만큼의 메모리를 사용하려고 시도한다.
- 파드의 node name 속성을 수정할 수 없다.
- 이미 존재하는 Pod에 노드를 assign하는 방법은 'binding object'나 POST request를 보내는 방법이 있다.
# pod-bind-defintion.yaml
apiVersion: v1
kind: binding
metadata:
name: nginx
target:
apiVersion: v1
kind: Node
name: <target Node>
# then send a POST request to the pod's binding API
$ curl --header "Content-type:application/json" --request POST --data '{"apiVersion":"v1", "kind": "Binding" ...}' http://$SERVER/api/v1/namespaces/default/pods
동작 원리
(1) Request 기준 스케줄링
- 스케줄러는 Pod의 Request 값과 노드의 가용 메모리를 비교하여 Pod를 배치한다.
- 예: Request가 500Mi인 Pod은 가용 메모리가 500Mi 이상인 노드에만 배치
(2) Limit 초과 시 동작
- 컨테이너가 Limit을 초과하면, OOM Killer가 작동하여 컨테이너를 Restart 시킨다.
(3) Request와 Limit을 모두 설정하지 않은 경우
- Request와 Limit이 지정되지 않으면, Namespace의 디폴트 값이 사용되거나 제한 없이 메모리를 사용할 수있다
Request < Limit
일반적으로 설정하는 방식으로, Pod이 최소 자원을 보장받으면서 필요 시 더 많은 자원을 사용할 수 있도록 설정.
Request == Limit
고정된 메모리 자원이 필요한 워크로드에 사용.예: 안정적으로 동작해야 하는 데이터베이스 컨테이너.
Request > Limit
잘못된 설정으로, 이 상태에서는 Pod이 스케줄링되지 않음.
Memory Request와 Limit의 비교
Memory Request | Memory Limit | |
역할 | 최소한으로 보장된 메모리 자원 | 최대 사용할 수 있는 메모리 자원 |
스케줄링 영향 | 노드 선택에 영향을 줌 | 스케줄링에 영향 없음 |
초과 사용 시 결과 | 요청한 양 이상으로 사용할 수 있음 | 초과 시 컨테이너 종료(OOM Kill) |
주요 목적 | 안정적인 자원 할당 | 자원 과도 사용 방지 |
# 노드 지정 실습
controlplane ~ ➜ cat nginx.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx
name: nginx
controlplane ~ ➜ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 0/1 Pending 0 19s <none> <none> <none> <none>
controlplane ~ ➜ kubectl describe pod nginx
Name: nginx
Namespace: default
Priority: 0
Service Account: default
Node: <none>
Labels: <none>
Annotations: <none>
Status: Pending
IP:
IPs: <none>
Containers:
nginx:
Image: nginx
Port: <none>
Host Port: <none>
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-hb55w (ro)
Volumes:
kube-api-access-hb55w:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
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>
controlplane ~ ➜ kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-69f9c977-mhmrr 1/1 Running 0 35m
coredns-69f9c977-prgmd 1/1 Running 0 35m
etcd-controlplane 1/1 Running 0 35m
kube-apiserver-controlplane 1/1 Running 0 36m
kube-controller-manager-controlplane 1/1 Running 0 35m
kube-proxy-5v5zd 1/1 Running 0 35m
kube-proxy-nrhv4 1/1 Running 0 35m
# 스케줄러가 running중이지 않은 것 확인 가능
controlplane ~ ➜ cat nginx.yaml
---
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
nodeName: node01 # 이 부분 추가
containers:
- image: nginx
name: nginx
$ kubectl replace --force -f nginx.yaml # 사용하거나 지우고 recreate 하거나
controlplane ~ ➜ kubectl apply -f nginx.yaml
pod/nginx created
controlplane ~ ➜ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 0/1 ContainerCreating 0 6s
controlplane ~ ➜ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 8s
# 같은 pod를 controlplane에 재할당하기.
controlplane ~ ➜ cat nginx.yaml
---
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
nodeName: controlplane
containers:
- image: nginx
name: nginx
controlplane ~ ➜ kubectl replace --force -f nginx.yaml
pod "nginx" deleted
pod/nginx replaced
controlplane ~ ➜ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 38s 10.244.0.4 controlplane <none> <none>
1GB = 1000,000,000 bytes
1GiB =
1KiB = 1,024 bytes
1MB = 1024 kB
1MB = 1000kB
1MiB = 1024 KiB
# Requests
[master manifests]$ cat pod-nginx-resources.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod-env
spec:
containers:
- name: nginx-container
image: nginx:1.14
ports:
- containerPort: 80
protocol: TCP
resources:
requests:
memory: 500Mi # 스케줄링 요청
cpu: 1
[master manifests]$ kubectl create -f pod-nginx-resources.yaml
pod/nginx-pod-env created
[master manifests]$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-pod-env 1/1 Running 0 53s 10.5.1.5 node2 <none> <none>
nginx-pod-env-node1 1/1 Running 0 2m18s 10.5.0.9 node1 <none> <none>
[master manifests]$ kubectl describe pod nginx-pod-env
Name: nginx-pod-env
...
Containers:
nginx-container:
Container ID: containerd://ed82eb0fede9588dde97770122f936f3f14df82beb064f47edc527189e5da1cb
Image: nginx:1.14
Image ID: docker.io/library/nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Sun, 18 Feb 2024 16:21:20 +0000
Ready: True
Restart Count: 0
Requests:
cpu: 1
memory: 500Mi
# 기존 파드 삭제
[master manifests]$ kubectl delete pod --all
pod "nginx-pod-env" deleted
pod "nginx-pod-env-node1" deleted
# limits
#request 없이 최대 쓸 수 있는 용량 제한
[master ~]$ cat > pod-nginx-resources.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod-resources
spec:
containers:
- name: nginx-container
image: nginx:1.14
ports:
- containerPort: 80
protocol: TCP
resources:
limits: # 쓸 수 있는 용량 제한
memory: 500Mi
cpu: 1
[master ~]$ kubectl create -f pod-nginx-resources.yaml
pod/nginx-pod-resources created
[master ~]$ kubectl describe pod nginx-pod-resources
Name: nginx-pod-resources
...
Containers:
nginx-container:
Container ID: containerd://c74703db987c7f9a5b60307b01337a7b92e7edcba74ff650c9fe941a28ebc479
Image: nginx:1.14
Image ID: docker.io/library/nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Mon, 19 Feb 2024 03:00:46 +0000
Ready: True
Restart Count: 0
Limits:
cpu: 1
memory: 500Mi
Requests:
cpu: 1
memory: 500Mi # limit만 걸었는데 동일한 값으로 request가 들어간다.
✔ requests만 하면 limits가 걸리지 않지만, limits은 requests도 걸린다.
# 각 워커노드의 최대 사용이 cpu 2인데, 2 core를 요청했을 때
[master ~]$ cat pod-nginx-resources.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod-resources
spec:
containers:
- name: nginx-container
image: nginx:1.14
ports:
- containerPort: 80
protocol: TCP
resources:
requests:
memory: 500Mi
cpu: 2
[master ~]$ kubectl create -f pod-nginx-resources.yaml
pod/nginx-pod-resources created
[master ~]$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-pod-resources 1/1 Pending 0 6s
# Pending : 스케줄링을 아직 받지 못한 상태
# OS, kubelet, 등등의 Pod가 동작중이라 CPU 2core 만큼의 여유가 없기 때문에 Pending이 된다.
# 추후 2core 할당이 가능한 노드가 생기면 바로 실행이 될 수 있다.
# requset, limits 둘 다 할당 시
[master ~]$ cat pod-nginx-resources.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod-resources
spec:
containers:
- name: nginx-container
image: nginx:1.14
ports:
- containerPort: 80
protocol: TCP
resources:
requests:
memory: 500Mi
cpu: 200m
limits:
memory: 1Gi
cpu: 1
[master ~]$ kubectl create -f pod-nginx-resources.yaml
pod/nginx-pod-resources created
[master ~]$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-pod-resources 1/1 Running 0 12s
[master ~]$ kubectl describe pod nginx-pod-resources
Name: nginx-pod-resources
...
Containers:
nginx-container:
Container ID: containerd://1638afea35ca5c5a9189ecd0132ff8cf8470437f529f3b6aa6e40f8b637786f4
Image: nginx:1.14
Image ID: docker.io/library/nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Mon, 19 Feb 2024 03:12:57 +0000
Ready: True
Restart Count: 0
Limits:
cpu: 1
memory: 1Gi
Requests:
cpu: 200m
memory: 500Mi
Environment: <none>
# Editing pods and Deployments
기존의 Pod에서는 specifcations(environment variables, service accounts, resource limits)을 edit할 수 없다.
- spec.containers[*].image
- spec.initContainers[*].image
- spec.activeDeadlineSeconds
- spec.tolerations
👩대안
# command를 사용해서 YAML 포맷 추출
$ kubectl get pods webapp -o yaml > my-new-pod.yaml
# 추출된 YAML파일 수정하기
$ vi my-new-pod.yaml
# 기존의 파드 삭제 및 재생성하기.
$ kubectl delete pod webapp
$ kubectl create -f my-new-pod.yaml
+ Deployment 관련 Pod 템플릿은 edit할 수 있다.
change가 발생하면 자동으로 delete 및 create가 된다.
# 실습
$ kubectl describe pod elephant
Name: elephant
Namespace: default
Priority: 0
Service Account: default
Node: controlplane/192.28.33.3
Start Time: Wed, 24 Apr 2024 14:19:35 +0000
Labels: <none>
Annotations: <none>
Status: Running
IP: 10.42.0.10
IPs:
IP: 10.42.0.10
Containers:
mem-stress:
Container ID: containerd://205218bf2ec491766a2a136fd3b77e624cecc118614824b725be7474be5c35fd
Image: polinux/stress
Image ID: docker.io/polinux/stress@sha256:b6144f84f9c15dac80deb48d3a646b55c7043ab1d83ea0a697c09097aaad21aa
Port: <none>
Host Port: <none>
Command:
stress
Args:
--vm
1
--vm-bytes
15M # 15Mi memory를 사용하고 있다. => OOMkill 발생
--vm-hang
1
State: Waiting
Reason: CrashLoopBackOff
Last State: Terminated
Reason: OOMKilled
Exit Code: 1
Started: Wed, 24 Apr 2024 14:23:06 +0000
Finished: Wed, 24 Apr 2024 14:23:06 +0000
Ready: False
Restart Count: 5
Limits:
memory: 10Mi
Requests:
memory: 5Mi
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-d4k4f (ro)
$ kubectl edit pod elephant
error: pods "elephant" is invalid
A copy of your changes has been stored to "/tmp/kubectl-edit-1916738946.yaml" # 임시파일이 저장된다.
error: Edit cancelled, no valid changes were saved.
$ kubectl replace --force -f /tmp/kubectl-edit-1916738946.yaml
pod "elephant" deleted
pod/elephant replaced
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
elephant 1/1 Running 0 22s
controlplane ~ ➜ kubectl describe pod elephant
Name: elephant
Namespace: default
Priority: 0
Service Account: default
Node: controlplane/192.28.33.3
...
Command:
stress
Args:
--vm
1
--vm-bytes
15M
--vm-hang
1
State: Running
Started: Wed, 24 Apr 2024 14:30:08 +0000
Ready: True
Restart Count: 0
Limits:
memory: 20Mi
Requests:
memory: 5Mi
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-d4k4f (ro)
반응형
'Container > Kubernetes' 카테고리의 다른 글
[K8S] ReplicationController (0) | 2024.02.19 |
---|---|
[K8S] Pod 환경 변수 설정 (0) | 2024.02.19 |
[K8S] pause container / Static container (0) | 2024.02.19 |
[K8S] init container (0) | 2024.02.18 |
[K8S] Liveness Probe (Self-healing) Pod (1) | 2024.02.16 |