콘텐츠로 이동

스토리지

Terminal window
pcvctl storage pool list

출력 예시:

NAME SIZE USED AVAIL CAP HEALTH
pcvpool 8.0T 2.1T 5.9T 26% ONLINE
datapool 4.0T 1.5T 2.5T 38% ONLINE
Terminal window
# mirror 풀 (2-디스크 미러)
pcvctl storage pool create --name datapool --vdev /dev/sdb /dev/sdc --type mirror
# raidz1 풀 (3-디스크 RAIDZ)
pcvctl storage pool create --name raidpool --vdev /dev/sdb /dev/sdc /dev/sdd --type raidz1

RPC 직접 호출:

Terminal window
echo '{"jsonrpc":"2.0","method":"storage.pool.create","params":{
"name": "datapool",
"vdevs": ["/dev/sdb", "/dev/sdc"],
"type": "mirror"
},"id":"1"}' | nc -U /var/run/purecvisor/daemon.sock | python3 -m json.tool
Terminal window
# 풀 헬스 (health, scrub 진행률, 용량)
pcvctl storage pool health pcvpool
# 스크럽 시작
pcvctl storage pool scrub pcvpool
# 풀 삭제
pcvctl storage pool destroy datapool
Terminal window
# 현재 사용량 추세 기반 용량 고갈 예측
pcvctl storage pool forecast pcvpool
Terminal window
pcvctl storage zvol list

출력 예시:

NAME VOLSIZE USED REFER
pcvpool/vms/web-prod 20.0G 8.5G 8.5G
pcvpool/vms/db-prod 100.0G 45.2G 45.2G
pcvpool/vms/web-staging 20.0G 8.5G 8.5G (clone)
Terminal window
# zvol 생성
pcvctl storage zvol create pcvpool/vms/new-disk --size 50G
# zvol 삭제
pcvctl storage zvol delete pcvpool/vms/old-disk

RPC 직접 호출:

Terminal window
# 목록
echo '{"jsonrpc":"2.0","method":"storage.zvol.list","params":{},"id":"1"}' \
| nc -U /var/run/purecvisor/daemon.sock | python3 -m json.tool
# 생성
echo '{"jsonrpc":"2.0","method":"storage.zvol.create","params":{
"name": "pcvpool/vms/test-disk",
"size": "50G"
},"id":"1"}' | nc -U /var/run/purecvisor/daemon.sock | python3 -m json.tool
# 삭제
echo '{"jsonrpc":"2.0","method":"storage.zvol.delete","params":{
"name": "pcvpool/vms/test-disk"
},"id":"1"}' | nc -U /var/run/purecvisor/daemon.sock | python3 -m json.tool

클론 데이터셋을 독립 데이터셋으로 전환합니다 (원본 스냅샷 의존 해소).

Terminal window
pcvctl storage promote pcvpool/vms/web-staging

pcvctl 에는 iscsi 서브커맨드가 없습니다. iSCSI 타겟 관리는 RPC(또는 REST·웹 UI) 로만 합니다 — 아래 예시를 쓰세요.
(이 자리에 있던 pcvctl iscsi list/create/delete --name iqn.2026-04.… 예시는 실제로 존재한 적이 없는 명령이었고 IQN 접두사도 틀렸습니다.
현재 접두사는 iqn.2026-03.purecvisor 이며, 타겟은 IQN 이 아니라 vm_name 으로 지정합니다 — IQN 은 데몬이 조립합니다.)

RPC 직접 호출:

Terminal window
# 타겟 목록 — 응답 요소는 {vm_name, tid, iqn}.
# ★ 정본 식별자는 iqn 이다. tid 는 커널 LIO 와 무관한 인메모리 순번(하위 호환 잔존 필드)이므로
# tid 로 커널 자원을 찾으려 하지 말 것.
echo '{"jsonrpc":"2.0","method":"iscsi.target.list","params":{},"id":"1"}' \
| nc -U /var/run/purecvisor/daemon.sock | python3 -m json.tool
# 타겟 생성 — params 는 vm_name·zvol_path 두 개다(IQN 은 데몬이 조립한다).
# vm_name 은 1~64자 [a-zA-Z0-9_-] 로 제한되며, IQN 은 iqn.2026-03.purecvisor:<vm_name> 이 된다.
echo '{"jsonrpc":"2.0","method":"iscsi.target.create","params":{
"vm_name": "disk1",
"zvol_path": "/dev/zvol/pcvpool/iscsi/disk1"
},"id":"1"}' | nc -U /var/run/purecvisor/daemon.sock | python3 -m json.tool
# 타겟 삭제 (멱등)
echo '{"jsonrpc":"2.0","method":"iscsi.target.delete","params":{"vm_name":"disk1"},"id":"1"}' \
| nc -U /var/run/purecvisor/daemon.sock | python3 -m json.tool
# 이니시에이터: 원격 타겟 로그인 / 로그아웃
echo '{"jsonrpc":"2.0","method":"iscsi.connect","params":{
"target_ip": "192.0.2.50", "vm_name": "disk1"
},"id":"1"}' | nc -U /var/run/purecvisor/daemon.sock | python3 -m json.tool
echo '{"jsonrpc":"2.0","method":"iscsi.disconnect","params":{
"target_ip": "192.0.2.50", "vm_name": "disk1"
},"id":"1"}' | nc -U /var/run/purecvisor/daemon.sock | python3 -m json.tool

타겟 백엔드는 커널 LIO다(D4 전환).
데몬은 tgtadm 같은 외부 명령을 실행하지 않고 /sys/kernel/config/target 아래 configfs 트리를 직접 만든다.
따라서 tgt 패키지·데몬이 필요 없고, 대신 target_core_mod·iscsi_target_mod·target_core_iblock 커널 모듈이 올라와 있어야 한다(/etc/modules-load.d/purecvisor-lio.confdeb 가 conffile 로 설치하며, deb 를 쓰지 않는 배포에서만 운영자가 직접 만든다).
모듈이 없으면 데몬은 degraded 경고만 남기고 기동하며, 타겟 생성 시 실패 경로를 명확히 알려 준다.

CHAP 인증: daemon.conf[iscsi] chap_user/chap_password 를 설정하면 타겟에 CHAP 이 적용됩니다.
타겟 측 비밀번호는 프로세스 인자로 나가지 않습니다 — 데몬이 configfs auth/password 파일에 직접 씁니다(D4 전환의 목적).

데몬은 타겟을 만들기 전에 자격을 검증하고, 아래 중 하나라도 걸리면 생성을 거부합니다(조용히 넘어가지 않습니다):

  • 한쪽만 설정chap_user 만 있고 chap_password 가 없거나 그 반대.
    그대로 두면 커널에 “인증 불필요”가 기록되어 누구나 인증 없이 그 LUN 에 접속할 수 있게 됩니다.
    chap_password 가 암호화 저장돼 있는데 복호에 실패한 경우(머신 ID 변경, 다른 노드에서 복원한 설정 파일 등)도 같은 경로이므로, 살아 있는 타겟의 인증이 재생성 중에 꺼지는 일이 없습니다.
  • "NULL" 로 시작하는 값 — 커널이 그 자격을 미설정으로 되돌립니다.
  • 255자 초과 — 커널이 조용히 잘라 저장하므로 로그인이 영영 실패합니다.
  • 개행이 섞인 값 — configfs 는 개행을 제거하지 않아 자격의 일부가 됩니다.

거부 시 오류 메시지는 어느 항목이 문제인지만 알려 주고 값 자체는 절대 싣지 않습니다.

이니시에이터(클라이언트) 측 CHAP도 비밀번호를 iscsiadm 인자로 전달하지 않습니다.
discovery 뒤 open-iscsi 호환 lock을 잡고 같은 target/address/port의 모든 TPGT·iface node record를 0600 임시 파일과 atomic rename으로 갱신합니다.
일부 파일 갱신 중 오류가 나면 이미 교체한 record를 역순 원복하며, 무매치·symlink·중복 auth key·반쪽 CHAP 설정은 login 전에 fail-closed합니다.
discovery는 discoverydb --discover로 record를 영속하며, 최종 활성 /var/lib/iscsi/nodes/... record(legacy 설치는 /etc/iscsi/nodes/...)에는 open-iscsi가 로그인에 사용할 비밀번호가 저장되므로 해당 트리와 root 권한은 계속 비밀 경계입니다.
같은 target이 두 root에 모두 있으면 정본을 추측하지 않고 거부합니다(ADR-0036).

ZFS 풀의 디스크를 NVMe/SSD/HDD 계층으로 자동 분류합니다.

Terminal window
# 티어 목록
pcvctl storage tier list

출력 예시:

TIER DEVICES IOPS LATENCY
NVMe nvme0n1 500K 0.1ms
SSD sda, sdb 50K 0.5ms
HDD sdc, sdd 200 5.0ms
Terminal window
# 설정된 모든 iso_dirs에서 ISO/IMG 파일 스캔
pcvctl iso list

출력 예시:

PATH SIZE
/pcvpool/iso/ubuntu-24.04-live-server-amd64.iso 2.6G
/pcvpool/iso/debian-12.0-amd64-netinst.iso 628M
/var/lib/libvirt/images/cloud-init.img 384K

다중 ISO 경로: daemon.conf [storage] iso_dirs에 콤마로 구분하여 여러 디렉터리를 지정할 수 있습니다.

/api/v1/metrics에서 다음 스토리지 메트릭을 수집합니다:

# ZFS 풀 메트릭 (6개)
purecvisor_zpool_size_bytes{pool="pcvpool"}
purecvisor_zpool_used_bytes{pool="pcvpool"}
purecvisor_zpool_free_bytes{pool="pcvpool"}
purecvisor_zpool_capacity_percent{pool="pcvpool"}
purecvisor_zpool_fragmentation_percent{pool="pcvpool"}
purecvisor_zpool_health{pool="pcvpool"}
# 파일시스템 메트릭
node_filesystem_size_bytes{mountpoint="/",fstype="ext4"}
node_filesystem_avail_bytes{mountpoint="/",fstype="ext4"}
node_filesystem_files{mountpoint="/"}
# Disk I/O 메트릭
node_disk_reads_completed_total{device="sda"}
node_disk_writes_completed_total{device="sda"}
node_disk_read_bytes_total{device="sda"}
node_disk_written_bytes_total{device="sda"}
node_disk_io_time_seconds_total{device="sda"}