iSCSI LUN 을 붙이고 fio 로 잰다
목표
같은 VM 안에 LIO 타깃을 세워 LUN 을 내주고, 이니시에이터로 발견·로그인·_netdev 마운트·자동 로그인을 구성한 뒤, 그 디스크 위에서 fio 로 큐 깊이에 따른 IOPS 와 지연을 재고 JSON 에서 숫자를 꺼내 보고합니다.
왜 중요한가
SAN 의 LUN 을 서버에 붙이는 일은 인프라 엔지니어의 일상인데, 로컬 디스크와 다른 세 가지(네트워크를 기다리는 마운트, 이름으로 하는 접근 제어, 여러 경로)를 모르면 재부팅 한 번에 서버가 멈춥니다. 그리고 "디스크가 느리다" 는 신고에 답하려면 조건을 고정한 측정이 필요합니다. 큐 깊이 하나만 바꿔도 IOPS 와 지연이 함께 움직이는 것을 직접 보면, 사양서의 숫자와 애플리케이션이 겪는 숫자가 왜 다른지 설명할 수 있게 됩니다.
이 실습은 우분투 24.04 VM 에서 root 로 돕니다. 타깃과 이니시에이터가 같은 VM 에서 127.0.0.1:3260 으로 만나므로 네트워크 스토리지의 절차를 그대로 밟되, 측정 숫자는 진짜 SAN 의 숫자가 아닙니다 — fileio 백스토어는 타깃 쪽 페이지 캐시를 거치므로 큐 깊이 1 에서도 수만 IOPS 가 나옵니다(실측). 절대값이 아니라 조건 하나를 바꿨을 때 숫자가 어떻게 움직이는지를 보는 것이 목적입니다. 세션은 60분에 시작해 최대 180분까지 연장할 수 있고, VM 은 세션이 끝나면 사라집니다.
단계
/var/lib/sto/lun0.img(512MiB) 를 fileio 백스토어lun0으로 만들어 타깃iqn.2026-09.io.labhub:sto의tpg1에 LUN 으로 붙이고, 이 VM 의 이니시에이터 이름을 ACL 에 넣은 뒤targetcli saveconfig로 저장하세요.127.0.0.1포털을 발견(sendtargets) 하고 출력을/root/sto/iscsi/discovery.txt에 저장하세요.- 타깃에 로그인해 새 디스크가 TRAN
iscsi로 보이게 하고,lsblk -o NAME,SIZE,TRAN,VENDOR,MODEL출력을/root/sto/iscsi/lsblk.txt에 저장하세요. - iSCSI 디스크를 ext4 로 포맷하고
/etc/fstab에 UUID= 와_netdev가 들어간 줄로/mnt/iscsi에 마운트되게 한 뒤, 지금 마운트해 두세요. - 노드 기록의
node.startup을 automatic 으로 바꾸세요. /mnt/iscsi/fio.dat(128MiB) 에 4KiBrandread,libaio,direct=1,iodepth=1, 10초를 재고 JSON 을/root/sto/fio/qd1.json에 저장하세요.- 같은 조건에
iodepth=32만 바꿔 재고 JSON 을/root/sto/fio/qd32.json에 저장하세요. /root/sto/fio/report.txt에qd1_iops=,qd1_p99_us=,qd32_iops=,qd32_p99_us=,qd32_little=다섯 줄을 JSON 에서 계산해 적으세요.
참고
- 타깃:
targetcli ls,/backstores/fileio create,/iscsi create,…/tpg1/luns create,…/tpg1/acls create,saveconfig. - 이니시에이터:
iscsiadm -m discovery -t sendtargets -p 127.0.0.1,iscsiadm -m node -T <IQN> -p 127.0.0.1 --login,iscsiadm -m session. - fio JSON:
jobs[0].read.iops,jobs[0].read.lat_ns.mean,jobs[0].read.clat_ns.percentile["99.000000"](나노초). - 흔한 실수 1: fstab 에
/dev/sdb를 적거나_netdev를 빼는 경우. - 흔한 실수 2:
direct=1을 빼서 페이지 캐시 속도를 디스크 속도로 보고하는 경우.
LIO 타깃으로 LUN 내주기
/var/lib/sto/lun0.img (512MiB) 를 fileio 백스토어 lun0 으로 만들고, 타깃 iqn.2026-09.io.labhub:sto 의 tpg1 에 LUN 으로 붙이세요. 이 VM 의 이니시에이터 이름(/etc/iscsi/initiatorname.iscsi 의 InitiatorName= 값)을 ACL 에 넣고 targetcli saveconfig 로 설정을 저장하세요.
targetcli 는 경로처럼 생긴 트리를 채웁니다 — /backstores/fileio create, /iscsi create, /iscsi//tpg1/luns create, /iscsi//tpg1/acls create. 포털(0.0.0.0:3260)은 타깃을 만들 때 기본으로 생깁니다.
타깃 발견
이니시에이터로 127.0.0.1 포털을 발견(sendtargets) 하고, 그 출력을 /root/sto/iscsi/discovery.txt 에 저장하세요.
iscsiadm -m discovery -t sendtargets -p <포털> 입니다. 발견은 세션을 맺지 않고 노드 기록만 만듭니다.
로그인하고 새 디스크 확인
타깃 iqn.2026-09.io.labhub:sto 에 로그인하세요. 새로 생긴 디스크가 lsblk 의 TRAN 열에 iscsi 로 보여야 합니다. lsblk -o NAME,SIZE,TRAN,VENDOR,MODEL 출력을 /root/sto/iscsi/lsblk.txt 에 저장하세요.
iscsiadm -m node -T -p <포털> --login 입니다. 로그인한 세션은 iscsiadm -m session 으로 봅니다.
_netdev 로 fstab 에 등록
iSCSI 디스크를 ext4 로 포맷하고, /etc/fstab 에 UUID= 로 시작하고 옵션에 _netdev 가 들어간 줄로 /mnt/iscsi 에 마운트되게 하세요. mount /mnt/iscsi 처럼 fstab 줄로 붙여 지금 마운트돼 있어야 합니다.
이 디스크는 /dev/disk/by-path/ip-127.0.0.1:3260-iscsi-iqn.2026-09.io.labhub:sto-lun-0 로도 가리킬 수 있습니다. /dev/sdX 이름은 부팅마다 바뀔 수 있으니 fstab 에는 UUID 를 적습니다. _netdev 가 없으면 부팅 때 네트워크보다 먼저 마운트를 시도합니다.
자동 로그인 켜기
타깃 iqn.2026-09.io.labhub:sto (포털 127.0.0.1) 의 노드 기록에서 node.startup 을 automatic 으로 바꾸세요.
iscsiadm -m node -T -p <포털> --op update -n node.startup -v automatic 입니다. 현재 값은 iscsiadm -m node -T -p <포털> 출력에서 찾을 수 있습니다.
큐 깊이 1 로 재기
fio 로 /mnt/iscsi/fio.dat (크기 128MiB) 에 4KiB 무작위 읽기를 ioengine=libaio, direct=1, iodepth=1 로 10초(runtime=10, time_based) 재고, JSON 결과를 /root/sto/fio/qd1.json 에 저장하세요.
fio --name=<이름> --filename=<파일> --size=128M --rw=randread --bs=4k --ioengine=libaio --direct=1 --iodepth=1 --runtime=10 --time_based --output-format=json --output=<파일> 모양입니다. direct=1 을 빼면 페이지 캐시를 재게 됩니다.
큐 깊이 32 로 재기
6단계와 같은 파일, 같은 조건에서 iodepth=32 만 바꿔 다시 재고, JSON 결과를 /root/sto/fio/qd32.json 에 저장하세요.
조건을 하나만 바꿔야 비교가 됩니다. 이름과 출력 파일, iodepth 만 다르게 하세요.
JSON 에서 숫자 꺼내기와 리틀의 법칙
두 JSON 에서 숫자를 꺼내 /root/sto/fio/report.txt 에 다섯 줄을 적으세요: qd1_iops=, qd1_p99_us=, qd32_iops=, qd32_p99_us= (IOPS 는 반올림한 정수, p99 는 clat_ns.percentile 의 99.000000 을 마이크로초로 바꿔 반올림한 정수), 그리고 qd32_little= (qd32 의 IOPS × 평균 지연 lat_ns.mean 을 초로 바꾼 값, 소수 첫째 자리까지).
값은 손으로 옮기지 말고 python3 로 JSON 을 읽어 계산하세요. jobs[0]['read'] 아래에 iops, lat_ns, clat_ns 가 있습니다. 나노초는 1,000 으로 나누면 마이크로초, 10억으로 나누면 초입니다. qd32_little 이 큐 깊이에 가까우면 리틀의 법칙이 맞은 것입니다.