이야기박스
Kubernetes. 포드의 계산 리소스 관리 본문
# 개요
- Resource Request & Limit
- Pod의 request / limit
- QoS (우선순위)
- 플러그인 (LimitRange, ResourceQuota)
- 모니터링
# 포드 컨테이너의 리소스 요청
포드의 리소스 request(최소) & limit(최대)은 컨테이너에서 정의
apiVersion: v1
kind: Pod
metadata:
name: frontend
spec:
containers:
- name: db
image: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "password"
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
- name: wp
image: wordpress
resources:
requests:
memory: "64Mi" <-- 메비바이트
cpu: "250m" <-- 밀리코어
limits:
memory: "128Mi"
cpu: "500m"
위 리소스 조건을 충족하는 노드에서만 Pod가 생성 가능
# Request
## 스케줄러 시점
노드의 개별 리소스를 보는게 아니라 노드에 배포된 기존 포드가 요청한 리소스의 합계만 봄
스케줄러가 포드의 요청에 응답하는 방법
- 스케줄러는 포드에 맞지 않는 노드 목록부터 제거
- 남은 노드 목록 중, 우선순위 지정 방식에 따라 결정
## 우선순위 지정 방식
LeastRequestedPriority
리소스가 많이 남아있는 노드에 배포
MostRequestedPriority
리소스가 적게 남아 있는 노드에 배포
- 리소스를 균등하게 분배할 필요가 없는 클라우드 인프라 서비스 같은 곳에서 사용
- 노드를 적게 쓰는 장점
Note. Fit 하게 리소스를 분배
예를 들어, 1000의 CPU 리소스를 가진 노드에 배포를 진행하려고 함
* A Pod : 400
* B Pod : 300
두 Pod를 배포하였고, 이후 새로운 Pod를 배포하려고 한다.
* C Pod : 300
세 Pod 리소스의 합은 1000이니까 실행이 되어야 하지만, 실제로는 안됨.
kube-system과 같은 프로세스에서 사용하고 있기 때문
반드시 C Pod를 스케줄링 하고 싶으면, A나 B Pod를 삭제하여야 함
* CPU 리소스 제한이 없는 경우, 남은 리소스를 Pod의 비율 만큼 나눠갖게 됨
# Limit
CPU보다는 Memory에 치명적, 메모리는 압축이 안되기 때문에 다른 서비스에 영향 줄 수 있음
만약 Requests를 설정하지 않으면 limit과 동일하게 설정됨
## Overcommit
Request와 다르게 Limit은 노드의 리소스에 영향받지 않음
즉, 노드 리소스보다 크게 잡는게 가능
이렇게 100% 초과하면 특정 컨테이너가 강제 종료됨
==> 한계초과
## 한계초과
주로 메모리에서 이슈가 발생. (CPU는 I/O wait 등 사용량 조절이 가능함)
빈번히 실패하면 아래 상태를 표시 (책에서는 쿠버네티스를 다시 시작한다고 나옴, 번역 오류인가?)
$ kubectl get po
NAME READY STATUS RESTARTS AGE
memoryhog 0/1 CrashLoopBackOff 3 1m
==> CrashLoopBackoff이 Pod를 포기한걸 의미하는게 아니라, 재시작을 시도하는 대기시간이 길어졌다는걸 의미.
20, 40, 80.. 이런식으로 배수로 늘어나다가 최대 300초로 설정됨.
원인 분석
$ kubectl describe pod
Name: memoryhog
...
Containers:
main:
...
State: Terminated
Reason: OOMKilled
Exit Code: 137
Started: Tue, 27 Dec 2016 14:55:53 +0100
Finished: Tue, 27 Dec 2016 14:55:58 +0100
Last State: Terminated
Reason: OOMKilled
Exit Code: 137
Started: Tue, 27 Dec 2016 14:55:37 +0100
Finished: Tue, 27 Dec 2016 14:55:50 +0100
Ready: False
...
OOMKilled => 메모리가 부족해 종료
Note. Pod 종료
OOMKilled 이외에도 리소스가 부족하여 프로세스를 강제 종료시키는 경우가 있음.
뒤 QoS 파트에서 다시 설명
## 컨테이너 top
컨테이너는 항상 노드 전체의 메모리를 봄.
컨테이너가 사용 가능한 메모리 양의 한계를 설정해도 컨테이너는 이 한계를 인식하지 못함.
자바 애플리케이션 사용할 때, -Xmx 옵션을 사용해 힙을 지정하지 않으면 문제가 발생.
JVM에서 호스트의 총 메모리를 기반으로 동작하기 때문
단, -Xmx 옵션도 자바 off heap에는 영향을 주지 못함
마찬가지로 CPU도 영향이 있을 수 있음
예를들어 CPU나 메모리 리소스를 검색하여 실행하는 애플리케이션을 가정.
컨테이너에 제한된 리소스만 보는게 아니라 전체 리소스를 검색하게 될 것임
==> 치명적인 문제가 될 수도 있음
대안
- Downward API 사용 --> 컨테이너에 리소스 한계 전달
- cgroups 시스템에서 정보를 얻어올 것
# QoS
포드에 대하여 3가지 Qos 클래스 분류
- BestEffort (최하위 우선순위)
- Burstable (버스트 가능)
- Guranteed (최우선)
포드에 Qos 정의는 메니페스트 파일로 하는게 아니라, 리소스 Request + Limit 조합으로 파생됨
## BestEffort
우선순위가 가장 낮은 클래스
Request, Limit 모두 설정되지 않은 경우
단, 리소스가 충분하면 마음껏 쓸 수 있음 (다른 포드가 없다면)
## Guranteed
리소스 Request = Limit (둘 다 반드시 설정되어야 함)
각 컨테이너마다 설정
## Burstable
위 두 개를 제외한 나머지 케이스가 속함
## 다수의 컨테이너를 포함한 포드의 QoS
컨테이너 간의 클래스가 동일 한 경우 --> Pod의 클래스가 됨
컨테이너 간의 클래스가 다른 경우 --> Burstable
## 종료
앞에서 나왔던 OOMKilled 이외에 프로세스가 강제 종료되는 케이스
기본적으로 BestEffort --> Burstable --> Guranteed 순서로 종료.
만약 동일한 클래스를 가진다면?
OOM 점수를 토대로 종료
Note. OOM 점수의 계산
1. 가용 메모리 비율
2. 고정된 OOM 점수 조정
가용 메모리 = Pod의 사용중인 메모리 / 한계 메모리 * 100 %
# Plugin 1. LimitRange
Namespace 단위로 리소스 Request/Limit 지정하는 것
## 생성
apiVersion: v1
kind: LimitRange
metadata:
name: example
spec:
limits:
- type: Pod
min:
cpu: 50m
memory: 5Mi
max:
cpu: 1
memory: 1Gi
- type: Container
defaultRequest:
cpu: 100m
memory: 10Mi
default:
cpu: 200m
memory: 100Mi
min:
cpu: 50m
memory: 5Mi
max:
cpu: 1
memory: 1Gi
maxLimitRequestRatio:
cpu: 4
memory: 10
- type: PersistentVolumeClaim
min:
storage: 1Gi
max:
storage: 10Gi
# Plugin2. ResourceQuota
k8s 플러그인 중 하나
네임스페이스에서 사용할 수 있는 총 리소스 양을 제한하는 방법
## 생성
apiVersion: v1
kind: ResourceQuota
metadata:
name: cpu-and-mem
spec:
hard:
requests.cpu: 400m
requests.memory: 200Mi
limits.cpu: 600m
limits.memory: 500Mi
LimitRange와 같이 네임스페이스에 적용되지만, ResourceQuota는 개별 포드에 적용되지는 않는다.
## Persistent Storage
apiVersion: v1
kind: ResourceQuota
metadata:
name: storage
spec:
hard:
requests.storage: 500Gi
ssd.storageclass.storage.k8s.io/requests.storage: 300Gi
standard.storageclass.storage.k8s.io/requests.storage: 1Ti
쿠버네티스는 동적 PV 요청도 받을 수 있도록, 개별 할당량 정의할 수 있도록 구성되어 있음
## 객체 수 제한
리소스 뿐 아니라, 객체 수 제한도 가능함
apiVersion: v1
kind: ResourceQuota
metadata:
name: objects
spec:
hard:
pods: 10
replicationcontrollers: 5
secrets: 10
configmaps: 10
persistentvolumeclaims: 4
services: 5
services.loadbalancers: 1
services.nodeports: 2
ssd.storageclass.storage.k8s.io/persistentvolumeclaims: 2
## 특정 Scope의 할당량 지정
apiVersion: v1
kind: ResourceQuota
metadata:
name: besteffort-notterminating-pods
spec:
scopes:
- BestEffort
- NotTerminating
hard:
pods: 4
QoS 또는 파드의 상태를 통해서 ResourceQuota의 범위를 지정할 수 있음.
# 모니터링
Kubelet은 cAdvisor라는 에이전트를 포함하고 있음. 이 에이전트를 통하여 노드 전체의 리소스 소비 데이터를 수집함.
이후, 전체 클러스터의 통계를 중앙에서 수집하기 위하여 "힙스터"라는 컴포넌트가 필요
힙스터는 노드 중 하나에서 포드 형태로 실행되며, IP 형태로 접근 가능
## 실제 사용 조회
$ kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
minikube 170m 8% 556Mi 27%
$ kubectl top pod --all-namespaces
NAMESPACE NAME CPU(cores) MEMORY(bytes)
kube-system influxdb-grafana-2r2w9 1m 32Mi
kube-system heapster-40j6d 0m 18Mi
default kubia-3773182134-63bmb 0m 9Mi
kube-system kube-dns-v20-z0hq6 1m 11Mi
kube-system kubernetes-dashboard-r53mc 0m 14Mi
kube-system kube-addon-manager-minikube 7m 33Mi
## 에러 메시지
$ kubectl top pod
W0312 22:12:58.021885 15126 top_pod.go:186] Metrics not available for pod default/kubia-3773182134-63bmb, age: 1h24m19.021873823s
error: Metrics not available for pod default/kubia-3773182134-63bmb, age: 1h24m19.021873823s
이거 발생한 경우, 잠시 기다렸다가 다시 시도 (몇분)
## Grafana
influxDB를 이용
등록된 그라파나 클러스트 등록을 확인하려면
$ kubectl cluster-info
...
monitoring-grafana is running at
https://192.168.99.100:8443/api/v1/proxy/namespaces/kube-
system/services/monitoring-grafana
'Computer & Data > Orchestration' 카테고리의 다른 글
(작성중) Cheating Kubernetes & Docker (0) | 2019.11.19 |
---|---|
(작성중) Docker <none>:<none> images (0) | 2019.11.14 |
Intellij - Docker desktop; Spring Web app 이미지 만들기 (0) | 2019.10.16 |
Kubernetes 9. Deployments (3) | 2019.09.04 |
Kubernetes 8. Accesing pod metadata and other resources from applications (0) | 2019.09.03 |