Skip to content

필사 모드: CPU steal time과 스로틀링 — top의 st, 버스터블 크레딧, CFS 쿼터를 가르는 법

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

들어가며 — CPU는 40%인데 p99가 3초입니다

용량 회의에서 가장 자주 나오는 문장이 있습니다. "CPU 사용률이 40%밖에 안 되니까 CPU 문제는 아닙니다." 이 문장은 세 가지 상황에서 틀립니다. 그리고 그 세 가지가 이 글의 전부입니다.

top -bn1 | head -4
# top - 14:22:31 up 9 days,  4:12,  1 user,  load average: 3.21, 3.04, 2.88
# Tasks: 214 total,   2 running, 212 sleeping,   0 stopped,   0 zombie
# %Cpu(s): 31.2 us,  4.1 sy,  0.0 ni, 42.6 id,  0.4 wa,  0.0 hi,  0.5 si, 21.2 st

마지막 열의 21.2 st가 이 글의 출발점입니다. 유휴가 42.6%로 보이지만 21.2%는 이미 남에게 뺏긴 시간이고, 애플리케이션이 쓸 수 있었던 CPU는 그만큼 줄었습니다. 그리고 여기 나타나지 않는 세 번째 원인이 하나 더 있습니다. 컨테이너 스로틀링은 이 화면 어디에도 표시되지 않습니다.

steal time의 정의 — 하이퍼바이저가 주지 않은 시간

stvCPU가 실행할 준비가 되어 있었는데 하이퍼바이저가 물리 CPU를 배정하지 않아 대기한 시간의 비율입니다. 게스트 커널 안에서 일어난 일이 아니라 게스트 바깥에서 일어난 일이고, 게스트는 이것을 사후에 통보받을 뿐입니다.

동작 원리는 준가상화 인터페이스입니다. KVM에서는 게스트 커널이 MSR_KVM_STEAL_TIME을 통해 공유 메모리 구조체를 등록하고, 하이퍼바이저가 vCPU를 스케줄 아웃한 누적 나노초를 거기에 씁니다. 게스트 커널은 그 값을 읽어 /proc/stat의 8번째 필드에 반영합니다. Xen도 runstate 정보로 같은 일을 합니다.

head -2 /proc/stat
# cpu  9284712 1832 1204831 88213904 42193 0 18922 1928374 0 0
# cpu0 1160589  229  150604 11026738  5274 0  2365  241046 0 0
#      user    nice system idle    iowait irq softirq steal guest guest_nice

여덟 번째 숫자가 steal 누적 tick입니다. top이나 mpstat은 이 값의 차분을 보여 주는 것뿐입니다.

mpstat -P ALL 1 3 | tail -5
# 14:23:03  CPU   %usr  %nice  %sys %iowait  %irq %soft %steal %guest %gnice  %idle
# 14:23:03  all  30.51   0.00  4.02    0.38  0.00  0.51  21.34   0.00   0.00  43.24
# 14:23:03    0  29.90   0.00  3.96    0.50  0.00  0.99  22.28   0.00   0.00  42.37
# 14:23:03    1  31.14   0.00  4.08    0.26  0.00  0.03  20.40   0.00   0.00  44.09

CPU별로 고르게 21% 근처면 호스트 전체가 과밀한 것이고, 특정 vCPU에만 몰려 있다면 그 vCPU가 배치된 물리 코어에 경쟁자가 있는 것입니다. 후자는 인스턴스를 재기동해 다른 호스트로 옮기는 것만으로 해결되는 경우가 많습니다.

여기서 가장 흔한 오해를 짚습니다. st가 높다고 내 프로세스가 CPU를 많이 쓰는 것이 아닙니다. 오히려 반대입니다. 내가 쓰고 싶었는데 못 쓴 시간이고, 원인은 인스턴스 바깥에 있습니다. 애플리케이션 코드를 아무리 최적화해도 이 수치는 내려가지 않습니다.

두 번째 오해도 중요합니다. st가 0이라고 해서 하이퍼바이저 경합이 없다는 뜻은 아닙니다. steal 회계는 하이퍼바이저가 그 정보를 게스트에 노출할 때만 동작합니다. VMware 환경의 게스트는 대체로 st가 0으로 보이고, 실제 경합은 호스트 쪽 %RDY(CPU ready) 지표에서만 확인됩니다. 온프레미스 가상화에서 "st가 0이니 문제없다"고 결론 내리는 것이 대표적인 오진입니다.

# 준가상화 클럭과 steal 회계가 활성인지 확인
grep -o 'kvm\|xen\|vmware\|hyperv' /sys/hypervisor/type 2>/dev/null
systemd-detect-virt
# kvm

grep -E 'CONFIG_PARAVIRT_TIME_ACCOUNTING' /boot/config-$(uname -r)
# CONFIG_PARAVIRT_TIME_ACCOUNTING=y

st가 몇 퍼센트부터 문제인가, 그리고 무엇을 할 수 있는가

절대 기준은 없지만 운영 경험칙은 비교적 일관됩니다.

  • 1% 미만: 정상입니다. 공유 인프라에서 0은 오히려 드뭅니다.
  • 1~5%: 관찰 대상입니다. 지연에 민감한 서비스라면 이미 p99에 영향이 있을 수 있습니다.
  • 5~10% 지속: 조치 대상입니다. 처리량이 실제로 그만큼 깎입니다.
  • 10% 초과 지속: 즉시 옮겨야 합니다. 그 호스트에서는 어떤 튜닝도 효과가 없습니다.

중요한 것은 순간값이 아니라 지속성입니다. 백업 창이나 이웃의 배치 작업 때문에 몇 분간 튀는 것은 흔한 일입니다. 알람은 5분이나 15분 평균으로 걸어야 오탐이 줄어듭니다.

대응은 네 가지입니다.

# 1) 인스턴스 재배치 — 중지 후 시작하면 다른 물리 호스트에 배치됩니다
#    (재부팅은 같은 호스트에 남으므로 효과가 없습니다)
aws ec2 stop-instances --instance-ids i-0abc123def4567890
aws ec2 start-instances --instance-ids i-0abc123def4567890

재부팅과 중지-시작의 차이가 핵심입니다. 게스트 안에서의 reboot은 물리 호스트를 바꾸지 않습니다. 클라우드 API를 통한 정지와 시작이라야 배치가 다시 일어납니다.

나머지 세 가지는 구조적 조치입니다. 물리 코어 전체를 점유하는 크기의 인스턴스로 올리면 이웃 자체가 사라집니다. 전용 호스트나 베어메탈 인스턴스는 하이퍼바이저 공유를 아예 없애는 대신 비용이 큽니다. 그리고 지연에 민감한 워크로드를 st가 낮은 인스턴스 패밀리로 분리 배치하는 것도 실용적인 선택입니다.

한 가지 함정. st가 높을 때 vCPU 개수를 늘리는 것은 종종 역효과입니다. 호스트가 이미 과밀한 상태라면 vCPU가 늘어난 만큼 스케줄링 기회를 더 기다려야 하고, 게스트 안에서는 스핀락 경합까지 늘어납니다. 코어 수보다 인스턴스 크기(호스트 점유 비율)를 올리는 편이 맞습니다.

버스터블 인스턴스의 크레딧 고갈 — 같은 증상, 다른 원인

두 번째 원인입니다. AWS의 T 계열, 다른 클라우드의 유사 등급은 기준 성능(baseline)과 크레딧이라는 개념으로 동작합니다. 기준 이하로 쓰면 크레딧이 쌓이고, 기준을 넘겨 쓰면 크레딧을 소모합니다.

인스턴스vCPUvCPU당 기준 성능시간당 적립 크레딧
t3.nano25%6
t3.micro210%12
t3.small220%24
t3.medium220%24
t3.large230%36
t3.xlarge440%96
t3.2xlarge840%192

크레딧 1개는 vCPU 하나를 100% 성능으로 1분 쓸 수 있는 양입니다. t3.medium은 시간당 24개를 벌고 vCPU가 2개이므로, 지속 가능한 사용량은 2 곱하기 20%, 즉 vCPU 하나 기준 40%에 해당합니다. 그 이상 계속 쓰면 잔고는 반드시 0으로 갑니다.

증상이 특징적입니다. 처음 몇 시간은 멀쩡하다가 어느 순간부터 성능이 계단식으로 떨어져 회복되지 않습니다. 부하는 그대로인데 응답 시간만 몇 배가 됩니다. standard 모드에서 크레딧이 바닥나면 하이퍼바이저가 기준 성능으로 강제 제한하고, 게스트는 이것을 steal time으로 인식합니다. 즉 st가 올라가지만 원인은 이웃이 아니라 내 예산입니다.

구분하는 방법은 간단합니다. steal이 시간에 따라 무작위로 오르내리면 이웃이고, 크레딧 잔고가 0에 닿은 시각부터 steal이 계단처럼 올라 고정되면 크레딧입니다.

aws cloudwatch get-metric-statistics \
  --namespace AWS/EC2 --metric-name CPUCreditBalance \
  --dimensions Name=InstanceId,Value=i-0abc123def4567890 \
  --start-time 2026-07-25T00:00:00Z --end-time 2026-07-26T00:00:00Z \
  --period 300 --statistics Average \
  --query 'sort_by(Datapoints, &Timestamp)[].[Timestamp,Average]' --output text | tail -6
# 2026-07-25T09:00:00Z	142.3
# 2026-07-25T10:00:00Z	88.1
# 2026-07-25T11:00:00Z	31.4
# 2026-07-25T12:00:00Z	0.0
# 2026-07-25T13:00:00Z	0.0
# 2026-07-25T14:00:00Z	0.0

12시부터 0입니다. 지연 그래프가 정확히 그 시각부터 나빠졌다면 진단은 끝났습니다.

선택지는 세 가지입니다. unlimited 모드로 전환하면 크레딧이 없어도 계속 버스트하고 초과분은 추가 과금됩니다(CPUSurplusCreditsCharged 지표로 실제 비용을 확인할 수 있습니다). 지속적으로 기준을 넘겨 쓰고 있다면 M이나 C 계열의 고정 성능 인스턴스로 옮기는 것이 결국 더 쌉니다. 버스트가 진짜로 간헐적이라면 T 계열을 유지하되 크레딧 잔고를 알람에 거는 것이 맞습니다.

# unlimited 전환
aws ec2 modify-instance-credit-specification \
  --instance-credit-specifications \
  'InstanceId=i-0abc123def4567890,CpuCredits=unlimited'

비용 판단 기준은 이렇습니다. unlimited 모드의 초과 과금이 상시 발생한다면, 그 금액과 한 단계 위 고정 성능 인스턴스의 차액을 비교하십시오. 상시 버스트 상태에서는 대부분 후자가 저렴하고 성능도 예측 가능합니다.

컨테이너 CFS 쿼터 스로틀링 — top에 전혀 보이지 않는 세 번째 원인

가장 중요한 절입니다. 앞의 두 원인은 최소한 st라는 흔적을 남깁니다. 스로틀링은 아무 흔적도 남기지 않습니다.

동작은 이렇습니다. cgroup에 CPU 상한이 걸려 있으면 커널은 주기(기본 100ms)마다 쿼터를 배분합니다. 그 그룹의 태스크들이 주기 안에서 쿼터를 다 쓰면, 커널은 남은 시간 동안 그 그룹 전체를 런큐에서 빼 버립니다. 다음 주기가 시작될 때까지 아무것도 실행되지 않습니다.

이 상태에서 무슨 일이 벌어지는지 봅시다. CPU limit이 1코어인 파드에 스레드가 8개 있습니다. 8개가 동시에 돌면 100ms 쿼터를 12.5ms 만에 소진합니다. 나머지 87.5ms 동안 이 파드는 완전히 정지합니다. 요청 하나가 하필 그 구간에 걸리면 응답에 87.5ms가 더해집니다. 평균 CPU 사용률은 정확히 100%(1코어 중 1코어)로 보이지도 않습니다. 12.5% 근처로 보입니다.

그래서 이런 그래프가 나옵니다. 평균 CPU 사용률은 낮고, 스틸도 0이고, 로드 애버리지도 조용한데, p99만 규칙적으로 튑니다. 스로틀링당한 태스크는 런큐에서 빠지기 때문에 로드 애버리지에도 잡히지 않습니다.

확인은 cpu.stat 한 파일이면 됩니다.

# cgroup v2 (컨테이너 안에서, cgroup 네임스페이스가 private이면 그대로 보입니다)
cat /sys/fs/cgroup/cpu.max
# 100000 100000

cat /sys/fs/cgroup/cpu.stat
# usage_usec 4128374621
# user_usec 3719283746
# system_usec 409090875
# nr_periods 86400
# nr_throttled 41287
# throttled_usec 2914837261

cpu.max의 두 숫자는 쿼터와 주기이고 단위는 마이크로초입니다. 100000 100000은 100ms 주기에 100ms 쿼터, 즉 1코어입니다. 제한이 없으면 첫 값이 max입니다.

읽어야 할 비율은 하나입니다.

스로틀링 비율 = nr_throttled / nr_periods = 41287 / 86400 = 47.8%
주기당 평균 정지 시간 = throttled_usec / nr_throttled = 2914837261 / 41287 = 70.6ms

전체 주기의 절반에서 스로틀링이 발생했고, 발생할 때마다 평균 70ms씩 멈췄습니다. p99 지연의 정체가 여기 있습니다. 실무 기준으로 비율 5%를 넘으면 조사 대상, 10%를 넘으면 조치 대상입니다.

cgroup v1이라면 파일이 다릅니다.

cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us
# 100000
cat /sys/fs/cgroup/cpu/cpu.cfs_period_us
# 100000
cat /sys/fs/cgroup/cpu/cpu.stat
# nr_periods 86400
# nr_throttled 41287
# throttled_time 2914837261000

v1의 throttled_time은 나노초, v2의 throttled_usec은 마이크로초입니다. 1000배 차이이므로 대시보드를 옮길 때 자주 틀리는 지점입니다.

호스트에서 파드 단위로 훑으려면 이렇게 합니다.

for f in /sys/fs/cgroup/kubepods.slice/*/*/cpu.stat; do
  awk -v p="${f%/cpu.stat}" '
    /^nr_periods/  {np=$2}
    /^nr_throttled/{nt=$2}
    END {if (np > 0 && nt/np > 0.05) printf "%5.1f%%  %s\n", nt*100/np, p}
  ' "$f"
done | sort -rn | head -5
#  47.8%  /sys/fs/cgroup/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod9a1c8f2e.slice
#  12.3%  /sys/fs/cgroup/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod4d22b71a.slice

프로메테우스에서는 cAdvisor 지표를 씁니다.

sum by (pod) (rate(container_cpu_cfs_throttled_periods_total[5m]))
  / sum by (pod) (rate(container_cpu_cfs_periods_total[5m]))

container_cpu_cfs_throttled_seconds_total만 보는 대시보드를 자주 보는데, 그 값은 "얼마나 오래 멈췄나"이고 정작 필요한 것은 "몇 번 중 몇 번 멈췄나"입니다. 두 개를 함께 걸어야 합니다.

커널 버전도 확인할 값입니다. 5.4 이전 커널에는 CPU 슬라이스 만료 처리 버그가 있어, 쿼터를 다 쓰지 않았는데도 스로틀링이 발생했습니다. 5.4에서 이 만료 로직이 제거되어 증상이 크게 줄었습니다. 오래된 노드에서 설명되지 않는 스로틀링이 보인다면 커널부터 확인하십시오.

uname -r
# 6.8.0-45-generic

5.14부터는 cpu.max.burst가 추가되어, 쓰지 않은 쿼터를 일정 한도까지 적립했다가 순간적으로 초과 사용할 수 있습니다. 짧은 스파이크성 워크로드에 효과가 큽니다.

# 최대 50ms까지 적립 허용
echo 50000 | sudo tee /sys/fs/cgroup/kubepods.slice/.../cpu.max.burst

세 원인을 가르는 표와 쿠버네티스 CPU limit 논쟁

지금까지의 세 가지를 한 표로 정리합니다. 증상이 비슷해 보이지만 진단 지점과 대응이 전부 다릅니다.

원인실제 사건top의 stcpu.stat 변화로드 애버리지대응
하이퍼바이저 경합이웃 VM이 물리 CPU를 점유5% 이상변화 없음영향 적음중지 후 시작, 큰 인스턴스, 전용 호스트
크레딧 고갈내 버스트 예산 소진계단식 상승변화 없음영향 적음unlimited 전환, M/C 계열 이동
CFS 쿼터 스로틀링cgroup 상한으로 강제 정지0nr_throttled 증가오르지 않음limit 상향/제거, 병렬도 조정, burst

세 번째 행의 "로드 애버리지가 오르지 않음"이 특히 반직관적입니다. 스로틀링된 태스크는 런큐에서 제거되므로 대기열에 잡히지 않습니다. 로드도, CPU 사용률도, steal도 전부 조용한데 서비스만 느립니다. 이 조합이 나오면 cpu.stat을 보십시오.

이제 논쟁입니다. 쿠버네티스에서 CPU limit을 아예 제거하자는 주장이 있습니다. 양쪽 근거를 정확히 봐야 합니다.

제거를 지지하는 논거. CPU는 압축 가능한 자원입니다. 메모리와 달리 부족해도 죽지 않고 느려질 뿐입니다. 그리고 request가 이미 cpu.weight(v1의 cpu.shares)로 변환되어 경합 시 비례 배분을 보장합니다. 즉 노드가 바쁠 때는 request 비율대로 나눠 갖고, 노드가 한가할 때는 limit이 없으면 남는 CPU를 그냥 쓸 수 있습니다. limit이 있으면 노드에 CPU가 남아도는 상황에서도 강제로 멈춥니다. 이것은 순수한 낭비입니다.

유지를 지지하는 논거. limit이 없으면 한 파드의 폭주가 같은 노드의 이웃을 실제로 느리게 만듭니다. weight는 경합 시 최소 몫을 보장할 뿐 상한을 두지 않으므로, 스레드를 수백 개 만드는 파드는 컨텍스트 스위치와 캐시 오염으로 이웃의 실효 성능을 떨어뜨립니다. 또한 limit이 없으면 성능 특성이 노드의 여유에 따라 달라져 용량 계획과 부하 테스트 결과의 재현성이 무너집니다. 멀티테넌트 클러스터라면 격리는 협상 대상이 아닙니다. 그리고 CPU 매니저의 static 정책으로 전용 코어를 할당받으려면 Guaranteed QoS, 즉 limit이 request와 같아야 합니다.

균형점은 다음과 같이 정리할 수 있습니다.

  1. request는 항상 설정합니다. 이것은 논쟁 대상이 아닙니다. 스케줄링 배치와 경합 시 몫이 모두 여기서 나옵니다.
  2. limit을 제거할 후보는 지연에 민감하고 신뢰할 수 있는 자사 서비스입니다. 제거하되 노드 전체 CPU 사용률과 이웃 파드의 지연을 함께 관찰해야 합니다.
  3. limit을 유지할 대상은 배치 작업, 신뢰도가 낮은 워크로드, 멀티테넌트 네임스페이스입니다. 여기서는 예측 가능성이 효율보다 중요합니다.
  4. limit을 유지한다면 병렬도에 맞춰 잡습니다. limit 1코어에 스레드 8개는 구조적으로 스로틀링을 만듭니다.
  5. 런타임에 상한을 알려 줍니다. 이것이 단일 조치로는 효과가 가장 큽니다.

5번을 부연합니다. JVM이나 Go 런타임은 기본적으로 호스트의 전체 코어 수를 봅니다. 64코어 노드에서 CPU limit 1인 컨테이너 안의 Go 프로그램은 GOMAXPROCS를 64로 잡고, 64개 스레드가 1코어짜리 쿼터를 나눠 쓰다가 즉시 스로틀링에 걸립니다.

# Go: 자동 조정 라이브러리를 쓰거나 환경 변수로 직접
GOMAXPROCS=1 ./myapp

# JVM: 컨테이너 인식은 기본 활성이지만 확인이 필요합니다
java -XX:+PrintFlagsFinal -version | grep -E 'ActiveProcessorCount|UseContainerSupport'
#      intx ActiveProcessorCount   = -1
#      bool UseContainerSupport    = true

# 명시적으로 지정
java -XX:ActiveProcessorCount=2 -jar app.jar

JVM의 컨테이너 인식은 CPU limit을 코어 수로 환산할 때 올림을 씁니다. limit이 1.5코어면 2로 봅니다. 소수점 limit을 쓴다면 이 반올림이 스로틀링을 만드는지 확인해야 합니다.

노드 차원의 선택지도 두 가지 있습니다. kubelet의 --cpu-manager-policy=static은 정수 CPU를 요청한 Guaranteed 파드에 전용 코어를 배타 할당해 CFS 쿼터 자체를 우회합니다. --cpu-cfs-quota-period를 100ms에서 10ms 정도로 줄이면 한 번의 정지 시간이 짧아져 지연 스파이크의 진폭이 줄어듭니다. 다만 주기가 짧아지면 스케줄링 오버헤드가 늘고, 이 플래그는 아직 안정 기능이 아니므로 검증 후 적용해야 합니다.

재발 방지 — 대시보드에 무엇을 걸 것인가

세 원인이 각각 다른 지표로 잡히므로 셋 다 걸어야 합니다. 하나라도 빠지면 그 원인은 영원히 보이지 않습니다.

# 1) steal — 노드 단위, 5분 평균
avg by (instance) (rate(node_cpu_seconds_total{mode="steal"}[5m])) > 0.05

# 2) 스로틀링 비율 — 파드 단위
sum by (namespace, pod) (rate(container_cpu_cfs_throttled_periods_total[5m]))
  / sum by (namespace, pod) (rate(container_cpu_cfs_periods_total[5m])) > 0.10

# 3) CPU 압박 — PSI. 스로틀링과 경합을 모두 포착합니다
avg by (instance) (rate(node_pressure_cpu_waiting_seconds_total[5m])) > 0.20

PSI를 함께 거는 이유가 있습니다. cpu.pressure는 "실행할 수 있었는데 못 한 시간"을 직접 재기 때문에, steal이든 스로틀링이든 런큐 경합이든 원인과 무관하게 결과를 잡아냅니다. cgroup 단위로도 존재합니다.

cat /sys/fs/cgroup/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod9a1c8f2e.slice/cpu.pressure
# some avg10=68.42 avg60=61.03 avg300=44.18 total=182937461283
# full avg10=52.11 avg60=47.88 avg300=33.02 total=91827364512

some이 68%라는 것은 최근 10초 중 6.8초 동안 이 파드의 어떤 태스크가 CPU를 기다렸다는 뜻입니다. 스로틀링 비율 47.8%와 함께 보면 같은 사실을 두 각도에서 확인하는 셈입니다.

정기 점검 스크립트로 남겨 두면 장애 때 기억을 더듬지 않아도 됩니다.

#!/usr/bin/env bash
# cpu-triage.sh — CPU 지연의 세 가지 원인을 한 번에 확인합니다
set -u

echo "== 1. steal time (5초 평균) =="
mpstat 5 1 | awk '/Average/ {printf "  %%steal = %s\n", $(NF-3)}'

echo "== 2. 가상화 환경 =="
printf '  '; systemd-detect-virt

echo "== 3. cgroup 스로틀링 (v2) =="
if [ -r /sys/fs/cgroup/cpu.stat ]; then
  awk '/^nr_periods/{np=$2} /^nr_throttled/{nt=$2} /^throttled_usec/{tu=$2}
       END {
         if (np > 0)
           printf "  비율 %.1f%%  (%d/%d), 발생 시 평균 %.1fms\n",
                  nt*100/np, nt, np, (nt>0 ? tu/nt/1000 : 0)
       }' /sys/fs/cgroup/cpu.stat
  printf '  cpu.max = %s\n' "$(cat /sys/fs/cgroup/cpu.max 2>/dev/null)"
fi

echo "== 4. CPU 압박 (PSI) =="
[ -r /proc/pressure/cpu ] && sed 's/^/  /' /proc/pressure/cpu

마치며 — 사용률이 낮다는 것이 CPU가 한가하다는 뜻은 아닙니다

하나만 기억한다면 이것입니다. CPU 사용률은 "얼마나 썼나"이지 "얼마나 쓸 수 있었나"가 아닙니다. 쓰고 싶었지만 못 쓴 시간은 steal, 크레딧 고갈, 스로틀링이라는 세 가지 형태로 나타나고, 그중 스로틀링은 사용률 그래프 어디에도 흔적을 남기지 않습니다.

판단 순서를 압축하면 이렇습니다.

  1. mpstat -P ALL 1%steal을 먼저 봅니다. 5분 평균 5%를 넘으면 인스턴스 문제이고 게스트 안에서 할 수 있는 일이 없습니다.
  2. steal이 특정 시각부터 계단식으로 올라 고정됐다면 크레딧 잔고를 확인합니다. 이웃이 아니라 예산 문제입니다.
  3. steal이 0인데 지연이 튀면 cpu.statnr_throttled를 봅니다. 사용률과 로드 애버리지는 이 문제를 보여 주지 못합니다.
  4. 스로틀링이 확인되면 limit을 올리기 전에 런타임의 병렬도부터 맞춥니다. GOMAXPROCSActiveProcessorCount 조정이 대개 더 큰 효과를 냅니다.
  5. CPU limit 제거는 만능 처방이 아닙니다. request를 정확히 설정하는 것이 먼저이고, 제거는 신뢰할 수 있는 워크로드에 한정해 관측과 함께 진행합니다.
  6. 알람은 steal, 스로틀링 비율, PSI 세 개를 모두 겁니다. 세 원인이 서로를 가려 주지 않습니다.

현재 단락 (1/140)

용량 회의에서 가장 자주 나오는 문장이 있습니다. "CPU 사용률이 40%밖에 안 되니까 CPU 문제는 아닙니다." 이 문장은 세 가지 상황에서 틀립니다. 그리고 그 세 가지가 이...

작성 글자: 0원문 글자: 10,665작성 단락: 0/140