259 lines
7.7 KiB
JSON
259 lines
7.7 KiB
JSON
{
|
|
"version": "1.1",
|
|
"id": "vms-sharing-one-nvme",
|
|
"title": "가상 머신 둘과 호스트 프로세스가 하나의 NVMe 로 모인다",
|
|
"question": "서로 다른 곳에서 시작한 I/O 는 어디에서 하나로 모여 device 로 나가는가",
|
|
"type": "flow",
|
|
"direction": "LR",
|
|
"audience": [
|
|
"가상 머신 위에서 본 저장소 지연의 원인을 가르려는 사람",
|
|
"Storage Contention 과 CPU Contention 을 나눠 재려는 사람"
|
|
],
|
|
"summary": "VM1 QEMU 와 VM2 QEMU, Nginx, 호스트의 다른 프로세스에서 시작한 I/O 가 모두 하나의 Host Block Layer queue 로 들어가 NVMe 로 dispatch 된다.",
|
|
"alt": "VM1 QEMU, VM2 QEMU, Nginx, Host 기타 네 곳에서 나온 화살표가 하나의 Host Block Layer 로 모이고 거기서 NVMe 로 나가는 수렴 흐름도.",
|
|
"long_description": "위쪽에 네 출발점이 나란히 있다. VM1 QEMU 는 WRITE X 와 READ Y, WRITE Z 를 내고 VM2 QEMU 는 READ A 와 WRITE B 를 내며, 그 옆에 호스트의 Nginx 와 다른 프로세스가 있다. 네 갈래가 모두 가운데의 Host Block Layer 하나로 모인다. Host Block Layer 는 그 I/O 가 가상 머신 안에서 시작했는지 호스트 프로세스에서 시작했는지를 본질적으로 구분해 처리하는 계층이 아니라 들어온 것을 모두 Host block request 로 다루고, 그 요청들을 queue 에서 관리해 맨 아래 NVMe 로 dispatch 한다. 여기서 생기는 경쟁이 Storage Contention 이고 CPU 실행 시간을 두고 벌어지는 CPU Contention 과는 다투는 자원이 다르다는 것은 본문 문단이 맡는다.",
|
|
"source_context": {
|
|
"document": "docs/virtualization/final/document.md",
|
|
"document_sha256": "8c4ecc64c8cea9a4450ed7131fdd9cb2048dc092b66cd969f6346ed77887c210",
|
|
"anchor": {
|
|
"kind": "heading",
|
|
"value": "159. 여러 VM이 하나의 NVMe를 공유하면",
|
|
"line": 7039
|
|
}
|
|
},
|
|
"composition": {
|
|
"profile": "component-flow",
|
|
"diagram_only": true,
|
|
"reference_ids": [
|
|
"payment-event-flow"
|
|
],
|
|
"rationale": "이 절이 주장하는 것은 서로 다른 네 곳에서 시작한 요청이 한 자리로 모인다는 것이다. query-fanout 은 하나가 여러 저장소로 갈라지는 문법이라 방향이 반대이고, orchestrator-workers 는 가운데가 아래의 워커들에게 일을 나눠 주는 그림이라 「모인다」가 「나눈다」로 뒤집힌다. comparison 은 네 출발점을 나란히 늘어놓기만 해서 하나의 queue 로 모인다는 사실이 사라진다.",
|
|
"focus_node": "host-block-layer"
|
|
},
|
|
"groups": [],
|
|
"nodes": [
|
|
{
|
|
"id": "vm1-qemu",
|
|
"label": "VM1 QEMU",
|
|
"kind": "service",
|
|
"role": "source",
|
|
"shape": "box",
|
|
"details": [
|
|
"WRITE X",
|
|
"READ Y",
|
|
"WRITE Z"
|
|
],
|
|
"description": "가상 머신 하나의 QEMU 프로세스. 게스트의 I/O 가 여기서 호스트 파일 I/O 가 된다.",
|
|
"evidence": [
|
|
{
|
|
"start_line": 7042,
|
|
"end_line": 7042
|
|
},
|
|
{
|
|
"start_line": 7054,
|
|
"end_line": 7057
|
|
}
|
|
],
|
|
"assumption": false
|
|
},
|
|
{
|
|
"id": "vm2-qemu",
|
|
"label": "VM2 QEMU",
|
|
"kind": "service",
|
|
"role": "source",
|
|
"shape": "box",
|
|
"details": [
|
|
"READ A",
|
|
"WRITE B"
|
|
],
|
|
"description": "다른 가상 머신의 QEMU 프로세스.",
|
|
"evidence": [
|
|
{
|
|
"start_line": 7044,
|
|
"end_line": 7044
|
|
},
|
|
{
|
|
"start_line": 7059,
|
|
"end_line": 7061
|
|
}
|
|
],
|
|
"assumption": false
|
|
},
|
|
{
|
|
"id": "nginx",
|
|
"label": "Nginx",
|
|
"kind": "service",
|
|
"role": "source",
|
|
"shape": "box",
|
|
"description": "호스트에서 직접 도는 프로세스.",
|
|
"evidence": [
|
|
{
|
|
"start_line": 7046,
|
|
"end_line": 7046
|
|
}
|
|
],
|
|
"assumption": false
|
|
},
|
|
{
|
|
"id": "host-other",
|
|
"label": "Host 기타",
|
|
"kind": "service",
|
|
"role": "source",
|
|
"shape": "box",
|
|
"description": "그 밖의 호스트 프로세스.",
|
|
"evidence": [
|
|
{
|
|
"start_line": 7048,
|
|
"end_line": 7051
|
|
}
|
|
],
|
|
"assumption": false
|
|
},
|
|
{
|
|
"id": "host-block-layer",
|
|
"label": "Host Block Layer",
|
|
"kind": "service",
|
|
"role": "queue",
|
|
"shape": "box",
|
|
"emphasis": "primary",
|
|
"details": [
|
|
"Host block request",
|
|
"blk-mq"
|
|
],
|
|
"description": "어디서 왔는지 구분하지 않고 모두 Host block request 로 다루는 계층. queue 에서 관리해 device 로 내보낸다.",
|
|
"evidence": [
|
|
{
|
|
"start_line": 7044,
|
|
"end_line": 7044
|
|
},
|
|
{
|
|
"start_line": 7030,
|
|
"end_line": 7035
|
|
},
|
|
{
|
|
"start_line": 7067,
|
|
"end_line": 7067
|
|
},
|
|
{
|
|
"start_line": 7071,
|
|
"end_line": 7073
|
|
}
|
|
],
|
|
"assumption": false
|
|
},
|
|
{
|
|
"id": "nvme",
|
|
"label": "NVMe",
|
|
"kind": "device",
|
|
"role": "sink",
|
|
"shape": "cylinder",
|
|
"description": "네 갈래가 결국 함께 쓰는 하나의 물리 device.",
|
|
"evidence": [
|
|
{
|
|
"start_line": 7044,
|
|
"end_line": 7044
|
|
},
|
|
{
|
|
"start_line": 7032,
|
|
"end_line": 7032
|
|
},
|
|
{
|
|
"start_line": 7079,
|
|
"end_line": 7082
|
|
}
|
|
],
|
|
"assumption": false
|
|
}
|
|
],
|
|
"edges": [
|
|
{
|
|
"id": "vm1-to-block-layer",
|
|
"from": "vm1-qemu",
|
|
"to": "host-block-layer",
|
|
"label": "",
|
|
"kind": "data",
|
|
"style": "solid",
|
|
"order": 1,
|
|
"evidence": [
|
|
{
|
|
"start_line": 7042,
|
|
"end_line": 7044
|
|
}
|
|
],
|
|
"assumption": false
|
|
},
|
|
{
|
|
"id": "vm2-to-block-layer",
|
|
"from": "vm2-qemu",
|
|
"to": "host-block-layer",
|
|
"label": "",
|
|
"kind": "data",
|
|
"style": "solid",
|
|
"order": 2,
|
|
"evidence": [
|
|
{
|
|
"start_line": 7044,
|
|
"end_line": 7044
|
|
}
|
|
],
|
|
"assumption": false
|
|
},
|
|
{
|
|
"id": "nginx-to-block-layer",
|
|
"from": "nginx",
|
|
"to": "host-block-layer",
|
|
"label": "",
|
|
"kind": "data",
|
|
"style": "solid",
|
|
"order": 3,
|
|
"evidence": [
|
|
{
|
|
"start_line": 7044,
|
|
"end_line": 7046
|
|
}
|
|
],
|
|
"assumption": false
|
|
},
|
|
{
|
|
"id": "host-other-to-block-layer",
|
|
"from": "host-other",
|
|
"to": "host-block-layer",
|
|
"label": "",
|
|
"kind": "data",
|
|
"style": "solid",
|
|
"order": 4,
|
|
"evidence": [
|
|
{
|
|
"start_line": 7044,
|
|
"end_line": 7048
|
|
}
|
|
],
|
|
"assumption": false
|
|
},
|
|
{
|
|
"id": "block-layer-to-nvme",
|
|
"from": "host-block-layer",
|
|
"to": "nvme",
|
|
"label": "dispatch",
|
|
"kind": "data",
|
|
"style": "solid",
|
|
"order": 5,
|
|
"evidence": [
|
|
{
|
|
"start_line": 7044,
|
|
"end_line": 7044
|
|
},
|
|
{
|
|
"start_line": 7067,
|
|
"end_line": 7067
|
|
}
|
|
],
|
|
"assumption": false
|
|
}
|
|
],
|
|
"legend": [],
|
|
"metadata": {
|
|
"rationale": "component-flow 를 고른 이유는 이 절이 답하는 물음이 「여러 곳에서 온 요청이 어디에서 하나가 되는가」이기 때문이다. 현재 renderer에서는 LR로 두어 네 출발점이 Host Block Layer 로 수렴하는 선을 상자 충돌 없이 보이게 한다. 네 출발점의 화살표에는 같은 Host block request 라벨을 반복하지 않고 그 의미를 모이는 노드의 details 로 올렸다. blk-mq 와 I/O Scheduler 의 세부는 다른 절이 맡는다."
|
|
}
|
|
}
|