feat: 가상화 문서들 추가
This commit is contained in:
+197
@@ -0,0 +1,197 @@
|
||||
---
|
||||
id: 5bcae89b-0873-4a2b-af4a-10e5234c085b
|
||||
kind: CONCEPT
|
||||
slug: kvm-vcpu-to-physical-cpu
|
||||
title: KVM 에서 vCPU 가 물리 CPU 에서 실행되기까지
|
||||
topic: cpu-virtualization
|
||||
topicName: CPU 가상화
|
||||
project: virtualization
|
||||
status: 초안
|
||||
basisVersion: x86_64 Intel VMX(VT-x) · Linux KVM(kvm · kvm_intel) · QEMU/libvirt · VM 안의 K3s cgroup CPU limit
|
||||
studio: "https://hyeonworks.com/studio/documents/5bcae89b-0873-4a2b-af4a-10e5234c085b/edit"
|
||||
assets:
|
||||
- key: vm-exit-handling-cycle
|
||||
file: ../../../final/assets/diagrams/vm-exit-handling-cycle/vm-exit-handling-cycle.svg
|
||||
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
|
||||
source:
|
||||
- final/document.md#1-이-문서의-범위
|
||||
- final/document.md#2-전체-구조
|
||||
- final/document.md#3-각-구성요소의-역할
|
||||
- final/document.md#4-vcpu와-vcpu-thread
|
||||
- final/document.md#5-host-linux-scheduler와-실제-cpu
|
||||
- final/document.md#6-kvm_run과-guest-실행
|
||||
- final/document.md#7-vm-entry와-vm-exit
|
||||
- final/document.md#8-무엇이-실제로-vm-exit을-발생시키는가
|
||||
- final/document.md#9-vm-exit-이후-처리
|
||||
- final/document.md#10-guest가-idle이면-물리-cpu는-어떻게-되는가
|
||||
- final/document.md#11-vm의-4-vcpu는-정확히-무엇을-의미하는가
|
||||
- final/document.md#12-cpu-contention과-overcommit
|
||||
- final/document.md#13-steal-time
|
||||
- final/document.md#14-실제-linux에서-확인할-수-있는-것
|
||||
- final/document.md#15-cpu-가상화-관점에서-장애를-보는-방법
|
||||
- final/document.md#16-현재-keycloak-k3s-실험과의-관계
|
||||
- final/document.md#18-bare-metal-k3s와-vm-기반-k3s의-차이
|
||||
- final/document.md#19-이-ssot에서-파생될-concept
|
||||
- final/document.md#22-현재-단계의-핵심-claim
|
||||
- final/document.md#24-cpu-가상화-계층에서-발생할-수-있는-문제
|
||||
- final/document.md#25-cpu-문제를-계층별로-구분하는-진단표
|
||||
- final/document.md#26-현재-keycloak-실험에서-cpu-문제를-오판하지-않기-위한-기준
|
||||
- final/document.md#28-concept-->-open-question-->-case-적용-기준
|
||||
---
|
||||
|
||||
# KVM 에서 vCPU 가 물리 CPU 에서 실행되기까지
|
||||
|
||||
`virsh` 로 가상 머신을 시작하면 그 뒤로 CPU 를 쓰는 쪽은 QEMU 프로세스다. vCPU 하나마다 QEMU vCPU 스레드가 하나씩 있다. 그 스레드를 호스트 Linux 스케줄러가 다른 호스트 스레드와 나란히 놓고 논리 CPU 에 배치한다. 게스트 코드는 그 스레드가 `KVM_RUN` 을 호출한 뒤 VM Entry 를 지나 물리 CPU 에서 직접 실행된다. 하이퍼바이저가 개입해야 하는 조건을 만나면 VM Exit 으로 KVM 에 제어권이 넘어간다. Keycloak 멀티 노드 실험을 가상 머신 두 대 위에서 돌리다 보니, 이 경로를 알아 두면 게스트 안의 지연을 애플리케이션·저장소 문제와 호스트 자원 문제로 갈라 볼 수 있다.
|
||||
|
||||
## 관계
|
||||
|
||||
- **pinning 없이 vCPU 스레드는 호스트 논리 CPU 사이를 옮겨 다니는가**
|
||||
이 글은 vCPU 스레드가 호스트 스케줄러에 따라 다른 논리 CPU 에서 실행될 수 있다고만 적었다. 그 이동을 `PSR` 로 실제로 재는 질문이다.
|
||||
- **실제 작업에서 주로 발생하는 VM Exit 은 무엇인가**
|
||||
무엇이 VM Exit 을 부르는지는 여기 적었지만, 어떤 작업에서 어떤 이유의 Exit 이 얼마나 나오는지는 이 호스트에서 세지 않았다.
|
||||
- **가상 머신 두 대에 동시에 부하를 주면 이 호스트에서 vCPU 경쟁이 실제로 생기는가**
|
||||
경쟁과 초과 할당은 예시 숫자로 설명했다. 이 테스트 환경의 논리 CPU 수와 두 가상 머신의 vCPU 합은 SSOT 에 적혀 있지 않다.
|
||||
- **cgroup CPU 제한과 호스트 vCPU 경쟁을 지표로 가를 수 있는가**
|
||||
진단표는 두 원인을 다른 행으로 갈라 놓았다. 그 구분이 지표로도 갈리는지는 같은 크기의 지연을 두 원인으로 각각 재현해야 안다.
|
||||
- **운영 서버는 CPU 가상화 계층의 영향을 받는 구조인가**
|
||||
진단표의 어느 행부터 보는지가 이 답에 달려 있다.
|
||||
- **이 호스트의 NUMA 토폴로지는 가상 머신 성능을 고려해야 할 구조인가**
|
||||
이 글은 NUMA 를 진단표의 한 행으로만 두고 메모리 배치는 범위 밖으로 미뤘다. 단일 NUMA node 면 이 실험에서 우선순위를 낮추고, 다중이면 vCPU 와 메모리 배치를 따로 확인한다.
|
||||
|
||||
## 본문
|
||||
|
||||
<!-- body:start -->
|
||||
|
||||
## virsh 뒤에서 가상 머신을 실행하는 프로세스
|
||||
|
||||
`virsh` 는 libvirt 기반 가상 머신을 관리하는 명령줄 도구다. `virsh start ubuntu-vm` 을 실행하면 명령이 libvirt 로 전달되고 libvirt 가 QEMU 프로세스를 실행한다. 명령 전달이 끝나면 `virsh` 자체는 종료될 수 있고, 가상 머신을 실제로 실행하는 QEMU 프로세스는 계속 살아 있다.
|
||||
|
||||
libvirt 는 가상 머신의 수명 주기와 구성을 관리하는 계층이다. 가상 머신 정의에는 RAM 8 GiB, vCPU 4 같은 값이 들어 있다. libvirt 는 그 정의를 바탕으로 QEMU 를 적절한 옵션과 함께 실행하고 관리한다.
|
||||
|
||||
QEMU 는 호스트의 사용자 공간에서 실행되는 프로세스다. 4 vCPU 가상 머신이라면 메인·제어 스레드 하나와 vCPU 스레드 넷이 만들어진다. KVM 가속을 쓸 때 게스트의 일반 CPU 명령을 QEMU 가 하나씩 소프트웨어로 번역해 실행하는 경로가 핵심은 아니다. vCPU 스레드가 KVM 을 통해 게스트 실행을 요청하면 게스트 코드는 VMX 를 이용해 실제 CPU 에서 직접 실행된다.
|
||||
|
||||
`/dev/kvm` 은 프로세스가 아니라 Linux 가 사용자 공간 프로그램에 KVM API 를 노출하는 문자 장치(character device) 인터페이스다. QEMU 는 이 파일을 열고 `ioctl` 로 `KVM_CREATE_VM`, `KVM_CREATE_VCPU`, `KVM_SET_USER_MEMORY_REGION`, `KVM_RUN` 같은 동작을 요청한다.
|
||||
|
||||
커널 안쪽은 두 층으로 갈린다. KVM Core 가 CPU 제조사에 독립적인 공통 가상화 로직을 맡고, 제조사별 구현은 `kvm_intel` 과 `kvm_amd` 로 나뉜다. `kvm_intel` 은 Intel CPU 환경에서 KVM 이 Intel 의 하드웨어 가상화 기능을 쓸 수 있게 하는 커널 모듈이다. AMD 환경에서는 `kvm_amd` 가 SVM 을 쓴다.
|
||||
|
||||
VMX(Virtual Machine Extensions)는 Intel CPU 자체가 제공하는 하드웨어 가상화 기능이어서 프로세스도 커널 모듈도 아니다. VMX 는 실행 영역을 호스트·하이퍼바이저 쪽인 VMX Root Operation 과 게스트 쪽인 VMX Non-Root Operation 으로 구분한다. 여기서 Root 는 Linux 의 `root` 사용자와 무관하다. 게스트 Linux 에서 `root` 권한으로 프로그램을 실행하더라도 게스트 전체는 VMX 관점에서 여전히 Non-Root Operation 에서 실행된다.
|
||||
|
||||
## vCPU 하나마다 QEMU 스레드 하나
|
||||
|
||||
가상 머신에 4 vCPU 를 설정하면 게스트 OS 는 그것을 자신의 CPU 처럼 인식한다. 호스트에는 각 vCPU 의 실행 주체에 대응하는 QEMU vCPU 스레드가 하나씩 존재한다. 4 vCPU 는 게스트 OS 가 최대 4개의 CPU 실행 흐름을 가질 수 있도록 4개의 가상 CPU 실행 컨텍스트를 제공한다는 의미에 가깝다. 호스트의 물리 CPU 4개가 그 가상 머신으로 영구히 넘어가지는 않는다.
|
||||
|
||||
vCPU 스레드가 실행될 논리 CPU 를 특정 집합으로 제한하는 설정을 CPU pinning 이라고 한다. pinning 도 별도의 CPU 격리도 하지 않았다면 vCPU 스레드는 호스트 Linux 스케줄러가 스케줄링한다. 호스트가 6 Core / 12 Thread 라면 Linux 에서는 일반적으로 12개의 논리 CPU 가 스케줄링 대상으로 보인다. vCPU 스레드도 Chrome 스레드나 Java 스레드와 마찬가지로 그 12개 위에 배치된다. 그래서 시간에 따라 같은 스레드가 서로 다른 논리 CPU 에서 실행될 수도 있다. 다만 이 호스트에서 그 이동을 재지는 않았다. 스레드가 최근 실행된 논리 CPU 를 알려 주는 `PSR` 값을 시간에 따라 여러 번 보면 확인되는데, 그 관찰을 아직 돌리지 않았다.
|
||||
|
||||
호스트 CPU 가 부족하면 QEMU vCPU 스레드와 호스트의 다른 작업이 같은 논리 CPU 자원을 두고 경쟁한다.
|
||||
|
||||
## KVM_RUN 이 게스트 실행을 시작한다
|
||||
|
||||
QEMU 의 vCPU 스레드가 게스트 vCPU 를 실행하려면 KVM 에 `KVM_RUN` 을 요청한다.
|
||||
|
||||
```c label="vCPU thread 가 Guest 실행을 요청하는 호출"
|
||||
ioctl(vcpu_fd, KVM_RUN, 0);
|
||||
```
|
||||
|
||||
KVM 은 이 요청을 받아 VM Entry 로 CPU 가 게스트 실행을 시작하거나 재개하게 한다. 이 상태에서 `ADD`, `MOV`, `SUB`, `CMP`, `JMP` 같은 게스트의 일반 명령은 실제 CPU 에서 직접 실행된다. 명령 하나마다 QEMU 까지 돌아갔다가 다시 실행하는 구조가 아니다.
|
||||
|
||||
## 무엇이 VM Exit 을 부르는가
|
||||
|
||||
VM Exit 은 가상 머신 종료가 아니다. CPU 가 VMX Non-Root 에서 게스트를 실행하다가 하이퍼바이저가 개입해야 하는 조건을 만나면, 게스트 실행에서 빠져나와 VMX Root 쪽 KVM 으로 제어권을 넘긴다. QEMU 가 종료되지도, 가상 머신 메모리가 지워지지도 않는다. 필요한 처리가 끝나면 다시 VM Entry 를 통해 게스트 실행을 이어 간다.
|
||||
|
||||
무엇을 가로챌지는 Intel VMX 의 VMCS(Virtual Machine Control Structure)에 있는 VM-Execution Control 등이 정한다. 특권 명령이면 전부 VM Exit 이라거나 `root` 가 실행하면 VM Exit 이라는 규칙은 맞지 않는다. Exit 여부는 VMX 설정과 해당 동작의 종류에 따라 정해진다.
|
||||
|
||||
| 무엇이 실행되나 | 가로채는 설정과 그 이유 |
|
||||
|---|---|
|
||||
| `HLT` 계열 | 게스트 커널이 유휴 경로로 들어갔다. `HLT` exiting 을 쓰면 KVM 이 vCPU 를 재울 수 있다 |
|
||||
| `IN` · `OUT` | I/O port 접근을 QEMU 의 가상 장치 동작으로 처리하도록 설정할 수 있다 |
|
||||
| `CPUID` | 게스트에게 보여 줄 CPU 모델과 기능이 호스트 CPU 와 달라 CPU 정보를 가상화한다 |
|
||||
| `CR0` · `CR3` · `CR4` 접근 | VMX 설정으로 어떤 접근을 가로챌지 고른다. 모든 접근이 Exit 을 부르지는 않는다 |
|
||||
| `RDMSR` · `WRMSR` | 특정 MSR(Model-Specific Register) 접근을 가로채도록 설정했을 때 발생한다 |
|
||||
| 예외 | Exception Bitmap 설정에 따라 게스트가 직접 처리할 수도, 하이퍼바이저가 가로챌 수도 있다 |
|
||||
| 외부 인터럽트 | 호스트가 처리해야 할 물리 인터럽트가 들어왔고 인터럽트 설정이 그렇게 돼 있다 |
|
||||
|
||||
`CR3` 처럼 페이지 테이블과 관련된 레지스터는 게스트 커널도 자주 쓴다. 그런 접근까지 전부 가로채면 Exit 이 늘어나기 때문에 현대 가상화에서는 불필요한 Exit 을 줄이는 쪽으로 설정한다.
|
||||
|
||||
## Exit 을 KVM 이 처리할 때와 QEMU 까지 돌아갈 때
|
||||
|
||||
VM Exit 이 발생하면 KVM 은 먼저 Exit Reason 을 확인한다. KVM 이 커널 안에서 처리할 수 있는 Exit 은 처리한 뒤 바로 게스트로 재진입한다. 사용자 공간에서 가상 장치를 흉내 내야 할 때처럼 사용자 공간 처리가 필요할 때만 `KVM_RUN` 이 반환된다. 그러면 QEMU 가 필요한 가상 장치 동작을 처리한 뒤 다시 `KVM_RUN` 을 호출해 게스트 실행을 재개한다.
|
||||
|
||||

|
||||
|
||||
VM Exit 자체는 정상적인 가상화 동작이어서 Exit 이 있다고 문제가 되지 않는다. 어떤 작업에서 하이퍼바이저가 개입해야 하는 Exit 이 지나치게 빈번하고 그 처리 비용이 커지면 성능에 영향을 줄 수 있다. 그래서 Exit 횟수만 세지 않는다. Exit 이 난 이유와 작업 종류, 처리한 곳이 KVM 인지 QEMU 사용자 공간인지, 애플리케이션 지연이 Exit 증가와 같은 시점에 나타나는지를 같이 본다.
|
||||
|
||||
## 게스트에 할 일이 없으면 물리 CPU 가 풀린다
|
||||
|
||||
게스트에 실행할 작업이 없으면 게스트 커널은 유휴 경로로 들어가고 `HLT` 계열 동작이 사용될 수 있다. KVM 과 VMX 가 `HLT` exiting 을 쓴다면 여기서 VM Exit 이 발생한다. KVM 은 vCPU 가 당장 할 일이 없는 상태를 처리하면서 그 스레드를 재우거나 대기 상태로 둘 수 있다. 그동안 호스트 스케줄러는 그 논리 CPU 를 호스트의 다른 작업에 쓴다.
|
||||
|
||||
나중에 타이머, 인터럽트, I/O 완료처럼 vCPU 를 다시 실행해야 할 이유가 생기면 vCPU 가 깨어나 실행 대기 상태가 된다. 호스트 스케줄러가 그 스레드를 논리 CPU 에 배치하면 KVM 이 VM Entry 로 게스트 실행을 재개한다. 가상 머신에 4 vCPU 를 설정했어도 그 가상 머신에 할 일이 없는 동안에는 호스트가 CPU 자원을 다른 작업에 쓴다.
|
||||
|
||||
## CPU 가 모자랄 때 게스트 안에서 보이는 값
|
||||
|
||||
호스트에 논리 CPU 가 12개 있고 8 vCPU 가상 머신을 네 대 올리면 32 vCPU 가 12개의 논리 CPU 위에서 실행될 수 있다. 그 가상 머신들이 대부분 유휴 상태면 이 구성 자체가 장애를 뜻하지 않는다. 여러 가상 머신의 vCPU 가 동시에 실행 대기 상태가 될 때 CPU 경쟁과 스케줄링 지연이 늘어난다.
|
||||
|
||||
vCPU 스레드끼리만 경쟁하지도 않는다. 호스트에 Nginx 를 직접 설치하고 가상 머신 두 대를 실행하는 테스트 환경이라면 호스트 쪽 Nginx 와 K3s, DB, Redis, 그 밖의 호스트 프로세스도 같은 Linux 스케줄러를 거친다.
|
||||
|
||||
게스트 안에서 이 경쟁이 드러나는 값이 steal time 이다. 게스트 Linux 의 `top` 에서 `%st` 로 확인할 수 있다. 게스트 vCPU 에 실행할 작업이 있고 호스트에서 그 스레드가 CPU 를 필요로 하는데, 다른 작업 때문에 즉시 실행되지 못한 시간을 나타낸다. 이 값이 높으면 호스트 CPU 경쟁이나 논리 CPU 보다 많은 vCPU 를 할당한 초과 할당을 의심할 수 있지만, 단독으로 원인을 확정하는 지표는 아니다. 호스트 CPU 포화와 실행 대기열, 친화도, 어떤 작업이 돌고 있었는지를 함께 확인한다.
|
||||
|
||||
vCPU 스레드가 실행 대기 상태가 되어도 호스트 스케줄러가 실제 논리 CPU 에 배치할 때까지 기다릴 수 있다. 호스트가 포화될수록 이 대기 시간이 길어지고 게스트에서는 애플리케이션 지연 증가로 보인다. 그래서 vCPU 수를 늘린다고 항상 빨라지지 않는다. 게스트 쪽 작업이 그만큼의 병렬성을 쓰지 못하거나 호스트 전체 CPU 에 비해 vCPU 가 지나치게 많으면 스케줄링 대상만 늘어난다. pinning 도 잘못 설정하면 특정 CPU 에 작업이 몰리기 때문에 pinning 여부만 보지 않고 CPU 별 사용률과 친화도도 본다.
|
||||
|
||||
## 어느 계층에서 느려졌는지 가르는 표
|
||||
|
||||
가상 머신 안의 Keycloak 이 느려졌을 때 CPU 경로는 애플리케이션에서 물리 CPU 까지 여러 층을 지난다. Keycloak 파드는 K3s 의 cgroup CPU 상한 아래에서 실행된다. 그 아래로 게스트 Linux 와 vCPU, QEMU vCPU 스레드, 호스트 Linux 스케줄러, KVM 과 VMX, 물리 CPU 와 NUMA 가 이어진다. 같은 「CPU 가 느리다」는 현상도 층마다 원인이 다르다.
|
||||
|
||||
| 어떤 문제인가 | 주로 어느 계층인가 | 무엇부터 확인하나 |
|
||||
|---|---|---|
|
||||
| 게스트 CPU 포화 | 게스트 | 게스트 CPU, 프로세스·스레드, load |
|
||||
| CPU 제한(throttling) | K3s / cgroup | CPU 상한, throttled time |
|
||||
| vCPU 과다 할당 | 가상 머신 구성 | vCPU 수, 작업 병렬성 |
|
||||
| CPU 초과 할당 | 호스트 구성 | 전체 vCPU, 호스트 논리 CPU |
|
||||
| CPU 경쟁 | 호스트 스케줄러 | 호스트 CPU, 실행 대기열, CPU 별 사용률 |
|
||||
| steal time 증가 | 게스트에서 관측 | `%st`, 호스트 경쟁 |
|
||||
| 스케줄링 지연 | 호스트 스케줄러 | 실행 대기열, 스케줄러 관찰 |
|
||||
| 잘못된 pinning | 호스트 / 가상 머신 설정 | 친화도, CPU 별 사용률 |
|
||||
| 과도한 VM Exit | KVM / VMX | Exit 횟수와 이유, 작업 |
|
||||
| 호스트 CPU 포화 | 호스트 | 호스트 CPU·load·실행 대기열 |
|
||||
| NUMA locality | 하드웨어 / 메모리 | NUMA 토폴로지, CPU·메모리 배치 |
|
||||
|
||||
이 표로 하나의 지표를 골라 원인을 확정하지 않는다. 어느 계층부터 조사할지 범위를 줄이는 데 쓴다.
|
||||
|
||||
특히 두 원인이 겹쳐 보인다. 호스트 CPU 를 제때 받지 못하는 문제는 경쟁과 steal time, 스케줄링 쪽이고, 파드가 자신에게 걸린 CPU 상한을 넘겨 제한되는 문제는 K3s cgroup 쪽이다. 호스트 CPU 에 여유가 있어도 Keycloak 파드는 설정된 상한 때문에 실행이 제한될 수 있다. cgroup 제한은 KVM 문제가 아니지만 가상 머신 안에서 K3s 를 운영하는 이 실험에서는 같은 애플리케이션 지연으로 관찰되기 때문에 진단 경계에 포함한다.
|
||||
|
||||
호스트 OS 에 K3s 를 직접 설치했다면 컨테이너의 프로세스는 호스트 커널을 공유하고 호스트 스케줄러가 직접 스케줄링하는 대상이어서 QEMU 와 `/dev/kvm`, KVM, VMX 를 지나지 않는다. 가상 머신 안에 K3s 를 구성하면 게스트 Linux 와 vCPU, QEMU vCPU 스레드, KVM 과 VMX 계층이 그 아래에 더해진다. 같은 부하 테스트라도 가상 머신 기반 환경에서는 호스트 가상화 자원 병목을 추가로 확인한다. 운영 서버에서는 위 표의 어느 행부터 보는지가 달라질 수 있다. 운영 서버가 호스트에 K3s 를 직접 설치한 구성인지 상위 하이퍼바이저나 클라우드 가상 머신 위에 있는지를 아직 확인하지 않았기 때문이다. 부하를 걸어 재야 아는 것이 아니라 서버 구성을 한 번 확인하면 답이 정해진다.
|
||||
|
||||
## 호스트에서 이 경로를 확인하는 명령
|
||||
|
||||
이 경로가 실제 호스트에서도 그대로인지는 명령으로 하나씩 확인할 수 있다. CPU 가 하드웨어 가상화를 지원하는지는 플래그로 본다.
|
||||
|
||||
```bash label="Intel 은 vmx, AMD 는 svm flag 를 확인한다"
|
||||
grep -E 'vmx|svm' /proc/cpuinfo
|
||||
```
|
||||
|
||||
커널 모듈은 `lsmod | grep kvm` 으로, KVM API 진입점은 `ls -l /dev/kvm` 으로 확인한다. 실행 중인 가상 머신은 `virsh list` 로 본다. `ps -ef | grep '[q]emu'` 를 실행하면 가상 머신이 살아 있는 동안 함께 남아 있는 쪽이 `virsh` 가 아니라 QEMU 프로세스임을 확인할 수 있다.
|
||||
|
||||
QEMU 프로세스의 스레드는 `ps -T -p <QEMU_PID>` 나 `top -H -p <QEMU_PID>` 로 본다. 스레드 이름은 환경과 QEMU 버전에 따라 다를 수 있지만 vCPU 관련 스레드를 호스트에서 관찰할 수 있다. 그 스레드가 최근 어느 논리 CPU 에서 실행됐는지는 `PSR` 열이 알려 준다.
|
||||
|
||||
```bash label="vCPU thread 가 최근 실행된 logical CPU"
|
||||
ps -eLo pid,tid,psr,pcpu,comm | grep qemu
|
||||
```
|
||||
|
||||
여기 보이는 값은 vCPU 가 물리 CPU 에 영구 고정돼 있다는 뜻이 아니라, pinning 을 하지 않았을 때 스케줄링에 따라 달라지는 값이다. 게스트 쪽에서는 `top` 등으로 steal time 을 확인하고, 환경이 지원하면 `perf kvm` 으로 KVM 관련 실행 통계를 본다.
|
||||
|
||||
```bash label="KVM Exit 관찰"
|
||||
sudo perf kvm stat live
|
||||
```
|
||||
|
||||
지원되는 명령과 표시되는 Exit 이유는 커널과 `perf` 버전, CPU 아키텍처 및 설정에 따라 다르기 때문에 그 환경에서 무엇이 되는지 `perf kvm --help` 로 확인한다. 필요하면 KVM tracepoint 를 이용한 별도 추적도 검토한다.
|
||||
|
||||
## 이 문서가 확정하지 않는 것
|
||||
|
||||
CPU 가상화 개념에서 확정하는 수준은 셋까지다. 구조적으로 어떤 문제가 발생할 수 있는가, 어떤 지표로 그 문제를 의심할 수 있는가, 어느 계층에서 확인해야 하는가. 현재 테스트 서버에서 실제로 그 문제가 일어나는지는 여기서 사실로 확정하지 않는다.
|
||||
|
||||
이 호스트에서 잰 값은 하나도 없다. 관찰 명령은 무엇을 볼 수 있는지 적어 둔 목록이다. VM Exit 분포도 steal time 도, pinning 없이 vCPU 스레드가 논리 CPU 사이를 옮겨 다니는지도 아직 측정하지 않았다. 검증은 VMX 와 SVM 확인에서 시작한다. 그다음 KVM 모듈과 `/dev/kvm`, `virsh` 가상 머신, QEMU 프로세스, vCPU 스레드, 호스트 논리 CPU 스케줄링, 게스트가 유휴일 때와 부하를 받을 때의 비교, steal time, VM Exit 관찰로 이어진다. 값이 나오면 각각 재현 조건을 붙인 기록으로 남기고, 그때도 답하지 못한 항목은 열린 질문으로 유지한다.
|
||||
|
||||
범위 밖으로 미룬 영역도 있다. 네트워크·메모리·스토리지 가상화와 PCIe/VFIO/IOMMU 상세, K3s 네트워크와 컨테이너 런타임 상세는 이 문서가 다루지 않는다. NUMA 는 문제가 생길 수 있다는 것과 CPU 친화도와의 연관까지만 적었다. 메모리 배치와 NUMA 튜닝은 메모리 가상화 개념 문서에서 다룬다.
|
||||
|
||||
Keycloak refresh token 경쟁도 CPU 가상화 문제와 같은 문제가 아니다. 다만 가상 머신 기반 실험 환경의 CPU 경쟁이 실험 결과를 왜곡할 수 있어서 두 문제를 분리해 측정한다. 그래서 그 경쟁을 검증하는 첫 실험에서는 CPU 자원을 여유 있게 유지한 채 같은 세션과 같은 refresh token 에 대한 동시 요청을 만든다. 트래픽을 올려 자원 포화를 보는 부하·스트레스 실험은 따로 돌린다. 나눠 돌리는 이유는 결과를 「동일 상태에 동시에 접근해서 발생한 문제」와 「시스템 자원이 부족해져서 발생한 문제」로 갈라 읽기 위해서다. 한 실험에서 둘을 같이 일으키면 원인을 분리하기 어려워진다.
|
||||
|
||||
<!-- body:end -->
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
---
|
||||
id: d103bb81-45df-402f-86e5-e41d66ed7f8d
|
||||
kind: QUESTION
|
||||
slug: exit-distribution-for-keycloak-workload
|
||||
title: Keycloak 작업의 VM Exit 분포는 idle · CPU-bound · I/O-bound 와 어떻게 다른가
|
||||
topic: cpu-virtualization
|
||||
topicName: CPU 가상화
|
||||
project: virtualization
|
||||
status: 초안
|
||||
questionStatus: OPEN
|
||||
studio: "https://hyeonworks.com/studio/documents/d103bb81-45df-402f-86e5-e41d66ed7f8d/edit"
|
||||
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
|
||||
source:
|
||||
- final/document.md#27-문제-영역에서-파생되는-추가-open-question-oq-11
|
||||
- final/document.md#24-cpu-가상화-계층에서-발생할-수-있는-문제-24-9
|
||||
- final/document.md#14-실제-linux에서-확인할-수-있는-것-14-9
|
||||
---
|
||||
|
||||
# Keycloak 작업의 VM Exit 분포는 idle · CPU-bound · I/O-bound 와 어떻게 다른가
|
||||
|
||||
VM Exit 은 게스트를 실행하던 CPU 가 하이퍼바이저가 개입해야 하는 조건을 만나 제어권을 KVM 쪽으로 넘기는 전환이다. 정상적인 가상화 동작이라 Exit 이 있다는 것만으로 문제가 되지 않는다. 다만 하이퍼바이저가 개입해야 하는 Exit 이 특정 작업에서 지나치게 빈번하고 처리 비용이 커지면 성능에 영향을 줄 수 있다. Keycloak 을 돌리는 구간이 그런 작업인지 보려면 다른 구간의 Exit 분포와 견줘야 하는데, 이 호스트에서 Exit 을 관측하는 도구가 열리는지부터 확인하지 않았다.
|
||||
|
||||
## 관계
|
||||
|
||||
- **KVM 에서 vCPU 가 물리 CPU 에서 실행되기까지**
|
||||
무엇이 VM Exit 을 부르고 그 처리가 커널에서 끝나는지 QEMU 사용자 공간까지 가는지를 이 개념이 설명한다.
|
||||
- **실제 작업에서 주로 발생하는 VM Exit 은 무엇인가**
|
||||
그쪽은 작업 다섯의 분포를 서로 견주는 물음이고, 이 질문은 Keycloak 구간의 분포가 같은 구간의 지연과 같이 움직이는지를 묻는다.
|
||||
다섯 구간을 한 번 받으면 두 질문의 자료가 함께 나오지만 닫는 기준이 달라 기록은 따로 둔다. 도구가 이 환경에서 열리는지 보는 첫 단계도 둘이 같이 쓴다.
|
||||
|
||||
## 사실
|
||||
|
||||
- VM Exit 은 정상적인 가상화 동작이어서 Exit 이 존재한다는 것만으로 문제가 되지 않는다.
|
||||
- 하이퍼바이저가 개입해야 하는 Exit 이 특정 작업에서 지나치게 빈번하고 처리 비용이 커지면 성능에 영향을 줄 수 있다.
|
||||
- 확인할 때 함께 보는 것은 넷이다.
|
||||
Exit 이유
|
||||
작업 종류
|
||||
Exit 처리 위치가 KVM 인지 QEMU 사용자 공간인지
|
||||
애플리케이션 지연과 Exit 증가가 함께 나타나는지
|
||||
- Exit 이 많다는 관측 하나로 장애라고 판단하지 않는다.
|
||||
- 환경이 지원하면 perf kvm 으로 KVM 관련 실행 통계를 확인할 수 있고, 예로 든 명령은 sudo perf kvm stat live 다.
|
||||
- 지원되는 명령과 표시되는 Exit 이유는 커널과 perf 버전, CPU 아키텍처와 설정에 따라 다를 수 있어 perf kvm --help 를 함께 확인한다. 필요하면 KVM tracepoint 를 이용한 별도 추적도 검토한다.
|
||||
- 비교 후보로 적어 둔 구간은 idle, CPU-bound 작업, I/O 가 많은 작업, Keycloak 정상 요청, Keycloak 부하 테스트 다섯이다.
|
||||
이 목록은 개념 문서가 앞선 물음 자리에 적어 둔 것이고, 이 질문의 제목이 든 것은 그 가운데 앞쪽 셋이다. 받아야 하는 구간은 제목이 든 것보다 둘 많다.
|
||||
|
||||
## 가정
|
||||
|
||||
- 이 호스트에서 perf kvm 이나 KVM tracepoint 가운데 하나는 열린다고 보고 측정 순서를 짠다.
|
||||
둘 다 열리지 않는 결과도 이 질문의 정상적인 답이다.
|
||||
- 다섯 구간을 같은 도구로 같은 길이만큼 잴 수 있다고 전제한다.
|
||||
- Keycloak 부하 구간의 지연은 실험이 이미 재고 있는 값에서 가져올 수 있다고 본다.
|
||||
- I/O 가 많은 구간을 이 환경에서 따로 만들 수 있다고 보고 짰다. 만드는 방법은 개념 문서에 적혀 있지 않다.
|
||||
|
||||
## 미지수
|
||||
|
||||
- 이 호스트에서 perf kvm 의 어떤 하위 명령이 열리는지, 열리지 않으면 tracepoint 쪽이 열리는지.
|
||||
- Keycloak 구간의 Exit 이유 분포가 나머지 네 구간과 얼마나 다른지.
|
||||
- 그 차이가 같은 구간의 Keycloak 지연과 같이 움직이는지.
|
||||
- Exit 처리 위치가 KVM 인지 QEMU 사용자 공간인지를 이 환경의 출력으로 가를 수 있는지.
|
||||
- 관측이 열린다면 얼마나 오래 받아야 구간 사이의 차이가 잡히는지.
|
||||
|
||||
## 제약
|
||||
|
||||
- 표시되는 Exit 이유는 커널과 perf 버전, CPU 아키텍처와 설정에 따라 달라지므로 다른 환경에서 나온 분포와 이 호스트의 분포를 바로 견주지 않는다.
|
||||
- Exit 횟수만 세지 않는다. Exit 이유와 작업 종류, 처리 위치, 같은 구간의 지연을 함께 받아 적는다.
|
||||
- 도구가 열려야 측정이 시작된다. 열리지 않으면 이 질문은 값 없이 닫힌다.
|
||||
- sudo 가 필요한 명령이라 이 호스트에서 그 권한으로 실행할 수 있어야 한다.
|
||||
- 이 호스트에서 Exit 을 실제로 받아 본 기록이 없다.
|
||||
|
||||
## 선택지
|
||||
|
||||
### 1. perf kvm stat live 로 다섯 구간을 차례로 받는다
|
||||
|
||||
perf kvm --help 로 열리는 하위 명령을 먼저 확인하고, 열리면 다섯 구간을 각각 돌리며 Exit 이유 분포를 받는다.
|
||||
같은 도구로 다섯을 받으므로 구간 사이의 차이를 그대로 견줄 수 있다.
|
||||
|
||||
구간마다 부하를 따로 만들어야 하고, 분포가 관측 길이에 따라 흔들리면 같은 구간을 여러 번 받아야 한다.
|
||||
|
||||
### 2. KVM tracepoint 를 직접 켜서 받는다
|
||||
|
||||
perf kvm 이 이 커널과 perf 버전에서 열리지 않을 때 검토하는 방법이다.
|
||||
tracepoint 를 직접 켜면 Exit 이유를 더 세밀하게 받을 수 있다.
|
||||
|
||||
받은 결과를 다섯 구간에 걸쳐 같은 형태로 정리하는 일이 첫 번째 방법보다 손이 많이 가서, perf kvm 이 열리지 않는 것을 확인한 뒤에 간다.
|
||||
|
||||
### 3. Keycloak 구간만 받아 절대값으로 판단한다 — 제외
|
||||
|
||||
Keycloak 구간의 Exit 수가 크면 Exit 처리 비용이 있다고 읽는 방법이다.
|
||||
Exit 이 많다는 관측 하나로 장애라고 판단하지 않기로 했고, 무엇과 견줘야 「많다」인지도 이 호스트에는 아직 기준이 없다. 그래서 다른 구간 없이 Keycloak 구간만 받지 않는다.
|
||||
|
||||
## 다음 검증
|
||||
|
||||
1. perf kvm --help 로 이 환경이 지원하는 하위 명령을 확인한다.
|
||||
2. 열리면 sudo perf kvm stat live 로 idle, CPU-bound, I/O 가 많은 구간, Keycloak 정상 요청, Keycloak 부하 다섯의 Exit 이유 분포를 받는다.
|
||||
3. 같은 다섯 구간의 Keycloak 지연을 실험이 이미 재는 값에서 가져와 분포 옆에 적는다.
|
||||
4. perf kvm 이 열리지 않으면 KVM tracepoint 를 쓰는 쪽을 검토하고, 검토 결과와 그 판단 근거도 함께 기록한다.
|
||||
|
||||
닫는 조건 : Keycloak 구간의 Exit 분포가 다른 구간과 다르고 그 차이가 지연과 같이 움직이면 그 측정이 Case 가 되고 닫는다. 분포가 다르지 않거나 지연과 따로 움직이면, 이 작업에서 Exit 처리 비용은 조사 대상이 아니라고 적고 진단표의 「과도한 VM Exit」 행을 뒤로 미루는 근거로 남긴 뒤 닫는다.
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
---
|
||||
id: 688c6c02-c1bd-4cd2-a615-2396db145386
|
||||
kind: QUESTION
|
||||
slug: host-numa-topology
|
||||
title: 이 호스트의 NUMA 토폴로지는 가상 머신 성능을 고려해야 할 구조인가
|
||||
topic: cpu-virtualization
|
||||
topicName: CPU 가상화
|
||||
project: virtualization
|
||||
status: 초안
|
||||
questionStatus: OPEN
|
||||
studio: "https://hyeonworks.com/studio/documents/688c6c02-c1bd-4cd2-a615-2396db145386/edit"
|
||||
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
|
||||
source:
|
||||
- final/document.md#27-문제-영역에서-파생되는-추가-open-question-oq-12
|
||||
- final/document.md#24-cpu-가상화-계층에서-발생할-수-있는-문제-24-11
|
||||
---
|
||||
|
||||
# 이 호스트의 NUMA 토폴로지는 가상 머신 성능을 고려해야 할 구조인가
|
||||
|
||||
멀티소켓이나 NUMA(Non-Uniform Memory Access) 구조의 호스트에서는 vCPU 가 어느 노드의 CPU 에서 실행되고 그 가상 머신의 메모리가 어느 노드에 놓였는지가 성능에 영향을 줄 수 있다. 이 물음은 그 영향을 재는 것이 아니라, 이 호스트가 애초에 그 조건에 들어가는지를 먼저 가른다. 단일 노드로 나오면 지금 실험에서 우선순위를 낮추고, 다중 노드로 나오면 vCPU 와 메모리 배치를 따로 다룬다.
|
||||
|
||||
## 관계
|
||||
|
||||
- **KVM 에서 vCPU 가 물리 CPU 에서 실행되기까지**
|
||||
vCPU 스레드가 어느 논리 CPU 에서 실행될지를 호스트 스케줄러가 정한다는 것이 이 물음의 전제다.
|
||||
|
||||
## 사실
|
||||
|
||||
- 멀티소켓 또는 NUMA 구조의 호스트에서는 CPU 가 실행되는 NUMA 노드와 가상 머신 메모리가 놓인 NUMA 노드가 어디냐에 따라 성능이 달라질 수 있다.
|
||||
- vCPU 가 노드 0 의 CPU 에서 실행되는데 필요한 메모리가 주로 노드 1 에 배치되어 있으면 다른 노드의 메모리를 읽는 접근(remote memory access)이 생길 수 있다.
|
||||
- NUMA 는 CPU 가상화와 메모리 가상화의 경계에 걸쳐 있다. 그래서 지금 개념 문서는 문제가 있다는 것과 CPU 친화도와 어떻게 얽히는지까지만 기록했고, 상세한 메모리 배치와 NUMA 튜닝은 메모리 가상화를 다루는 개념 문서로 넘겼다.
|
||||
- 이 물음의 종료 기준은 개념 문서가 직접 적어 두었다.
|
||||
단일 NUMA 노드 : 지금 실험에서 우선순위를 낮춘다
|
||||
다중 NUMA 노드 : vCPU 와 메모리 배치를 별도 Case 후보로 올린다
|
||||
개념 문서가 남긴 열린 물음 열둘 가운데 닫는 갈래를 스스로 적어 둔 것은 이 하나다.
|
||||
- 개념 문서는 이 확인에 쓸 명령을 적지 않았다. 다른 확인 항목과 달리 NUMA 쪽에는 예로 든 명령이 없다.
|
||||
- 이 호스트의 NUMA 노드 수를 확인한 기록이 없다.
|
||||
|
||||
## 가정
|
||||
|
||||
- 호스트에 붙어 노드 수를 읽을 수 있다고 본다.
|
||||
- 단일 노드로 나오면 vCPU 가 실행되는 노드와 메모리가 놓인 노드가 갈리지 않으므로 다른 노드의 메모리를 읽을 일이 지금 실험에서 성능 차이를 만들지 않는다고 본다.
|
||||
그 추론을 이 호스트에서 확인하지는 않았다.
|
||||
- 두 가상 머신의 메모리 배치가 실행 중에 바뀌지 않는다고 전제한다.
|
||||
|
||||
## 미지수
|
||||
|
||||
- 이 호스트가 단일 NUMA 노드인지 다중 NUMA 노드인지.
|
||||
- 다중이라면 두 가상 머신의 vCPU 와 메모리가 각각 어느 노드에 배치되어 있는지.
|
||||
- 노드 수와 배치를 이 환경에서 어떤 명령으로 읽는지. 개념 문서가 그 명령을 적지 않아 실행하는 쪽이 정한다.
|
||||
- 다중으로 나왔을 때 배치를 바꾸는 일이 지금 가상 머신 구성에서 가능한지.
|
||||
|
||||
## 제약
|
||||
|
||||
- 이 질문이 다중 노드로 닫혀도 여기서 NUMA 튜닝을 정하지 않는다. 상세한 메모리 배치는 메모리 가상화를 다루는 개념 문서가 받는다.
|
||||
- 쓸 명령을 개념 문서가 정해 주지 않으므로, 실행한 명령과 그 출력을 함께 증거로 남겨야 다음 사람이 같은 값을 다시 읽을 수 있다.
|
||||
- 이 호스트에서 잰 값이 없어 다른 장비의 노드 구성을 근거로 삼지 않는다.
|
||||
|
||||
## 선택지
|
||||
|
||||
### 1. 노드 수만 먼저 읽고 거기서 갈린다
|
||||
|
||||
호스트의 NUMA 노드 수 하나로 우선순위 판정이 끝나기 때문에 확인이 짧고, 단일로 나오면 더 볼 것이 없다.
|
||||
|
||||
다중으로 나오면 vCPU 와 메모리 배치를 읽으려고 한 번 더 붙어야 한다.
|
||||
|
||||
### 2. 노드 수와 두 가상 머신의 배치를 한 번에 읽는다
|
||||
|
||||
호스트에 붙은 김에 노드 수와 각 가상 머신의 vCPU · 메모리 배치를 같이 받아 적는다. 다중으로 나왔을 때 바로 다음 단계로 넘어갈 수 있다.
|
||||
|
||||
단일로 나오면 함께 받은 배치는 쓰지 않게 되는데, 대신 실행이 한 번으로 끝난다.
|
||||
|
||||
### 3. 메모리 가상화 개념 문서를 쓸 때 함께 본다 — 제외
|
||||
|
||||
상세한 메모리 배치를 그쪽에서 다루기로 했으니 확인도 그때 하자는 방법이다.
|
||||
지금 필요한 판단은 이 항목을 실험 목록의 어디에 둘지 하나이고, 그것은 노드 수만으로 갈린다. 메모리 가상화 쪽을 기다리면 그동안 우선순위를 정하지 못한 채로 둔다.
|
||||
개념 문서가 적은 다음 기반 영역은 메모리 가상화가 아니라 네트워크 가상화이고, 메모리 쪽을 언제 정리하는지는 적혀 있지 않다.
|
||||
|
||||
## 다음 검증
|
||||
|
||||
1. 호스트의 NUMA 노드 구성을 확인해 노드 수를 적는다.
|
||||
2. 이 확인에 쓴 명령과 그 출력을 함께 증거로 남긴다. 개념 문서가 명령을 적어 두지 않아 실행한 쪽이 무엇을 썼는지 기록해야 한다.
|
||||
3. 다중 노드로 나오면 vCPU 가 실행되는 노드와 가상 머신 메모리가 배치된 노드까지 이어서 적는다.
|
||||
|
||||
닫는 조건 : 단일 NUMA 노드로 나오면 지금 실험에서 우선순위를 낮추고 닫는다. 다중 NUMA 노드로 나오면 vCPU 와 메모리 배치를 별도 Case 후보로 올리고, 이 프로젝트가 메모리 가상화 쪽 정리를 가질 때 그리로 넘긴다.
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
---
|
||||
id: 4a2d3332-81c3-44fa-a4fb-216a41abb504
|
||||
kind: QUESTION
|
||||
slug: idle-vcpu-thread-appearance
|
||||
title: 게스트가 유휴 상태일 때 vCPU 스레드는 이 테스트 환경에서 어떻게 보이는가
|
||||
topic: cpu-virtualization
|
||||
topicName: CPU 가상화
|
||||
project: virtualization
|
||||
status: 초안
|
||||
questionStatus: OPEN
|
||||
studio: "https://hyeonworks.com/studio/documents/4a2d3332-81c3-44fa-a4fb-216a41abb504/edit"
|
||||
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
|
||||
source:
|
||||
- final/document.md#20-이-concept에서-파생되는-open-question-oq-3
|
||||
- final/document.md#10-guest가-idle이면-물리-cpu는-어떻게-되는가
|
||||
- final/document.md#14-실제-linux에서-확인할-수-있는-것-14-6
|
||||
---
|
||||
|
||||
# 게스트가 유휴 상태일 때 vCPU 스레드는 이 테스트 환경에서 어떻게 보이는가
|
||||
|
||||
게스트에 할 일이 없으면 vCPU 스레드가 잠들거나 대기 상태로 들어가고, 그동안 호스트는 그 물리 CPU 를 다른 작업에 쓸 수 있다. 이 서술이 이 환경에서도 그대로 보이는지는 QEMU 프로세스의 스레드 목록을 유휴와 부하 두 상태에서 찍어 봐야 아는데, 아직 어느 쪽도 찍지 않았다. 이 QEMU 버전에서 vCPU 스레드가 어떤 이름으로 나오는지도 모른다.
|
||||
|
||||
## 관계
|
||||
|
||||
- **KVM 에서 vCPU 가 물리 CPU 에서 실행되기까지**
|
||||
vCPU 스레드가 왜 잠들 수 있는지, 무엇이 그것을 깨우는지를 이 개념이 설명한다.
|
||||
- **pinning 없이 vCPU 스레드는 호스트 논리 CPU 사이를 옮겨 다니는가**
|
||||
같은 `ps -eLo` 출력의 `psr` 값을 본다. 여기서 스레드를 가려내는 방법이 정해지면 그쪽 측정이 바로 이어진다.
|
||||
|
||||
## 사실
|
||||
|
||||
가상 머신에 4 vCPU 를 설정했다고 해서 4개의 호스트 논리 CPU 가 계속 예약되지는 않는다 : §10
|
||||
|
||||
§10 이 그린 유휴 흐름
|
||||
|
||||
Guest 에 실행할 작업 없음
|
||||
Guest Kernel idle
|
||||
HLT 등
|
||||
VM Exit
|
||||
KVM
|
||||
vCPU Thread block/sleep
|
||||
|
||||
이때 호스트 스케줄러는 물리 CPU 를 호스트의 다른 작업에 쓸 수 있다 : §10
|
||||
|
||||
§10 이 그린 깨어나는 흐름
|
||||
|
||||
vCPU wake-up
|
||||
runnable
|
||||
Host Linux Scheduler
|
||||
Logical CPU 에서 vCPU Thread 실행
|
||||
KVM / VM Entry
|
||||
Guest 실행 재개
|
||||
|
||||
§10 은 깨우는 이유로 타이머, 인터럽트, I/O 완료를 든다.
|
||||
|
||||
§14.6 은 ps -T -p <QEMU_PID> 또는 top -H -p <QEMU_PID> 로 vCPU 관련 스레드를 호스트에서 관찰할 수 있다고 적으면서, 환경과 QEMU 버전에 따라 이름은 다를 수 있다는 단서를 함께 단다.
|
||||
|
||||
§20 은 게스트의 유휴 상태와 CPU 부하 상태를 비교하라고 적고 확인 명령으로 둘을 든다.
|
||||
|
||||
top -H -p <QEMU_PID>
|
||||
ps -eLo pid,tid,psr,pcpu,stat,comm
|
||||
|
||||
## 가정
|
||||
|
||||
QEMU 프로세스의 PID 를 먼저 찾아야 한다. 가상 머신 두 대가 도는 호스트에서 어느 PID 가 어느 가상 머신인지 가리는 방법을 아직 정하지 않았다.
|
||||
|
||||
vCPU 스레드를 이름으로 못 가리면 스레드 수를 그 가상 머신의 vCPU 수와 맞춰 가린다고 전제한다.
|
||||
|
||||
유휴라고 부를 상태를 이 가상 머신에서 만들 수 있다. 가상 머신 안에서 도는 것이 있으면 완전한 유휴가 아니다.
|
||||
|
||||
pcpu 와 stat 를 한 번씩 찍은 값으로 두 상태를 가를 수 있다.
|
||||
|
||||
## 미지수
|
||||
|
||||
이 환경의 QEMU 에서 vCPU 스레드가 어떤 이름으로 보이는지.
|
||||
|
||||
유휴 상태에서 그 스레드의 pcpu 와 stat 값.
|
||||
|
||||
CPU 부하를 걸었을 때 같은 두 값이 어떻게 바뀌는지.
|
||||
|
||||
vCPU 스레드 말고 어떤 스레드가 같은 QEMU 프로세스 아래에 함께 보이는지, 그 스레드들이 유휴 상태에서도 CPU 를 쓰는지.
|
||||
|
||||
유휴인데도 주기적으로 깨어나는 구간이 있는지. §10 은 타이머와 인터럽트를 깨우는 이유로 들었다.
|
||||
|
||||
## 제약
|
||||
|
||||
이 호스트에서 찍은 출력이 없다. §10 은 개념 흐름을 그린 것이고 이 환경의 실제 출력이 아니다. 결과가 §10 과 같으면 개념에 흡수되고 다르면 Case 가 된다는 갈림을 처음에는 이 물음을 따로 세우지 않을 이유로 봤다. 지금은 그것을 그대로 닫는 조건으로 쓴다 — 어느 쪽으로 갈리든 물음은 닫힌다.
|
||||
|
||||
§14.6 이 스레드 이름은 환경과 QEMU 버전에 따라 다를 수 있다고 적기 때문에, 이름으로 거르는 절차를 미리 굳혀 둘 수 없다.
|
||||
|
||||
§20 이 든 확인 명령 둘은 그 시점의 스레드 목록과 값을 보여 준다. §10 이 적은 HLT 에서 VM Exit 을 거쳐 block/sleep 으로 가는 전이를 단계마다 짚어 주지는 않는다.
|
||||
|
||||
상태를 바꾸는 것 말고 가상 머신 구성은 건드리지 않는다. vCPU 수를 조정하면 유휴와 부하의 차이 대신 구성 차이를 보게 된다.
|
||||
|
||||
## 선택지
|
||||
|
||||
### 1. 스레드 이름부터 확정한다
|
||||
|
||||
§14.6 의 ps -T -p <QEMU_PID> 로 그 QEMU 프로세스의 스레드 목록을 받아, vCPU 스레드로 보이는 것이 그 가상 머신의 vCPU 수와 같은 수로 나오는지 맞춰 본다. 이름을 확정해 두면 뒤의 두 출력에서 어느 줄을 읽을지 정해진다.
|
||||
|
||||
### 2. 유휴와 부하를 같은 명령 두 개로 찍어 나란히 둔다
|
||||
|
||||
§20 이 확인 명령으로 top -H -p <QEMU_PID> 와 ps -eLo pid,tid,psr,pcpu,stat,comm 둘을 들었다. 두 상태에서 같은 두 명령을 돌리면 pcpu 와 stat 두 열을 그대로 견줄 수 있다. §14.7 이 스레드가 어느 논리 CPU 에서 돌았는지 볼 때 든 ps 에는 stat 열이 없다. §20 은 이 물음의 확인 명령에만 그 열을 더했고, 스레드가 자고 있는지 실행 상태인지는 그 열에서 읽는다.
|
||||
|
||||
### 3. 호스트 쪽 CPU 사용량도 같이 본다
|
||||
|
||||
§10 은 vCPU 스레드가 잠들면 호스트가 그 물리 CPU 를 다른 작업에 쓸 수 있다고 적는다. vCPU 스레드의 pcpu 만 보면 그 스레드가 CPU 를 안 쓴다는 데까지만 확인되고, 비워 준 CPU 를 호스트가 실제로 다른 작업에 썼는지는 안 보인다.
|
||||
|
||||
### 4. 제외 — 추적으로 전이 시점을 직접 잡는다
|
||||
|
||||
HLT 로 VM Exit 이 나고 스레드가 잠드는 순간을 추적하면 §10 의 흐름을 단계마다 확인할 수 있다. 그러나 이 질문은 두 상태의 출력이 갈리는지를 묻고 §20 도 확인 명령을 두 줄로 적어 두었기 때문에, 더 무거운 도구는 두 출력이 갈리지 않을 때 꺼낸다.
|
||||
|
||||
## 다음 검증
|
||||
|
||||
1. 가상 머신을 유휴 상태로 둔 채 top -H -p <QEMU_PID> 와 ps -eLo pid,tid,psr,pcpu,stat,comm 을 찍는다.
|
||||
2. 같은 가상 머신에 CPU 부하를 걸고 같은 두 명령을 다시 찍는다.
|
||||
3. 두 출력을 나란히 둔다. §20 이 적은 확인 명령 그대로다.
|
||||
|
||||
닫는 조건 : 유휴 상태에서 vCPU 스레드의 pcpu 가 0 에 가깝고 stat 가 sleep 계열이며 부하에서 실행 상태로 바뀌면, §10 의 서술이 이 환경에서도 성립하는 것으로 개념의 확인 사례에 흡수하고 닫는다. 두 상태에서 출력이 갈리지 않거나 §10 과 반대로 나오면 그 출력이 Case 가 된다.
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
---
|
||||
id: 2acec7d5-3eaf-4115-9d61-45647c4ec01e
|
||||
kind: QUESTION
|
||||
slug: is-production-on-a-hypervisor
|
||||
title: 운영 서버는 CPU 가상화 계층의 영향을 받는 구조인가
|
||||
topic: cpu-virtualization
|
||||
topicName: CPU 가상화
|
||||
project: virtualization
|
||||
status: 초안
|
||||
questionStatus: OPEN
|
||||
studio: "https://hyeonworks.com/studio/documents/2acec7d5-3eaf-4115-9d61-45647c4ec01e/edit"
|
||||
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
|
||||
source:
|
||||
- final/document.md#20-이-concept에서-파생되는-open-question-oq-6
|
||||
- final/document.md#18-bare-metal-k3s와-vm-기반-k3s의-차이
|
||||
- final/document.md#25-cpu-문제를-계층별로-구분하는-진단표
|
||||
---
|
||||
|
||||
# 운영 서버는 CPU 가상화 계층의 영향을 받는 구조인가
|
||||
|
||||
§18 과 §20 은 K3s 가 호스트 스케줄러로 바로 가는 경로와 게스트 · vCPU · 하이퍼바이저를 더 지나는 경로를 나란히 적었다.
|
||||
§25 의 진단표는 문제마다 주된 계층을 갈라 놓아서, Virtualization 과 Host 계층에만 걸리는 행이 따로 있다.
|
||||
운영 서버가 두 경로 중 어느 쪽인지는 SSOT 에 적혀 있지 않은데, 그 구조가 정해져야 진단표의 어느 행을 운영 진단에 쓸지 고를 수 있다.
|
||||
|
||||
## 관계
|
||||
|
||||
- **KVM 에서 vCPU 가 물리 CPU 에서 실행되기까지**
|
||||
운영 서버가 가상 머신 위라면 무엇이 더 끼어드는지를 설명한 기록이다.
|
||||
|
||||
## 사실
|
||||
|
||||
§18 은 호스트 OS 에 K3s 를 직접 설치했을 때의 CPU 경로를 적었다.
|
||||
컨테이너에서 도는 작업은 K3s 와 컨테이너 런타임을 지나 호스트 Linux 스케줄러로, 다시 물리 CPU 로 간다.
|
||||
|
||||
그 호스트 위에 별도 가상 머신이 없다면 그 작업이 QEMU 와 /dev/kvm, KVM, VMX 경로를 타지는 않는다.
|
||||
컨테이너의 프로세스는 호스트 커널을 공유하고 호스트 스케줄러가 직접 스케줄링한다.
|
||||
|
||||
가상 머신 안에 K3s 를 구성하면 계층이 더 붙는다.
|
||||
§18 이 든 것은 게스트 Linux 와 K3s, vCPU, QEMU vCPU 스레드, 호스트 Linux 스케줄러, KVM / VMX 다.
|
||||
그래서 같은 부하 테스트라도 가상 머신 기반 환경에서는 호스트 가상화 자원 병목을 추가로 확인해야 한다.
|
||||
|
||||
§20 의 OQ-6 은 두 경로를 K3s -> Host Scheduler -> Physical CPU 와 K3s -> Guest -> vCPU -> Hypervisor -> Physical CPU 로 나란히 적고, 구조에 따라 진단 지표가 달라진다고 밝혔다.
|
||||
|
||||
§25 의 진단표는 문제마다 주된 계층을 갈라 적었다.
|
||||
|
||||
vCPU 과다 할당 : VM 구성
|
||||
CPU overcommit : Host 구성
|
||||
CPU contention · Scheduling latency : Host Scheduler
|
||||
잘못된 pinning : Host / VM 설정
|
||||
과도한 VM Exit : KVM / VMX
|
||||
Steal time 증가 : Guest 에서 관측
|
||||
Host CPU saturation : Host
|
||||
|
||||
운영 서버가 bare-metal 인지 상위 하이퍼바이저나 클라우드 가상 머신 위인지는 SSOT 에 적혀 있지 않다.
|
||||
|
||||
## 가정
|
||||
|
||||
운영 서버도 K3s 로 Keycloak 을 돌린다고 전제한다. §20 이 나눈 두 경로는 둘 다 K3s 에서 시작한다.
|
||||
|
||||
운영 서버가 그 두 갈래 중 하나라고 전제한다. 중첩 가상화처럼 계층이 더 들어가는 구성은 이 물음에 넣지 않았다.
|
||||
|
||||
구조가 정해지면 §25 의 진단표를 운영 진단에도 그대로 쓴다고 전제한다. 진단표를 만든 근거는 이 테스트 환경이다.
|
||||
|
||||
## 미지수
|
||||
|
||||
운영 서버가 bare-metal 호스트에 직접 K3s 를 설치한 것인가, 상위 하이퍼바이저나 클라우드 가상 머신 위에 있는가.
|
||||
|
||||
하이퍼바이저 위라면 그 호스트의 CPU 지표를 우리가 볼 수 있는가.
|
||||
클라우드 가상 머신이면 호스트 쪽 실행 대기열과 사용률을 읽을 수 없어 §25 의 Host 행을 그대로 쓰기 어려워진다.
|
||||
|
||||
운영 서버에 직접 붙어 명령을 돌릴 수 있는가.
|
||||
|
||||
## 제약
|
||||
|
||||
이 물음은 부하를 걸어 재는 것이 아니라 구성을 확인해서 닫는다.
|
||||
|
||||
§14.1~§14.3 은 그 장비가 가상 머신을 직접 돌리는 호스트 인지를 보여 준다.
|
||||
그 장비 자신이 어떤 하이퍼바이저의 게스트 인지는 이 세 명령이 말해 주지 않는다.
|
||||
|
||||
구조가 정해지기 전에는 §25 의 어느 행을 운영 진단에 넣을지 고를 수 없다.
|
||||
|
||||
§25 는 그 표의 목적을 「하나의 지표로 장애 원인을 확정하는 것이 아니라, 어느 계층부터 조사해야 하는지 범위를 줄이는 것」이라고 적었다.
|
||||
그래서 이 물음이 닫혀도 운영 장애의 원인이 정해지는 것은 아니다. 정해지는 것은 어느 계층부터 조사할지다.
|
||||
|
||||
## 선택지
|
||||
|
||||
### 1. 구성 기록과 도입 경로로 확인한다
|
||||
|
||||
서버를 어떻게 마련했는지 남은 기록으로 bare-metal 인지 하이퍼바이저나 클라우드 가상 머신 위인지 가른다.
|
||||
운영 서버에 붙지 않아도 되고 부하도 걸지 않는다.
|
||||
|
||||
기록이 실제 구성과 어긋나 있으면 어긋난 채로 적히므로 2번과 함께 쓴다.
|
||||
|
||||
### 2. 서버에 붙어 명령으로 확인한다
|
||||
|
||||
§14.1~§14.3 의 grep -E 'vmx|svm' /proc/cpuinfo · lsmod | grep kvm · ls -l /dev/kvm 로 그 장비가 가상 머신을 직접 돌리는 호스트인지부터 적는다.
|
||||
이어서 게스트 안에서 top 의 %st 가 관측되는지 본다.
|
||||
|
||||
세 명령이 모두 비어 있으면 그 장비가 가상 머신을 직접 돌리지는 않는다는 뜻이고, 그 위에 하이퍼바이저가 있는지는 1번의 구성 기록으로 가른다.
|
||||
|
||||
### 3. 제외 — 테스트 환경의 구조를 운영에 옮겨 적는다
|
||||
|
||||
테스트 환경이 가상 머신 위라는 것이 운영 서버의 구조를 말해 주지 않는다.
|
||||
두 환경을 같다고 적으면 §25 의 Virtualization 행을 근거 없이 운영 진단에 넣게 된다.
|
||||
|
||||
## 다음 검증
|
||||
|
||||
1. 운영 서버의 구성 기록이나 도입 경로로 bare-metal 인지 하이퍼바이저 / 클라우드 가상 머신 위인지 확인한다.
|
||||
2. 서버에 붙을 수 있으면 §14.1~§14.3 의 grep -E 'vmx|svm' /proc/cpuinfo · lsmod | grep kvm · ls -l /dev/kvm 으로 그 장비가 가상 머신을 직접 돌리는 호스트인지 적는다.
|
||||
3. 게스트 안에서 top (§14.8) 의 %st 가 관측되는지 함께 본다.
|
||||
|
||||
닫는 조건 : 운영 서버가 bare-metal 로 확인되면 §25 의 Virtualization · Host 행을 운영 진단에서 빼도 된다고 적고 닫는다. 하이퍼바이저나 클라우드 가상 머신 위로 확인되면 그 사실이 운영 진단의 전제가 되고, §25 의 어느 행을 운영에서 쓸지는 그 뒤 Decision 이 정한다.
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
---
|
||||
id: 62319064-17ef-4b2f-bf8b-e363cd0e36a6
|
||||
kind: QUESTION
|
||||
slug: pinning-before-and-after
|
||||
title: CPU pinning 전후로 Keycloak 지연과 vCPU 스케줄링 변동이 달라지는가
|
||||
topic: cpu-virtualization
|
||||
topicName: CPU 가상화
|
||||
project: virtualization
|
||||
status: 초안
|
||||
questionStatus: OPEN
|
||||
studio: "https://hyeonworks.com/studio/documents/62319064-17ef-4b2f-bf8b-e363cd0e36a6/edit"
|
||||
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
|
||||
source:
|
||||
- final/document.md#27-문제-영역에서-파생되는-추가-open-question-oq-10
|
||||
- final/document.md#24-cpu-가상화-계층에서-발생할-수-있는-문제-24-7
|
||||
- final/document.md#14-실제-linux에서-확인할-수-있는-것-14-7
|
||||
---
|
||||
|
||||
# CPU pinning 전후로 Keycloak 지연과 vCPU 스케줄링 변동이 달라지는가
|
||||
|
||||
vCPU 스레드가 실행될 호스트 논리 CPU 를 특정 집합으로 제한하는 설정을 CPU pinning 이라고 한다. 적절히 걸면 스케줄링 변동이 줄지만 잘못 걸면 특정 CPU 에만 작업이 몰린다. 이 호스트에서는 pinning 을 걸지 않은 상태의 Keycloak 지연도, 건 상태의 지연도 아직 재지 않았으므로 pinning 이 지금 작업에 이점을 주는지는 말할 수 없다.
|
||||
|
||||
## 관계
|
||||
|
||||
- **KVM 에서 vCPU 가 물리 CPU 에서 실행되기까지**
|
||||
pinning 도 CPU 격리도 하지 않았을 때 vCPU 스레드를 누가 어디에 배치하는지를 이 개념이 설명한다.
|
||||
- **pinning 없이 vCPU 스레드는 호스트 논리 CPU 사이를 옮겨 다니는가**
|
||||
그쪽이 이동 자체를 관측하고, 이 질문은 그 이동을 없앴을 때 Keycloak 지연이 달라지는지를 받는다.
|
||||
|
||||
## 사실
|
||||
|
||||
- CPU pinning 은 특정 vCPU 스레드를 특정 호스트 논리 CPU 에 제한하는 설정이다.
|
||||
- 적절히 쓰면 스케줄링 변동을 줄일 수 있고, 잘못 설정하면 특정 CPU 에 작업이 집중될 수 있다.
|
||||
- 그래서 pinning 을 걸었는지만 보지 않고 CPU 별 사용률과 친화도를 함께 확인한다.
|
||||
- 개념 문서가 잘못 건 예로 그린 것은 vCPU 스레드 둘과 호스트 프로세스 하나가 같은 논리 CPU 에 묶이고 나머지 논리 CPU 는 상대적으로 유휴한 그림이다.
|
||||
치우침을 만드는 쪽에 호스트 프로세스가 함께 들어 있다.
|
||||
- 스레드가 최근 실행된 논리 CPU 는 ps -eLo pid,tid,psr,pcpu,comm | grep qemu 의 PSR 로 볼 수 있다.
|
||||
- PSR 값 하나가 vCPU 가 물리 CPU 에 영구 고정되어 있다는 뜻은 되지 않는다. pinning 을 걸지 않았다면 스케줄링에 따라 달라질 수 있다.
|
||||
- pinning 이 지금 작업에서 실제 이점을 주는지는 실험으로 확인하기로 했고, 아직 그 실험을 돌리지 않았다.
|
||||
|
||||
## 가정
|
||||
|
||||
- 지금 두 가상 머신에 pinning 도 별도의 친화도 설정도 걸려 있지 않다고 보고 「전」 실행을 잡는다.
|
||||
걸려 있는지는 개념 문서에 적혀 있지 않아 실행할 때 함께 확인한다.
|
||||
- pinning 없이 돌리면 같은 tid 의 PSR 이 시간에 따라 바뀐다고 본다.
|
||||
이 호스트에서 그 이동을 아직 관측하지 않았다.
|
||||
- 두 실행에 같은 Keycloak 부하를 같은 방식으로 걸 수 있다고 전제한다.
|
||||
- 두 실행 사이에 vCPU 수와 가상 머신 배치를 바꾸지 않는다고 두고 짠다. 그래야 차이를 pinning 쪽으로 읽을 수 있다.
|
||||
|
||||
## 미지수
|
||||
|
||||
- pinning 뒤 Keycloak 지연이 달라지는지, 달라진다면 어느 방향인지.
|
||||
- 같은 tid 의 PSR 변동이 실제로 줄어드는지.
|
||||
- 변동이 줄어드는 대신 특정 논리 CPU 로 작업이 몰리는지.
|
||||
- 어떤 논리 CPU 집합에 묶을지. 이 호스트의 논리 CPU 수와 각 가상 머신의 vCPU 수를 아직 적지 않았다.
|
||||
- 호스트 쪽 Nginx 와 다른 호스트 프로세스가 그 집합을 함께 쓰는지.
|
||||
|
||||
## 제약
|
||||
|
||||
- pinning 여부만으로 판정하지 않는다. 지연과 PSR 변동, CPU 별 사용률 셋을 같은 실행에서 받아 적는다.
|
||||
- 「전」과 「후」 두 실행의 부하가 같아야 지연 차이를 pinning 쪽으로 읽을 수 있다.
|
||||
- 이 호스트에서 잰 값이 하나도 없어 견줄 값을 이번 실행이 함께 만든다.
|
||||
- 이 실행 전에 pinning 을 쓸지 말지를 먼저 정하지 않는다. 잰 값이 없는 상태로 정하면 그 선택이 감수하는 비용을 적을 수 없다.
|
||||
- 묶는 대상은 vCPU 스레드다. 게스트 안의 Keycloak 파드 배치는 이 질문이 다루지 않는다.
|
||||
|
||||
## 선택지
|
||||
|
||||
### 1. 같은 부하로 전후 두 실행을 재고 세 항목을 나란히 놓는다
|
||||
|
||||
pinning 없이 Keycloak 부하를 걸어 지연과 PSR 변동과 CPU 별 사용률을 남기고, vCPU 스레드를 논리 CPU 에 묶은 뒤 같은 부하로 같은 세 항목을 다시 남긴다.
|
||||
지연이 좋아졌는지와 그 대가로 특정 CPU 에 몰렸는지를 한 실행 쌍에서 같이 볼 수 있다.
|
||||
|
||||
가상 머신 설정을 바꿔 다시 부하를 거는 만큼 시간이 든다. 두 실행 사이에 다른 조건이 바뀌면 그 실행 쌍은 버린다.
|
||||
|
||||
### 2. 부하 없이 PSR 변동만 견준다
|
||||
|
||||
유휴 구간에서 PSR 을 여러 번 찍어 pinning 전후를 견주는 방법이다. 부하를 만들지 않아도 되고 실행이 짧다.
|
||||
|
||||
이 방법으로는 질문의 절반만 답한다. pinning 이 스케줄링 변동을 줄이는지는 보이지만 Keycloak 지연이 달라지는지는 보이지 않고, 부하가 없으면 특정 CPU 에 작업이 몰리는지도 드러나지 않는다.
|
||||
|
||||
### 3. 지연만 견주고 CPU 별 사용률은 뒤로 미룬다 — 제외
|
||||
|
||||
전후 지연만 재면 실행 하나가 짧아진다.
|
||||
다만 잘못 건 pinning 도 짧은 구간에서는 지연이 좋아진 것으로 보일 수 있다. 그 경우를 가려내려고 CPU 별 사용률과 친화도를 함께 보기로 했으므로 이 방법은 쓰지 않는다.
|
||||
|
||||
## 다음 검증
|
||||
|
||||
1. pinning 을 걸지 않은 상태에서 Keycloak 부하를 걸고, 지연과 ps -eLo pid,tid,psr,pcpu,comm | grep qemu 의 PSR 변동, CPU 별 사용률을 남긴다.
|
||||
2. 같은 실행에서 그 가상 머신에 친화도 설정이 이미 걸려 있는지도 함께 적는다.
|
||||
3. vCPU 스레드를 논리 CPU 에 묶고 같은 부하를 다시 걸어 같은 세 항목을 남긴다.
|
||||
4. 두 실행을 나란히 놓고 지연 차이와 CPU 별 사용률의 치우침을 함께 읽는다.
|
||||
|
||||
닫는 조건 : pinning 뒤 지연이 좋아지고 CPU 별 사용률이 특정 CPU 로 몰리지 않으면, pinning 을 쓸지 말지를 Decision 으로 넘긴다. 그 Decision 이 감수할 비용은 잘못 건 pinning 이 특정 CPU 에 작업을 집중시킨다는 것이다. 두 실행에서 지연 차이가 없으면 이 작업에서는 pinning 이 이점을 주지 않는다고 적고 닫는다.
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
---
|
||||
id: 2d058fb5-01f1-4be8-80bb-0e377868573c
|
||||
kind: QUESTION
|
||||
slug: steal-time-increase-under-two-cpu-bound-vms
|
||||
title: 가상 머신 두 대를 CPU-bound 로 만들면 게스트 steal time 은 얼마나 오르는가
|
||||
topic: cpu-virtualization
|
||||
topicName: CPU 가상화
|
||||
project: virtualization
|
||||
status: 초안
|
||||
questionStatus: OPEN
|
||||
studio: "https://hyeonworks.com/studio/documents/2d058fb5-01f1-4be8-80bb-0e377868573c/edit"
|
||||
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
|
||||
source:
|
||||
- final/document.md#27-문제-영역에서-파생되는-추가-open-question-oq-7
|
||||
- final/document.md#13-steal-time
|
||||
- final/document.md#24-cpu-가상화-계층에서-발생할-수-있는-문제-24-4
|
||||
---
|
||||
|
||||
# 가상 머신 두 대를 CPU-bound 로 만들면 게스트 steal time 은 얼마나 오르는가
|
||||
|
||||
§24.4 는 steal time 을 게스트에 실행할 작업이 있는데도 하이퍼바이저나 호스트가 그 vCPU 스레드를 즉시 실행시키지 못한 시간으로 적었다.
|
||||
게스트의 `top` 에서 `%st` 로 보이는 값이지만, §13 과 §24.4 는 그 값 하나로 원인을 확정해서는 안 된다고 함께 못 박았다.
|
||||
§27 은 이 물음에서 호스트의 CPU 사용률과 실행 대기열, QEMU vCPU 스레드, 각 게스트의 `%st` 를 함께 재라고 적었다.
|
||||
이 호스트에서 `%st` 를 잰 값이 없어서, 부하 전 기준값부터 남겨야 증가폭을 숫자로 적을 수 있다.
|
||||
|
||||
## 관계
|
||||
|
||||
- **KVM 에서 vCPU 가 물리 CPU 에서 실행되기까지**
|
||||
게스트가 관측하는 steal time 이 호스트에서 무엇 때문에 생기는지를 설명한 기록이다.
|
||||
- **가상 머신 두 대에 동시에 부하를 주면 이 호스트에서 vCPU 경쟁이 실제로 생기는가**
|
||||
같은 부하 실행을 쓴다. 경쟁이 있는지를 묻는 쪽과 그것이 `%st` 로 얼마나 보이는지를 묻는 쪽으로 갈린다.
|
||||
- **vCPU 를 늘릴수록 이 호스트에서 Keycloak 처리량도 계속 오르는가**
|
||||
총 vCPU 를 늘린 구성에서 `%st` 가 어떻게 달라지는지가 그쪽 실행에서 다시 나온다.
|
||||
|
||||
## 사실
|
||||
|
||||
§13 은 게스트 Linux 에서 top 등의 CPU 지표를 볼 때 st(steal time)를 확인할 수 있다고 적었다.
|
||||
|
||||
§13 이 적은 steal time 은 이런 상황을 가리키는 단서다.
|
||||
게스트 vCPU 에 실행할 작업이 있고, 호스트에서 vCPU 스레드가 CPU 를 필요로 하는데, 다른 작업 때문에 즉시 실행되지 못한다.
|
||||
|
||||
높은 steal time 은 가상화 환경에서 호스트 CPU 경쟁이나 CPU 초과 할당을 의심할 수 있는 지표 중 하나다.
|
||||
다만 그 값 하나로 원인을 확정해서는 안 되고, 호스트 CPU 포화와 실행 대기열, 친화도, 어떤 작업이 돌고 있었는지를 함께 확인해야 한다고 같은 절이 적었다.
|
||||
|
||||
§24.4 는 게스트에 실행할 작업이 있는데 하이퍼바이저나 호스트가 그 vCPU 스레드를 즉시 실행시키지 못한 시간을 게스트가 steal time 으로 관찰한다고 적었다.
|
||||
그 값은 게스트의 top 등에서 %st 로 본다.
|
||||
같은 절은 높은 steal time 을 호스트 CPU 경쟁 또는 초과 할당을 조사하라는 단서로 두되, 단독으로 원인을 확정하는 지표는 아니라고 적었다.
|
||||
|
||||
§24.3 은 경쟁 대상이 QEMU vCPU 스레드만은 아니라고 적었다.
|
||||
호스트에 Nginx 를 직접 설치하고 가상 머신 두 대를 실행하는 테스트 환경에서는 가상 머신 밖의 호스트 작업도 CPU 경쟁에 포함된다.
|
||||
|
||||
§27 의 OQ-7 은 함께 측정할 항목으로 넷을 들었다.
|
||||
|
||||
Host CPU utilization
|
||||
Host run queue
|
||||
QEMU vCPU thread
|
||||
각 Guest 의 %st
|
||||
|
||||
이 호스트에서 %st 를 실제로 잰 값은 없다.
|
||||
|
||||
## 가정
|
||||
|
||||
두 가상 머신을 동시에 CPU-bound 로 만들면 vCPU 스레드끼리 호스트 CPU 시간을 두고 경쟁하게 된다고 전제한다.
|
||||
이 호스트의 논리 CPU 수와 두 가상 머신의 vCPU 합계가 SSOT 에 적혀 있지 않아서, 경쟁이 생기는 구성인지도 아직 전제로만 두었다.
|
||||
|
||||
두 게스트에 같은 정도의 부하를 걸 수 있다고 전제한다.
|
||||
한쪽이 더 세게 걸리면 두 %st 를 나란히 놓고 읽을 수 없다.
|
||||
|
||||
부하 전과 부하 중을 각각 한 번씩 찍으면 비교할 수 있다고 전제한다.
|
||||
값이 흔들리면 한 번씩 찍은 두 값만으로는 증가인지 흔들림인지 갈리지 않는다.
|
||||
|
||||
## 미지수
|
||||
|
||||
두 가상 머신을 동시에 CPU-bound 로 만들었을 때 각 게스트의 %st 가 부하 전 대비 얼마나 오르는가.
|
||||
|
||||
그 증가가 호스트 실행 대기열과 같은 방향으로 움직이는가.
|
||||
|
||||
이 호스트의 논리 CPU 수는 얼마이고 두 가상 머신의 vCPU 합계는 그 수에 견줘 어느 정도인가.
|
||||
|
||||
## 제약
|
||||
|
||||
§13 이 steal time 하나로 원인을 확정하지 않는다고 적었으므로 %st 만 재서는 이 물음이 닫히지 않는다.
|
||||
|
||||
부하 전 기준값을 먼저 남기지 않으면 부하 중 값만으로 증가를 적을 수 없다.
|
||||
|
||||
네 항목을 같은 시각에 찍어야 서로 견줄 수 있다. 따로 찍은 값을 한 표에 놓으면 부하 구간이 어긋난다.
|
||||
|
||||
부하 구간에 호스트에서 Nginx 같은 다른 작업이 함께 돌면 %st 의 증가분을 두 가상 머신 사이의 경쟁으로만 읽을 수 없다.
|
||||
|
||||
OQ-1 과 이 물음은 같은 부하 실행에서 값을 얻는다. 그래도 한 물음으로 합치지 않았다.
|
||||
합치면 경쟁이 있었다는 결론과 그것이 %st 로 얼마나 보였다는 결론 가운데 어느 쪽 기준으로 닫혔는지가 남지 않는다.
|
||||
|
||||
## 선택지
|
||||
|
||||
### 1. 부하 전후로 네 항목을 같은 실행에서 남긴다
|
||||
|
||||
§27 이 든 네 항목을 부하 전에 한 번, 두 가상 머신을 동시에 CPU-bound 로 만든 뒤에 한 번 같은 시각으로 기록한다.
|
||||
%st 가 올랐을 때 호스트 실행 대기열도 함께 올랐는지를 같은 표에서 읽을 수 있다.
|
||||
|
||||
실행이 한 번이라 값이 흔들리는 정도는 알 수 없다. 흔들림이 의심되면 부하 구간을 늘려 여러 번 찍는다.
|
||||
|
||||
### 2. 제외 — %st 만 부하 전후로 비교한다
|
||||
|
||||
찍을 것이 하나뿐이라 실행은 가볍다.
|
||||
다만 §13 이 함께 확인하라고 든 호스트 CPU 포화와 실행 대기열이 빠져서, %st 가 올라도 그것이 호스트 경쟁 때문인지 게스트 쪽 작업 때문인지 가를 수 없다.
|
||||
|
||||
### 3. 제외 — 가상 머신 한 대만 CPU-bound 로 만들어 비교군을 하나 더 만든다
|
||||
|
||||
이 물음이 묻는 것은 두 대를 동시에 부하로 만든 상태이고, 부하 전 값이 이미 비교군이다.
|
||||
한 대 부하가 필요해지면 1번 실행을 마친 뒤에 따로 더한다.
|
||||
|
||||
## 다음 검증
|
||||
|
||||
1. 부하 전에 Host CPU utilization 과 run queue, ps -eLo pid,tid,psr,pcpu,comm | grep qemu (§14.7) 의 QEMU vCPU thread 사용량, 각 Guest 의 top (§14.8) %st 를 기준값으로 남긴다.
|
||||
2. 가상 머신 두 대를 동시에 CPU-bound 로 만든다.
|
||||
3. 같은 네 항목을 같은 시각에 다시 기록한다.
|
||||
|
||||
닫는 조건 : 부하 전후의 %st 와 호스트 실행 대기열을 한 표로 놓을 수 있으면 그 표가 Case 가 되고 닫는다. %st 가 부하 전과 다르지 않으면 이 호스트 구성에서는 두 가상 머신 동시 부하가 steal time 으로 나타나는 경쟁을 만들지 않는다고 적는다. 그 결론은 OQ-1 과 함께 닫는다.
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
---
|
||||
id: 116b806c-b176-401c-9363-1489fffb721c
|
||||
kind: QUESTION
|
||||
slug: throttling-vs-contention
|
||||
title: cgroup CPU 제한과 호스트 vCPU 경쟁을 지표로 가를 수 있는가
|
||||
topic: cpu-virtualization
|
||||
topicName: CPU 가상화
|
||||
project: virtualization
|
||||
status: 초안
|
||||
questionStatus: OPEN
|
||||
studio: "https://hyeonworks.com/studio/documents/116b806c-b176-401c-9363-1489fffb721c/edit"
|
||||
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
|
||||
source:
|
||||
- final/document.md#27-문제-영역에서-파생되는-추가-open-question-oq-9
|
||||
- final/document.md#24-cpu-가상화-계층에서-발생할-수-있는-문제-24-8
|
||||
- final/document.md#25-cpu-문제를-계층별로-구분하는-진단표
|
||||
---
|
||||
|
||||
# cgroup CPU 제한과 호스트 vCPU 경쟁을 지표로 가를 수 있는가
|
||||
|
||||
가상 머신 안에서 K3s 를 돌리는 지금 구성에서는 Keycloak 파드가 자신에게 걸린 CPU 상한에 막혀 느려진 것(cgroup throttling)과 호스트 CPU 를 제때 받지 못해 느려진 것(Host vCPU contention)이 같은 애플리케이션 지연으로 관찰될 수 있다. 계층별 진단표는 두 원인을 다른 계층에 갈라 놓고 먼저 볼 항목도 따로 적어 두었다. 다만 이 호스트에서 두 원인을 각각 재현해 그 항목들이 실제로 다르게 움직이는지는 확인하지 않았다.
|
||||
|
||||
## 관계
|
||||
|
||||
- **KVM 에서 vCPU 가 물리 CPU 에서 실행되기까지**
|
||||
호스트 CPU 경쟁이 게스트 안에서 어떤 값으로 드러나는지를 이 개념이 설명한다.
|
||||
- **Keycloak 동시 refresh 실험 중 CPU 가상화 계층이 결과를 흔들 만큼 포화되는가**
|
||||
그쪽에서 가상화 계층 지표가 움직인다는 답이 나오면, 그 움직임을 cgroup 쪽 제한과 가를 수 있는지는 이 질문이 받는다.
|
||||
|
||||
## 사실
|
||||
|
||||
- 가상 머신 안에서 K3s 를 돌리면 물리 CPU 와 Keycloak 파드 사이에 호스트·하이퍼바이저, 게스트 Linux, K3s, cgroup CPU limit 이 차례로 놓인다.
|
||||
- 호스트 CPU 에 여유가 있어도 Keycloak 파드는 설정된 CPU 상한 때문에 실행이 제한될 수 있다.
|
||||
- 호스트 CPU 를 받지 못해 생긴 문제와 파드가 자신의 CPU 상한을 넘겨 생긴 문제는 서로 다른 계층에 있다.
|
||||
앞의 것은 경쟁과 steal time, 스케줄링 쪽이고 뒤의 것은 cgroup 제한 쪽이다.
|
||||
- cgroup 제한 자체는 KVM 문제가 아니다.
|
||||
그래도 가상 머신 안에서 K3s 를 운영하는 지금 실험에서는 두 원인이 같은 애플리케이션 지연으로 관찰될 수 있어 진단 경계에 넣었다.
|
||||
개념 문서가 다루기로 한 범위는 CPU 가상화 하나인데, cgroup 제한은 그 범위 밖에서 진단 경계 안으로 들여온 항목이다.
|
||||
- 계층별 진단표가 적은 우선 확인 항목은 이렇게 갈린다.
|
||||
CPU throttling : CPU limit · throttled time
|
||||
CPU contention : 호스트 CPU · 실행 대기열 · CPU 별 사용률
|
||||
- 같은 표가 두 원인의 대표적인 현상도 갈라 적었다.
|
||||
cgroup 쪽은 파드가 CPU 를 더 쓰려 해도 상한에 막힌 것이고, 경쟁 쪽은 실행 가능한 작업이 늘면서 지연이 늘어난 것이다.
|
||||
갈라 적힌 현상은 각 계층에서 보이는 모습이라, 애플리케이션 지연만 보고 있으면 그 구분이 드러나지 않는다.
|
||||
- 그 표는 지표 하나로 원인을 확정하려고 만든 것이 아니라 어느 계층부터 조사할지 범위를 줄인다.
|
||||
- 이 호스트에서 throttled time 도 steal time 도 잰 값이 없다.
|
||||
|
||||
## 가정
|
||||
|
||||
- 같은 크기의 Keycloak 지연 증가를 두 원인으로 각각 만들어 낼 수 있다고 보고 비교를 짠다.
|
||||
두 재현이 실제로 같은 크기가 되는지는 해 보기 전에 알 수 없다.
|
||||
- 다른 가상 머신에 CPU 부하를 걸면 호스트 쪽 경쟁이 생긴다고 본다.
|
||||
이 호스트에서 두 가상 머신 동시 부하가 경쟁을 만드는지는 아직 관측하지 않았다.
|
||||
- Keycloak 파드의 cgroup CPU limit 은 실험을 위해 낮췄다가 되돌릴 수 있다고 본다.
|
||||
- 두 재현 사이에 다른 조건이 바뀌지 않는다는 것을 전제로 두 실행을 견준다.
|
||||
|
||||
## 미지수
|
||||
|
||||
- 두 원인을 각각 재현했을 때 throttled time · CPU limit · 게스트 CPU 와 %st, 호스트 CPU 와 실행 대기열이 서로 다른 조합으로 움직이는지.
|
||||
- 갈린다면 어느 항목이 가장 먼저 갈리는지.
|
||||
- 지금 Keycloak 파드에 CPU limit 이 걸려 있는지, 걸려 있다면 얼마인지. 개념 문서에 적혀 있지 않다.
|
||||
- throttled time 을 이 환경에서 어떤 경로로 읽는지. 개념 문서는 확인 항목으로만 적고 실제로 읽는 명령을 적지 않았다.
|
||||
- 두 원인이 동시에 걸린 구간에서도 지표가 갈리는지. 이번 검증은 하나씩 만든 두 실행만 견준다.
|
||||
|
||||
## 제약
|
||||
|
||||
- 두 재현이 비슷한 크기의 지연 증가를 만들어야 지표 조합을 견줄 수 있다.
|
||||
- 지표 하나로 원인을 확정하지 않는다. 게스트 · 호스트 · K3s 세 쪽을 같은 시각에 받아 적는다.
|
||||
- refresh 경쟁 실험은 CPU 자원을 여유 있게 둔 상태에서 먼저 돌리므로 이 재현은 그 실험과 같은 시간에 걸지 않는다.
|
||||
- 이 호스트의 논리 CPU 수와 두 가상 머신의 vCPU 수를 개념 문서가 적어 두지 않았다.
|
||||
부하 쪽 재현이 실제로 경쟁을 만드는지는 그 두 값을 적은 뒤에 판단한다.
|
||||
|
||||
## 선택지
|
||||
|
||||
### 1. 두 원인을 따로 재현해 지표 조합을 나란히 놓는다
|
||||
|
||||
Keycloak 파드의 cgroup CPU limit 을 낮춰 한 번, 다른 가상 머신에 CPU 부하를 걸어 한 번, 같은 크기의 지연을 두 번 만든다.
|
||||
두 실행에서 게스트 · 호스트 · K3s 쪽 항목을 같은 이름으로 받아 적으면 어느 항목이 두 재현에서 다르게 움직이는지 그대로 보인다.
|
||||
|
||||
셋 가운데 손이 가장 많이 간다. 부하 쪽 재현은 다른 가상 머신을 함께 써야 하고, cgroup 쪽 재현은 파드 설정을 바꿨다가 되돌려야 한다.
|
||||
|
||||
### 2. 호스트 쪽 항목부터 보고 범위를 줄인다
|
||||
|
||||
호스트 CPU 와 실행 대기열, CPU 별 사용률을 먼저 본다.
|
||||
호스트에 여유가 있는데 파드만 느리면 조사 범위가 cgroup 쪽으로 줄어든다.
|
||||
|
||||
호스트가 포화된 것으로 나오면 거기서 끝나지 않는다. 그 구간에 파드의 상한도 함께 걸려 있었는지는 이 순서로 가려낼 수 없어서, 결국 첫 번째 선택지의 두 재현으로 돌아간다.
|
||||
|
||||
### 3. throttled time 하나로 가른다 — 제외
|
||||
|
||||
throttled time 이 0 이 아니면 cgroup 제한, 0 이면 호스트 경쟁으로 읽는 방법이다.
|
||||
진단표는 두 행에 각각 두 항목 이상을 적어 두었다. 지표 하나로 원인을 확정하지 않기로 하고 만든 표이므로 이 순서는 쓰지 않는다.
|
||||
|
||||
## 다음 검증
|
||||
|
||||
1. 부하를 걸기 전에 파드의 throttled time 과 CPU limit, 게스트 CPU 와 게스트에서 top 으로 본 %st, 호스트 CPU 와 실행 대기열을 한 번 찍어 기준값으로 둔다.
|
||||
2. Keycloak 파드의 cgroup CPU limit 을 낮춰 Keycloak 지연을 올리고 같은 다섯 항목을 같은 시각에 받아 적는다.
|
||||
3. limit 을 되돌린 뒤, 이번에는 다른 가상 머신에 CPU 부하를 걸어 비슷한 크기의 지연을 만들고 같은 다섯 항목을 다시 받아 적는다.
|
||||
4. 두 실행의 기록을 기준값과 함께 한 표에 나란히 놓는다.
|
||||
|
||||
닫는 조건 : 두 재현에서 지표 조합이 갈리면 그 대조표가 Case 가 되고, 진단표의 두 행을 어떤 순서로 보는지 정하는 근거가 된다. 갈리지 않으면 「이 지표들로는 두 원인이 구분되지 않는다」를 적고, 무엇을 더 봐야 하는지를 새 Question 으로 낸 뒤 이 질문은 닫는다.
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
---
|
||||
id: 723d8930-9e82-4552-8376-038a6446ec71
|
||||
kind: QUESTION
|
||||
slug: throughput-vs-vcpu-count
|
||||
title: vCPU 를 늘릴수록 이 호스트에서 Keycloak 처리량도 계속 오르는가
|
||||
topic: cpu-virtualization
|
||||
topicName: CPU 가상화
|
||||
project: virtualization
|
||||
status: 초안
|
||||
questionStatus: OPEN
|
||||
studio: "https://hyeonworks.com/studio/documents/723d8930-9e82-4552-8376-038a6446ec71/edit"
|
||||
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
|
||||
source:
|
||||
- final/document.md#27-문제-영역에서-파생되는-추가-open-question-oq-8
|
||||
- final/document.md#11-vm의-4-vcpu는-정확히-무엇을-의미하는가
|
||||
- final/document.md#24-cpu-가상화-계층에서-발생할-수-있는-문제-24-6
|
||||
---
|
||||
|
||||
# vCPU 를 늘릴수록 이 호스트에서 Keycloak 처리량도 계속 오르는가
|
||||
|
||||
§11 은 4 vCPU 를 실행 컨텍스트 4개를 주는 것으로 적었지, 물리 CPU 4개를 가상 머신이 영구적으로 소유하는 것으로 적지 않았다.
|
||||
§24.6 은 vCPU 를 많이 할당한다고 항상 성능이 좋아지지는 않는다고 적었다.
|
||||
§27 은 비교 구성으로 2 vCPU · 4 vCPU · 8 vCPU 를 들었다.
|
||||
세 구성에 같은 Keycloak 부하를 걸어 본 기록이 이 호스트에 없어서, 처리량이 어디서부터 더 오르지 않는지는 모른다.
|
||||
|
||||
## 관계
|
||||
|
||||
- **KVM 에서 vCPU 가 물리 CPU 에서 실행되기까지**
|
||||
vCPU 수가 무엇을 뜻하고 호스트 CPU 가 부족할 때 무엇이 경쟁하는지를 설명한 기록이다.
|
||||
- **가상 머신 두 대를 CPU-bound 로 만들면 게스트 steal time 은 얼마나 오르는가**
|
||||
총 vCPU 를 늘린 구성에서 `%st` 가 어떻게 나오는지를 그쪽과 같은 방법으로 읽는다.
|
||||
|
||||
## 사실
|
||||
|
||||
§11 은 4 vCPU 를 게스트 OS 가 최대 4개의 CPU 실행 흐름을 가질 수 있도록 가상 CPU 실행 컨텍스트 4개를 제공하는 뜻으로 적었다.
|
||||
호스트의 물리 CPU 4개를 가상 머신이 영구적으로 소유한다는 뜻은 아니다.
|
||||
호스트 CPU 가 부족하면 QEMU vCPU 스레드와 호스트의 다른 작업이 같은 논리 CPU 자원을 두고 경쟁할 수 있다고 같은 절이 덧붙였다.
|
||||
|
||||
§24.6 은 특정 가상 머신에 vCPU 를 많이 할당한다고 항상 성능이 좋아지는 것은 아니라고 적었다.
|
||||
게스트 쪽 작업이 실제로 그만큼의 병렬성을 쓰지 못하거나 호스트 전체 CPU 에 비해 지나치게 많은 vCPU 를 할당하면 스케줄링 대상만 늘 수 있다.
|
||||
§24.6 은 이것을 「vCPU 수가 많다 = 항상 빠르다로 판단하지 않는다」는 한 줄로 못 박았다.
|
||||
그래서 실제 작업의 병렬성과 호스트 전체 CPU 를 함께 확인해야 한다고 같은 절이 적었다.
|
||||
|
||||
§27 의 OQ-8 은 vCPU 추가가 실제 처리량과 지연에 어떤 영향을 주는지 확인하는 비교 구성으로 2 vCPU / 4 vCPU / 8 vCPU 를 들었다.
|
||||
|
||||
이 호스트에서 vCPU 수를 바꿔 가며 Keycloak 처리량을 잰 값은 없다.
|
||||
|
||||
## 가정
|
||||
|
||||
세 구성에서 Keycloak 설정과 부하 도구, 부하 크기를 같게 둘 수 있다고 전제한다.
|
||||
vCPU 수만 달라져야 처리량 차이를 vCPU 수 탓으로 읽을 수 있다.
|
||||
|
||||
Keycloak 작업이 vCPU 를 늘린 만큼 병렬로 쓴다고는 전제하지 않는다.
|
||||
§24.6 이 든 두 원인 가운데 병렬성 부족 쪽은 이 작업에서 확인하지 않았다.
|
||||
|
||||
2 · 4 · 8 세 점으로 처리량이 꺾이는 구간을 짚을 수 있다고 전제한다.
|
||||
상한이 4 와 8 사이에 있으면 세 점만으로는 몇 vCPU 인지 나오지 않는다.
|
||||
§27 은 그 세 구성을 「예를 들어」로 들었다. 사이 값이 필요해지면 점을 더해도 그 절이 든 비교 구성을 벗어나지 않는다.
|
||||
|
||||
## 미지수
|
||||
|
||||
vCPU 를 2 에서 4, 8 로 올렸을 때 처리량과 지연이 어디서부터 더 좋아지지 않는가.
|
||||
|
||||
좋아지지 않는다면 원인이 작업의 병렬성 부족인가 호스트 전체 CPU 부족인가.
|
||||
|
||||
이 호스트의 논리 CPU 수는 얼마이고, 8 vCPU 구성이 그 수를 넘는가.
|
||||
|
||||
## 제약
|
||||
|
||||
vCPU 수만 바꾸고 Keycloak 설정과 부하는 세 실행에서 고정한다.
|
||||
|
||||
8 vCPU 가 호스트 논리 CPU 수를 넘는지에 따라 재는 것이 작업의 병렬성인지 초과 할당인지 달라지므로, 호스트 논리 CPU 수를 먼저 적는다.
|
||||
|
||||
§24.6 이 든 두 원인을 가르려면 처리량과 지연만으로는 부족하다. 게스트의 %st 를 같은 실행에서 남긴다.
|
||||
|
||||
## 선택지
|
||||
|
||||
### 1. 2 · 4 · 8 세 구성에 같은 부하를 걸고 처리량과 지연, %st 를 남긴다
|
||||
|
||||
§27 이 든 비교 구성 그대로다. 세 값이 한 표에 놓이면 어느 구간부터 처리량이 더 오르지 않는지를 그 표에서 읽는다.
|
||||
%st 를 함께 남기므로 처리량이 멈춘 구간에서 호스트가 포화됐는지 아닌지를 가를 수 있다.
|
||||
|
||||
가상 머신을 세 번 다시 구성하고 부하를 세 번 걸어야 해서 실행이 가장 무겁다.
|
||||
|
||||
### 2. 제외 — 2 와 4 만 재고 8 을 건너뛴다
|
||||
|
||||
실행이 둘로 줄지만 §24.6 이 말한 지나치게 많은 vCPU 쪽은 8 구성에서만 나타난다.
|
||||
2 에서 4 로 오르는 것만 보고 vCPU 를 더 줘도 된다고 적으면 §24.6 이 막으려던 판단을 그대로 하게 된다.
|
||||
|
||||
### 3. 제외 — 호스트 CPU 사용률만 보고 vCPU 수를 정한다
|
||||
|
||||
사용률이 낮아도 게스트 쪽 작업이 병렬성을 쓰지 못하면 처리량은 오르지 않는다.
|
||||
§24.6 이 병렬성과 호스트 전체 CPU 를 함께 확인하라고 적었으므로 처리량을 직접 잰다.
|
||||
|
||||
## 다음 검증
|
||||
|
||||
1. 가상 머신 구성을 2 vCPU · 4 vCPU · 8 vCPU 로 바꿔 가며 같은 Keycloak 부하를 걸고 처리량과 지연을 각각 기록한다.
|
||||
2. 세 실행 모두에서 호스트 논리 CPU 수 대비 총 vCPU 를 함께 적는다.
|
||||
3. 세 실행 모두에서 게스트의 top (§14.8) %st 를 남겨 §24.6 이 말한 병렬성 부족과 호스트 전체 CPU 부족을 갈라 둔다.
|
||||
|
||||
닫는 조건 : 처리량이 더 오르지 않기 시작하는 vCPU 수가 나오면 그 지점을 이 작업의 상한으로 적고 그 세 실행이 Case 가 된다. 세 구성이 모두 같은 방향으로 오르면 이 호스트에서는 상한에 닿지 않았다고 적고 닫는다. 어느 vCPU 수로 운영할지는 그 뒤 Decision 이 정한다.
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
---
|
||||
id: eba4a877-276a-4050-9a97-d32614546c71
|
||||
kind: QUESTION
|
||||
slug: vcpu-contention-under-two-vm-load
|
||||
title: 가상 머신 두 대에 동시에 부하를 주면 이 호스트에서 vCPU 경쟁이 실제로 생기는가
|
||||
topic: cpu-virtualization
|
||||
topicName: CPU 가상화
|
||||
project: virtualization
|
||||
status: 초안
|
||||
questionStatus: OPEN
|
||||
studio: "https://hyeonworks.com/studio/documents/eba4a877-276a-4050-9a97-d32614546c71/edit"
|
||||
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
|
||||
source:
|
||||
- final/document.md#20-이-concept에서-파생되는-open-question-oq-1
|
||||
- final/document.md#12-cpu-contention과-overcommit
|
||||
- final/document.md#16-현재-keycloak-k3s-실험과의-관계
|
||||
---
|
||||
|
||||
# 가상 머신 두 대에 동시에 부하를 주면 이 호스트에서 vCPU 경쟁이 실제로 생기는가
|
||||
|
||||
Keycloak 멀티 노드 실험은 물리 호스트 한 대 위의 가상 머신 두 대에서 돌아간다. 두 가상 머신이 동시에 CPU 를 많이 쓰면 QEMU vCPU 스레드끼리 호스트 CPU 시간을 두고 경쟁할 수 있다. 그런데 이 호스트에 논리 CPU 가 몇 개인지도, 두 가상 머신에 vCPU 를 몇 개씩 줬는지도 문서에 적혀 있지 않아 경쟁이 생길 조건인지부터 모른다.
|
||||
|
||||
## 관계
|
||||
|
||||
- **KVM 에서 vCPU 가 물리 CPU 에서 실행되기까지**
|
||||
vCPU 스레드가 호스트 Linux 스케줄러를 거쳐 논리 CPU 에 배치되는 경로를 이 개념이 설명한다.
|
||||
- **가상 머신 두 대를 CPU-bound 로 만들면 게스트 steal time 은 얼마나 오르는가**
|
||||
같은 부하를 걸고 게스트 쪽 지표만 따로 묻기 때문에, 호스트 쪽 지표까지 한 번에 찍으면 두 질문이 같은 측정으로 닫힌다. 한 물음으로 합칠지는 값을 잰 뒤에야 알 수 있어 지금은 둘로 두고 관계로만 이었다.
|
||||
|
||||
## 사실
|
||||
|
||||
§12 는 호스트에 논리 CPU 가 12개 있고 8 vCPU 짜리 가상 머신 넷을 올린 예를 드는데, 그러면 총 32 vCPU 가 12개의 논리 CPU 위에서 실행될 수 있다.
|
||||
|
||||
모든 가상 머신이 동시에 CPU 를 많이 사용하면 vCPU 스레드끼리 호스트 CPU 시간을 두고 경쟁한다 : §12
|
||||
이런 상황에서는 게스트 안의 애플리케이션이 느려졌더라도 원인이 그 애플리케이션이 아니라 호스트 CPU 경쟁일 수 있다 : §12
|
||||
|
||||
§16 이 그린 테스트 환경은 Physical Host 아래 Host Nginx 와 가상 머신 두 대이고, VM 1 과 VM 2 가 각각 K3s 노드와 Keycloak 을 돌린다.
|
||||
|
||||
§16 이 결과 해석에서 분리하라고 든 원인 일곱
|
||||
|
||||
Keycloak refresh/session 동시성
|
||||
PostgreSQL contention/locking
|
||||
Redis 상태 관리
|
||||
K3s resource scheduling
|
||||
VM vCPU scheduling
|
||||
Host CPU saturation
|
||||
Nginx/LB
|
||||
|
||||
§20 이 이 물음의 확인 대상으로 든 다섯
|
||||
|
||||
Host logical CPU 수
|
||||
각 VM vCPU 수
|
||||
QEMU vCPU thread CPU 사용량
|
||||
Host run queue
|
||||
Guest steal time
|
||||
|
||||
이 호스트의 논리 CPU 수 : 문서에 없음
|
||||
두 가상 머신의 vCPU 수 : 문서에 없음
|
||||
|
||||
§12 의 12 와 8 과 32 는 경쟁이 어떻게 생기는지 설명하려고 든 예시 숫자이지 이 호스트에서 읽은 값이 아니다.
|
||||
|
||||
## 가정
|
||||
|
||||
두 가상 머신은 같은 물리 호스트의 CPU 를 나눠 쓴다. §16 이 그린 구조가 지금 실험 환경과 같다고 전제한다.
|
||||
|
||||
두 가상 머신에 같은 시각에 CPU 부하를 걸 수 있고, 그때 호스트와 두 게스트의 지표를 같은 시각에 기록할 수 있다.
|
||||
|
||||
게스트 Linux 의 top 이 이 환경에서 %st 를 실제로 채워 준다. %st 열이 보여 주는 steal time 은 게스트의 vCPU 에 실행할 작업이 있는데도 다른 작업 때문에 곧바로 실행되지 못한 상황을 가리킨다(§13). 이 열이 비면 게스트 쪽에서는 경쟁의 단서를 못 본다.
|
||||
|
||||
호스트 쪽 Nginx 도 같은 물리 CPU 를 쓰는데, 부하 구간의 호스트 CPU 사용량을 전부 QEMU vCPU 스레드 몫으로 읽으면 이 전제가 깨진다.
|
||||
|
||||
## 미지수
|
||||
|
||||
이 호스트의 논리 CPU 수.
|
||||
|
||||
두 가상 머신에 준 vCPU 수와 그 합. 그 합이 논리 CPU 수를 넘는지.
|
||||
|
||||
부하를 걸기 전 QEMU vCPU 스레드의 CPU 사용량과 호스트의 실행 대기열(run queue), 그리고 두 게스트의 %st. 부하 전 값이 없으면 부하 중 값만 가지고는 그 값이 움직인 것인지 판정할 수 없다.
|
||||
|
||||
두 가상 머신에 동시에 부하를 걸었을 때 그 세 지표가 어떻게 움직이는지.
|
||||
|
||||
vCPU 합이 논리 CPU 수 이하인데도 %st 가 오르는 구간이 있는지.
|
||||
|
||||
## 제약
|
||||
|
||||
이 호스트에서 잰 값이 하나도 없다. 근거는 개념을 정리한 문서 한 편이고 §12 의 숫자는 예시다.
|
||||
|
||||
§20 이 확인 대상을 다섯으로 잡았으므로 steal time 하나만 찍고 닫을 수 없다. 호스트 쪽 사용량과 실행 대기열도 함께 본다. 이 물음은 닫는 조건이 없다고 보아 한 번 기록에서 뺐다가 되돌렸다. §20 이 이미 적어 둔 확인 대상 다섯이 그대로 닫는 조건이 되기 때문이다.
|
||||
|
||||
§16 은 CPU 가상화가 Keycloak refresh token 경쟁의 원인은 아니라고 못박는다. 이 질문은 원인을 찾으려는 것이 아니라 실험 결과를 어느 계층 쪽으로 읽을지 가르는 데 쓴다.
|
||||
|
||||
측정하는 동안 실험 환경 구성은 바꾸지 않는다. pinning 을 걸거나 vCPU 수를 줄이면 지금 구성에서 경쟁이 생기는지를 못 본다.
|
||||
|
||||
## 선택지
|
||||
|
||||
### 1. 호스트 논리 CPU 수와 각 가상 머신의 vCPU 수를 먼저 읽는다
|
||||
|
||||
이 두 값은 부하를 걸지 않고도 지금 읽을 수 있다. 둘만 있으면 vCPU 합이 논리 CPU 수를 넘는지 갈리고, 넘지 않는 구성이라면 §12 가 든 32 대 12 같은 초과 할당 상태는 아니라는 것까지 확정된다. 움직이는 나머지 셋은 그 뒤에 잰다.
|
||||
|
||||
### 2. 다섯 지표를 부하 전과 부하 중 두 시점에 찍는다
|
||||
|
||||
부하를 걸기 전에 한 번, 두 가상 머신에 동시에 부하를 건 뒤에 한 번, 같은 명령으로 기록한다. 호스트 쪽은 ps -eLo pid,tid,psr,pcpu,comm | grep qemu 로 QEMU vCPU 스레드를 보고, 게스트 쪽은 top 으로 %st 를 본다.
|
||||
|
||||
### 3. 가상 머신 한 대에만 먼저 부하를 걸어 본다
|
||||
|
||||
한 대만 걸었을 때 지표가 어떻게 움직이는지 알아 두면, 두 대를 동시에 걸었을 때 늘어난 값이 vCPU 경쟁 때문인지 그 가상 머신 안의 CPU 포화 때문인지 갈린다. 다만 이 질문은 두 대를 동시에 돌렸을 때를 묻기 때문에 이 측정만으로는 닫히지 않는다.
|
||||
|
||||
### 4. 제외 — pinning 을 걸어 놓고 잰다
|
||||
|
||||
vCPU 스레드를 특정 논리 CPU 에 고정하면 경쟁 구간을 만들기 쉽다. 그러나 지금 구성에서 경쟁이 생기는지를 묻는 질문이라, 구성을 바꾸고 잰 값은 답이 되지 않는다. pinning 은 별도 질문으로 뺀다.
|
||||
|
||||
## 다음 검증
|
||||
|
||||
1. 호스트 논리 CPU 수와 각 가상 머신의 vCPU 수를 먼저 적는다. §20 이 든 확인 대상 다섯 가운데 부하 없이 읽을 수 있는 둘이다.
|
||||
2. 부하를 걸기 전에 호스트에서 ps -eLo pid,tid,psr,pcpu,comm | grep qemu (§14.7) 로 QEMU vCPU 스레드의 CPU 사용량을, 호스트 실행 대기열을, 두 게스트에서 top (§14.8) 으로 %st 를 같은 시각에 기록한다.
|
||||
3. VM 1 과 VM 2 에 동시에 CPU 부하를 건다.
|
||||
4. 부하 중에 2번의 세 지표를 같은 방법으로 다시 기록한다.
|
||||
|
||||
닫는 조건 : 두 가상 머신의 vCPU 합이 호스트 논리 CPU 이하이고 동시 부하에서도 게스트 %st 와 호스트 실행 대기열이 부하 전과 다르지 않으면, 이 호스트 구성에서는 경쟁이 관측되지 않는다고 적고 닫는다. %st 나 실행 대기열이 움직이면 그 부하 전후 표가 Case 가 되고 이 질문은 그 Case 가 닫는다. vCPU 수를 줄일지 가상 머신 배치를 바꿀지는 그 Case 가 나온 뒤 Decision 으로 넘긴다.
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
---
|
||||
id: cd58d35d-3a93-4682-82b8-b64ce3a8813c
|
||||
kind: QUESTION
|
||||
slug: vcpu-thread-migration-without-pinning
|
||||
title: pinning 없이 vCPU 스레드는 호스트 논리 CPU 사이를 옮겨 다니는가
|
||||
topic: cpu-virtualization
|
||||
topicName: CPU 가상화
|
||||
project: virtualization
|
||||
status: 초안
|
||||
questionStatus: OPEN
|
||||
studio: "https://hyeonworks.com/studio/documents/cd58d35d-3a93-4682-82b8-b64ce3a8813c/edit"
|
||||
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
|
||||
source:
|
||||
- final/document.md#20-이-concept에서-파생되는-open-question-oq-5
|
||||
- final/document.md#5-host-linux-scheduler와-실제-cpu
|
||||
- final/document.md#14-실제-linux에서-확인할-수-있는-것-14-7
|
||||
---
|
||||
|
||||
# pinning 없이 vCPU 스레드는 호스트 논리 CPU 사이를 옮겨 다니는가
|
||||
|
||||
§5 는 QEMU vCPU 스레드도 다른 호스트 스레드와 마찬가지로 Linux 스케줄러가 실행할 논리 CPU 를 정한다고 적었다.
|
||||
관찰 수단은 §14.7 이 든다. `PSR` 은 `ps` 가 찍어 주는 값이고, 그 스레드가 최근 실행된 논리 CPU 를 가리킨다.
|
||||
다만 이 호스트에서 `PSR` 을 찍어 본 기록이 없어서, 같은 vCPU 스레드가 시간에 따라 다른 논리 CPU 로 옮겨 가는지는 아직 모른다.
|
||||
|
||||
## 관계
|
||||
|
||||
- **KVM 에서 vCPU 가 물리 CPU 에서 실행되기까지**
|
||||
vCPU 스레드가 호스트 Linux 스케줄러의 스케줄링 대상이라는 설명이 이 물음의 전제다.
|
||||
- **CPU pinning 전후로 Keycloak 지연과 vCPU 스케줄링 변동이 달라지는가**
|
||||
이동이 실제로 일어나야 pinning 을 걸어 볼 이유가 생긴다.
|
||||
- **게스트가 유휴 상태일 때 vCPU 스레드는 이 테스트 환경에서 어떻게 보이는가**
|
||||
두 물음이 같은 `ps` 출력을 읽으므로 한 번 찍어 둘을 같이 본다.
|
||||
|
||||
## 사실
|
||||
|
||||
§5 는 QEMU vCPU 스레드도 다른 호스트 스레드와 마찬가지로 Linux 스케줄러가 실행할 논리 CPU 를 정한다고 적었다.
|
||||
그래서 같은 vCPU 스레드라도 시간에 따라 서로 다른 논리 CPU 에서 실행될 수 있다.
|
||||
같은 절은 그 이동을 세 시점으로 그려 두었다. T1 에 CPU7 에서 돌던 vCPU 스레드 0 이 T2 에는 CPU7 을 다른 스레드에게 내주고, T3 에는 CPU3 에서 돈다.
|
||||
CPU pinning 을 적용하면 실행 위치를 특정 논리 CPU 집합으로 제한할 수 있다고 같은 절이 덧붙였다.
|
||||
|
||||
§14.7 은 ps -eLo pid,tid,psr,pcpu,comm | grep qemu 를 들고, PSR 로 스레드가 최근 실행된 논리 CPU 를 관찰할 수 있다고 적었다.
|
||||
같은 절은 그 값이 vCPU 가 물리 CPU 에 영구 고정되어 있다는 뜻은 아니라고 못 박고, pinning 을 하지 않았다면 스케줄링에 따라 달라질 수 있다고 덧붙였다.
|
||||
|
||||
§20 의 OQ-5 는 PSR 과 스케줄러 추적으로 관찰한다고만 적었을 뿐 관찰한 결과는 남기지 않았다.
|
||||
|
||||
이 호스트에서 PSR 을 실제로 찍은 기록은 SSOT 에 없다.
|
||||
|
||||
## 가정
|
||||
|
||||
두 가상 머신에 pinning 이나 CPU 친화도를 걸지 않았다고 전제하고 이 물음을 세웠다.
|
||||
실제로 걸었는지는 SSOT 에 적혀 있지 않다.
|
||||
|
||||
일정 간격으로 여러 번 찍으면 이동이 PSR 값의 변화로 잡힌다고 전제한다.
|
||||
다만 표본과 표본 사이에 다른 논리 CPU 로 갔다가 돌아오면 두 표본은 같은 값으로 나온다.
|
||||
|
||||
게스트 부하가 있을 때와 없을 때 호스트 스케줄러가 스레드를 놓는 논리 CPU 가 달라질 수 있다고 전제한다.
|
||||
§5 는 스케줄러가 실행할 논리 CPU 를 정한다고만 적었지 부하에 따라 무엇이 달라지는지는 적지 않았다.
|
||||
|
||||
## 미지수
|
||||
|
||||
이 호스트에서 pinning 없이 같은 vCPU 스레드의 PSR 이 시간에 따라 실제로 바뀌는가.
|
||||
|
||||
바뀐다면 게스트가 유휴일 때와 CPU 부하가 있을 때가 서로 다른가.
|
||||
|
||||
현재 두 가상 머신에 친화도가 걸려 있는가.
|
||||
|
||||
스케줄러 추적을 이 호스트에서 쓸 수 있는가. §20 이 관찰 수단으로 들었지만 지원 여부는 확인하지 않았다.
|
||||
|
||||
## 제약
|
||||
|
||||
이 프로젝트에는 이 호스트에서 잰 값이 하나도 없어서, 지금 이동 여부를 적으면 관측이 아니라 추측이 된다.
|
||||
|
||||
PSR 은 최근 실행된 논리 CPU 하나만 보여 주므로 두 표본 사이에 일어난 이동은 잡히지 않는다.
|
||||
|
||||
§20 이 든 관찰 수단은 PSR 과 스케줄러 추적 둘이고, 이 물음은 그 둘 안에서 닫는다.
|
||||
|
||||
이 물음을 pinning 전후를 비교하는 쪽의 관측 항목으로 넣지 않고 따로 세웠다. 이동이 없으면 그 비교를 걸어 볼 이유가 없어져서 이쪽이 먼저 닫혀야 한다.
|
||||
그 대신 이동이 성능에 얼마나 걸리는지는 여기서 재지 않는다.
|
||||
|
||||
## 선택지
|
||||
|
||||
### 1. ps 출력을 일정 간격으로 여러 번 찍는다
|
||||
|
||||
§14.7 이 든 ps -eLo pid,tid,psr,pcpu,comm | grep qemu 를 그대로 쓰고 같은 tid 의 PSR 을 시간순으로 늘어놓는다.
|
||||
게스트를 건드리지 않고 호스트에서만 찍으면 되고 따로 설치할 도구도 없다.
|
||||
|
||||
표본 사이의 이동은 보이지 않으니 몇 초 간격으로 몇 번 찍었는지를 값과 함께 적는다.
|
||||
|
||||
### 2. 스케줄러 추적으로 이동 시점을 본다
|
||||
|
||||
§20 이 PSR 과 함께 든 수단이다. 표본 간격에 기대지 않고 스레드가 옮겨 간 시점을 볼 수 있다.
|
||||
|
||||
다만 이 호스트에서 추적을 쓸 수 있는지 아직 확인하지 않았고, 호스트에 도구와 권한이 더 필요하다.
|
||||
1번으로 이동이 이미 보이면 여기까지 가지 않는다.
|
||||
|
||||
### 3. 제외 — 친화도 설정만 읽고 답한다
|
||||
|
||||
설정에 pinning 이 없다는 것과 스케줄러가 실제로 스레드를 옮겼다는 것은 다르다.
|
||||
설정 확인은 따로 두지 않고 1번 실행에서 함께 적는 항목으로 넣는다.
|
||||
|
||||
## 다음 검증
|
||||
|
||||
1. ps -eLo pid,tid,psr,pcpu,comm | grep qemu 를 일정 간격으로 여러 번 찍어 같은 tid 의 PSR 이 바뀌는지 본다.
|
||||
2. 게스트가 유휴일 때와 CPU 부하가 있을 때를 나눠 각각 찍는다.
|
||||
3. 같은 실행에서 그 가상 머신에 친화도 설정이 있는지도 함께 적는다.
|
||||
|
||||
닫는 조건 : 관측 구간에서 같은 tid 의 PSR 이 바뀌면 이동한다는 사실을 개념의 확인 사례로 흡수하고 닫는다. 그 이동이 성능에 영향을 주는지는 pinning 전후를 비교하는 OQ-10 이 받는다. PSR 이 고정으로 나오면 친화도 설정을 먼저 확인하고, 설정이 없는데도 고정이면 그 관측이 Case 가 된다.
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
---
|
||||
id: da3a7b56-5691-4a9f-90c5-3a1a5d0f0013
|
||||
kind: QUESTION
|
||||
slug: virtualization-layer-saturation-during-refresh
|
||||
title: Keycloak 동시 refresh 실험 중 CPU 가상화 계층이 결과를 흔들 만큼 포화되는가
|
||||
topic: cpu-virtualization
|
||||
topicName: CPU 가상화
|
||||
project: virtualization
|
||||
status: 초안
|
||||
questionStatus: OPEN
|
||||
studio: "https://hyeonworks.com/studio/documents/da3a7b56-5691-4a9f-90c5-3a1a5d0f0013/edit"
|
||||
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
|
||||
source:
|
||||
- final/document.md#20-이-concept에서-파생되는-open-question-oq-2
|
||||
- final/document.md#16-현재-keycloak-k3s-실험과의-관계
|
||||
- final/document.md#26-현재-keycloak-실험에서-cpu-문제를-오판하지-않기-위한-기준
|
||||
---
|
||||
|
||||
# Keycloak 동시 refresh 실험 중 CPU 가상화 계층이 결과를 흔들 만큼 포화되는가
|
||||
|
||||
Keycloak refresh token 경쟁 실험은 가상 머신 두 대 위에서 돌기 때문에 원래 검증하려던 구조 아래에 KVM 계층이 하나 더 붙는다. 실험 구간에서 요청이 느려지거나 실패했을 때 그것을 refresh 경쟁 문제로 읽어도 되는지는 같은 구간의 호스트 CPU 사용량과 steal time 을 봐야 갈린다. steal time 은 게스트의 vCPU 에 실행할 작업이 있는데도 다른 작업 때문에 곧바로 실행되지 못한 상황을 가리키는 지표다(§13). 그런데 §20 이 함께 관찰하라고 든 다섯 지표를 아직 한 번도 같이 찍지 않았다.
|
||||
|
||||
## 관계
|
||||
|
||||
- **KVM 에서 vCPU 가 물리 CPU 에서 실행되기까지**
|
||||
게스트 안의 지연이 가상화 계층까지 내려가는 경로를 이 개념이 설명한다.
|
||||
- **가상 머신 두 대에 동시에 부하를 주면 이 호스트에서 vCPU 경쟁이 실제로 생기는가**
|
||||
경쟁이 생길 수 있는 구성인지를 먼저 묻는다. 그쪽이 닫히면 여기서 기준값을 다시 만들지 않아도 된다.
|
||||
- **cgroup CPU 제한과 호스트 vCPU 경쟁을 지표로 가를 수 있는가**
|
||||
§26 이 나눈 여섯 경계 가운데 K3s 와 Virtualization 을 어떻게 가르는지를 따로 묻는다.
|
||||
|
||||
## 사실
|
||||
|
||||
§16 이 그린 원래 검증 대상 구조
|
||||
|
||||
Client
|
||||
Nginx / Load Balancer
|
||||
K3s
|
||||
Keycloak Node 1 · Keycloak Node 2
|
||||
Session / Token State
|
||||
PostgreSQL · Redis
|
||||
|
||||
테스트 환경에서는 이 구조 아래에 KVM 계층이 추가된다 : §16
|
||||
Physical Host 아래에 Host Nginx 와 가상 머신 두 대가 있고 가상 머신마다 K3s 노드와 Keycloak 이 돈다 : §16
|
||||
|
||||
§16 이 테스트 결과를 해석할 때 분리하라고 든 원인 일곱
|
||||
|
||||
Keycloak refresh/session 동시성
|
||||
PostgreSQL contention/locking
|
||||
Redis 상태 관리
|
||||
K3s resource scheduling
|
||||
VM vCPU scheduling
|
||||
Host CPU saturation
|
||||
Nginx/LB
|
||||
|
||||
§16 은 KVM CPU 가상화를 이해하는 목적을 이렇게 적었다.
|
||||
|
||||
Keycloak 멀티 노드 실험에서 발생한 지연이나 실패가 application/storage 문제인지, VM/Host 자원 문제인지 구분할 수 있도록 실험 기반을 이해하기 위해서다.
|
||||
|
||||
§26 은 같은 원인들을 여섯 경계로 다시 나눈다.
|
||||
|
||||
Application / Auth : Refresh Token 경쟁 · Session 상태 경쟁 · Keycloak 내부 처리
|
||||
Storage : PostgreSQL lock / latency · Redis latency / consistency
|
||||
K3s : Pod CPU throttling · Pod scheduling/resource limit
|
||||
Guest : Guest CPU saturation
|
||||
Virtualization : vCPU scheduling · Steal time · VM Exit overhead
|
||||
Host : CPU contention · CPU overcommit · Host saturation
|
||||
|
||||
§26 은 refresh 경쟁을 검증하는 첫 실험에서 가능하면 CPU 자원을 여유 있게 유지하고, 그 상태에서 같은 세션과 같은 refresh token 에 대한 동시 요청을 만들어 동시성 문제를 먼저 확인하라고 적는다. 트래픽을 늘려 CPU/DB/Redis/K3s 자원 포화를 관찰하는 것은 별도의 부하·스트레스 Case 로 나눈다.
|
||||
|
||||
§20 이 refresh 경쟁 실험 중 동시에 관찰하라고 든 다섯
|
||||
|
||||
Host CPU
|
||||
Guest CPU
|
||||
steal time
|
||||
Keycloak latency
|
||||
DB/Redis latency
|
||||
|
||||
§20 은 그 목적이 refresh 경쟁과 호스트 자원 경쟁을 분리하는 것이라고 밝힌다.
|
||||
|
||||
## 가정
|
||||
|
||||
refresh 경쟁 실험이 Keycloak latency 와 DB/Redis latency 를 이미 재고 있다고 전제한다. 그 실험이 어떤 값을 어떤 주기로 내는지는 이 근거 문서에 적혀 있지 않다.
|
||||
|
||||
기준값을 찍는 구간과 실험 구간 사이에 호스트의 다른 작업이 달라지지 않는다.
|
||||
|
||||
다섯 지표의 시각을 맞춰 읽을 수 있다고 전제한다. 호스트 쪽과 게스트 쪽 시계가 어긋나면 부하 구간을 겹쳐 놓을 수 없기 때문이다.
|
||||
|
||||
§26 이 말한 「CPU 자원을 여유 있게 유지한」 상태를 이 호스트에서 만들 수 있다.
|
||||
|
||||
## 미지수
|
||||
|
||||
실험을 걸기 전 다섯 지표의 기준값.
|
||||
|
||||
실험 구간의 호스트 CPU 와 게스트 CPU, 그리고 각 게스트의 steal time.
|
||||
|
||||
같은 구간의 Keycloak latency 와 DB/Redis latency.
|
||||
|
||||
가상화 쪽 지표가 얼마나 움직여야 실험 결과를 다르게 읽어야 하는지. 그 문턱을 아직 정하지 않았다.
|
||||
|
||||
두 가상 머신이 같은 호스트에 있으므로 한쪽 Keycloak 노드에 몰린 요청이 다른 쪽 게스트의 steal time 을 올리는지.
|
||||
|
||||
## 제약
|
||||
|
||||
§26 이 첫 실험을 CPU 여유 상태로 못박기 때문에, 이 질문은 실험 조건을 바꾸지 않고 관찰 지표만 덧붙여 답해야 한다. §17.1 이 refresh token 경쟁을 확인하는 데 반드시 호스트 CPU 를 100% 까지 밀 필요는 없다고 적었으므로, 실험을 그대로 두고 관찰만 덧붙이는 것이 §26 의 조건과도 어긋나지 않는다.
|
||||
|
||||
이 호스트에서 잰 값이 없어 기준값부터 만들어야 한다. 실험 구간의 값만 있으면 그 값이 평소 값인지 실험 때문에 오른 값인지 갈리지 않는다.
|
||||
|
||||
§22 의 Claim 12·13 은 이 환경에서 실제로 그러한지를 주장하는 것이라, 재기 전에는 Case 도 Question 도 되지 않는다고 보고 그대로 두었다. 이 물음을 그와 갈라 먼저 올린 것은 아는 것과 모르는 것이 실험 전에도 갈리기 때문이다.
|
||||
|
||||
§16 은 CPU 가상화가 refresh token 경쟁의 원인은 아니라고 적는다. 여기서 「포화되지 않았다」가 나와도 refresh 경쟁 실험의 결론이 바뀌지는 않고, 그 결론을 애플리케이션·저장소 쪽으로 읽어도 되는지만 갈린다.
|
||||
|
||||
§20 이 든 다섯 가운데 Keycloak latency 와 DB/Redis latency 는 실험 쪽 도구가 낸다. 가상화 쪽에서 새로 만들 값은 Host CPU · Guest CPU · steal time 셋이다.
|
||||
|
||||
## 선택지
|
||||
|
||||
### 1. 실험을 그대로 두고 관찰만 덧붙인다
|
||||
|
||||
§26 이 첫 실험의 CPU 조건을 정해 두었으므로 실험 자체는 건드리지 않는다. 같은 실험을 돌리면서 호스트 쪽 QEMU vCPU 스레드 사용량과 게스트 쪽 %st 만 함께 기록한다. 이 방법으로는 이번 실험 구간에서 가상화 계층이 움직였는지 하나만 알 수 있다.
|
||||
|
||||
### 2. 실험 직전 구간을 기준값으로 따로 찍는다
|
||||
|
||||
부하를 걸기 전 같은 다섯 지표를 한 번 찍어 두면 실험 구간의 값을 견줄 대상이 생긴다. 기준값 없이 실험 구간만 찍으면 steal time 이 어떤 값으로 나오든 그것이 평소 값인지 실험 때문에 오른 값인지 판정할 수 없다.
|
||||
|
||||
### 3. 여섯 경계 가운데 가상화 쪽 둘만 먼저 잰다
|
||||
|
||||
§26 은 Application / Auth 부터 Host 까지 여섯 경계를 든다. 여섯을 한 번에 분리하려면 경계마다 지표를 붙여야 하는데, 이 질문은 Virtualization 과 Host 두 경계가 실험 결과를 흔들었는지만 묻는다. 나머지 넷은 실험 쪽 기록을 그대로 쓰고 이 둘만 새로 잰다.
|
||||
|
||||
### 4. 제외 — CPU 를 일부러 포화시켜 견준다
|
||||
|
||||
포화 구간과 여유 구간을 나란히 놓으면 가상화 계층이 결과를 얼마나 흔드는지 바로 보인다. 그러나 §26 이 첫 refresh 실험을 CPU 여유 상태로 정해 두어서 같은 실험 안에서는 할 수 없다. 별도의 부하·스트레스 Case 로 뺀다.
|
||||
|
||||
## 다음 검증
|
||||
|
||||
1. 실험을 걸기 전 §20 이 든 다섯 지표를 한 번 찍어 기준값으로 둔다.
|
||||
2. refresh 경쟁 실험을 돌리면서 같은 다섯을 같은 시각에 기록한다. 게스트의 steal time 은 top (§14.8), 호스트 쪽 QEMU vCPU 스레드는 ps -eLo pid,tid,psr,pcpu,comm | grep qemu (§14.7) 로 본다.
|
||||
3. Keycloak 과 DB/Redis latency 는 실험이 이미 재는 값을 그대로 쓴다.
|
||||
|
||||
닫는 조건 : 실험 구간의 호스트 CPU 와 steal time 이 기준값과 다르지 않으면, 그 실험 결과를 애플리케이션·저장소 문제로 읽어도 된다고 적고 닫는다. 둘 중 하나라도 움직이면 §26 의 여섯 경계를 분리해 다시 재고, refresh 경쟁 실험을 CPU 여유 상태에서 따로 돌릴지는 Decision 으로 넘긴다.
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
---
|
||||
id: 61b7486f-5dab-41df-8f4f-e8fc21d88617
|
||||
kind: QUESTION
|
||||
slug: vm-exit-distribution-by-workload
|
||||
title: 실제 작업에서 주로 발생하는 VM Exit 은 무엇인가
|
||||
topic: cpu-virtualization
|
||||
topicName: CPU 가상화
|
||||
project: virtualization
|
||||
status: 초안
|
||||
questionStatus: OPEN
|
||||
studio: "https://hyeonworks.com/studio/documents/61b7486f-5dab-41df-8f4f-e8fc21d88617/edit"
|
||||
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
|
||||
source:
|
||||
- final/document.md#20-이-concept에서-파생되는-open-question-oq-4
|
||||
- final/document.md#8-무엇이-실제로-vm-exit을-발생시키는가
|
||||
- final/document.md#14-실제-linux에서-확인할-수-있는-것-14-9
|
||||
---
|
||||
|
||||
# 실제 작업에서 주로 발생하는 VM Exit 은 무엇인가
|
||||
|
||||
VM Exit 은 게스트를 실행하던 CPU 가 하이퍼바이저가 개입해야 하는 조건을 만나 KVM 쪽으로 제어권을 넘기는 전환이고, 가상 머신이 꺼지는 것이 아니다(§7.2). §8 은 Exit 을 낼 수 있는 동작을 일곱 가지로 들지만, 그 가운데 무엇이 실제로 Exit 을 내는지는 이 호스트의 VMX 설정과 돌리는 작업이 정한다. 유휴 구간과 CPU-bound 구간, Keycloak 부하 구간이 서로 다른 Exit 분포를 낼지는 재 봐야 알고, 그 전에 `perf kvm` 이 이 환경에서 열리는지부터 확인하지 않았다.
|
||||
|
||||
## 관계
|
||||
|
||||
- **KVM 에서 vCPU 가 물리 CPU 에서 실행되기까지**
|
||||
VM Entry 와 VM Exit 이 무엇이고 Exit 뒤에 무엇이 처리하는지를 이 개념이 설명한다.
|
||||
- **Keycloak 작업의 VM Exit 분포는 idle · CPU-bound · I/O-bound 와 어떻게 다른가**
|
||||
같은 측정에서 Keycloak 쪽 분포만 떼어 묻는다. 도구가 열리지 않으면 두 질문이 같은 이유로 닫힌다.
|
||||
|
||||
## 사실
|
||||
|
||||
§8 이 든, VM Exit 을 발생시킬 수 있는 동작
|
||||
|
||||
HLT
|
||||
I/O Port 접근 - IN / OUT
|
||||
CPUID
|
||||
Control Register 접근
|
||||
MSR 접근
|
||||
Exception
|
||||
External Interrupt
|
||||
|
||||
Intel VMX 에는 VMCS(Virtual Machine Control Structure)가 있고 하이퍼바이저는 VM-Execution Control 등을 통해 어떤 동작을 가로챌지 설정한다 : §8
|
||||
|
||||
§8 은 「특권 명령이면 전부 VM Exit」이나 「root 가 실행하면 VM Exit」 같은 규칙이 맞지 않는다고 적는다. VM Exit 여부는 VMX 설정과 해당 동작의 종류에 따라 결정된다.
|
||||
|
||||
모든 CR(control register) 접근이 항상 VM Exit 을 발생시키지는 않는다 : §8.4
|
||||
Page Fault, Breakpoint, Debug Exception 같은 CPU 예외도 Exception Bitmap 등의 설정에 따라 게스트가 직접 처리할 수도 있고 하이퍼바이저가 가로챌 수도 있다 : §8.6
|
||||
|
||||
CPU 에는 MSR(Model-Specific Register)이 있고 RDMSR 과 WRMSR 로 접근한다. 특정 MSR 접근을 하이퍼바이저가 가로채도록 설정했다면 VM Exit 이 발생할 수 있다 : §8.5
|
||||
|
||||
§8.2 는 I/O port 접근에서 나온 Exit 을 KVM 이 받고, 사용자 공간에서 가상 장치를 흉내 내야 하면 KVM_RUN 이 반환되어 QEMU 가 처리한 뒤 다시 KVM_RUN 을 호출한다고 적는다.
|
||||
|
||||
§14.9 는 환경이 지원하면 perf kvm 으로 KVM 관련 실행 통계를 확인할 수 있다고 하면서 sudo perf kvm stat live 를 예로 든다. 지원되는 명령과 표시되는 Exit 이유는 커널, perf 버전, CPU 아키텍처 및 설정에 따라 다를 수 있다. 그래서 perf kvm --help 를 함께 확인하고, 필요하면 KVM tracepoint 를 이용한 별도 추적도 검토하라고 적는다.
|
||||
|
||||
§20 이 든 비교 후보 다섯
|
||||
|
||||
idle
|
||||
CPU-bound workload
|
||||
I/O-heavy workload
|
||||
Keycloak 정상 요청
|
||||
Keycloak 부하 테스트
|
||||
|
||||
## 가정
|
||||
|
||||
다섯 작업을 이 호스트에서 각각 만들 수 있다. Keycloak 정상 요청과 부하 테스트는 이미 돌리는 실험을 그대로 쓴다고 전제한다.
|
||||
|
||||
호스트에서 sudo 로 perf 를 돌릴 수 있다.
|
||||
|
||||
한 작업을 재는 동안 다른 가상 머신이 내는 Exit 이 결과에 섞이지 않는다고 전제하는데, perf kvm 이 호스트 전체를 보는지 프로세스 하나만 보는지는 확인하지 않았다.
|
||||
|
||||
Exit 이유가 다섯 작업 사이에서 같은 이름으로 표시된다.
|
||||
|
||||
## 미지수
|
||||
|
||||
이 환경에서 perf kvm 이 어떤 하위 명령을 지원하는지.
|
||||
|
||||
열린다면 어떤 Exit 이유가 표시되는지.
|
||||
|
||||
다섯 작업의 Exit 이유 분포가 서로 얼마나 다른지.
|
||||
|
||||
perf kvm 이 열리지 않을 때 KVM tracepoint 로 같은 것을 볼 수 있는지.
|
||||
|
||||
한 작업을 얼마나 오래 재야 분포가 더 흔들리지 않는지.
|
||||
|
||||
## 제약
|
||||
|
||||
이 호스트에서 잰 값이 없기 때문에, 분포를 재기 전에 도구가 열리는지부터 확인해야 한다. 도구가 이 환경에서 되는지부터 봐야 한다는 것은 이 물음을 접을 이유가 아니라 다음 검증의 첫 단계다. 열리지 않는 것으로 확인되는 것도 이 물음을 닫는 결과이기 때문이다.
|
||||
|
||||
§8 에 따르면 어떤 동작이 Exit 을 내는지는 VMX 설정이 정하기 때문에, 나온 분포는 이 호스트의 설정에 딸린 값이라 다른 호스트로 옮겨 읽을 수 없다.
|
||||
|
||||
§14.9 는 표시되는 Exit 이유가 커널 · perf 버전 · CPU 아키텍처 및 설정에 따라 다를 수 있다고 적는다. 표의 열 이름도 이 환경에서 나온 그대로 쓴다.
|
||||
|
||||
Exit 총 횟수만으로는 작업을 견줄 수 없다. §8.2 처럼 QEMU 까지 돌아가는 Exit 과 KVM 안에서 끝나는 Exit 은 처리 경로가 다르다. §24.9 도 확인할 때 Exit 횟수만 보지 말라고 적으면서 「VM Exit이 많다 = 장애로 바로 판단하지 않는다」로 닫는다.
|
||||
|
||||
## 선택지
|
||||
|
||||
### 1. perf kvm --help 로 열리는 하위 명령부터 확인한다
|
||||
|
||||
§14.9 가 지원 여부는 환경마다 다르다고 적어 두었기 때문에 도구부터 확인한다. 여기서 안 열리면 뒤의 계획이 통째로 바뀐다.
|
||||
|
||||
### 2. 열리면 sudo perf kvm stat live 로 다섯 작업을 각각 돌린다
|
||||
|
||||
§20 이 든 다섯을 하나씩 돌리며 Exit 이유 분포를 받아 적는다. 유휴 구간을 먼저 재 두면 나머지 넷에서 늘어난 Exit 이 무엇인지 견줄 수 있다.
|
||||
|
||||
### 3. 열리지 않으면 KVM tracepoint 추적을 검토한다
|
||||
|
||||
§14.9 가 대안으로 든 방법이다. 이쪽도 안 되면 「이 호스트에서는 Exit 분포를 관측할 수 없다」가 이 질문의 답이 된다.
|
||||
|
||||
### 4. 제외 — Exit 총 횟수만 세어 작업을 견준다
|
||||
|
||||
숫자 하나로 다섯을 늘어놓을 수 있어 간단하다. 그러나 §8.2 가 적은 대로 Exit 마다 처리 경로가 달라서, 총 횟수는 작업 사이의 차이를 설명하지 못한다.
|
||||
|
||||
## 다음 검증
|
||||
|
||||
1. perf kvm --help 로 이 환경이 지원하는 하위 명령을 확인한다.
|
||||
2. 열리면 sudo perf kvm stat live 로 §20 의 비교 후보 다섯을 각각 돌리며 Exit 이유 분포를 받아 적는다.
|
||||
3. 열리지 않으면 §14.9 가 말한 KVM tracepoint 추적을 검토하고 그 결과도 기록한다.
|
||||
|
||||
닫는 조건 : 다섯 작업의 Exit 이유 분포를 한 표로 놓을 수 있으면 그 표가 Case 가 되고 닫는다. perf kvm 도 tracepoint 도 이 환경에서 열리지 않으면, 「이 호스트에서는 Exit 분포를 관측할 수 없다」를 그대로 적고 §24.9 의 확인 항목에서 Exit 이유를 빼는 근거로 남긴 뒤 닫는다.
|
||||
Reference in New Issue
Block a user