프로메테우스는 PromQL을 사용하여 메트릭을 수집한다. Pod 와 Service 단위의 모니터링을 개발 해야 할 때 , 프로메테우스에서는
쿼리를 통한 가공이 필요하다.
- container_cpu_seconds_total 데이터와 container_memory_work_bytes 데이터를 가공
- 메모리는 정량적인 사용량 기반으로 메트릭을 단순하게 뽑아낼수 있는데, cpu는 전체 core에 대한 영향을 받기 때문에 함수 이용
1. 컨테이너 또는 POD의 리소스 사용량 (CPU, 메모리)에 대한 메트릭을 계산
2. 프로메테우스의 함수에 대해서 이해
CPU는 분모가 명확하지 않기때문에, sum 또는 rate 함수를 적용해야한다.
1. CPU 계산법
- 컨테이너는 쿠버네티스의 가장 최소단위로 한개의 POD안에 여러개 또는 단일 컨테이너로 구성되있다.
- 컨테이너 cpu 사용량
# ---컨테이너 전부다
container_cpu_usage_seconds_total
# ---컨테이너 namespace
container_cpu_usage_seconds_total{namespace="istio-system"}
# ---컨테이너 / namespace ^ pod name 분류해서 가져오기
container_cpu_usage_seconds_total{namespace="kube-system",pod="kube-apiserver-node1"}
- 기준은 어떻게 될까? cpu 사용량을 구하기 위해서 위와 같이 container_cpu_usage_seconds_total 지표를 이용
container_cpu_usage_seconds_total 지표의 값은 초 (seconds) 단위
메트릭은 컨테이너의 CPU 사용 시간을 초 단위로 측정하고 있는것이다. 하지만, 해당 값은 분모를 모르기때문에 객관적인 지표로 이용하기에는 무리가 있다.
top 명령어로 확인 해보면?
▶ 실시간 cores 사용량을 확인 할수 있음.
▶ 밀리코어 단위로 측정됨
▶ 절대값은 아님 ( 분모를 모르기때문 = 노드의 전체 코어수를 모르기 때문 )
- 따라서 avg / rate / sum 등의 함수를 사용해야 한다.
(koo@homeeks:N/A) [root@home-eks-host ~]# kubectl top pod -n kube-sysetm
root@node1:~# kubectl top pod -n kube-system
NAME CPU(cores) MEMORY(bytes)
calico-kube-controllers-6dfcdfb99-lft6m 4m 43Mi
calico-node-ck765 13m 115Mi
calico-node-f65mc 12m 115Mi
calico-node-fd5h6 13m 114Mi
# 단위 접미사 m은 " 1/1000 코어 "를 나타냅니다
- 단위 접미사 m은 밀리코어를 나타내는 단위로 1000밀리코어는 1코어이다.
- 왜 cpu를 측정하는 단위가 시간 (초) 단위일까? 이는 CFS 스케쥴러와 관련이 깊다.
- CPU 사용률을 시간 단위로 측정하는 이유는 CFS가 공정한 스케줄링을 유지하기 위해 각 태스크의 CPU 사용 시간을 지속적으로 모니터링하기 때문입니다.
- CFS는 초 단위로 CPU 사용 시간을 계산하여 각 태스크가 얼마나 CPU를 점유했는지를 확인하고, 이를 통해 전체 시스템의 효율성과 성능을 유지합니다.
# 현재 CFS 주기 확인
cat /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_period_us
10000
# CFS 주기를 200ms(200000μs)로 변경
echo 200000 > /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_period_us
리눅스는 CPU Core 를 어떤 형태로 사용 할까?
리눅스는 기본적으로 100ms ( 기본 주기 100밀리세컨드 ) 주기를 가지고 동작합니다.
Kubernetes와 CFS의 스케줄링 방식에 따라, 100ms 주기로 쿼터 제어가 이루어질 때, kubectl top pod로 측정된
990밀리코어(0.99코어) CPU 사용량을 가지는 Pod는,
10개의 주기 중 9번은 CPU 1개를 전부 점유하고, 나머지 1번은 90밀리코어만 점유하는 방식으로 스케줄링됩니다. 이러한 스케쥴러의 방식은 병렬형 어플리케이션의
경우 캐시미스 또는 컨텍스트 스위칭이 발생 할 가능성이 높아 cpuset 또는 cpu pinning을 사용 하는걸 권장합니다.
병렬 처리를 위해 CPU를 많이 소모하는 워크로드를 수행해야 한다면 cpu-shares, cpus 혹은 cpu-period + cpu-quota 옵션보다는 cpuset-cpus 옵션을 사용하면 특정 컨테이너가 특정 CPU에서만 동작하는 CPU 친화성(Affinity)을 보장할 수 있고, CPU 캐시 미스 또는 컨텍스트 스위칭과 같이 성능을 하락시키는 요인을 최소화할 가능성이 높아집니다.
왜 함수를 사용해야 할까?
CPU 사용률은 avg,rate,sum 함수들을 사용하여 필요한 데이터를 구합니다.
CPU 사용률을 계산 할때는 rate 함수를 통해 계속적으로 증가하는 메트릭에 사용되며 주어진 범위 내에서 시계열의 초당 평균 증가율을 계산 해야합니다.
즉 CPU 사용량을 나타내는 메트릭은 누적된 CPU시간을 나타내기에 계속해서 증가한다. (프로메테우스 그래프)
따라서 함수를 통해 주어진 범위 내에서 초당 평균 증가율을 계산 하여 현재 이용율을 구할수 있습니다.
- 노드의 cpu 사용률
- ㅇ
# node의 cpu 사용률
sum by (instance,nodename) (irate(node_cpu_seconds_total{mode!~"guest.*|idle|iowait"}[1m]))
# node_cpu_seconds_total의 mode는 idle, nice, user, system으로 나뉜다.
# idle 모드를 제외한 나머지 모드에서 cpu는 계산 중 상태이므로, 100%에서 idle한 비율을 빼는 방법을 사용한다.
# 60초 동안 idle한 시간이 0초라면 cpu는 100%이고, idle한 시간이 60초이면 cpu는 0%다.
# 이렇게 계산 할수도 있다.
((1- (avg (rate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance)))*100) * on(instance) group_left(nodename) (sum by (instance, nodename) (node_uname_info))
iowait 시간을 cpu 사용율에 포함해야 할까에 대한 의견은 환경에 따라 다를수 있지 않을까?
iowait 하는 시간도 cpu를 점유하고 있는 것은 마찬가지라고 생각 하는데 어플리케이션의 특성에 따라 다를수 있지만
만약 당신의 환경에서 iowait 시간이 생각보다 많이 cpu 리소스를 잡아먹는 환경이라면 보수적인 계산을 위해
iowait 시간도 cpu 사용율에 포함해야 할것이다.
왜냐하면 메모리의 할당 시간은 상황과 환경 에 따라 page_fault까지 발생할수 있고 그로인해 물리적인 메모리에서 데이터를 읽어와야 하는 경우 특정 numa 노드에서는 remote access가 발생할수도 있다.
이러한 Kernel 단의 성능 지연을 추적하기 위해 최근들어 ebpf와 같은 커널 Observability를 높이는 기술등이
쿠버네티스 커뮤니티에서 최근 각광받고있는 기술중에 하나이다.
2. Memory 계산법
메모리 사용율에 대한 내용은 사실상 다룰것이 많이 없다. 분모가 필요하지도 않고 함수가 필요하지도 않기 때문이다.
이포스팅에서 다루진 않지만. 리눅스에서 메모리의 관리에 대해 단순하게 생각하는 형태가 많기 때문에
다음 시간에는 쿠버네티스 운영 환경에서 메모리를 어떤식으로 관리하고 모니터링하는것이 맞을까에 대한 주제로 내용을 다뤄보고 싶다.
✅ 컨테이너 memory 사용량
# 컨테이너 메모리 사용량
sum by (instance) (container_memory_usage_bytes)
* on(instance) group_left(nodename) (sum by (instance, nodename) (node_uname_info))
✅ 노드 memory 사용량
# 노드 메모리 사용량
sum by(instance) (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes)
* on(instance) group_left(nodename) (sum by(instance, nodename) (node_uname_info))
# 노드 메모리 사용율 (%)
(sum by(instance) (100 -((node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100)))
*on(instance) group_left(nodename) (sum by (instance, nodename) (node_uname_info))
'컨테이너 > Prometheus' 카테고리의 다른 글
[Prometheus] helm으로 프로메테우스 스택 설치하기 (0) | 2023.06.10 |
---|---|
[프로메테우스] (3) CAdvisor란? (0) | 2020.12.16 |
[프로메테우스] (2) 쿠버네티스 모니터링 : "프로메테우스" (0) | 2020.12.16 |
[프로메테우스] (1) 프로메테우스 설치 (0) | 2020.12.11 |