결론은 두 줄입니다
정각의 몇 초는 공유 호스트에서 흔합니다. 그 스파이크만 보고 물리 서버를 사면, 채우지 못하는 기계를 받게 됩니다. 샘플은 영업일 피크, 1초 또는 10초 간격, 최소 5일입니다. 새벽 백업은 따로 저장합니다. 두 지표가 같은 창의 API p95와 같이 움직이면 요금표를 엽니다. 하나만 맞으면 클라우드 사양을 올리고, 다음 주에 같은 창으로 다시 잽니다.
한 테넌트 서버가 지우는 것은 옆 고객입니다. 느린 SQL, 없는 인덱스, 락 대기는 그대로입니다. 사용자와 기기의 거리도 그대로입니다. 느림이 CPU와 디스크인지 확인한 뒤에 월 요금을 계산합니다.
청구서 이름과 모니터링 열
클라우드 서버는 대개 KVM 계열 가상 머신입니다. 호스트에 다른 테넌트가 있습니다. 게스트는 steal을 봅니다. vCPU는 달릴 수 있었는데, 그 시간을 다른 고객이 가져갔습니다. 디스크는 네트워크 볼륨인 경우가 많고 IOPS는 사양이나 크레딧입니다. 메모리에는 한도가 있고, balloon으로 비어 있는 페이지를 호스트가 거둬 갑니다. 클라우드와 단독서버의 차이는 이 세 열에 다른 사람이 있는지로 먼저 읽습니다.
VPS는 가상 머신인지 컨테이너인지부터 나눕니다. 가상 머신형 VPS는 클라우드와 같은 곡선이고, 코어와 메모리 한도가 더 작은 경우가 많습니다. 컨테이너에는 steal 열이 없습니다. CPU는 cgroup 스로틀 횟수, 메모리 한도는 메모리 컨트롤러에 있습니다. 스로틀을 장애로 읽으면 판단이 빗나갑니다. 쿼터의 끝으로 읽어야 steal과 같은 결론이 됩니다. VPS는 아직 한 호스트에서 잘라 낸 몫입니다. 단독서버는 스케줄러를 한 고객에게 넘깁니다. 베어메탈도 이 글에서는 그 단독서버입니다. 호스트 OS의 steal은 0 근처입니다. 디스크는 그 섀시의 NVMe이고, 메모리는 그 섀시의 물리 모듈이며 용량은 주문할 때 정합니다.
이웃이 CPU를 가져가면 steal이 붙습니다
steal은 “돌고 싶은데 호스트가 CPU를 쥐고 있는” 시간입니다. Linux에서는 vmstat의 st, top의 %st가 그 비율입니다. Prometheus에서는 node_cpu_seconds_total의 steal 모드를 rate로 구한 뒤 코어 평균을 냅니다.
몇 초에서 십수 초의 steal은 이웃의 짧은 버스트입니다. 클라우드에 두어도 됩니다. 사양도 트래픽도 그대로인데 피크에서 steal이 약 10% 이상으로 여러 번 오르고, 몇 분 머물며, API p95도 같이 오릅니다. CPU를 오래 빼앗긴 상태입니다. 이미 붐비는 호스트에서 vCPU를 더하면 줄만 길어지는 경우가 많습니다.
다른 피크는 구분합니다. user와 sys가 거의 가득 차고 steal이 0에 가깝다면, 코어는 직접 쓴 것입니다. 먼저 클라우드 CPU를 올립니다. 올린 뒤에도 영업시간에 steal이 반복되면 호스트가 제약입니다. 10%는 그래프를 읽는 선이지 경보 규정이 아닙니다. 지연 예산이 빡빡하면 선을 낮추고, 기다려도 되는 배치는 높입니다. 여러 영업일과 p95가 같은 방향인 것이 한 세트입니다.
컨테이너 VPS에는 st가 없습니다. CPU 컨트롤러의 cpu.stat에서 nr_throttled와 throttled_usec를 읽습니다. 피크에 스로틀 시간이 계속 늘면 쿼터가 끝난 것입니다. 그 상품의 상한까지 올렸는데도 남으면 steal과 같은 판단입니다.
물리 서버의 호스트 OS에서 steal은 0 근처에 있어야 합니다. 그 위에 직접 가상 머신을 올리면 게스트에 steal이 다시 나옵니다. 32코어를 나누는 방식이지, 옆 고객이 아닙니다.
워킹셋이 인스턴스 한도를 넘을 때
워킹셋은 그 시간 동안 반복해서 닿아 메모리에 남아 있어야 하는 페이지입니다. Linux는 남는 메모리를 캐시로 씁니다. MemAvailable이 낮아도 지연이 안정적이면 대개 캐시입니다. “사용률 90%”만으로 이전하면 캐시를 담을 메모리를 사게 됩니다.
영업시간에 다음이 같이 나오면 적습니다. vmstat의 si, so가 0으로 돌아오지 않습니다. 메이저 폴트가 오르고 데이터베이스 지연도 오릅니다. 커널 로그에 OOM이 있습니다. 원하는 버퍼 풀이 이 VM 메모리보다 크고, 클라우드 사양표에 쓸 수 있는 다음 단계가 없습니다.
balloon은 프로세스가 덜 찬 것처럼 보여도 게스트를 압박합니다. 호스트가 페이지를 거둬 가기 때문입니다. 압박이 풍선인지 워킹셋인지 먼저 가릅니다.
워킹셋이 대략 32GB이고 스왑도 OOM도 없으면 클라우드 메모리를 한 단계 올립니다. 이미 그 클라우드가 파는 최대 메모리에 닿았을 때가 물리 서버의 두 단계입니다. 둘 다 DDR4-3200 ECC RDIMM이며 128GB 또는 256GB입니다. 주문 뒤에 모듈을 추가하지 않습니다. 피크 워킹셋에 OS와 페이지 캐시 여유를 더해 고릅니다. 128GB에 들어가지 않으면 256GB이고 월 $592입니다. 둘 다 담지 못하는 부하는 이 장비로도 담지 못합니다.
가용 메모리가 낮고 지연이 안정적이면 캐시로 둡니다. 영업시간의 스왑, OOM, 한도를 넘은 버퍼 풀이 메모리 지표입니다.
디스크 대기열이 커밋을 붙잡을 때
데이터베이스가 느릴 때는 NIC보다 데이터 디스크 대기열을 먼저 봅니다. iostat -xz 1의 aqu-sz는 평균 대기열, w_await는 쓰기 대기입니다. OLTP가 보는 것은 커밋 때의 fsync입니다. 백업의 순차 대역은 오후 커밋을 설명하지 않습니다.
피크에 데이터 디스크 aqu-sz가 자주 1을 넘고, w_await가 수십 밀리초에 이르며, 슬로 로그의 커밋도 같이 길어집니다. 대기열이 데이터베이스를 붙잡고 있습니다. 이때 MB/s는 여전히 낮을 수 있습니다.
네트워크 볼륨에는 IOPS 크레딧이 붙습니다. 크레딧이 비면 대기가 갑자기 늘었다가 몇 시간 뒤 돌아옵니다. 매일 같은 시간대에만 느리고 프로세스를 재시작해도 그대로인 곡선입니다.
IOPS를 그 클라우드의 최상단까지 샀는데도 영업일에 반복되면 제한은 공유 스토리지입니다.
밤에 백업으로 디스크가 가득 차고 낮의 w_await가 평소와 같으면 백업 시간을 옮깁니다. 대기는 낮은데 느린 쿼리가 락이나 풀 스캔이면 SQL을 고칩니다.
NVMe에서 %util이 100%에 가까워도 그것만으로 포화를 보지 않습니다. 대기열 길이와 쓰기 대기를, 이전한 뒤에도 씁니다.
| 피크에서 보인 것 | 클라우드에 남김 | 물리 서버 요금을 봄 |
|---|---|---|
| steal이 몇 초만 튀고 p95는 그대로 | 사양 유지 | 해당 없음 |
| steal이 약 10% 이상으로 수 분, p95도 같은 방향. vCPU를 더해도 남음 | 증설은 이미 시도 | 이웃이 코어를 가져감 |
| user+sys가 가득, steal은 0 근처 | 클라우드 CPU를 올림 | 아직 옮기지 않음 |
| 컨테이너 스로틀이 피크에 늘고 쿼터는 상한 | steal과 같은 판단 | 상한인데도 스로틀이 남음 |
| 가용 메모리 낮음, 페이징 없음, 지연 안정 | 캐시로 남김 | 해당 없음 |
| 피크에 페이징 또는 OOM, 버퍼 풀이 VM보다 큼 | 더 큰 클라우드 메모리 없음 | 워킹셋으로 128GB 또는 256GB |
| 디스크가 바쁜 시간은 백업뿐 | 백업을 옮김 | 해당 없음 |
| 데이터 디스크 대기열이 자주 1 초과, 쓰기 대기 수십 ms, 커밋이 느림, IOPS는 상한 | 디스크 등급은 바꿈 | 대기는 공유 스토리지 |
지금 서버에서 숫자를 뽑습니다
물리 서버를 주문하기 전에, 지금 쓰는 클라우드 VM이나 VPS에서 끝냅니다. 명령은 채집만 합니다.
-
1
영업일 피크 5일
vmstat 1에서us,sy,st,si,so를 남깁니다. 같은 창의 p95를 뽑습니다. 백업 시간은 따로 둡니다. -
2
캐시와 워킹셋
MemAvailable을 버퍼 풀 설정, 피크 실제 사용과 나란히 봅니다. OOM이 있으면 커널 로그를 남깁니다. 컨테이너는 메모리 한도도 읽습니다. -
3
데이터 디스크만
iostat -xz 1로 데이터 디스크의aqu-sz와w_await를 슬로 로그 커밋과 함께 적습니다. -
4
세 줄로 모읍니다
한 줄에 지표 하나입니다. 있는지, 어느 날인지, p95가 같은 방향인지. “있음”이 두 줄이면 구성 페이지에서 요금을 봅니다. 한 줄이면 클라우드 사양을 바꾸고 다음 주에 다시 잽니다.
vmstat 1
iostat -xz 1
us는 사용자, sy는 시스템, id는 유휴, wa는 I/O 대기, st는 steal입니다. si와 so는 스왑 인·아웃입니다.
컨테이너는 nr_throttled 증가분을 st 옆에 둡니다. 그 열이 없으면 CPU 결론을 내리지 않습니다.
지연의 주된 원인이 거리라면 steal이 사라져도 왕복은 남습니다. 서버는 일본 도쿄에 둡니다. 일본과 인근으로의 경로와, 더 먼 지역으로의 경로는 다른 문제입니다. 락, 인덱스 부재, 리전을 넘는 호출은 이 세 지표 밖입니다.
물리 서버로 옮긴 뒤 곡선이 앉는 자리
두 줄이 성립한 뒤에 볼 것은, 장비가 그 두 줄을 받는가입니다. CPU는 단일 소켓 AMD EPYC 7543P, 32코어/64스레드, 2.8–3.7 GHz입니다. 이 CPU를 쓰는 고객은 하나입니다. 호스트 OS의 steal은 0 근처여야 합니다. 직접 나눈 가상 머신의 steal은 32코어를 어떻게 나누는지입니다.
메모리는 두 단계입니다. 128GB는 월 $465, 256GB는 월 $592이며 둘 다 DDR4-3200 ECC RDIMM입니다. 피크 워킹셋으로 고릅니다. 128GB에 들어가면 128GB입니다.
디스크 기본은 2 × 1TB NVMe, 하드웨어 RAID 없음, 디스크는 각각 직결입니다. 사용 용량은 2TB로 읽습니다. 대기가 네트워크 볼륨에서 왔다면 로컬 NVMe로 바꾼 뒤 쓰기 대기가 먼저 내려가는 경우가 많습니다. 내려가지 않으면 SQL인지, 디스크 한 장이 부족한지 봅니다. 2TB를 0장에서 2장까지 추가할 수 있습니다. 한 장 월 $83이며 역시 직결입니다. 기존 어레이에 자동으로 들어가지 않습니다. 소프트 RAID를 하면 사용 용량은 약 1TB로 돌아갑니다. 백업은 기기 밖에 둡니다.
대역폭 기본은 250 Mbps, 트래픽 무제한입니다. 디스크 대기열은 스토리지 대기이므로, fsync 때문에 1G(월 +$251)나 2G(월 +$749)로 올리지 않습니다. 250M 포트 자체가 찰 때 올립니다. IPv4는 1개가 포함됩니다. 추가는 개당 월 $2, 한 대 합계 최대 256개이며 서브넷으로 팔지 않습니다. 시스템은 Ubuntu 24.04를 고를 수 있습니다. Windows는 Standard가 월 +$21, Datacenter가 월 +$27입니다. Linux는 SSH, Windows는 RDP입니다.
월 요금은 기종 가격에 추가 디스크 수 × 83, 대역폭 가산, 추가 IP 수 × 2, OS 가산을 더한 값입니다. 내야 할 금액은 월 요금 × 개월 수입니다. 월, 분기, 반년, 연은 이 곱입니다. 설치비는 없습니다. 서버는 일본 도쿄에 둡니다. 디스크 대기열만 맞고 CPU와 메모리가 조용하면, 클라우드 디스크를 최상단까지 올린 뒤에 월 $465부터인 물리 서버와 비교합니다. 워킹셋도 대기열도 가벼운 부하는 클라우드에 남는 편이 맞는 경우가 많습니다. 두 줄이 맞으면 구성 페이지에서 128GB 또는 256GB를 고릅니다.