NAS HW 오프로드

NAS(Network Attached Storage) H/W 오프로드 종합 가이드 — HW RAID, Intel DSA/IOAT 데이터 이동 가속, Copy Offload(XCOPY/ODX/NVMe Copy), dm-crypt/blk-crypto/SED 암호화 3경로, TSO/RDMA/TOE 네트워크 가속, NVMe-oF/iSCSI HBA/FC HBA 스토리지 프로토콜 오프로드, QAT 압축, GPU/NPU 미디어 가속, P2P DMA, 상용 NAS 아키텍처 비교, Linux 커널 빌딩 블록 매핑, 오프로드 결정 트리

전제 조건: Block I/O(블록 레이어, blk-mq, I/O 스케줄러 기초), Device Mapper / LVM(dm-crypt, MD RAID, LVM 기초), SCSI / iSCSI(SCSI 스택, iSCSI 프로토콜 기초), Linux Crypto Framework(암호화 API, 하드웨어 가속 기초) 문서를 먼저 읽으세요.
일상 비유: NAS H/W 오프로드는 대형 택배 물류 센터에 비유할 수 있습니다. HW RAID는 자동 분류기(Sorter)로, 수작업(SW RAID) 대신 자동으로 분류합니다. DSA는 컨베이어 벨트로, 사람(CPU memcpy) 대신 자동 이동시킵니다. SED는 잠금 금고 컨테이너로, 포장 작업(dm-crypt) 없이 컨테이너 자체가 잠금 기능을 내장합니다. RDMA는 전용 고속 도로로, 일반 도로(TCP/IP 스택)를 우회합니다. QAT는 자동 진공 포장기로, 사람 대신 기계가 초고속 압축합니다. NAS의 핵심 과제는 다수의 동시 클라이언트에게 최대 처리량을 제공하면서 CPU를 데이터 경로에서 최대한 제거하는 것입니다.

핵심 요약

  • 한 줄 정의: NAS H/W 오프로드란 스토리지 I/O 경로의 데이터 처리(RAID 패리티 연산, 암호화, 압축, 네트워크 프로토콜 등)를 CPU 대신 전용 하드웨어(RAID 컨트롤러, DSA, QAT, RDMA NIC, SED 등)에서 수행하여 처리량을 극대화하는 기술입니다.
  • 핵심 역할: 멀티 유저 NAS에서 동시 파일 서비스(SMB/NFS), iSCSI 블록 서비스, 미디어 트랜스코딩, 백업/복제가 동시에 발생하면 CPU가 병목이 됩니다. 7대 오프로드(RAID, 데이터 이동, 복사, 암호화, 네트워크, 프로토콜, 압축)를 적절히 조합하면 CPU 부하를 극적으로 줄일 수 있습니다.
  • 사용 이유: 10GbE 이상의 고속 네트워크 환경에서 소프트웨어 RAID + dm-crypt + TCP 체크섬 연산만으로도 CPU 코어가 포화되어 NAS 처리량이 네트워크 대역폭에 미치지 못하는 현상이 발생합니다. HW 오프로드로 CPU를 데이터 경로에서 제거하면 라인 레이트(Line Rate) 달성이 가능합니다.
  • Linux 구현: md/dm(RAID) + DMA Engine/DSA(데이터 이동) + blk-crypto/SED(암호화) + crypto API/QAT(압축) + RDMA/TOE(네트워크) + LIO/NVMe target(프로토콜)을 커널 서브시스템 조합으로 구현합니다.
  • 핵심 수치: HW RAID 6 vs SW RAID 6(CPU 사용률 80%→5%), QAT deflate(CPU 200MB/s→QAT 10GB/s), SED 암호화(성능 손실 0%), RDMA SMB Direct(CPU 50%↓, 지연 10×↓)

단계별 이해

  1. 애플리케이션 I/O 요청
    NAS 클라이언트(SMB/NFS/iSCSI)로부터 I/O 요청이 도착하면, 커널의 VFS(Virtual File System) 계층을 통해 해당 파일시스템(ext4, Btrfs, XFS 등)에 전달됩니다. 이 단계에서 네트워크 프로토콜 오프로드(RDMA, TSO)가 CPU 부하를 줄입니다.
  2. Block 레이어와 I/O 스케줄러
    파일시스템이 블록 I/O를 생성하면 블록 레이어(Block Layer)의 blk-mq를 통해 I/O 스케줄러에 전달됩니다. 이 단계에서 blk-crypto 인라인 암호화나 REQ_OP_COPY_OFFLOAD 복사 오프로드가 적용될 수 있습니다.
  3. RAID/DM 변환 + 암호화/압축 오프로드
    MD(Multiple Devices) 또는 Device Mapper 레이어에서 RAID 변환이 수행됩니다. HW RAID 컨트롤러(MegaRAID, SmartPQI)는 이 과정 전체를 하드웨어에서 처리합니다. dm-crypt는 CPU에서, blk-crypto는 인라인 HW에서, SED/OPAL은 드라이브 내부에서 암호화합니다.
  4. 스토리지 프로토콜 HBA 오프로드
    SCSI/NVMe 드라이버가 디스크에 명령을 전달합니다. HW iSCSI HBA(Chelsio T6, QLogic)는 TCP/iSCSI 처리를 하드웨어에서 수행하고, FC HBA(lpfc, qla2xxx)는 Fibre Channel 프로토콜을 처리합니다. NVMe-oF RNIC는 RDMA 기반 원격 NVMe 접근을 가속합니다.
  5. 네트워크 전송 오프로드
    NAS가 클라이언트에 데이터를 전송할 때, NIC의 TSO/GSO/GRO/체크섬 오프로드가 TCP 세그먼테이션을 가속합니다. RDMA(RoCE/iWARP)를 사용하면 커널 TCP/IP 스택을 완전히 우회하여 zero-copy 전송이 가능합니다. QAT는 전송 전 데이터 압축을, kTLS은 TLS 암호화를 오프로드합니다.

선수 지식 수준 가이드

지식 영역필수/권장수준학습 자료
Linux 블록 I/O 기초필수bio, request, blk-mq 개념Block I/O
RAID 개념필수RAID 0/1/5/6/10 차이, 패리티 계산Device Mapper
SCSI/iSCSI권장SCSI 명령, iSCSI 프로토콜SCSI / iSCSI
암호화 기초권장AES, dm-crypt, LUKS 개념Crypto Framework
네트워크 오프로드권장TSO, GRO, RDMA 개념GSO/GRO

NAS H/W 오프로드 개요 — I/O 경로와 오프로드 포인트

NAS는 일반 서버와 달리 다수의 동시 클라이언트혼합 워크로드(순차 대용량 읽기 + 랜덤 소규모 쓰기 + 메타데이터 연산)를 동시에 요청합니다. 이로 인해 CPU가 I/O 경로의 각 단계에서 데이터를 처리하느라 병목이 발생하며, 네트워크 대역폭을 100% 활용하지 못하는 상황이 흔합니다.

NAS I/O 전체 경로와 오프로드 포인트 NAS I/O 경로와 7대 오프로드 포인트 SMB/NFS 클라이언트 ⑤ 네트워크 오프로드 TSO/RDMA/kTLS ⑥ 프로토콜 오프로드 iSCSI HBA/FC HBA/NVMe-oF VFS / 파일시스템 Block Layer (blk-mq) ③ Copy 오프로드 XCOPY/ODX/NVMe Copy ④ 암호화 오프로드 dm-crypt/blk-crypto/SED MD / Device Mapper ① HW RAID 오프로드 MegaRAID/SmartPQI/BBU ② 데이터 이동 가속 Intel DSA/IOAT/DMA Engine ⑦ 압축 오프로드 QAT deflate/lz4 SCSI / NVMe 드라이버 HDD / SSD / NVMe GPU/NPU 미디어 QSV/V4L2/트랜스코딩 P2P DMA NVMe → GPU 직접 범례: RAID 데이터이동 복사/압축 암호화 네트워크 프로토콜 ① ~ ⑦ 각 오프로드 포인트에서 전용 하드웨어가 CPU를 대체합니다. 실선 화살표는 주요 데이터 경로, 점선은 선택적 오프로드 경로입니다.

NAS가 일반 서버와 다른 I/O 특성

특성일반 서버NAS
동시 클라이언트1~10수십~수백
워크로드 패턴단일 애플리케이션혼합 (파일/블록/미디어)
I/O 크기 분포비교적 균일4KB~수MB 혼합
데이터 보호선택적RAID + 암호화 + 스냅샷 필수
네트워크 대역폭1~10 Gbps10~100 Gbps (다중 NIC)
CPU 부하 패턴연산 중심I/O 경로 처리 중심

CPU-bound vs I/O-bound 분석

NAS 워크로드에서 CPU가 병목이 되는 대표적인 상황:

핵심: NAS에서 CPU 부하는 비즈니스 로직이 아닌 데이터 경로 처리에 집중됩니다. 이 데이터 경로의 각 단계를 하드웨어로 오프로드하는 것이 NAS H/W 오프로드의 본질입니다.

오프로드 없는 NAS의 CPU 사용률 분석

10GbE NAS에서 동시 워크로드를 실행했을 때, 오프로드 없이 CPU만으로 처리하면 어떤 분포를 보이는지 분석합니다. Xeon E-2388G(8코어 16스레드) 기준입니다.

처리 단계CPU 코어 소모CPU 비율오프로드 가능 HW
SW RAID 6 XOR/PQ 연산2~3 코어25~38%HW RAID, IOAT DMA
dm-crypt AES-XTS 암/복호화1~2 코어12~25%SED, blk-crypto
TCP/IP 프로토콜 처리1~2 코어12~25%RDMA, TSO/GRO
SMB3/NFS 프로토콜 처리1~2 코어12~25%ksmbd 커널 서버
gzip 압축 (백업 동시)1~2 코어12~25%QAT
미디어 트랜스코딩 (동시)4~8 코어50~100%QSV, dGPU
memcpy (버퍼 복사)0.5~1 코어6~12%DSA
⚠️ CPU 과부하 시나리오: 위의 모든 워크로드가 동시에 실행되면 합산 CPU 요구량이 10~20코어에 달합니다. 8코어 CPU에서는 모든 워크로드의 처리량이 저하되어 NAS 클라이언트 응답 시간이 급격히 증가합니다. 오프로드를 적용하면 CPU 요구량을 2~3코어 수준으로 줄일 수 있으며, 나머지 코어를 클라이언트 요청 처리에 할당할 수 있습니다.

perf로 오프로드 효과 측정하는 방법

# 1단계: 오프로드 전 CPU 프로파일링
perf record -g -a -- sleep 30    # 30초간 시스템 전체 프로파일
perf report --sort=comm,dso,symbol --stdio | head -50
# 결과 예시:
#  35.2%  md0_raid6   [kernel]  raid5_compute_sector
#  22.1%  kcryptd     [kernel]  aesni_ctr_enc
#  15.3%  ksoftirqd   [kernel]  tcp_v4_rcv
#   8.7%  kworker     [kernel]  memcpy_orig

# 2단계: HW RAID 적용 후 프로파일링
# raid5_compute_sector가 사라지고 CPU 여유 확인
perf stat -e cycles,instructions,cache-misses -- fio ...

# 3단계: SED 적용 후 프로파일링
# aesni_ctr_enc가 사라짐

# 4단계: RDMA 적용 후 프로파일링
# tcp_v4_rcv가 사라지고 mlx5_ib 하드웨어 처리

# CPU 사용률 변화 요약 (mpstat)
mpstat -P ALL 5 3    # 5초 간격, 3회 측정

오프로드 적용 전후 성능 비교 예시

지표오프로드 없음부분 오프로드전체 오프로드
순차 쓰기 (RAID 6)~1.5 GB/s~5 GB/s (HW RAID)~8 GB/s (HW RAID + SED)
CPU 사용률 (순차 쓰기)90%40%10%
SMB 동시 클라이언트 4K IOPS~50K~150K~400K (RDMA)
CPU 사용률 (SMB 서비스)85%35%15%
백업 압축 처리량~200 MB/s (gzip SW)~2 GB/s (lz4 SW)~10 GB/s (QAT deflate)
4K 트랜스코딩 동시 스트림1개 (CPU)15개 (QSV)30개 (dGPU)
rebuild 중 서비스 성능 유지율50%80%95%

오프로드 7대 분류 체계

NAS H/W 오프로드 7대 분류 트리 NAS H/W 오프로드 ① RAID 오프로드 MegaRAID, SmartPQI async_tx, BBU/FBWC ② 데이터 이동 Intel DSA, IOAT idxd, ENQCMD ③ Copy 오프로드 XCOPY, ODX NVMe Copy Cmd ④ 암호화 오프로드 dm-crypt, blk-crypto SED/OPAL ⑤ 네트워크 TSO, RDMA, TOE iSER, kTLS ⑥ 프로토콜 NVMe-oF, iSCSI HBA FC HBA 압축 QAT 각 분류별 커널 서브시스템 매핑 분류 대표 HW 커널 API / 드라이버 성능 효과 ① RAID MegaRAID, SmartPQI, hpsa megaraid_sas, smartpqi, async_tx CPU 80%→5%, RAID rebuild 3×↑ ② 데이터 이동 Intel DSA, IOAT, CBDMA idxd, ioatdma, dmaengine 대용량 memcpy CPU→0% ③ 복사 NVMe SSD, SAS 어레이 blk-copy, target_xcopy, nvme_copy 서버 측 복사 CPU→0%, 대역폭 2×↑ ④ 암호화 SED/OPAL SSD, UFS ICE blk-crypto, sed-opal, dm-crypt SED: 성능 손실 0%, blk-crypto: <2% ⑤ 네트워크 RDMA NIC, ConnectX, T6 rdma_cm, ib_core, ndo_features CPU 50%↓, 지연 10×↓ (RDMA) ⑥ 프로토콜 iSCSI HBA, FC HBA, NVMe-oF cxgb4i, qla2xxx, nvme_rdma 프로토콜 처리 CPU→HW ⑦ 압축 Intel QAT C62x/4xxx qat_comp, crypto_acomp 처리량 50×↑, CPU 100%→5%

HW RAID 오프로드 — MegaRAID, async_tx, BBU/FBWC

HW RAID 컨트롤러는 NAS에서 가장 전통적이고 효과적인 오프로드 수단입니다. XOR/P+Q 패리티 연산, 캐시 관리, 디스크 장애 복구를 모두 컨트롤러 펌웨어와 전용 프로세서에서 처리하므로, 호스트 CPU는 RAID의 존재를 인식하지 못합니다.

HW RAID 컨트롤러 데이터 흐름 Host (CPU) Application VFS / FS Block Layer SCSI mid-layer megaraid_sas HW RAID Controller XOR/P+Q Engine Write Cache BBU / FBWC ARM/MIPS CPU DDR Cache Disk 0 Disk 1 Disk 2 Disk 3 Parity PCIe x8/x16 호스트 CPU는 가상 디스크(Virtual Disk)만 인식 RAID 레벨, 패리티, 캐시 정책은 컨트롤러가 관리 BBU/FBWC가 정전 시 캐시 데이터를 플래시에 보존

주요 HW RAID 드라이버 비교

드라이버벤더대표 제품RAID 레벨최대 디스크캐시 보호
megaraid_sasBroadcom (LSI)MegaRAID 9560, 96700/1/5/6/10/50/60240+BBU, FBWC (CacheVault)
smartpqiMicrochip (Adaptec)SmartRAID 32000/1/5/6/10/50/60256ZMCP, maxCache
hpsasmartpqiHPESmart Array P816i-a0/1/5/6/10/50/6068FBWC

커널 소스 분석: megaraid_sas 명령 제출 경로

/* drivers/scsi/megaraid/megaraid_sas_fusion.c (간략화) */
static int
megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance,
                                   struct scsi_cmnd *scmd)
{
    struct megasas_cmd_fusion *cmd;
    struct MPI2_RAID_SCSI_IO_REQUEST *io_request;

    cmd = megasas_get_cmd_fusion(instance, scmd->request->tag);
    io_request = cmd->io_request;

    /* SCSI CDB를 MPI2 RAID 요청으로 변환 */
    memcpy(io_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
    io_request->DevHandle = cpu_to_le16(device_id);

    /* RAID 가속 경로: 컨트롤러가 직접 디스크에 접근 */
    if (megasas_is_ldio(scmd))
        megasas_build_ldio_fusion(instance, scmd, cmd);

    /* 도어벨 레지스터를 통해 컨트롤러에 명령 전달 */
    instance->instancet->fire_cmd(instance,
        cmd->request_desc_phys, 0, instance->reg_set);
    return 0;
}
코드 설명
  • 핵심megasas_build_and_issue_cmd_fusion() — SCSI mid-layer에서 받은 명령을 MPI2(Message Passing Interface 2) 프레임으로 변환하여 HW RAID 컨트롤러에 전달합니다. 컨트롤러는 내부 XOR/P+Q 엔진으로 패리티를 계산하고, DDR 캐시를 통해 쓰기를 가속합니다. 호스트 CPU는 프레임 구성과 도어벨(doorbell) 알림만 수행하며, 실제 RAID 연산에는 관여하지 않습니다.

BBU/FBWC 모니터링과 캐시 정책

HW RAID의 성능은 Write-back 캐시에 크게 의존합니다. Write-back은 데이터를 컨트롤러 캐시에만 기록하고 즉시 완료를 반환하므로 쓰기 지연이 극적으로 줄어듭니다. 단, BBU(Battery Backup Unit) 또는 FBWC(Flash-Backed Write Cache)가 정상이어야 정전 시 데이터를 보호할 수 있습니다.

# storcli BBU 상태 확인 (MegaRAID)
storcli /c0/bbu show all
# 주요 확인 항목:
#   Battery State       : Optimal
#   Charging Status     : None
#   Temperature         : 23 C
#   Design Capacity     : 1400 mAh
#   Full Charge Capacity: 1350 mAh (95% 이상 권장)

# Write Policy 확인
storcli /c0/v0 show | grep "Cache Policy"
# WriteBack → 정상 (BBU OK)
# WriteThrough → BBU 불량 시 자동 전환 (성능 급락!)

# smartpqi (Adaptec) BBU 확인
arcconf getconfig 1 | grep -A5 "Battery"
⚠️ BBU 방전 시 성능 급락: BBU가 방전되면 컨트롤러가 자동으로 Write-through 모드로 전환되어 쓰기 성능이 5~10배 저하됩니다. NAS 운영 시 BBU 상태를 정기적으로 모니터링하고, FBWC(슈퍼캐패시터 기반) 업그레이드를 권장합니다. FBWC는 배터리 수명 문제가 없어 장기 운영에 유리합니다.

async_tx API — 커널 XOR/PQ 연산 오프로드 프레임워크

Linux 커널의 async_tx API는 RAID 5/6의 XOR 패리티 연산 및 PQ(P+Q) 이중 패리티 연산을 DMA 엔진으로 오프로드하는 프레임워크입니다. HW RAID 컨트롤러 없이도 SW RAID(md)에서 XOR 가속을 활용할 수 있으며, HW RAID와 결합하면 rebuild 성능을 더욱 향상시킬 수 있습니다. async_tx는 drivers/dma/ 디렉토리의 DMA 엔진 드라이버와 연동하며, DMA 엔진이 없으면 자동으로 CPU 기반 소프트웨어 폴백을 수행합니다.

커널 소스 분석: async_xor() — XOR 패리티 연산 오프로드

/* crypto/async_tx/async_xor.c */
struct dma_async_tx_descriptor *
async_xor(struct page *dest, struct page **src_list,
          unsigned int offset, int src_cnt, size_t len,
          struct async_submit_ctl *submit)
{
    struct dma_chan *chan = async_tx_find_channel(submit,
                            DMA_XOR, &dest, 1, src_list,
                            src_cnt, len);
    struct dma_device *device = chan ? chan->device : NULL;
    struct dmaengine_unmap_data *unmap = NULL;

    BUG_ON(src_cnt <= 1);

    if (device && src_cnt <= device->max_xor) {
        /* DMA 엔진이 XOR을 지원하고 소스 수가 범위 내 */
        unmap = dmaengine_get_unmap_data(device->dev,
                    src_cnt + 1, GFP_NOWAIT);
        if (likely(unmap)) {
            struct dma_async_tx_descriptor *tx;
            /* DMA 엔진에 XOR 작업 제출 */
            tx = device->device_prep_dma_xor(chan,
                    dma_dest, dma_src, src_cnt, len,
                    dma_flags);
            if (likely(tx)) {
                async_tx_submit(chan, tx, submit);
                return tx;
            }
        }
    }

    /* DMA 엔진 사용 불가 시 CPU 소프트웨어 폴백 */
    xor_blocks(src_cnt, len, dest_buf, srcs);
    return NULL;
}
코드 설명
  • 핵심async_xor()는 RAID 5/6 패리티 계산의 핵심 경로입니다. 먼저 async_tx_find_channel()로 XOR 기능을 지원하는 DMA 채널을 탐색합니다. Intel IOAT, Marvell XOR 엔진 등이 등록되어 있으면 device_prep_dma_xor()로 하드웨어 XOR 연산을 준비하고, async_tx_submit()으로 비동기 제출합니다. DMA 엔진이 없거나 제출에 실패하면 xor_blocks() 소프트웨어 폴백이 실행됩니다. 이 투명한 폴백 설계 덕분에 md RAID는 HW XOR 엔진 유무에 관계없이 동일한 코드 경로를 사용합니다.

RAID Rebuild 과정과 HW 가속 효과

RAID 어레이에서 디스크가 교체되면 rebuild(재구성) 프로세스가 시작됩니다. 이 과정은 나머지 디스크의 데이터와 패리티로부터 교체된 디스크의 데이터를 복원하는 것으로, 대규모 NAS에서는 수 시간에서 수일이 소요될 수 있습니다.

# SW RAID rebuild 속도 제한 설정
echo 200000 > /proc/sys/dev/raid/speed_limit_min    # 최소 200 MB/s
echo 500000 > /proc/sys/dev/raid/speed_limit_max    # 최대 500 MB/s

# rebuild 진행 상황 확인
cat /proc/mdstat
# md0 : active raid6 sda1[0] sdb1[1] sdc1[2] sdd1[3] sde1[4] sdf1[5]
#       19531776 blocks super 1.2 level 6, 512k chunk
#       [6/5] [UUUUU_]
#       [====>................]  recovery = 23.4% (1143040/4883072)
#                                finish=12.3min speed=508120K/sec

HW RAID vs SW RAID 성능 비교

항목HW RAID (MegaRAID 9560)SW RAID (md + AES-NI XOR)SW RAID (md + IOAT DMA)
순차 읽기 (RAID 6, 8×SSD)~12 GB/s~10 GB/s~11 GB/s
순차 쓰기 (RAID 6, 8×SSD)~8 GB/s~4 GB/s~6 GB/s
랜덤 4K 읽기 IOPS~900K~600K~700K
랜덤 4K 쓰기 IOPS~250K~80K~120K
Rebuild 중 CPU 사용률1~5%60~80%15~25%
Rebuild 중 서비스 성능 저하5~10%30~50%15~25%
패리티 연산 대역폭24 GB/s (전용 ASIC)~15 GB/s (AVX-512)~20 GB/s (DMA XOR)
쓰기 캐시4 GB FBWC페이지 캐시 의존페이지 캐시 의존
장점CPU 완전 해방, 캐시 보호투명성, 유연성, 무료CPU 부분 해방
단점높은 비용, 벤더 종속높은 CPU 부하Xeon 서버 전용

JBOD Passthrough 모드와 HBA 모드 (IT Firmware)

HW RAID 컨트롤러를 사용하지 않고 디스크를 OS에 직접 노출하려면 JBOD(Just a Bunch of Disks) 모드 또는 IT(Initiator Target) 모드 펌웨어를 사용합니다. ZFS, Btrfs 같은 소프트웨어 RAID/볼륨 관리자는 디스크에 직접 접근해야 최적의 성능과 기능(자가 복구, 스크럽, 스냅샷 등)을 제공할 수 있으므로, HBA 모드가 권장됩니다.

모드RAID 처리디스크 노출대표 컨트롤러적합 시나리오
IR 모드 (HW RAID)컨트롤러 ASIC가상 디스크 (VD)MegaRAID 9560, SmartRAID 3254전통적 NAS, 하드웨어 캐시 필요 시
IT 모드 (HBA)없음 (패스스루)개별 물리 디스크9500-16i (IT), HBA 9400ZFS/Btrfs NAS, TrueNAS
JBOD 모드RAID 가능 + 개별 노출혼합 가능MegaRAID (JBOD 설정)유연한 혼합 구성
# LSI/Broadcom 컨트롤러 IT 모드 확인
sas3flash -list
# Firmware Product ID: IT (Initiator Target)

# JBOD 모드 설정 (storcli)
storcli /c0 set jbod=on

# 개별 디스크를 JBOD으로 전환
storcli /c0/e252/s0 set jbod

# 디스크가 OS에 직접 노출되는지 확인
lsblk -d -o NAME,MODEL,SIZE,TRAN
# sda  ST16000NM001G  14.6T  sas
# sdb  ST16000NM001G  14.6T  sas
ZFS/Btrfs NAS에서 IT 모드를 사용하는 이유: ZFS와 Btrfs는 자체적으로 데이터 체크섬, 미러링/패리티, 스크럽(scrub), 자가 복구를 수행합니다. HW RAID 컨트롤러가 중간에 개입하면 이러한 기능이 제대로 동작하지 않습니다. 특히 HW RAID의 Write-back 캐시는 ZFS의 ZIL(ZFS Intent Log)과 충돌할 수 있으며, RAID 컨트롤러의 "silent data corruption" 대응 능력이 ZFS보다 열등합니다. TrueNAS는 공식적으로 IT 모드 HBA만 지원합니다.
크로스플래싱(Cross-flashing): MegaRAID 컨트롤러를 IT 모드로 변환하려면 SAS3108/SAS3516 칩셋 기반 컨트롤러에 IT 펌웨어를 플래싱해야 합니다. 이 과정은 보증을 무효화할 수 있으므로 주의가 필요합니다. 처음부터 IT 모드가 필요하다면 Broadcom HBA 9500 시리즈 또는 9400 시리즈를 선택하는 것이 안전합니다.

Intel DSA/IOAT 데이터 이동 가속 — idxd, work queue

Intel DSA(Data Streaming Accelerator)는 4세대 Xeon Scalable(Sapphire Rapids)부터 내장된 데이터 이동 가속기입니다. 기존 IOAT(I/O Acceleration Technology, Crystal Beach DMA)의 후속으로, 대용량 메모리 복사(memcpy), 0-fill, CRC 계산, 데이터 비교 등을 CPU 없이 수행합니다.

Intel DSA 아키텍처 Intel DSA 아키텍처 (Sapphire Rapids+) CPU Cores ENQCMD / ENQCMDS MOVDIR64B (fallback) DSA Engine memcpy, memfill, compare CRC gen, DIF check, drain Shared WQ Dedicated WQ Shared WQ: ENQCMD, 다중 사용자 공유 Dedicated WQ: MOVDIR64B, 단일 드라이버 전용 mdev: VM에 WQ 가상 할당 (SIOV) System Memory (DDR5) DMA 전송 NAS 활용 사례: RAID rebuild memcpy 가속 | NFS/SMB 대용량 파일 복사 | 스냅샷 CoW 복사 | 블록 zero-fill | CRC32C 무결성 검증

DSA vs IOAT 비교

항목IOAT (Crystal Beach DMA)DSA (Data Streaming Accelerator)
도입 세대Nehalem~Ice LakeSapphire Rapids~
커널 드라이버ioatdmaidxd
제출 방식MMIO descriptor ringENQCMD/ENQCMDS (CPU 명령어)
Work Queue단일 채널Shared WQ + Dedicated WQ
지원 연산memcpy, XORmemcpy, memfill, compare, CRC, DIF, drain, batch
가상화SR-IOV (제한적)mdev (SIOV, 유연한 할당)
배치 처리미지원batch descriptor로 다수 연산 묶어 제출

커널 소스 분석: idxd descriptor 제출

/* drivers/dma/idxd/submit.c (간략화) */
int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc,
                     enum idxd_submit_flags flags)
{
    struct idxd_device *idxd = wq->idxd;
    void __iomem *portal;

    portal = idxd_wq_portal_addr(wq);

    /*
     * Shared WQ: ENQCMDS 명령어로 제출 (실패 시 재시도)
     * Dedicated WQ: MOVDIR64B로 제출 (항상 성공)
     */
    if (wq_dedicated(wq)) {
        movdir64b(portal, desc->hw);
    } else {
        /* ENQCMDS는 WQ가 꽉 찬 경우 실패할 수 있음 */
        rc = enqcmds(portal, desc->hw);
        if (rc)
            return -EAGAIN;
    }
    return 0;
}
코드 설명
  • 핵심idxd_submit_desc() — DSA의 Work Queue에 작업 descriptor를 제출합니다. Dedicated WQ는 단일 드라이버가 독점하므로 MOVDIR64B 명령어로 무조건 성공합니다. Shared WQ는 다중 사용자(VM 포함)가 공유하므로 ENQCMDS 명령어를 사용하며, 큐가 꽉 차면 -EAGAIN을 반환합니다. NAS 환경에서는 RAID rebuild, 대용량 복사 등의 memcpy 작업을 DSA에 위임하여 CPU 코어를 클라이언트 요청 처리에 집중시킬 수 있습니다.

NAS RAID Rebuild에서 DSA memcpy 활용

RAID rebuild는 디스크에서 읽은 데이터 블록을 메모리에서 XOR 연산한 뒤 교체 디스크에 기록하는 과정입니다. 이 과정에서 대량의 memcpy 작업이 발생하며, DSA를 활용하면 CPU를 데이터 이동에서 완전히 해방할 수 있습니다.

특히 NAS가 rebuild 중에도 클라이언트 요청을 처리해야 하는 경우, DSA로 memcpy를 오프로드하면 CPU 코어를 SMB/NFS 프로토콜 처리에 집중시킬 수 있습니다. 8TB RAID 6 어레이의 rebuild 시 약 8TB의 읽기 + 8TB의 쓰기 + 지속적인 XOR 연산이 필요하며, memcpy 오프로드만으로도 CPU 사용률을 20~30% 절감할 수 있습니다.

Batch Descriptor 활용법

DSA는 단일 descriptor 제출뿐 아니라 Batch descriptor를 지원합니다. 여러 개의 작업을 하나의 batch로 묶어 제출하면 descriptor 제출 오버헤드를 줄이고 DSA 내부 파이프라인을 효율적으로 활용할 수 있습니다.

/* Batch descriptor 구성 예시 (사용자 공간 DSA 라이브러리) */
struct dsa_hw_desc batch_desc;
struct dsa_hw_desc sub_descs[MAX_BATCH_SIZE];

/* 서브 descriptor 배열 준비 */
for (int i = 0; i < batch_size; i++) {
    sub_descs[i].opcode = DSA_OPCODE_MEMMOVE;
    sub_descs[i].src_addr = src_buffers[i];
    sub_descs[i].dst_addr = dst_buffers[i];
    sub_descs[i].xfer_size = block_size;
    sub_descs[i].flags = IDXD_OP_FLAG_CRAV | IDXD_OP_FLAG_RCR;
}

/* Batch descriptor 설정 */
batch_desc.opcode = DSA_OPCODE_BATCH;
batch_desc.desc_list_addr = (uintptr_t)sub_descs;
batch_desc.desc_count = batch_size;
batch_desc.flags = IDXD_OP_FLAG_CRAV | IDXD_OP_FLAG_RCR;
batch_desc.completion_addr = (uintptr_t)&completion;

/* 단일 MOVDIR64B/ENQCMDS로 전체 batch 제출 */
movdir64b(wq_portal, &batch_desc);
Batch 크기 최적화: batch 크기가 너무 작으면 오버헤드 절감 효과가 미미하고, 너무 크면 단일 completion 지연이 길어집니다. NAS RAID rebuild에서는 스트라이프 크기(일반적으로 64KB~1MB)에 맞춰 8~32개의 memcpy를 하나의 batch로 묶는 것이 최적입니다. batch_size는 WQ의 max_batch_size 속성을 초과할 수 없습니다.

DSA vs CPU memcpy 벤치마크

블록 크기CPU memcpy (단일 코어)DSA Dedicated WQDSA Shared WQCPU 사용률 (DSA)
4 KB~12 GB/s~3 GB/s~2.5 GB/s<1%
64 KB~15 GB/s~25 GB/s~20 GB/s<1%
256 KB~16 GB/s~35 GB/s~30 GB/s<1%
1 MB~17 GB/s~40 GB/s~35 GB/s<1%
4 MB~17 GB/s~42 GB/s~38 GB/s<1%
주의: 4KB 이하의 소규모 전송에서는 DSA descriptor 제출 오버헤드로 인해 CPU memcpy가 더 빠릅니다. DSA의 장점은 64KB 이상의 대용량 전송에서 두드러지며, 특히 CPU를 완전히 해방한다는 점이 NAS 워크로드에서 핵심 가치입니다.

accel-config 도구 사용법

accel-config는 Intel DSA/IAX 장치를 사용자 공간에서 설정하고 관리하는 공식 도구입니다. Work Queue 생성, 엔진 바인딩, 디바이스 활성화 등을 수행합니다.

# DSA 장치 열거
accel-config list

# DSA 장치 설정 (dsa0)
# 1. 그룹 생성 및 엔진 할당
accel-config config-group dsa0/group0.0 \
    --read-buffers-reserved=8 \
    --read-buffers-allowed=8

accel-config config-engine dsa0/engine0.0 --group-id=0

# 2. Dedicated Work Queue 생성
accel-config config-wq dsa0/wq0.0 \
    --group-id=0 \
    --mode=dedicated \
    --wq-size=128 \
    --priority=10 \
    --type=kernel \
    --name=nas_raid_wq \
    --driver-name=dmaengine \
    --block-on-fault=1

# 3. 장치 및 WQ 활성화
accel-config enable-device dsa0
accel-config enable-wq dsa0/wq0.0

# 4. 상태 확인
accel-config list -i
# [
#   {
#     "dev": "dsa0",
#     "state": "enabled",
#     "max_groups": 4,
#     "max_work_queues": 8,
#     "max_engines": 4,
#     ...
#   }
# ]

# Shared WQ 설정 (VM/컨테이너 공유용)
accel-config config-wq dsa0/wq0.1 \
    --group-id=0 \
    --mode=shared \
    --wq-size=64 \
    --priority=5 \
    --type=user \
    --name=nas_shared_wq \
    --threshold=32

# DMA 엔진으로 등록되었는지 확인
ls /sys/class/dma/
# dma0chan0  dma0chan1  ...

# 성능 모니터링
cat /sys/bus/dsa/devices/dsa0/clients
cat /sys/bus/dsa/devices/wq0.0/state
영구 설정: accel-config 설정은 재부팅 시 초기화됩니다. accel-config save-config -s nas-dsa.conf로 저장하고, systemd 서비스 또는 /etc/accel-config/accel-config.conf.d/에 배치하여 부팅 시 자동 적용할 수 있습니다. NAS 환경에서는 type=kerneldriver-name=dmaengine을 사용하여 커널 DMA 서브시스템에 자동 등록하는 것이 일반적입니다.

Copy Offload — XCOPY, ODX, NVMe Copy

Copy Offload는 데이터 복사 시 호스트 CPU와 메모리를 경유하지 않고, 스토리지 장치 내부 또는 서버 측에서 직접 복사를 수행하는 기술입니다. NAS에서 VM 클론, 스냅샷 복사, 백업 등 대용량 데이터 이동 시 네트워크 대역폭과 CPU를 극적으로 절약합니다.

Copy Offload 3방식 비교 Copy Offload 3방식 비교 SCSI XCOPY (Extended Copy) Host Source LUN Dest LUN XCOPY cmd 서버 측 직접 복사 SMB ODX (Token 기반) Client Server Source Dest TOKEN 서버 내부 복사 NVMe Copy Command Host NVMe Controller 내부 NAND 복사 호스트 메모리 무경유 Copy cmd 방식별 특성 비교 항목 SCSI XCOPY SMB ODX NVMe Copy 복사 범위 동일 서버 내 LUN 간 SMB 공유 간 (서버 간 가능) 동일 NS 내 호스트 메모리 미경유 (서버 측 DMA) 미경유 (Token 기반) 완전 미경유 커널 지원 target_core_xcopy ksmbd: 제한적 nvme_cmd_copy (TP 4065) NAS 시나리오 iSCSI LUN 복제, VM 클론 Windows 파일 복사 스냅샷, CoW 복사

커널 소스 분석: NVMe Copy Command 설정

/* drivers/nvme/host/core.c (간략화) */
static void nvme_setup_copy(struct nvme_ns *ns,
                            struct nvme_command *cmd,
                            struct nvme_copy_range *ranges,
                            u16 nr_ranges, u64 dst_lba)
{
    cmd->copy.opcode  = nvme_cmd_copy;
    cmd->copy.nsid    = cpu_to_le32(ns->head->ns_id);
    cmd->copy.sdlba   = cpu_to_le64(dst_lba);   /* 대상 시작 LBA */
    cmd->copy.nr      = cpu_to_le16(nr_ranges - 1);
    /* 소스 LBA 범위들은 PRP/SGL로 전달 */
    /* 컨트롤러가 NAND 내부에서 직접 복사 수행 */
}
코드 설명
  • 핵심NVMe Copy Command — TP 4065 사양으로 정의된 NVMe Simple Copy 명령입니다. 소스 LBA와 대상 LBA를 지정하면 컨트롤러가 NAND 플래시 내부에서 직접 데이터를 복사합니다. 호스트 메모리를 전혀 경유하지 않으므로 CPU 부하 0%, PCIe 대역폭 미소모의 이상적인 복사가 가능합니다. 단, 동일 네임스페이스(NS) 내에서만 복사 가능하며, 컨트롤러별 최대 복사 크기(MSSRL/MCL) 제한이 있습니다.

XCOPY 실전 활용과 LIO 타겟 설정

SCSI XCOPY(Extended Copy, SPC-4)는 iSCSI/FC 환경에서 서버 측 데이터 복사를 수행합니다. NAS가 LIO 타겟으로 블록 서비스를 제공할 때, 클라이언트의 복사 요청을 서버 내부에서 처리하여 네트워크 트래픽을 제거합니다.

# LIO 타겟에서 XCOPY 지원 확인
targetcli
/> /backstores/block/nas-lun0 get attribute max_xcopy_target_sectors
# 2048 (기본값, 8MB)

# XCOPY 최대 크기 설정 (대용량 VM 클론용)
/> /backstores/block/nas-lun0 set attribute max_xcopy_target_sectors=8192

# 클라이언트에서 XCOPY 복사 (sg3_utils)
sg_xcopy --src=/dev/sda --dst=/dev/sdb --bs=512 --count=204800
# 100MB 복사 — 호스트 메모리 미경유, CPU 부하 최소

# dd 대비 XCOPY 성능
# dd: 호스트 read(source) → 메모리 → write(dest) = CPU+메모리 경유
# XCOPY: 호스트가 XCOPY 명령만 전송 → 타겟이 내부 복사
# 대용량 LUN 복제 시 XCOPY가 3~5배 빠름

SMB ODX(Offloaded Data Transfer) NAS 적용

SMB ODX는 Windows 클라이언트가 SMB 공유 간 파일을 복사할 때, 실제 데이터를 네트워크로 전송하지 않고 토큰 기반으로 서버 측에서 복사를 수행합니다. NAS에서 대용량 파일/폴더 복사 시 네트워크 부하를 제거합니다.

NVMe Copy와 파일시스템 연동

NVMe Copy 명령은 블록 레이어에서 동작하므로, 파일시스템이 이를 활용하려면 copy_file_range() 시스템콜과의 연동이 필요합니다.

파일시스템NVMe Copy 활용메커니즘상태
XFSreflink + copyCoW reflink 후 블록 복사 시 NVMe Copy 가능개발 중
Btrfsreflink (CoW)메타데이터만 복사, 실제 블록 복사 불필요네이티브 CoW
ext4미지원reflink 미지원-
ZFS간접적ZFS CoW + send/receive블록 레이어 미경유
CoW 파일시스템의 장점: Btrfs와 ZFS의 Copy-on-Write(CoW) 메커니즘은 파일 복사 시 메타데이터만 복사하고 실제 블록은 공유합니다. 이는 NVMe Copy보다 더 효율적입니다 — 블록 복사 자체가 불필요하기 때문입니다. NVMe Copy는 CoW를 지원하지 않는 파일시스템(ext4)이나, 실제 물리적 복사가 필요한 시나리오(스냅샷 해제, 백업)에서 가치가 있습니다.

암호화 오프로드 — dm-crypt/blk-crypto/SED 3경로

NAS에서 디스크 암호화는 규제 준수(GDPR, HIPAA)와 물리적 도난 대비를 위해 필수입니다. Linux는 세 가지 암호화 경로를 제공하며, 각각 성능 특성이 크게 다릅니다.

디스크 암호화 3경로 비교 디스크 암호화 3경로 Block I/O 요청 (bio) 경로 1: dm-crypt (SW) CPU에서 AES-XTS 연산 AES-NI 가속 가능, 성능 10-30%↓ 키 관리: LUKS1/LUKS2 경로 2: blk-crypto (인라인 HW) 스토리지 컨트롤러 내 Crypto Engine UFS ICE, NVMe 인라인 암호화 성능 손실 0-2% 경로 3: SED/OPAL (드라이브 내부) 드라이브 자체 AES-256 암호화 TCG Opal 2.0 표준 성능 손실 0%, 완전 투명 Physical Disk NAS 권장: • 최고 성능: SED/OPAL (성능 손실 0%, 단 비밀번호 분실 시 복구 불가) • 유연한 키 관리: dm-crypt + AES-NI (LUKS2, 성능 10-30% 감소) | 모바일/임베디드: blk-crypto (UFS/eMMC 인라인 암호화)

3경로 성능 비교

방식암호화 위치CPU 부하성능 영향키 관리사용 사례
dm-crypt (AES-NI)블록 레이어 (CPU)중~높음10-30% 감소LUKS1/LUKS2범용 NAS, 유연한 키 관리 필요 시
blk-crypto스토리지 컨트롤러 HW없음0-2% 감소blk-crypto frameworkUFS/NVMe 인라인 암호화 지원 장치
SED/OPAL드라이브 내부없음0% (투명)TCG Opal (sedutil)최고 성능, 물리 보안 중심 NAS
⚠️ SED 비밀번호 분실: SED/OPAL 드라이브의 비밀번호를 분실하면 데이터 복구가 절대 불가능합니다. PSID(Physical Security ID)를 사용한 공장 초기화(Crypto Erase)만 가능하며, 이 경우 모든 데이터가 삭제됩니다. 비밀번호는 반드시 안전한 키 관리 시스템(KMS)에 별도 보관하세요.

blk_crypto_submit_bio() — 인라인 암호화 경로

커널 소스 분석: blk_crypto_submit_bio() — 블록 레이어 인라인 암호화

/* block/blk-crypto.c */
bool blk_crypto_submit_bio(struct bio **bio_ptr)
{
    struct bio *bio = *bio_ptr;
    struct bio_crypt_ctx *bc = bio->bi_crypt_context;
    struct blk_crypto_keyslot *keyslot;

    if (!bc)
        return true;  /* 암호화 컨텍스트 없으면 통과 */

    /*
     * 하드웨어가 이 암호화 프로파일을 지원하는지 확인
     * — 지원하면 인라인 HW 암호화 사용
     * — 미지원이면 blk-crypto-fallback (SW) 경로
     */
    if (!blk_crypto_config_supported_natively(
            bio->bi_bdev, &bc->bc_key->crypto_cfg)) {
        /* SW 폴백: dm-crypt 유사 방식으로 CPU 암호화 */
        return blk_crypto_fallback_submit_bio(bio_ptr);
    }

    /* 키슬롯 할당: HW 컨트롤러의 키 테이블에 키 프로그래밍 */
    keyslot = blk_crypto_get_keyslot(bc->bc_key,
                bio->bi_bdev);
    if (IS_ERR(keyslot)) {
        bio->bi_status = BLK_STS_IOERR;
        return false;
    }

    /* bio에 키슬롯 번호를 설정하여 HW 컨트롤러에 전달 */
    bio_crypt_set_keyslot(bio, keyslot);
    return true;  /* 정상 I/O 경로 계속 */
}
코드 설명
  • 핵심blk_crypto_submit_bio()는 블록 I/O가 제출될 때 호출되어 인라인 암호화를 처리합니다. bi_crypt_context가 설정된 bio에 대해, 먼저 HW 컨트롤러가 해당 암호화 알고리즘(AES-256-XTS 등)을 지원하는지 확인합니다. 지원하면 키를 HW 키슬롯에 프로그래밍하고 bio에 키슬롯 번호를 설정하여 컨트롤러가 데이터 경로에서 투명하게 암/복호화를 수행합니다. UFS/eMMC 인라인 암호화 엔진이나 NVMe 컨트롤러의 암호화 기능이 이 경로를 사용합니다. HW 미지원 시 blk_crypto_fallback이 CPU에서 암호화를 수행합니다.

dm-crypt 워커 스레드 아키텍처 (kcryptd)

dm-crypt는 Device Mapper 기반의 블록 레이어 암호화로, NAS에서 가장 널리 사용되는 전체 디스크 암호화 솔루션입니다. 내부적으로 여러 워커 스레드를 사용하여 암호화/복호화를 병렬 처리합니다.

# dm-crypt 워커 스레드 확인
ps aux | grep kcrypt
# root  kcryptd
# root  kcryptd_io
# root  kcryptd_crypt/0
# root  kcryptd_crypt/1
# root  kcryptd_crypt/2
# root  kcryptd_crypt/3

# dm-crypt 성능 튜닝
# 동시 I/O 요청 수 (기본값: 적절한 값 자동 설정)
dmsetup table --showkeys /dev/mapper/nas-crypt
# 0 976773168 crypt aes-xts-plain64  0 /dev/sda2 0

# submit_from_crypt_cpus 옵션으로 I/O 제출 스레드 분리
# → 암호화 스레드가 I/O 완료 대기를 하지 않아 처리량 향상
echo 1 > /sys/block/dm-0/dm/submit_from_crypt_cpus

# no_read_workqueue / no_write_workqueue (5.9+)
# → 워크큐 없이 직접 처리하여 지연시간 감소 (NVMe SSD 권장)
cryptsetup open --perf-no_read_workqueue --perf-no_write_workqueue \
    /dev/nvme0n1p2 nas-crypt

per-file Encryption (fscrypt) vs Full-disk Encryption 비교

NAS에서는 전체 디스크 암호화(FDE)와 파일 단위 암호화(fscrypt) 중 선택해야 합니다. 각 방식의 특성이 NAS 워크로드에 미치는 영향을 비교합니다.

항목dm-crypt (FDE)fscrypt (per-file)SED (FDE)
암호화 단위블록 디바이스 전체파일/디렉토리 단위드라이브 전체
메타데이터 보호전체 (파일명 포함)파일명 암호화 선택적전체 (투명)
성능 영향10~30% (AES-NI)5~15% (AES-NI)0% (투명)
키 관리LUKS1/LUKS2 (단일 키)파일별/디렉토리별 키TCG Opal (드라이브 키)
멀티 유저 격리불가 (단일 키)가능 (유저별 키)불가 (단일 키)
NAS 공유 폴더 적합성높음 (전체 볼륨)높음 (폴더별 키)최고 (성능 무손실)
지원 파일시스템모든 파일시스템ext4, F2FS, UBIFS모든 파일시스템
HW 가속AES-NI / blk-cryptoAES-NI / blk-crypto드라이브 내장 AES
Synology DSM의 선택: Synology NAS는 공유 폴더 단위 암호화에 eCryptfs(fscrypt 이전 세대)를 사용하고, 볼륨 단위 암호화에 dm-crypt/LUKS를 사용합니다. DSM 7.2+에서는 볼륨 암호화(dm-crypt)가 권장되며, AES-NI 지원 CPU에서 성능 손실이 10% 이내입니다.

LUKS2 vs LUKS1 — NAS 적합성 비교

LUKS(Linux Unified Key Setup)는 dm-crypt의 표준 키 관리 형식입니다. LUKS2는 LUKS1의 후속 버전으로 NAS 환경에서 상당한 장점을 제공합니다.

항목LUKS1LUKS2
헤더 형식바이너리JSON 메타데이터
최대 키슬롯8개32개
키 유도 함수PBKDF2Argon2id (메모리 하드)
무결성 보호없음dm-integrity 연동 (AEAD)
온라인 재암호화불가가능 (cryptsetup reencrypt)
토큰 지원없음FIDO2, TPM2, systemd-cryptenroll
헤더 크기2 MB (고정)16 MB (가변, 확장 가능)
NAS 권장레거시 호환신규 설치 기본값
# LUKS2 볼륨 생성 (NAS 최적화 설정)
cryptsetup luksFormat --type luks2 \
    --cipher aes-xts-plain64 \
    --key-size 512 \
    --hash sha256 \
    --pbkdf argon2id \
    --pbkdf-memory 1048576 \
    --pbkdf-parallel 4 \
    --sector-size 4096 \
    /dev/md0

# LUKS2 무결성 보호 활성화 (AEAD 모드)
cryptsetup luksFormat --type luks2 \
    --cipher aes-gcm-random \
    --integrity aead \
    /dev/md0

# 온라인 재암호화 (서비스 중단 없이 키 변경)
cryptsetup reencrypt /dev/mapper/nas-crypt \
    --cipher aes-xts-plain64 --key-size 512

# TPM2 자동 잠금해제 설정 (NAS 자동 부팅)
systemd-cryptenroll /dev/md0 --tpm2-device=auto --tpm2-pcrs=7
⚠️ Argon2id 메모리 요구: LUKS2의 Argon2id KDF는 키 유도 시 대량의 메모리를 사용합니다 (기본 1GB). 임베디드 NAS(RAM 2GB 이하)에서는 --pbkdf-memory를 512MB 이하로 설정하세요. 메모리 부족 시 잠금해제가 실패하거나 OOM이 발생할 수 있습니다.

네트워크 프로토콜 오프로드 — TSO/RDMA/TOE/iSER

NAS는 네트워크를 통해 클라이언트에 데이터를 전달하므로, 네트워크 프로토콜 처리가 전체 CPU 부하의 상당 부분을 차지합니다. 10GbE 이상 환경에서는 TCP 처리만으로 CPU 코어가 포화될 수 있습니다.

네트워크 오프로드 L2~L7 스택 네트워크 오프로드 계층별 정리 계층 SW 처리 (CPU) HW 오프로드 (NIC) 성능 효과 L2 CPU Checksum 계산 HW Checksum (NETIF_F_*CSUM) CPU 5-10%↓ L3/L4 CPU TCP 세그먼테이션 (GSO) TSO + LRO/GRO (NIC HW) CPU 20-40%↓ TCP 전체 커널 TCP/IP 스택 TOE (Linux에서 거부됨) ⚠️ 미채택 RDMA TCP 소켓 기반 전송 RDMA (RoCE v2 / iWARP) CPU 50%↓, 지연 10×↓ L7 TLS CPU TLS 암복호화 kTLS NIC 오프로드 CPU 30-50%↓ NAS 권장: TSO/GRO (기본) + RDMA/SMB Direct (고성능) + kTLS (SMB3 암호화 가속)

RDMA 프로토콜 비교

프로토콜전송 계층Lossless 필요대표 NICNAS 사용 사례
RoCE v2UDP/IPPFC/ECN 필수ConnectX-6/7, BCM57508SMB Direct, NFS/RDMA
iWARPTCP/IP불필요Chelsio T6, Intel E810기존 네트워크 호환 RDMA
InfiniBandIB Native자체 Flow ControlConnectX-7 (IB)HPC 스토리지, 대규모 클러스터
TOE가 Linux에서 거부된 이유: TOE(TCP Offload Engine)는 전체 TCP 스택을 NIC 펌웨어에서 실행하므로, 커널의 TCP 최적화(BPF, congestion control, etc.)와 보안 패치를 적용할 수 없습니다. Linux 커뮤니티는 이를 "black box" 접근으로 간주하여 거부했으며, 대신 TSO/GRO 같은 부분 오프로드를 채택했습니다. RDMA는 별도의 프로토콜이므로 이 문제가 없습니다.

RDMA Queue Pair — 커널 QP 생성 경로

커널 소스 분석: rdma_create_qp() — RDMA Queue Pair 생성

/* drivers/infiniband/core/cma.c */
int rdma_create_qp(struct rdma_cm_id *id,
                   struct ib_pd *pd,
                   struct ib_qp_init_attr *qp_init_attr)
{
    struct rdma_id_private *id_priv;
    struct ib_qp *qp;
    int ret;

    id_priv = container_of(id, struct rdma_id_private, id);

    /*
     * Queue Pair 생성:
     * - Send Queue (SQ): RDMA Write/Send 요청 게시
     * - Receive Queue (RQ): 수신 버퍼 사전 등록
     * - Completion Queue (CQ): 완료 이벤트 수신
     */
    qp = ib_create_qp(pd, qp_init_attr);
    if (IS_ERR(qp))
        return PTR_ERR(qp);

    /* QP를 RDMA CM ID에 연결 */
    id->qp = qp;
    id_priv->qp_num = qp->qp_num;

    /* QP를 INIT 상태로 전환 */
    ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask);
    if (ret)
        goto err;

    ret = ib_modify_qp(qp, &qp_attr, qp_attr_mask);
    if (ret)
        goto err;

    return 0;
err:
    ib_destroy_qp(qp);
    return ret;
}
코드 설명
  • 핵심rdma_create_qp()는 RDMA 통신의 핵심 자료구조인 Queue Pair(QP)를 생성합니다. QP는 Send Queue(SQ)와 Receive Queue(RQ)로 구성되며, 각 큐에 Work Request(WR)를 게시하여 제로카피(zero-copy) 데이터 전송을 수행합니다. NAS에서 SMB Direct나 NFS/RDMA를 사용할 때 이 경로를 통해 QP가 생성됩니다. ib_create_qp()는 HW 드라이버(mlx5, bnxt_re 등)의 create_qp 콜백을 호출하여 NIC의 하드웨어 QP 자원을 할당합니다. QP는 INIT → RTR(Ready to Receive) → RTS(Ready to Send) 상태 전환을 거쳐 데이터 전송이 가능해집니다.

SMB Direct 프로토콜 흐름

SMB Direct는 SMB3 프로토콜을 RDMA 전송 계층 위에서 실행하는 Windows/Linux 호환 프로토콜입니다. ksmbd(커널 SMB 서버) 또는 Samba가 RDMA NIC을 통해 클라이언트와 직접 메모리 전송을 수행하여, TCP 대비 지연시간을 10배 이상 단축하고 CPU 부하를 50% 이상 절감합니다.

# ksmbd SMB Direct 설정
# 1. RDMA NIC 확인
rdma link show
# link mlx5_0/1 state ACTIVE physical_state LINK_UP netdev enp1s0f0

# 2. ksmbd SMB Direct 활성화
cat /etc/ksmbd/ksmbd.conf
# [global]
#   server string = NAS-RDMA
#   smb2 max read = 8388608
#   smb2 max write = 8388608
#   smbd max io size = 1048576
#   interfaces = enp1s0f0

# 3. SMB Direct 연결 확인
smbstatus --shares
# PID     Username   Group     Machine     Protocol  Encryption  Signing  Transport
# 1234    user1      users     client1     SMB3_11   -           AES-128  RDMA

NFS over RDMA 설정과 성능

NFS/RDMA(RFC 8267)는 NFS 프로토콜의 RPC 전송 계층을 TCP 대신 RDMA로 교체하는 기술입니다. 커널 NFS 서버(nfsd)와 NFS 클라이언트 모두 RDMA를 지원하며, 특히 대용량 순차 I/O 워크로드에서 TCP 대비 현저한 성능 향상을 보입니다.

# NFS 서버: RDMA 전송 활성화
# 1. 필요 모듈 로드
modprobe svcrdma    # 서버측 RDMA 전송
modprobe xprtrdma   # 클라이언트측 RDMA 전송

# 2. NFS 서버 RDMA 포트 활성화 (기본 20049)
echo "rdma 20049" > /proc/fs/nfsd/portlist

# 3. NFS export 설정 (일반 NFS와 동일)
cat /etc/exports
# /srv/nas  10.0.0.0/24(rw,sync,no_subtree_check)

# NFS 클라이언트: RDMA 마운트
mount -t nfs -o rdma,port=20049,vers=4.2 \
    nas-server:/srv/nas /mnt/nas-rdma

# 성능 확인
nfsstat -c   # 클라이언트 RPC 통계
nfsiostat    # NFS I/O 통계
워크로드NFS/TCP (25GbE)NFS/RDMA (25GbE RoCEv2)성능 향상
순차 읽기 (1MB)~2.8 GB/s~3.1 GB/s+11%
순차 쓰기 (1MB)~2.2 GB/s~2.9 GB/s+32%
랜덤 4K 읽기 IOPS~180K~280K+56%
랜덤 4K 쓰기 IOPS~90K~150K+67%
CPU 사용률 (서버)~65%~30%-54%
평균 지연시간 (4K)~120us~45us-63%

iSER — iSCSI Extensions for RDMA

iSER(iSCSI Extensions for RDMA, RFC 7145)는 iSCSI 프로토콜의 데이터 전송 계층을 RDMA로 교체합니다. iSCSI의 TCP 오버헤드(헤더 다이제스트, 데이터 다이제스트, 버퍼 복사)를 제거하여 NAS의 블록 스토리지 서비스 성능을 극대화합니다.

# iSER 타겟 설정 (LIO)
modprobe ib_isert
targetcli
/> /iscsi create iqn.2024-01.com.nas:storage
/> /iscsi/iqn.2024-01.com.nas:storage/tpg1/portals create 0.0.0.0 3260
# iSER은 동일한 포트에서 자동 협상됨

# iSER 이니시에이터 설정
modprobe ib_iser
iscsiadm -m discovery -t st -p nas-server:3260
iscsiadm -m node -T iqn.2024-01.com.nas:storage \
    -o update -n iface.transport_name -v iser
iscsiadm -m node -T iqn.2024-01.com.nas:storage --login

# iSER 연결 확인
iscsiadm -m session -P 3 | grep Transport
# iface.transport_name = iser
iSER vs NVMe-oF RDMA: iSER은 기존 iSCSI 인프라와의 호환성이 장점이지만, iSCSI 프로토콜 오버헤드가 여전히 존재합니다. 신규 구축 시에는 NVMe-oF/RDMA가 프로토콜 오버헤드가 적고 멀티큐를 네이티브로 지원하여 더 높은 성능을 제공합니다. 레거시 환경에서는 iSER이 마이그레이션 비용을 줄이는 좋은 선택입니다.

RoCEv2 네트워크 설정 가이드

RoCEv2(RDMA over Converged Ethernet v2)는 UDP/IP 위에서 RDMA를 제공하며, NAS RDMA 배포에서 가장 널리 사용됩니다. Lossless fabric 설정이 핵심이며, 잘못 구성하면 TCP보다 나쁜 성능을 보일 수 있습니다.

# 1. PFC(Priority Flow Control) 설정
# NIC 측 설정 (mlx5)
mlnx_qos -i enp1s0f0 --pfc 0,0,0,1,0,0,0,0
# → 우선순위 3에 PFC 활성화

# 2. ECN(Explicit Congestion Notification) 활성화
echo 1 > /sys/class/net/enp1s0f0/ecn/enable/3

# 3. DSCP/PCP 매핑
mlnx_qos -i enp1s0f0 --trust=dscp
# RDMA 트래픽에 DSCP 26 (CS4) 할당

# 4. MTU 설정 (Jumbo Frame)
ip link set enp1s0f0 mtu 9000
# 모든 경로(NIC, 스위치)에서 동일한 MTU 필수!

# 5. RoCEv2 모드 확인 및 설정
cma_roce_mode -d mlx5_0 -p 1 -m 2    # 모드 2 = RoCEv2
cat /sys/class/infiniband/mlx5_0/ports/1/gid_attrs/types/0
# RoCE v2

# 6. RDMA 연결 테스트
rdma link show
# link mlx5_0/1 state ACTIVE physical_state LINK_UP netdev enp1s0f0
rping -c -a nas-server -v    # RDMA ping 테스트

# 7. 스위치 설정 (Cisco Nexus 예시)
# interface Ethernet1/1
#   priority-flow-control mode on
#   priority-flow-control priority 3 no-drop
#   mtu 9216
#   no shutdown
⚠️ PFC Deadlock: PFC가 여러 포트에서 동시에 활성화되면 순환 의존성으로 인해 PFC deadlock(PFC storm)이 발생할 수 있습니다. PFC watchdog를 활성화하여 deadlock을 자동 감지하고 해제하세요. 대규모 환경에서는 PFC 대신 ECN만으로 충분한 경우도 있습니다. ConnectX-7은 adaptive routing으로 PFC 의존성을 줄일 수 있습니다.

스토리지 프로토콜 HW 가속 — NVMe-oF/iSCSI HBA/FC HBA

NAS가 백엔드 스토리지에 접근하거나 블록 서비스를 제공할 때, 스토리지 프로토콜 처리를 전용 HBA(Host Bus Adapter)로 오프로드할 수 있습니다.

스토리지 프로토콜 오프로드 비교 스토리지 프로토콜 오프로드 4단계 SW iSCSI (open-iscsi) TCP: 커널 스택 iSCSI PDU: iscsid (유저) 데이터: CPU bounce CPU 부하: 높음 HW iSCSI HBA TCP: HW TOE (Chelsio T6) iSCSI PDU: HW 처리 데이터: HW DMA CPU 부하: 낮음 FC HBA FC 프로토콜: HW 전용 FCP/SCSI: 펌웨어 64Gbps SAN 연결 CPU 부하: 매우 낮음 NVMe-oF RNIC RDMA: HW (ConnectX-7) NVMe capsule: RNIC zero-copy DMA CPU 부하: 최소 오프로드 수준 증가 → 주요 드라이버 iscsi_tcp, libiscsi cxgb4i, bnx2i, qla4xxx lpfc, qla2xxx nvme-rdma, nvme-tcp, nvme-fc NAS 시나리오 iSCSI LUN 제공 SAN 백엔드 연결 NVMe 확장 쉘프

NVMe-oF 전송 계층 비교

NVMe over Fabrics(NVMe-oF)는 NVMe 프로토콜을 네트워크로 확장하여 원격 NVMe SSD에 로컬과 동일한 지연시간으로 접근합니다. NAS의 스토리지 확장과 disaggregated storage 아키텍처에 핵심적입니다.

전송 계층대역폭지연시간CPU 부하필요 HWNAS 적합성
NVMe-oF/RDMA100+ Gbps~10μs최소RDMA NIC (ConnectX-7)최고 (고성능 NAS)
NVMe-oF/TCP100 Gbps~50μs중간일반 NIC높음 (범용)
NVMe-oF/FC64 Gbps~15μs최소FC HBASAN 환경
# NVMe-oF/RDMA 타겟 상세 설정
modprobe nvmet
modprobe nvmet-rdma

# 서브시스템 생성
mkdir -p /sys/kernel/config/nvmet/subsystems/nqn.nas-storage
cd /sys/kernel/config/nvmet/subsystems/nqn.nas-storage
echo 1 > attr_allow_any_host

# NVMe 네임스페이스 추가
mkdir namespaces/1
echo -n /dev/nvme0n1 > namespaces/1/device_path
echo 1 > namespaces/1/enable

# RDMA 포트 바인딩
mkdir -p /sys/kernel/config/nvmet/ports/1
echo "rdma" > /sys/kernel/config/nvmet/ports/1/addr_trtype
echo "10.0.0.1" > /sys/kernel/config/nvmet/ports/1/addr_traddr
echo "4420" > /sys/kernel/config/nvmet/ports/1/addr_trsvcid
echo "ipv4" > /sys/kernel/config/nvmet/ports/1/addr_adrfam
ln -s /sys/kernel/config/nvmet/subsystems/nqn.nas-storage \
    /sys/kernel/config/nvmet/ports/1/subsystems/

# 이니시에이터 연결
nvme discover -t rdma -a 10.0.0.1 -s 4420
nvme connect -t rdma -a 10.0.0.1 -s 4420 \
    -n nqn.nas-storage --nr-io-queues=16

iSCSI HBA vs SW iSCSI 성능 비교

항목SW iSCSI (open-iscsi)HW iSCSI (Chelsio T6)NVMe-oF/RDMA
순차 읽기~2 GB/s (25GbE)~2.8 GB/s (25GbE)~3.1 GB/s (25GbE)
랜덤 4K IOPS~150K~250K~400K
CPU 사용률60~80%10~20%5~10%
지연시간~200μs~80μs~15μs
TCP 오프로드커널 TCPFull TOERDMA (TCP 없음)
I/O 큐단일 세션 큐다중 HW 큐NVMe 멀티큐

FC HBA NAS 백엔드 연결

엔터프라이즈 NAS는 클라이언트에 NFS/SMB를 제공하면서, 백엔드 스토리지에는 FC(Fibre Channel) SAN으로 연결합니다. FC HBA는 FCP(Fibre Channel Protocol) 처리를 전용 ASIC에서 수행하여 CPU를 파일 서비스에 집중시킵니다.

# FC HBA 확인
lspci | grep Fibre
# 81:00.0 Fibre Channel: Broadcom LPe35002 32Gb 2-port

# FC 포트 상태 확인
cat /sys/class/fc_host/host0/port_state
# Online

# WWPN 확인 (SAN 조닝에 필요)
cat /sys/class/fc_host/host0/port_name
# 0x100000109b1234ab

# 멀티패스 설정
multipath -ll
# mpath0 (3600508b4000...) dm-2 LSI,INF-01-00
# size=1.0T features='1 queue_if_no_path' hwhandler='1 rdac'
#  |-+- policy='service-time 0' prio=14 status=active
#  | `- 0:0:0:0 sda 8:0   active ready running
#  `-+- policy='service-time 0' prio=9 status=enabled
#    `- 1:0:0:0 sdb 8:16  active ready running

압축 HW 가속 — QAT deflate/lz4, crypto_comp API

NAS에서 백업 데이터 압축, 파일시스템 투명 압축(Btrfs, ZFS), 네트워크 전송 압축 등에 하드웨어 압축 가속기를 활용하면 CPU 부하를 극적으로 줄일 수 있습니다.

QAT 압축 파이프라인 QAT 압축 가속 파이프라인 Application crypto_acomp API qat_comp 드라이버 QAT HW Engine 압축 데이터 SW vs QAT HW 압축 성능 비교 방식 처리량 CPU 사용률 지연시간 적합 시나리오 SW deflate (1 core) ~200 MB/s 100% ~5ms 소규모 백업 QAT deflate (C62x) ~10 GB/s <5% ~1ms 대용량 백업, 중복제거 SW lz4 (1 core) ~800 MB/s 100% ~1ms 실시간 파일시스템 QAT lz4 (4xxx) ~20 GB/s <5% ~0.5ms NVMe 전용 NAS

crypto_acomp API — 비동기 압축 인터페이스

커널 소스 분석: crypto_acomp_compress() — 비동기 HW 압축 API

/* include/crypto/acompress.h */
static inline int crypto_acomp_compress(
    struct acomp_req *req)
{
    struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
    struct crypto_alg *alg = tfm->base.__crt_alg;
    struct comp_alg_common *calg;

    calg = container_of(alg, struct comp_alg_common, base);

    /*
     * 비동기 압축 요청:
     * - req->src: 원본 데이터 (scatterlist)
     * - req->dst: 압축 결과 버퍼 (scatterlist)
     * - req->slen: 원본 길이
     * - req->dlen: 결과 버퍼 크기
     *
     * QAT 드라이버의 경우:
     * qat_comp_alg_compress() → adf_send_message()
     * → QAT HW 엔진에 DMA 전송 → 완료 콜백
     */
    return calg->compress(req);
}

/* 사용 예시: QAT 압축 요청 */
struct crypto_acomp *acomp;
struct acomp_req *req;

acomp = crypto_alloc_acomp("deflate", 0, 0);
req = acomp_request_alloc(acomp);

/* 콜백 설정 (비동기 완료 통지) */
acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
    compress_done_callback, &wait);

/* 소스/대상 버퍼 설정 */
acomp_request_set_params(req, src_sg, dst_sg,
    src_len, dst_len);

/* 비동기 압축 제출 */
ret = crypto_acomp_compress(req);
if (ret == -EINPROGRESS || ret == -EBUSY)
    wait_for_completion(&wait);  /* HW 완료 대기 */
코드 설명
  • 핵심crypto_acomp_compress()는 커널의 비동기 압축(acomp) API 진입점입니다. 동기식 crypto_comp와 달리 비동기로 동작하여 HW 가속기의 병렬 처리를 활용합니다. QAT 드라이버가 등록되어 있으면 qat_comp_alg_compress()가 호출되어 데이터를 QAT 엔진으로 DMA 전송하고, 압축 완료 시 콜백을 호출합니다. 이 비동기 모델 덕분에 CPU는 압축 대기 없이 다른 NAS 요청을 처리할 수 있습니다. scatterlist 기반이므로 비연속 페이지에 대해서도 추가 복사 없이 압축이 가능합니다.

QAT 인스턴스 관리와 동시 요청

QAT 장치는 여러 개의 인스턴스(instance)를 제공하며, 각 인스턴스는 독립적인 링 버퍼(ring pair)를 가집니다. NAS에서 다수의 동시 압축 요청을 효율적으로 처리하려면 인스턴스 할당과 부하 분산을 적절히 구성해야 합니다.

# QAT 장치 및 인스턴스 상태 확인
adf_ctl status
# qat_dev0 - type: 4xxx, bsf: 0000:6b:00.0, state: up
# qat_dev1 - type: 4xxx, bsf: 0000:70:00.0, state: up

# 인스턴스 설정 파일
cat /etc/4xxx_dev0.conf
# [GENERAL]
# ServicesEnabled = dc     # dc=압축, cy=암호화, sym=대칭, asym=비대칭
#
# [KERNEL]
# NumberDcInstances = 2
# NumConcurrentSymRequests = 512
# NumConcurrentAsymRequests = 64
#
# [SHIM]
# NumberDcInstances = 2    # 사용자 공간 인스턴스

# QAT 서비스 재시작
adf_ctl restart

# 성능 카운터 확인
cat /sys/kernel/debug/qat_4xxx_0000:6b:00.0/fw_counters

Btrfs/ZFS QAT 연동 상태

NAS 파일시스템의 투명 압축 기능과 QAT HW 가속의 연동 상태는 파일시스템마다 다릅니다.

파일시스템QAT 지원지원 알고리즘구현 방식비고
ZFS (OpenZFS)지원gzip, lz4qat_compress / qat_checksum 모듈zfs set compression=gzip + QAT 자동 사용
Btrfs미지원-SW 전용 (zstd/lzo/zlib)커널 crypto API 연동 미구현
dm-VDO간접 지원lz4커널 crypto API 경유QAT lz4 드라이버 등록 시 자동 사용
SquashFS간접 지원zlib, lz4, zstd커널 crypto API 경유읽기 전용, 압축 해제만
# ZFS QAT 압축 활성화
# 1. QAT 모듈 로드
modprobe qat_4xxx        # QAT 장치 드라이버
modprobe qat_common      # QAT 공통 프레임워크

# 2. ZFS QAT 모듈 활성화
echo 1 > /sys/module/zfs/parameters/zfs_qat_compress_disable
# 0 = QAT 활성화, 1 = QAT 비활성화 (기본값은 설치에 따라 다름)

# 3. ZFS 풀에 gzip 압축 설정 (QAT 자동 사용)
zfs set compression=gzip-6 tank/nas-data

# 4. QAT 압축 동작 확인
zpool iostat -v tank
cat /proc/spl/kstat/zfs/qat
# qat_comp_requests:     1234567
# qat_comp_total_in:     500 GB
# qat_comp_total_out:    200 GB (60% 압축률)

압축 알고리즘 선택 가이드

NAS 워크로드에 따라 최적의 압축 알고리즘이 달라집니다. CPU 사용률, 압축률, 지연시간의 트레이드오프를 고려해야 합니다.

알고리즘압축률압축 속도 (SW)해제 속도CPU 부하QAT 가속적합 워크로드
lz4낮음 (~2:1)~800 MB/s~4 GB/s낮음지원실시간 파일 서비스, NVMe SSD
zstd (level 1-3)중간 (~3:1)~500 MB/s~1.5 GB/s중간미지원범용 NAS 스토리지
zstd (level 10+)높음 (~4:1)~50 MB/s~1.5 GB/s높음미지원콜드 아카이브
deflate/gzip중간 (~3:1)~200 MB/s~400 MB/s높음지원QAT 가속 시 대용량 백업
lzo낮음 (~2:1)~600 MB/s~900 MB/s낮음미지원레거시 Btrfs
NAS 압축 전략 권장:
  • NVMe 전용 NAS: lz4 (지연시간 최소화, SSD 수명 절약)
  • HDD 기반 대용량 NAS: zstd level 3 (최적의 압축률/속도 균형)
  • QAT 장착 NAS: deflate/gzip (QAT HW 가속으로 CPU 무부하 고압축)
  • 백업/아카이브: zstd level 15+ 또는 QAT deflate (저장 공간 최소화)

중복제거와 HW 가속 — VDO, SHA-256 HW

VDO(Virtual Data Optimizer)는 Linux 커널에 통합된 인라인 중복제거 + 압축 솔루션입니다. 블록 단위로 SHA-256 해시를 계산하여 중복 데이터를 탐지하며, CPU의 SHA Extensions(Intel SHA-NI, ARM CE)를 활용하면 해시 계산 속도가 ~3배 향상됩니다.

VDO 중복제거 데이터 경로와 HW 가속 포인트 VDO 인라인 중복제거 + 압축 데이터 경로 BIO (4KB 블록) ① SHA-256 해시 계산 SHA-NI / sha256-ce HW 가속 ⚡ CPU 사용률 40% → 15% ② UDS 인덱스 조회 메모리 상주 (TB당 ~1GB) Sparse + Dense Index 2단계 중복? ③a 참조 카운트 증가 데이터 쓰기 없음 (0 I/O) YES ③b 압축 (lz4/zlib) QAT HW 가속 가능 NO ⚡ QAT: 2~5× 압축 처리량 ④ 물리 블록 쓰기 Slab 할당 → 디스크 VDO 내부 메모리 구조 UDS Sparse Index Chapter 기반 LRU 캐시 최근 접근 해시 빠른 조회 UDS Dense Index 전체 해시 → PBN 매핑 디스크 기반 (TB당 ~1GB RAM) Block Map LBN → PBN 논리/물리 매핑 트리 구조, 페이지 캐시 활용 Slab Allocator 물리 블록 할당/해제 Reference Count 관리 = HW 가속 가능 구간 = 중복 블록 (I/O 절약) = 비중복 블록 (압축 후 저장) 중복률 50%인 NAS 백업에서 VDO는 물리 I/O를 절반으로 줄이고, SHA-NI + QAT로 CPU 오버헤드를 최소화합니다

VDO 구성과 성능 튜닝

# VDO 볼륨 생성 (1TB 물리 → 3TB 논리)
vdo create --name=nas-dedup \
    --device=/dev/md0 \
    --vdoLogicalSize=3T \
    --vdoSlabSize=32G \
    --writePolicy=auto

# VDO 위에 파일시스템 생성
mkfs.xfs -K /dev/mapper/nas-dedup
mount /dev/mapper/nas-dedup /srv/nas-backup

# VDO 통계 확인
vdostats --human-readable
# Device             1K-blocks   Used    Available Use%  Space saving%
# nas-dedup          1073741824  214748  858993459  20%  68%

# SHA-256 HW 가속 확인
grep -i sha /proc/cpuinfo | head -1
# flags : ... sha_ni ...

# 커널 crypto API에서 사용 중인 SHA 구현 확인
cat /proc/crypto | grep -A4 "name.*sha256"
# name         : sha256
# driver       : sha256-ni
# module       : sha256_ssse3
# priority     : 250

VDO 데이터 경로와 HW 가속 포인트

VDO 커널 내부 — dm_vdo_target 구조

dm-vdo는 Device Mapper 타겟으로 커널에 통합되어, vdo_map_bio()가 BIO를 수신하면 해시 계산 → UDS 조회 → 중복/비중복 분기를 수행합니다. 핵심 자료구조와 흐름을 살펴봅니다.

/* drivers/md/dm-vdo/vdo.c (커널 6.9+) */
/* VDO의 BIO 처리 핵심 경로 */
static int vdo_map_bio(struct dm_target *ti, struct bio *bio)
{
    struct vdo *vdo = get_vdo_for_target(ti);
    struct data_vio *data_vio;

    /* data_vio: VDO의 I/O 추적 단위 (4KB 블록 1개에 대응) */
    data_vio = allocate_data_vio(vdo, bio);
    if (IS_ERR(data_vio))
        return DM_MAPIO_KILL;

    /*
     * 쓰기 경로: hash → UDS dedupe 조회 → 압축 → 물리 쓰기
     * 읽기 경로: Block Map에서 LBN→PBN 변환 → 물리 읽기 → 압축해제
     */
    if (bio_data_dir(bio) == WRITE)
        launch_write_data_vio(data_vio);  /* 비동기 파이프라인 시작 */
    else
        launch_read_data_vio(data_vio);

    return DM_MAPIO_SUBMITTED;
}
코드 설명

vdo_map_bio()는 Device Mapper의 map 콜백으로, 상위 파일시스템에서 내려오는 BIO를 가로채 VDO 파이프라인에 넣습니다. 각 4KB 블록은 data_vio라는 추적 구조체로 래핑되어, 해시 → 중복검사 → 압축 → 쓰기 단계를 비동기로 진행합니다. DM_MAPIO_SUBMITTED를 반환하면 DM은 BIO 완료를 VDO에게 위임합니다.

UDS 인덱스 — 해시 조회와 Sparse/Dense 모드

UDS(Universal Deduplication Service)는 SHA-256 해시를 키로 사용하여 블록의 물리 위치(PBN)를 조회합니다. 두 가지 인덱스 모드를 제공합니다.

인덱스 모드RAM 사용조회 속도커버리지NAS 권장 시나리오
DenseTB당 ~1GB빠름 (메모리 기반)전체 해시백업 NAS (높은 중복률)
SparseTB당 ~250MB보통 (디스크 참조)최근 + 빈번 해시범용 NAS (메모리 제한)
/* drivers/md/dm-vdo/indexer/index-session.c */
/*
 * UDS 해시 조회 API: 블록의 SHA-256 해시로 중복 여부 확인
 * 반환: UDS_SUCCESS + found=true → 중복, found=false → 신규
 */
int uds_index_session_lookup(struct uds_index_session *session,
                             const struct uds_record_name *name,
                             const struct uds_record_data *old_metadata,
                             struct uds_record_data *new_metadata,
                             bool *found)
{
    /* 1. Sparse Volume Index에서 빠른 조회 (LRU 캐시) */
    /* 2. 실패 시 Dense Index 디스크 참조 */
    /* 3. 해시 collision 방지: 전체 32바이트 SHA-256 비교 */
    ...
}
코드 설명

UDS의 해시 조회는 2단계로 진행됩니다. 먼저 Sparse Index의 LRU 캐시(메모리 상주)에서 빠른 조회를 시도하고, 미스 시 Dense Index(디스크 기반)를 참조합니다. found가 true이면 old_metadata에 기존 블록의 PBN이 담기고, VDO는 데이터 쓰기를 건너뛰고 참조 카운트만 증가시킵니다. NAS 백업 워크로드에서 중복률이 높으면 물리 I/O가 크게 줄어듭니다.

SHA-256 HW 가속 — Crypto API와 SHA-NI 내부

VDO의 해시 계산은 Linux Crypto API를 통해 수행됩니다. SHA-NI(Intel)나 SHA-CE(ARM) 확장이 있으면 자동으로 하드웨어 가속이 적용되며, priority 값이 높은 구현이 선택됩니다.

/* arch/x86/crypto/sha256_ssse3_glue.c */
static struct shash_alg sha256_ni_alg = {
    .digestsize     = SHA256_DIGEST_SIZE,     /* 32 bytes */
    .init           = sha256_ni_init,
    .update         = sha256_ni_update,       /* SHA-NI 명령어 사용 */
    .final          = sha256_ni_final,
    .base           = {
        .cra_name       = "sha256",
        .cra_driver_name = "sha256-ni",
        .cra_priority    = 250,   /* SW(100)보다 높아 자동 선택 */
        .cra_blocksize   = SHA256_BLOCK_SIZE, /* 64 bytes */
        .cra_module      = THIS_MODULE,
    }
};
/*
 * SHA-NI 명령어: sha256rnds2, sha256msg1, sha256msg2
 * 4KB 블록 해시: SW ~180 cycles/byte → NI ~7 cycles/byte (~25× 가속)
 * VDO가 초당 처리하는 4KB 블록: SW ~100K → NI ~400K
 */
코드 설명

SHA-NI 구현은 cra_priority가 250으로 SW 구현(100)보다 높아, Crypto API가 자동으로 SHA-NI를 선택합니다. VDO는 들어오는 모든 4KB 블록에 대해 crypto_shash_digest()를 호출하며, SHA-NI가 있으면 sha256rnds2 등 전용 x86 명령어로 해시를 계산합니다. NAS에서 1GB/s 쓰기 시 초당 약 256K 블록의 해시를 계산해야 하므로, SHA-NI 가속이 VDO 성능에 결정적인 영향을 미칩니다.

VDO 워크로드SW SHA-256SHA-NI (HW)SHA-NI + QAT 압축
순차 쓰기 처리량~400 MB/s~800 MB/s~1.2 GB/s
CPU 사용률 (4코어)~90%~45%~20%
중복제거 오버헤드높음중간낮음
4K 랜덤 쓰기 IOPS~15K~35K~50K
해시 계산 지연 (4KB)~4.5 μs~0.18 μs~0.18 μs

VDO 모니터링과 튜닝 실전

# VDO 상세 통계 — 중복제거 효율 확인
vdostats --verbose nas-dedup
# data blocks used        : 52428800
# overhead blocks used    : 1048576
# logical blocks          : 157286400
# savings percent         : 67%           ← 중복제거 + 압축 절약률

# VDO sysfs 실시간 모니터링
cat /sys/kvdo/nas-dedup/statistics/dedupe_advice_valid
# 중복으로 판정된 블록 수 (UDS 히트)
cat /sys/kvdo/nas-dedup/statistics/dedupe_advice_stale
# 스테일 어드바이스 (PBN 재활용 후 해시 충돌)
cat /sys/kvdo/nas-dedup/statistics/compressed_fragments_written
# 압축되어 저장된 프래그먼트 수

# VDO 스레드 튜닝 (NAS 코어 수에 맞춤)
# 해시 스레드: SHA-256 해시 계산 전담
# 논리 스레드: Block Map 관리
# 물리 스레드: Slab 할당/해제
vdo modify --name=nas-dedup \
    --vdoHashZoneThreads=2 \
    --vdoLogicalThreads=2 \
    --vdoPhysicalThreads=1

# VDO + dm-crypt 스택 (암호화 + 중복제거)
# 순서 중요: dm-crypt 아래에 VDO 배치 (암호화 전 중복제거)
# 잘못: 디스크 → VDO → dm-crypt → FS (암호화된 데이터는 중복제거 불가)
# 올바름: 디스크 → dm-crypt → VDO → FS (평문 블록 중복제거 후 암호화)
#   ※ 단, 이 경우 dm-crypt가 VDO 아래이므로 물리적으로 이 구성 불가
#   → 실제로는 SED + VDO 조합이 최적 (HW 암호화 + SW 중복제거)
ZFS 중복제거 vs VDO: ZFS의 인라인 중복제거는 블록당 DDT(Dedup Table) 엔트리를 ARC(메모리 캐시)에 유지해야 하므로 메모리 사용량이 매우 높습니다(TB당 ~5GB RAM). 메모리 제한이 있는 NAS에서는 VDO가 더 적합합니다. 다만, ZFS는 SHA-256 + XXHash128 이중 해시로 collision 안전성이 높습니다.
dm-vdo vs 독립형 VDO: RHEL 9 / 커널 6.9+에서 VDO는 dm-vdo Device Mapper 타겟으로 커널에 완전 통합되었습니다. 기존의 vdo 사용자 공간 도구 대신 lvcreate --type vdo로 LVM에서 직접 VDO 볼륨을 생성합니다. 커널 통합 버전은 사용자 공간 데몬이 불필요하여 부팅 의존성이 줄고, 커널 BIO 경로에서 직접 동작하므로 컨텍스트 스위칭 오버헤드도 감소합니다.

GPU/NPU 미디어 가속 — QSV, V4L2, NPU 커널 경로

미디어 NAS(Synology, QNAP 등)에서 실시간 트랜스코딩은 CPU 부하가 매우 높은 작업입니다. GPU/NPU 가속을 통해 CPU를 파일 서비스에 집중시킬 수 있습니다.

미디어 트랜스코딩 경로 미디어 트랜스코딩 경로 비교 SW: File → FFmpeg CPU decode → CPU filter → CPU encode → Output 12+ cores QSV: File → VAAPI/QSV HW decode (i915) → GPU filter → HW encode → Output <1 core V4L2: File → V4L2 M2M HW decode (SoC codec) → DMA → HW encode → Output <1 core QSV: Intel iGPU (J4125, N5105, i3-1215U) — Plex/Jellyfin 실시간 트랜스코딩 V4L2 M2M: ARM SoC (RK3588, S905X4) — 임베디드 NAS | NPU: Hailo-8, Intel Meteor Lake VPU — AI 기반 비디오 분석

Intel QSV 설정과 NAS 트랜스코딩

Intel Quick Sync Video(QSV)는 Intel CPU의 내장 GPU(iGPU)를 활용한 하드웨어 비디오 인코딩/디코딩 기술입니다. Celeron J4125, N5105부터 Core i3/i5까지 대부분의 Intel 프로세서가 QSV를 지원하며, NAS의 실시간 미디어 트랜스코딩에 핵심적인 역할을 합니다.

# Intel iGPU 확인
lspci | grep -i vga
# 00:02.0 VGA compatible controller: Intel Corporation Alder Lake-N [UHD Graphics]

# i915 드라이버 및 VAAPI 확인
ls /dev/dri/render*
# /dev/dri/renderD128

# VAAPI 지원 코덱 확인
vainfo --display drm --device /dev/dri/renderD128
# vainfo: Supported profile and target:
#   VAProfileH264Main            : VAEntrypointVLD
#   VAProfileH264Main            : VAEntrypointEncSlice
#   VAProfileHEVCMain            : VAEntrypointVLD
#   VAProfileHEVCMain            : VAEntrypointEncSlice
#   VAProfileAV1Profile0         : VAEntrypointVLD       # 12세대+

# FFmpeg QSV 트랜스코딩 (Plex/Jellyfin 내부 사용)
ffmpeg -hwaccel qsv -hwaccel_device /dev/dri/renderD128 \
    -i input.mkv \
    -c:v hevc_qsv -preset medium -global_quality 25 \
    -c:a copy output.mp4

# Docker 컨테이너에 GPU 패스스루
docker run -d --device=/dev/dri:/dev/dri \
    jellyfin/jellyfin:latest

NAS 미디어 가속 비교

가속기4K HEVC 트랜스코딩동시 1080p 스트림CPU 사용률전력 소비NAS 적합성
SW (x264, 4코어)~5 fps1~2개100%+65W낮음
Intel QSV (N5105)~30 fps8~12개<5%+5W높음
Intel QSV (i3-1215U)~60 fps15~20개<5%+10W최고
NVIDIA T400 (dGPU)~90 fps20~30개<2%+30W전문용
ARM V4L2 (RK3588)~30 fps8~12개<10%+3W임베디드

V4L2 M2M 커널 내부 — 임베디드 NAS HW 코덱

ARM 기반 NAS(Synology DS224+, QNAP TS-264 등)에서 비디오 트랜스코딩은 SoC 내장 코덱 IP를 V4L2 M2M(Memory-to-Memory) 인터페이스로 노출합니다. V4L2 M2M은 입력 큐(OUTPUT)와 출력 큐(CAPTURE)를 가진 비동기 파이프라인으로, 커널의 v4l2_m2m_ctx가 프레임 스케줄링을 관리합니다.

/* drivers/media/v4l2-core/v4l2-mem2mem.c */
/*
 * V4L2 M2M 디바이스 실행 — OUTPUT 큐에 인코딩할 프레임이 있고
 * CAPTURE 큐에 빈 버퍼가 있으면 HW 코덱 작업을 시작
 */
static void __v4l2_m2m_try_queue(struct v4l2_m2m_dev *m2m_dev,
                                 struct v4l2_m2m_ctx *m2m_ctx)
{
    /* OUTPUT 큐(원본 프레임)와 CAPTURE 큐(결과 버퍼) 확인 */
    if (list_empty(&m2m_ctx->out_q_ctx.rdy_queue) ||
        list_empty(&m2m_ctx->cap_q_ctx.rdy_queue))
        return;

    /*
     * 드라이버의 device_run 콜백 호출 → HW 코덱 시작
     * 예: rk3588_vpu_run(), hantro_run(), cedrus_run()
     */
    m2m_dev->m2m_ops->device_run(m2m_ctx->priv);
    /*
     * HW 코덱이 완료되면 인터럽트 핸들러에서
     * v4l2_m2m_buf_done()을 호출하여 CAPTURE 버퍼를
     * 사용자 공간에 반환 → 폴링으로 수신
     */
}

/* 코덱 세션당 처리량:
 * RK3588 Rkvdec2: 8K30/4K120 H.265 디코드
 * Hantro H1: 1080p60 H.264 인코드
 * Cedrus (Allwinner): 4K30 H.265 디코드
 */
코드 설명

__v4l2_m2m_try_queue()는 V4L2 M2M 프레임워크의 핵심 스케줄러입니다. OUTPUT 큐에 원본 프레임이 있고 CAPTURE 큐에 빈 버퍼가 있으면, 드라이버의 device_run() 콜백을 호출하여 SoC 코덱 IP에 작업을 제출합니다. ARM NAS에서 Plex/Jellyfin이 FFmpeg의 V4L2 M2M 백엔드를 사용하면, 이 경로를 통해 CPU 대신 SoC 코덱이 트랜스코딩을 처리합니다. RK3588 기반 NAS에서 CPU 사용률이 100%에서 10% 이하로 떨어집니다.

NPU 기반 AI 비디오 분석

최신 NAS는 단순 트랜스코딩을 넘어 AI 기반 비디오 분석(사물 인식, 얼굴 인식, 모션 감지)을 수행합니다. NPU(Neural Processing Unit)는 이러한 추론 워크로드를 CPU에서 분리합니다.

NAS AI 비디오 분석 파이프라인과 NPU/TPU 오프로드 NAS AI 비디오 분석 파이프라인 IP 카메라 RTSP H.264/265 HW 디코드 QSV / V4L2 M2M DMA-BUF NPU/TPU 추론 사물/얼굴/모션 감지 /dev/accel* | /dev/apex_0 메타데이터 DB 바운딩박스, 이벤트 NVMe 녹화 저장 연속 녹화 / 이벤트 녹화 NAS NPU/TPU 가속기 비교 가속기 성능 인터페이스 커널 드라이버 프레임워크 NAS 지원 Intel NPU (MTL) 11 TOPS 내장 (PCIe) intel_vpu OpenVINO Synology DSM Hailo-8 26 TOPS M.2 / PCIe hailo (misc) HailoRT QNAP QVR Pro Google Coral 4 TOPS USB / M.2 apex (gasket) TFLite Frigate NVR Hailo-8L 13 TOPS M.2 Key A+E hailo (misc) HailoRT Home Assistant CPU (SW 추론) ~0.5 TOPS - - OpenCV/ONNX NAS 부하↑↑ NPU 1개로 16채널 감시 카메라 AI 분석 가능 (CPU 대비 50배 효율)

DMA-BUF 제로카피 파이프라인 — GPU 디코드 → NPU 추론

NAS의 감시 시스템에서 최적의 성능을 얻으려면 GPU 디코더 출력을 시스템 메모리에 복사하지 않고 DMA-BUF를 통해 NPU에 직접 전달해야 합니다. 이 제로카피 파이프라인은 V4L2 M2M, VAAPI, DRM의 DMA-BUF 익스포트/임포트로 구현됩니다.

/* V4L2 M2M + DMA-BUF 제로카피 예시 (사용자 공간) */
#include <linux/videodev2.h>
#include <linux/dma-buf.h>

/* 1. V4L2 디코더: CAPTURE 버퍼를 DMA-BUF로 내보내기 */
struct v4l2_exportbuffer expbuf = {
    .type  = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
    .index = buf_idx,
    .flags = O_RDONLY,
};
ioctl(decoder_fd, VIDIOC_EXPBUF, &expbuf);
int dmabuf_fd = expbuf.fd;  /* DMA-BUF 파일 디스크립터 */

/*
 * 2. NPU에 DMA-BUF 전달 (제로카피)
 *    - Hailo: hailo_import_dmabuf(dmabuf_fd)
 *    - Coral: gasket_import_dmabuf(dmabuf_fd)
 *    - Intel NPU: VPU 드라이버 DMA-BUF 임포트
 *
 * 커널 내부 경로:
 *   V4L2 CAPTURE → dma_buf_export() → struct dma_buf
 *   NPU 드라이버 → dma_buf_attach() → dma_buf_map_attachment()
 *   → sg_table의 물리 주소를 NPU DMA 엔진에 프로그래밍
 *   → CPU 복사 없이 GPU 디코드 출력 → NPU 추론 입력
 */
코드 설명

V4L2 디코더의 CAPTURE 버퍼를 VIDIOC_EXPBUF로 DMA-BUF 파일 디스크립터로 내보냅니다. NPU 드라이버는 이 fd를 임포트하여 dma_buf_attach() + dma_buf_map_attachment()으로 SG 테이블을 얻고, 해당 물리 주소에서 직접 DMA로 데이터를 읽습니다. GPU → 시스템 메모리 → NPU의 2회 복사가 GPU → NPU 직접 전송으로 바뀌어, 16채널 감시 카메라 NAS에서 메모리 대역폭 병목을 제거합니다.

NAS 감시 시스템 NPU 설정 실전

# Google Coral TPU 설치 (Frigate NVR용)
# 1. PCIe M.2 Coral 드라이버 설치
apt install gasket-dkms
modprobe apex
ls /dev/apex_0    # Coral TPU 장치 확인

# 2. Docker에 Coral 패스스루
docker run -d --name frigate \
    --device /dev/apex_0:/dev/apex_0 \
    --device /dev/dri/renderD128:/dev/dri/renderD128 \
    -v /srv/nas/frigate:/media/frigate \
    ghcr.io/blakeblackshear/frigate:stable

# 3. Frigate 설정 (config.yml) — QSV 디코드 + Coral 추론
# detectors:
#   coral:
#     type: edgetpu
#     device: pci
# ffmpeg:
#   hwaccel_args: preset-vaapi  # Intel QSV HW 디코드

# Hailo-8 NPU 상태 확인
hailortcli fw-control identify
# Board Name: HAILO-8
# FW Version: 4.17.0
# Serial: xxxx

# Hailo-8 추론 벤치마크
hailortcli benchmark --hef yolov8s.hef
# FPS: 280 (YOLOv8s, 640×640, batch 8)
# Latency: 8.5ms (single frame)
# Power: ~2.5W

# Intel NPU 확인 (Meteor Lake+)
ls /dev/accel/accel0
cat /sys/class/accel/accel0/device/power/runtime_status
# active (추론 중) / suspended (유휴)

P2P DMA와 GPU Direct Storage

P2P(Peer-to-Peer) DMA는 NVMe SSD에서 GPU 메모리로 데이터를 CPU와 시스템 메모리를 경유하지 않고 직접 전송하는 기술입니다. AI/ML 학습 데이터 로딩이나 HPC 스크래치 파일시스템에서 활용됩니다.

P2P DMA vs 전통적 I/O 경로 비교 P2P DMA vs 전통적 I/O 경로 비교 전통적 경로: read() + cudaMemcpy() — CPU/메모리 경유 NVMe SSD PCIe Gen4 x4 시스템 메모리 DDR5 페이지 캐시 DMA CPU read() 시스템콜 복사 User Buffer cudaMemcpy() 소스 GPU VRAM PCIe 4회 데이터 복사, CPU 개입 필수, 시스템 메모리 대역폭 병목 실측: ~3 GB/s, CPU 1코어 100% P2P DMA 경로: cuFileRead() — CPU/메모리 바이패스 NVMe SSD P2P DMA CMB/SGL PCIe Switch / RC 직접 라우팅 (CPU 미경유) GPU VRAM nvidia-fs BAR 매핑 1회 DMA 전송, CPU 0%, 시스템 메모리 미사용 실측: ~6.5 GB/s (PCIe Gen4 x4), CPU 사용률 ≈ 0% PCIe 토폴로지와 P2P DMA 호환성 Root Complex (CPU) PCIe Switch A PCIe Switch B NVMe SSD 1 GPU A P2P 최적 (distance=2) NVMe SSD 2 RDMA NIC RC 경유 P2P (distance=4, 성능↓)

P2P DMA 커널 인터페이스

/* drivers/pci/p2pdma.c */
/* P2P DMA 가능 여부 확인 */
int distance = pci_p2pdma_distance_many(storage_dev,
                    &gpu_clients, 1, verbose);
/*
 * 반환값:
 *  > 0: P2P 가능 (값이 작을수록 최적)
 *   -1: P2P 불가능 (다른 PCIe 호스트 브리지)
 *
 * 같은 PCIe 스위치 하위 → distance = 2 (최적)
 * 같은 root complex 하위 → distance = 4 (가능)
 * 다른 NUMA 노드 → distance = -1 또는 높은 값
 */

P2P DMA 커널 내부 — pci_p2pdma_map_sg()

P2P DMA의 핵심은 DMA 매핑 과정에서 시스템 메모리 대신 피어 장치의 BAR(Base Address Register) 영역을 직접 참조하는 것입니다. NVMe 드라이버가 BIO를 처리할 때 SGL(Scatter-Gather List)에 GPU VRAM의 물리 주소를 넣어 NVMe 컨트롤러가 직접 데이터를 전송합니다.

/* drivers/pci/p2pdma.c */
/*
 * P2P DMA용 SG 리스트 매핑 — 피어 장치의 BAR 주소를 SGL에 배치
 * NVMe → GPU 전송 시: NVMe 드라이버가 이 함수로 GPU VRAM 주소를 SGL에 등록
 */
int pci_p2pdma_map_sg_attrs(struct device *dev,
                            struct scatterlist *sg, int nents,
                            enum dma_data_direction dir,
                            unsigned long attrs)
{
    struct scatterlist *s;
    int i;

    for_each_sg(sg, s, nents, i) {
        /* SG 엔트리가 P2P 메모리인지 확인 */
        if (is_pci_p2pdma_page(sg_page(s))) {
            /* 시스템 메모리 DMA 매핑 대신
             * 피어 장치의 PCI BAR 물리 주소를 직접 사용 */
            s->dma_address = pci_p2pdma_bus_addr(sg_page(s))
                           + s->offset;
            sg_dma_len(s) = s->length;
            sg_dma_mark_bus_address(s);  /* P2P 주소 마킹 */
        }
    }
    return nents;
}
코드 설명

pci_p2pdma_map_sg_attrs()는 일반 DMA 매핑(dma_map_sg())을 대체하여, P2P 메모리 페이지의 경우 시스템 IOMMU 변환 대신 피어 PCI 장치의 BAR 주소를 직접 사용합니다. NVMe 드라이버가 읽기 명령의 SGL에 이 주소를 넣으면, NVMe 컨트롤러는 DMA 엔진으로 해당 BAR 주소(= GPU VRAM)에 직접 데이터를 써넣습니다. CPU와 시스템 메모리는 전혀 관여하지 않습니다.

GPU Direct Storage — nvidia-fs와 cuFile API

NVIDIA GPU Direct Storage(GDS)는 nvidia-fs 커널 모듈을 통해 NVMe SSD와 GPU VRAM 간 P2P DMA를 파일시스템 수준에서 투명하게 지원합니다. cuFile API는 POSIX의 read()/write()를 대체하여 GPU 버퍼에 직접 I/O를 수행합니다.

/* NVIDIA cuFile API 사용 예시 (사용자 공간) */
#include <cufile.h>

/* 1. cuFile 드라이버 초기화 */
CUfileError_t status = cuFileDriverOpen();

/* 2. 파일 열기 + cuFile 핸들 등록 */
int fd = open("/mnt/nas-nvme/dataset/imagenet.tar", O_RDONLY | O_DIRECT);
CUfileDescr_t desc = { .type = CU_FILE_HANDLE_TYPE_OPAQUE_FD };
desc.handle.fd = fd;

CUfileHandle_t fh;
cuFileHandleRegister(&fh, &desc);

/* 3. GPU 메모리 할당 + cuFile 버퍼 등록 */
void *gpu_buf;
cudaMalloc(&gpu_buf, BUFFER_SIZE);
cuFileBufRegister(gpu_buf, BUFFER_SIZE, 0);

/* 4. NVMe → GPU VRAM 직접 읽기 (P2P DMA) */
ssize_t bytes = cuFileRead(fh, gpu_buf, BUFFER_SIZE,
                           file_offset, gpu_offset);
/*
 * 내부 경로: cuFileRead() → nvidia-fs 커널 모듈
 *   → NVMe 드라이버에 P2P SGL 제출
 *   → NVMe 컨트롤러가 GPU BAR 주소에 직접 DMA
 *   → CPU/시스템 메모리 미경유
 *
 * 성능: PCIe Gen4 x4 NVMe 기준 ~6.5 GB/s
 *       read()+cudaMemcpy() 대비 2~3× 처리량 향상
 */
코드 설명

cuFile API는 GPU 메모리에 대한 직접 파일 I/O를 제공합니다. cuFileBufRegister()로 GPU 버퍼를 등록하면 nvidia-fs 모듈이 해당 GPU VRAM의 BAR 주소를 파악하고, cuFileRead() 호출 시 NVMe 드라이버에 P2P SGL을 제출합니다. NVMe 컨트롤러는 이 SGL의 주소가 시스템 메모리가 아닌 GPU BAR임을 인지하고, PCIe 패브릭을 통해 GPU에 직접 데이터를 전송합니다. AI/ML NAS에서 학습 데이터 로딩 시 CPU 오버헤드를 완전히 제거합니다.

P2P DMA 성능과 토폴로지 요구사항

PCIe 토폴로지P2P 가능대역폭지연시간권장
같은 PCIe 스위치 하위최적PCIe 링크 속도최소강력 권장
같은 Root Complex가능RC 대역폭 제한중간사용 가능
다른 Root Complex (같은 NUMA)플랫폼 의존제한적높음비권장
다른 NUMA 노드대부분 불가--사용 불가

NVMe CMB P2P 메모리 할당

일부 NVMe 컨트롤러는 CMB(Controller Memory Buffer)를 제공하여 P2P DMA의 바운스 버퍼로 사용합니다. 이를 통해 피어 장치 간 직접 통신이 불가능한 토폴로지에서도 NVMe 컨트롤러의 온보드 메모리를 경유하여 P2P 전송을 수행할 수 있습니다.

/* drivers/nvme/host/pci.c */
/*
 * NVMe CMB(Controller Memory Buffer)를 P2P DMA용으로 등록
 * CMB는 NVMe 컨트롤러의 BAR에 매핑된 온보드 SRAM/DRAM
 */
static void nvme_map_cmb(struct nvme_dev *dev)
{
    u64 size = nvme_cmb_size(dev);
    if (!size)
        return;

    /* CMB BAR 영역을 P2P 메모리로 등록 */
    if (pci_p2pdma_add_resource(dev->pci_dev,
                                dev->cmb_bar, size, 0)) {
        dev_warn(dev->ctrl.device,
                 "failed to register CMB for P2P\n");
        return;
    }
    /*
     * 등록 후 다른 PCIe 장치(GPU, NIC)가
     * pci_p2pdma_alloc_pages()로 CMB 메모리를 할당하여
     * P2P DMA의 중간 버퍼로 사용 가능
     */
}
코드 설명

nvme_map_cmb()는 NVMe 컨트롤러의 CMB 영역을 pci_p2pdma_add_resource()로 커널 P2P 프레임워크에 등록합니다. 등록된 CMB 메모리는 struct page로 관리되며, 다른 PCIe 장치가 DMA 대상으로 사용할 수 있습니다. AI NAS에서 NVMe SSD의 CMB를 GPU DMA 버퍼로 활용하면, 같은 PCIe 스위치 아래가 아니어도 시스템 메모리를 경유하지 않는 P2P 전송이 가능합니다.

# PCIe 토폴로지 확인
lspci -tv
# -[0000:00]-+-00.0  Intel Device
#            +-01.0-[01-02]----00.0  NVIDIA A2000
#            +-02.0-[03-04]----00.0  Samsung NVMe SSD
#            # → 같은 root complex → P2P 가능

# NVIDIA GPU Direct Storage 설정
modprobe nvidia-fs
# cuFile API로 NVMe → GPU 직접 읽기
# cuFileRead(file_handle, gpu_buffer, size, file_offset, gpu_offset);

# P2P DMA 활성화 확인
cat /sys/bus/pci/devices/0000:01:00.0/p2pmem/size
# 268435456 (256MB P2P 메모리 영역)

# NVMe CMB P2P 지원 확인
cat /sys/bus/pci/devices/0000:03:00.0/p2pmem/size
# CMB 크기 (0이면 CMB 미지원)

# GDS 상태 확인
cat /proc/driver/nvidia-fs/stats
# Reads    : 1234567
# Writes   : 567890
# P2P Reads: 1234567   ← P2P DMA로 처리된 읽기
# P2P Fail : 0         ← P2P 불가 시 폴백 횟수

# gdsio 벤치마크 (NVIDIA GDS 도구)
gdsio -f /mnt/nas-nvme/testfile -d 0 -w 4 -s 1G -x 0 -I 1
# IoType: READ, Threads: 4, Bandwidth: 6.2 GiB/s
# GPU Util: 0%, CPU Util: 0.3%

P2P DMA와 IOMMU 상호작용

IOMMU 설정P2P DMA성능 영향NAS 권장
IOMMU 비활성직접 P2P (물리 주소)최고 성능전용 GPU NAS
IOMMU passthrough1:1 매핑, P2P 가능무시할 수준범용 권장
IOMMU strictATS(Address Translation Service) 필요지연 증가 (~5%)보안 요구 시
IOMMU + ACS 활성P2P 차단 가능P2P 불가ACS override 패치 필요
# IOMMU passthrough 모드 설정 (P2P DMA 최적)
# /etc/default/grub에 추가:
# GRUB_CMDLINE_LINUX="iommu=pt intel_iommu=on"

# ACS 확인 — P2P를 차단하는 ACS가 있는지 확인
setpci -s 01:00.0 ECAP_ACS+6.w
# 0000 → ACS 미활성 (P2P 허용)

# P2P DMA 가능 여부를 커널 로그에서 확인
dmesg | grep -i p2pdma
# nvme 0000:03:00.0: registered 256MB of P2P memory
# nvidia-fs: P2P DMA enabled for GPU 0000:01:00.0
NAS에서 P2P DMA 활용: AI 학습 데이터셋을 저장하는 NAS에서 GPU Direct Storage를 활용하면, NVMe SSD에서 GPU VRAM으로 데이터를 직접 전송하여 CPU와 시스템 메모리 병목을 제거합니다. 대규모 이미지/비디오 데이터셋 로딩에서 기존 read() + cudaMemcpy() 대비 처리량이 2~3배 향상됩니다. 다만 NVMe SSD와 GPU가 같은 PCIe 스위치 아래에 있어야 최적 성능을 발휘합니다.
NVMe-oF + P2P DMA 원격 NAS: NVMe-oF/RDMA로 원격 NAS의 NVMe 네임스페이스를 로컬에 마운트하면, GPU Direct Storage를 원격 스토리지에도 적용할 수 있습니다. 경로는 "원격 NVMe → RDMA NIC → PCIe → GPU VRAM"이 됩니다. 이 경우 네트워크 대역폭(100GbE ≈ 12 GB/s)이 병목이 되며, 로컬 NVMe P2P 대비 지연시간은 증가하지만 CPU 오프로드 효과는 동일합니다. NVIDIA Magnum IO GPUDirect RDMA가 이 구성을 지원합니다.

상용 NAS 아키텍처 비교 — Synology/QNAP/TrueNAS/NetApp

상용 NAS 오프로드 기능 매트릭스 상용 NAS 오프로드 기능 매트릭스 기능 Synology DSM QNAP QTS TrueNAS NetApp ONTAP DIY Linux NAS 파일시스템 Btrfs / ext4 ext4 / ZFS (QuTS) OpenZFS WAFL 선택 자유 RAID SW (mdadm/SHR) SW/HW (선택) ZFS RAID-Z RAID-DP (HW) HW/SW 선택 암호화 dm-crypt AES-NI dm-crypt AES-NI ZFS native + SED NSE/NVE (SED) 3경로 모두 네트워크 10GbE (옵션) 10GbE/25GbE 내장 10/25/100GbE 25/100GbE + RDMA 선택 자유 RDMA iSER (옵션) ✓ (NFS/RDMA) ✓ 구성 가능 GPU 가속 QSV (iGPU) QSV + dGPU 제한적 ✓ 자유 iSCSI SW iSCSI SW iSCSI SW + HW 옵션 FCP + iSCSI HW LIO + HW 옵션 NVMe-oF ✓ (CORE+) ✓ (AFF) ✓ nvmet 중복제거 QuTS hero (ZFS) ✓ (ZFS dedup) ✓ (인라인) VDO

상용 NAS 오프로드 구현 상세

각 상용 NAS 플랫폼이 하드웨어 오프로드를 어떻게 구현하는지 상세히 비교합니다.

Synology DSM

QNAP QTS/QuTS hero

TrueNAS (iXsystems)

NetApp ONTAP

Linux 커널 NAS 빌딩 블록 매핑

Linux 커널 NAS 서브시스템 매핑 Linux 커널 NAS 빌딩 블록 파일 서비스 ksmbd (SMB3 커널) knfsd (NFS 커널) Samba (사용자 공간) SMB Direct (RDMA) NFS/RDMA 블록 서비스 LIO target (iSCSI/FC/NVMe-oF) NVMe target (nvmet) iSER (RDMA iSCSI) XCOPY / ODX 스토리지 md (SW RAID) dm (Device Mapper) NVMe / SCSI / ATA HW RAID (megaraid_sas) VDO (중복제거) 네트워크 TCP/IP + TSO/GRO RDMA (ib_core, rdma_cm) kTLS (인라인 TLS) XDP (BPF 패킷 처리) 보안 dm-crypt / LUKS blk-crypto (인라인) SED/OPAL Kerberos / SELinux QAT crypto H/W 가속 계층 Intel DSA/IOAT QAT (암호화+압축) GPU (QSV/VAAPI) RDMA NIC HW RAID ctrl HDD / SSD / NVMe | 10/25/100 GbE NIC | PCIe 4.0/5.0

오프로드 결정 트리 (워크로드별 선택 가이드)

오프로드 결정 플로우차트 워크로드별 오프로드 결정 트리 NAS 워크로드 유형? 파일 서버 (SMB/NFS) 병목: 네트워크 + 암호화 1순위: RDMA/TSO 2순위: SED/blk-crypto 가상화 (iSCSI LUN) 병목: 프로토콜 + RAID 1순위: HW iSCSI/NVMe-oF 2순위: HW RAID + Copy Offload 미디어 (트랜스코딩) 병목: CPU 연산 1순위: GPU QSV/VAAPI 2순위: P2P DMA 백업/아카이브 병목: 압축 + 중복제거 1순위: QAT 압축 2순위: SHA HW + DSA memcpy 모든 워크로드 공통: TSO/GRO (기본) + AES-NI (CPU 암호화 가속) + 충분한 RAM (캐시) 워크로드별 오프로드 우선순위 워크로드 주요 병목 1순위 오프로드 2순위 오프로드 파일 서버 (10GbE+) 네트워크 + 암호화 RDMA (SMB Direct) + TSO SED/OPAL + kTLS 가상화 (iSCSI/NVMe-oF) 프로토콜 + I/O HW iSCSI HBA / NVMe-oF HW RAID + Copy Offload 미디어 (Plex/Jellyfin) CPU 연산 GPU (QSV/VAAPI) P2P DMA 백업/중복제거 압축 + 해시 QAT 압축 + SHA HW DSA memcpy + VDO

성능 벤치마크 방법론 — fio, iperf3, perf

스토리지 오프로드 효과 측정 (fio)

# 기준선: SW RAID 6 + dm-crypt
fio --name=baseline --ioengine=libaio --direct=1 --bs=1M \
    --rw=write --size=10G --numjobs=4 --iodepth=32 \
    --filename=/dev/mapper/crypt-raid6

# 비교: HW RAID + SED (동일 디스크 구성)
fio --name=hw-offload --ioengine=libaio --direct=1 --bs=1M \
    --rw=write --size=10G --numjobs=4 --iodepth=32 \
    --filename=/dev/sdX  # HW RAID 가상 디스크

# CPU 사용률 동시 모니터링
mpstat -P ALL 1  # 별도 터미널에서 실행

네트워크 오프로드 효과 측정 (iperf3)

# TCP 기본 (TSO 활성화 상태)
iperf3 -c nas-server -t 30 -P 8

# RDMA 대역폭 (perftest)
ib_write_bw -d mlx5_0 -s 1048576 nas-server

# CPU 사용률 비교
perf stat -e cycles,instructions -- iperf3 -c nas-server -t 10

오프로드 효과 검증 (perf)

# dm-crypt CPU 핫스팟 확인
perf top -g -p $(pgrep -d, kcryptd)

# RAID 패리티 연산 CPU 점유율
perf record -g -a -- sleep 10
perf report --sort=dso,symbol | grep -E "xor|raid|pq"

# DSA offload 확인
cat /sys/bus/dsa/devices/dsa0/state
cat /sys/bus/dsa/devices/wq0.0/state

RDMA 성능 벤치마크

# RDMA 대역폭 테스트 (서버측)
ib_write_bw -d mlx5_0 --report_gbits

# RDMA 대역폭 테스트 (클라이언트측)
ib_write_bw -d mlx5_0 --report_gbits nas-server

# RDMA 지연시간 테스트
ib_write_lat -d mlx5_0 nas-server

# SMB Direct 실제 파일 전송 벤치마크
smbclient //nas-server/share -U user%pass -c \
    "put /dev/zero testfile 10737418240"  # 10GB 쓰기

# NFS/RDMA vs NFS/TCP 비교
# TCP 마운트 → fio 실행 → 결과 기록
mount -t nfs -o tcp,vers=4.2 nas:/data /mnt/tcp
fio --name=nfs-tcp --directory=/mnt/tcp --rw=randread \
    --bs=4k --numjobs=16 --iodepth=32 --size=4G \
    --group_reporting --output=tcp-result.txt

# RDMA 마운트 → fio 실행 → 결과 기록
mount -t nfs -o rdma,port=20049,vers=4.2 nas:/data /mnt/rdma
fio --name=nfs-rdma --directory=/mnt/rdma --rw=randread \
    --bs=4k --numjobs=16 --iodepth=32 --size=4G \
    --group_reporting --output=rdma-result.txt

QAT 압축 벤치마크

# QAT 압축 성능 테스트 (qatzip 도구)
qzip -A deflate -O gzip -L 6 --hw-buff-sz 65536 \
    -i testdata-1GB.bin -o /dev/null

# 커널 crypto API 벤치마크
modprobe tcrypt
# dmesg 로그에서 QAT deflate 성능 확인
dmesg | grep -i "deflate.*qat"

# SW vs HW 비교 스크립트
for algo in deflate lz4; do
    echo "=== $algo SW ==="
    time openssl speed -evp $algo
    echo "=== $algo HW (QAT) ==="
    QAT_POLICY=1 time openssl speed -engine qatengine -evp $algo
done

종합 벤치마크 체크리스트

테스트 항목도구핵심 지표비교 대상
블록 I/O 성능fioIOPS, BW, latHW RAID vs SW RAID
암호화 오버헤드fio + perfCPU%, BW 감소율SED vs dm-crypt vs plain
RAID rebuild 영향fio + mdstatrebuild 중 서비스 IOPSHW vs SW rebuild
네트워크 대역폭iperf3, perftestGbps, CPU%TCP vs RDMA
파일 서비스 성능smbclient, nfsiostatMB/s, 동시 사용자SMB/TCP vs SMB Direct
압축 처리량qzip, openssl speedMB/s, CPU%SW vs QAT
트랜스코딩ffmpeg, MediaInfofps, 동시 스트림SW vs QSV
memcpy 오프로드dsa_perf_microsGB/s, CPU%CPU vs DSA

커널 설정 (Kconfig)

분류Kconfig 옵션설명
HW RAIDCONFIG_MEGARAID_SASBroadcom MegaRAID SAS 드라이버
CONFIG_SCSI_SMARTPQIMicrochip SmartPQI 드라이버
DSACONFIG_INTEL_IDXDIntel DSA/IAA 드라이버
CONFIG_INTEL_IDXD_SVMDSA SVM(Shared Virtual Memory) 지원
암호화CONFIG_BLK_INLINE_ENCRYPTION블록 레이어 인라인 암호화
CONFIG_BLK_SED_OPALSED/OPAL 커널 지원
CONFIG_CRYPTO_DEV_QAT_*Intel QAT 암호화/압축 드라이버
RDMACONFIG_INFINIBANDInfiniBand/RDMA 코어
CONFIG_MLX5_INFINIBANDConnectX RDMA 드라이버
CONFIG_SMB_SERVER_RDMAksmbd SMB Direct 지원
NVMe-oFCONFIG_NVME_TARGETNVMe 타겟 프레임워크
CONFIG_NVME_TARGET_RDMANVMe-oF/RDMA 타겟
iSCSI HBACONFIG_SCSI_CXGB4_ISCSIChelsio T6 iSCSI HW 오프로드
async_txCONFIG_ASYNC_TX_DMAasync_tx DMA 엔진 연동 활성화
CONFIG_ASYNC_XOR비동기 XOR 연산 (RAID 5/6 필수)
DMA 엔진CONFIG_DMADEVICESDMA 엔진 서브시스템
CONFIG_INTEL_IOATDMAIntel IOAT DMA (Crystal Beach)
P2P DMACONFIG_PCI_P2PDMAPCIe P2P DMA 지원
CONFIG_DMABUF_MOVE_NOTIFYDMA-BUF 이동 알림 (GPU 연동)
스토리지 프로토콜CONFIG_NVME_TARGET_TCPNVMe-oF/TCP 타겟
CONFIG_ISCSI_TARGETLIO iSCSI 타겟
CONFIG_TARGET_CORELIO 타겟 코어 (XCOPY 지원)
VDOCONFIG_DM_VDOVDO 중복제거/압축 (6.9+)
CONFIG_CRYPTO_SHA256_NISHA-256 HW 가속 (SHA-NI)
파일시스템CONFIG_BTRFS_FSBtrfs (CoW, 스냅샷, 압축)
CONFIG_FS_ENCRYPTIONfscrypt (파일 단위 암호화)
네트워크CONFIG_TLS_DEVICEkTLS HW 오프로드
CONFIG_SUNRPC_XPRT_RDMANFS/RDMA 전송 지원

NAS 오프로드별 Kconfig 의존성

각 오프로드 기능은 여러 Kconfig 옵션이 조합되어 동작합니다. 하나라도 빠지면 오프로드가 활성화되지 않으므로, 커널 빌드 시 다음 의존성을 확인하세요.

# RAID XOR HW 가속 의존성 체인
CONFIG_DMADEVICES=y          # DMA 서브시스템
CONFIG_INTEL_IOATDMA=m       # IOAT DMA 드라이버 (또는 mv_xor 등)
CONFIG_ASYNC_TX_DMA=y        # async_tx → DMA 연동
CONFIG_ASYNC_XOR=y           # XOR 비동기 연산
CONFIG_MD_RAID456=m          # md RAID 5/6

# blk-crypto 인라인 암호화 의존성
CONFIG_BLK_INLINE_ENCRYPTION=y
CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y  # HW 미지원 시 SW 폴백
CONFIG_FS_ENCRYPTION=y                    # fscrypt (선택적)
CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y       # fscrypt → blk-crypto 연동

# SMB Direct (ksmbd RDMA) 의존성
CONFIG_SMB_SERVER=m           # ksmbd
CONFIG_SMB_SERVER_RDMA=y      # RDMA 전송 활성화
CONFIG_INFINIBAND=m           # RDMA 코어
CONFIG_MLX5_INFINIBAND=m      # ConnectX 드라이버 (예시)
CONFIG_INFINIBAND_ADDR_TRANS=y

# QAT 압축 의존성
CONFIG_CRYPTO=y
CONFIG_CRYPTO_ACOMP2=y        # 비동기 압축 프레임워크
CONFIG_CRYPTO_DEV_QAT=m       # QAT 공통
CONFIG_CRYPTO_DEV_QAT_4XXX=m  # QAT 4xxx (Sapphire Rapids)
CONFIG_CRYPTO_DEV_QAT_DH895xCC=m  # QAT DH895xCC (선택)

# NFS/RDMA 의존성
CONFIG_NFSD=m                 # 커널 NFS 서버
CONFIG_NFSD_V4=y              # NFSv4 지원
CONFIG_SUNRPC_XPRT_RDMA=m    # RPC RDMA 전송
CONFIG_SVCRDMA=m              # 서버측 RDMA
커널 설정 확인 스크립트:
#!/bin/bash
# NAS 오프로드 Kconfig 확인 스크립트
CONFIGS="BLK_INLINE_ENCRYPTION INTEL_IDXD ASYNC_TX_DMA ASYNC_XOR
         INFINIBAND MLX5_INFINIBAND SMB_SERVER_RDMA
         NVME_TARGET NVME_TARGET_RDMA CRYPTO_DEV_QAT
         SUNRPC_XPRT_RDMA PCI_P2PDMA DM_VDO
         CRYPTO_SHA256_NI TLS_DEVICE"
for cfg in $CONFIGS; do
    val=$(grep "CONFIG_${cfg}=" /boot/config-$(uname -r) 2>/dev/null || echo "not set")
    printf "%-35s %s\n" "CONFIG_${cfg}" "$val"
done

실전 구성 예제

예제 1: 4-Bay NAS — HW RAID + dm-crypt + SMB3

# HW RAID 6 구성 (storcli)
storcli /c0 add vd r6 drives=252:0-3 wb ra cached

# dm-crypt LUKS2 설정
cryptsetup luksFormat --type luks2 --cipher aes-xts-plain64 \
  --key-size 512 /dev/sda  # HW RAID 가상 디스크
cryptsetup open /dev/sda crypt-nas

# ext4 + SMB3 공유
mkfs.ext4 /dev/mapper/crypt-nas
mount /dev/mapper/crypt-nas /srv/nas
# ksmbd 또는 Samba 설정

예제 2: 10GbE NAS — RDMA + NFS

# RoCE v2 설정
modprobe mlx5_ib
rdma link show  # RDMA 디바이스 확인

# NFS over RDMA 서버
cat >> /etc/nfs.conf << 'EOF'
[nfsd]
rdma=y
rdma-port=20049
EOF
systemctl restart nfs-server

# 클라이언트 마운트
mount -t nfs -o rdma,port=20049 nas-server:/export /mnt/nas

예제 3: All-Flash NAS — NVMe-oF + QAT 압축

# NVMe-oF/RDMA 타겟 설정
modprobe nvmet-rdma
mkdir -p /sys/kernel/config/nvmet/subsystems/nqn.nas
echo 1 > /sys/kernel/config/nvmet/subsystems/nqn.nas/attr_allow_any_host

# QAT 압축 활성화
modprobe qat_4xxx
modprobe intel_qat
# Btrfs + QAT (ZFS의 경우 qat_compress 모듈)
mkfs.btrfs -m raid1 -d raid6 /dev/nvme0n1 /dev/nvme1n1 /dev/nvme2n1 /dev/nvme3n1
mount -o compress=zstd /dev/nvme0n1 /srv/nas

예제 4: 고가용성 NAS — ZFS + iSER + SED

# ZFS 풀 구성 (IT 모드 HBA 필수)
zpool create -o ashift=12 tank \
    raidz2 /dev/sd{a,b,c,d,e,f} \
    log mirror /dev/nvme0n1p1 /dev/nvme1n1p1 \
    cache /dev/nvme2n1

# SED 잠금 설정
sedutil-cli --initialSetup debug /dev/sda
sedutil-cli --enableLockingRange 0 password /dev/sda
# 모든 디스크에 반복...

# iSER 타겟 구성 (LIO)
modprobe ib_isert
targetcli /iscsi create iqn.2024-01.com.nas:ha-zfs
targetcli /iscsi/.../tpg1/luns create /backstores/block/tank-zvol
# iSER은 TCP 포트 3260에서 자동 협상

# ZFS 스냅샷 자동화 (랜섬웨어 방어)
zfs set snapdir=visible tank
zfs snapshot -r tank@daily-$(date +%Y%m%d)
zfs hold anti-ransom tank@daily-$(date +%Y%m%d)

예제 5: Hyper-Converged NAS — DSA + RDMA + QAT

# 4세대 Xeon Sapphire Rapids 전용 구성
# DSA 설정 (RAID rebuild + 데이터 이동 가속)
accel-config config-wq dsa0/wq0.0 --mode=dedicated \
    --type=kernel --driver-name=dmaengine --wq-size=128
accel-config enable-device dsa0
accel-config enable-wq dsa0/wq0.0

# QAT 압축 활성화 (내장 QAT 4xxx)
modprobe qat_4xxx
adf_ctl restart

# RDMA + SMB Direct (ConnectX-7 100GbE)
modprobe mlx5_ib
rdma link show
# ksmbd SMB Direct 서비스 시작
ksmbd.mountd -s /etc/ksmbd/ksmbd.conf

# VDO 중복제거 + QAT 압축
vdo create --name=hci-dedup --device=/dev/md0 \
    --vdoLogicalSize=10T --vdoSlabSize=32G

# 시스템 모니터링 대시보드
# DSA 상태, QAT 카운터, RDMA 통계를 종합 확인
watch -n 5 'echo "=== DSA ===" && cat /sys/bus/dsa/devices/dsa0/clients && \
    echo "=== QAT ===" && adf_ctl status && \
    echo "=== RDMA ===" && rdma statistic show'

구성별 총 비용 대비 성능 비교

구성예상 비용 (USD)순차 쓰기랜덤 4K IOPS동시 사용자적합 규모
4-Bay HDD + SW RAID$500~800~400 MB/s~1K5~10명소규모 사무실
4-Bay HDD + HW RAID$800~1,500~500 MB/s~2K10~20명중소기업
8-Bay SSD + RDMA$3,000~6,000~5 GB/s~500K50~100명중견기업
All-NVMe + QAT + DSA$8,000~15,000~12 GB/s~1M100~500명데이터센터
HA Cluster + NVMe-oF$20,000+~25 GB/s~2M+500명+엔터프라이즈

흔한 실수와 안티패턴

⚠️ 실수 1: BBU 방전 미모니터링
HW RAID의 BBU가 방전되면 자동으로 Write-through 모드로 전환되어 쓰기 성능이 5-10배 저하됩니다. 정기적인 BBU 상태 점검과 SNMP/이메일 알림을 설정하세요.
⚠️ 실수 2: dm-crypt + HW RAID Write-back 데이터 손실
dm-crypt는 데이터를 암호화한 후 HW RAID에 전달합니다. HW RAID의 Write-back 캐시에 암호화된 데이터가 있는 상태에서 정전이 발생하면, BBU/FBWC가 없으면 데이터 손실이 발생합니다. 반드시 BBU/FBWC가 정상인지 확인 후 Write-back을 활성화하세요.
⚠️ 실수 3: RoCE v2 PFC 미설정
RoCE v2는 lossless fabric이 필수입니다. PFC(Priority Flow Control)를 설정하지 않으면 네트워크 혼잡 시 대량 패킷 손실이 발생하여 RDMA 성능이 TCP보다 나빠질 수 있습니다. iWARP는 TCP 기반이므로 PFC 없이도 동작합니다.
⚠️ 실수 4: SED 비밀번호 분실
SED/OPAL 드라이브의 비밀번호를 분실하면 데이터 복구가 절대 불가능합니다. PSID revert(공장 초기화)만 가능하며 모든 데이터가 삭제됩니다.
⚠️ 실수 5: QAT + 비호환 파일시스템
현재 Linux 커널의 Btrfs는 QAT 압축을 직접 지원하지 않습니다(zstd/lzo/zlib SW 전용). ZFS는 qat_compress 모듈로 QAT gzip/lz4 가속이 가능합니다. 파일시스템 선택 전 QAT 호환성을 확인하세요.
⚠️ 실수 6: DSA 소규모 전송에 사용
DSA는 4KB 이하의 소규모 memcpy에서 CPU보다 느립니다. descriptor 제출 오버헤드(~1μs)가 작은 전송에서 병목이 되기 때문입니다. DSA는 64KB 이상의 대규모 전송에만 사용하세요. 소규모 전송은 CPU의 REP MOVSB가 더 효율적입니다.
⚠️ 실수 7: NFS/RDMA에서 NFSv3 사용
NFS/RDMA는 NFSv4 이상에서만 안정적으로 지원됩니다. NFSv3 over RDMA는 실험적이며 프로덕션 환경에서 권장되지 않습니다. 또한 NFSv4.1+의 세션/트렁킹 기능을 활용해야 RDMA 멀티채널 성능을 최대화할 수 있습니다.
⚠️ 실수 8: HW RAID에서 ZFS/Btrfs 사용
ZFS RAID-Z나 Btrfs RAID는 디스크에 직접 접근해야 합니다. HW RAID 컨트롤러가 가상 디스크를 노출하면 ZFS의 자가 복구, 스크럽, 체크섬 검증이 무력화됩니다. ZFS/Btrfs NAS에서는 반드시 IT 모드(HBA) 컨트롤러를 사용하세요.
⚠️ 실수 9: LUKS2 Argon2id 메모리 부족
LUKS2의 기본 Argon2id KDF는 잠금해제 시 1GB 메모리를 사용합니다. RAM이 2GB 이하인 임베디드 NAS에서 부팅 시 잠금해제에 실패하거나 OOM이 발생할 수 있습니다. --pbkdf-memory 524288으로 512MB 이하로 설정하세요.
⚠️ 실수 10: RDMA MTU 불일치
RDMA(특히 RoCEv2)는 엔드투엔드 MTU가 일치해야 합니다. 스위치의 MTU가 NIC의 MTU보다 작으면 PMTU discovery 실패로 연결이 끊기거나 성능이 급락합니다. 모든 경로(NIC, 스위치, 라우터)에서 Jumbo Frame(MTU 9000)을 일관되게 설정하세요.

트러블슈팅 가이드

증상가능한 원인진단 방법해결책
RAID rebuild 중 NAS 응답 없음SW RAID CPU 과부하top에서 md worker 확인speed_limit_max 낮추기 또는 HW RAID 전환
dm-crypt 쓰기 성능 저하BBU 방전 → Write-throughstorcli /c0/bbu showBBU 교체 또는 FBWC 업그레이드
RDMA 연결 실패PFC 미설정, MTU 불일치rdma res show qp, ethtool -SPFC/ECN 설정, MTU 통일
QAT 압축 미작동인스턴스 미할당adf_ctl status설정 파일 확인 후 adf_ctl restart
DSA 작업 실패 (EAGAIN)Shared WQ 포화cat /sys/bus/dsa/devices/wq0.0/stateWQ 크기 증가 또는 Dedicated WQ 사용
SMB Direct 미활성RDMA NIC 미인식rdma link showmlx5_ib 모듈 로드, 펌웨어 업데이트
SED 잠금해제 실패비밀번호 오류, PBA 손상sedutil-cli --query /dev/sdXPSID revert (데이터 손실 주의)
NFS/RDMA 마운트 실패svcrdma 모듈 미로드cat /proc/fs/nfsd/portlistmodprobe svcrdma, portlist에 rdma 추가

NAS 워크로드별 오프로드 조합 권장

NAS 워크로드는 매우 다양하며, 각 워크로드에 최적인 오프로드 조합이 다릅니다. 아래에서 주요 NAS 워크로드 유형별 권장 오프로드 전략을 제시합니다.

파일 서버 (SMB/NFS)

가장 일반적인 NAS 워크로드로, 다수 사용자가 동시에 문서, 이미지, 스프레드시트 등을 읽고 씁니다. 소규모 랜덤 I/O가 주를 이루며, 동시 접속자 수에 따라 CPU 부하가 증가합니다.

구성 요소소규모 (5~20명)중규모 (20~100명)대규모 (100명+)
RAIDSW RAID 5/6 (md)HW RAID 6 + FBWCHW RAID 6 + 대용량 캐시
암호화dm-crypt + AES-NISED + dm-cryptSED 단독
네트워크1GbE TSO/GRO10GbE + kTLS25GbE RDMA + SMB Direct
프로토콜SMB3 (ksmbd)SMB3 멀티채널SMB Direct + 멀티채널
스토리지HDD SATAHDD + SSD 캐시All-SSD 또는 NVMe
CPU 여유율 목표>50%>40%>60% (오프로드 덕분)

백업 및 아카이브

대용량 순차 쓰기가 주 워크로드로, 압축과 중복제거가 저장 공간 효율에 핵심입니다.

# 백업 NAS 최적화 설정 예시
# 1. VDO 중복제거 + 압축
vdo create --name=backup-store --device=/dev/md0 \
    --vdoLogicalSize=20T --writePolicy=auto

# 2. ZFS + QAT 압축 (대안)
zpool create backup raidz2 /dev/sd{a..h}
zfs set compression=gzip-6 backup        # QAT 가속 자동 사용
zfs set dedup=on backup                  # RAM 충분 시에만

# 3. rsync/borg 백업 시 대역폭 확인
iotop -ao -d 30    # 30초간 프로세스별 I/O 확인

가상화 스토리지 (iSCSI/NVMe-oF)

VM 스토리지는 랜덤 4K I/O가 대부분이며, 지연시간이 VM 성능에 직접적인 영향을 줍니다.

미디어 서비스 (Plex/Jellyfin/감시)

미디어 트랜스코딩과 감시 카메라 녹화/AI 분석은 CPU 집약적 워크로드입니다.

AI/ML 데이터 레이크

대규모 학습 데이터셋을 저장하고 GPU 클러스터에 제공하는 NAS입니다.

워크로드별 오프로드 우선순위 매트릭스

오프로드파일 서버백업/아카이브가상화미디어AI/ML
HW RAID / XOR 가속중간높음높음낮음낮음
DSA memcpy낮음중간높음낮음높음
Copy Offload낮음중간높음낮음낮음
SED / dm-crypt높음높음높음중간낮음
RDMA / SMB Direct높음중간높음낮음필수
NVMe-oF낮음낮음필수낮음필수
QAT 압축낮음필수낮음낮음낮음
GPU QSV낮음낮음낮음필수낮음
P2P DMA없음없음낮음낮음필수

오프로드 도입 단계별 권장

NAS 오프로드를 한 번에 전부 도입하는 것은 비현실적입니다. 비용 효율이 높은 순서대로 단계적으로 도입하는 것을 권장합니다.

  1. 1단계 (무비용): TSO/GRO 활성화 확인, AES-NI 암호화 가속 확인, SHA-NI VDO 가속. 소프트웨어 설정만으로 즉시 효과.
  2. 2단계 (저비용): SED 드라이브 도입 (추가 비용 10~20%), 10GbE NIC 업그레이드, SSD 캐시 추가.
  3. 3단계 (중비용): HW RAID 컨트롤러 (FBWC 포함), 25GbE RDMA NIC, Intel QSV CPU 선택.
  4. 4단계 (고비용): QAT 가속기, DSA 지원 Xeon, 100GbE 인프라, NVMe-oF 확장.
  5. 5단계 (엔터프라이즈): P2P DMA + GPU Direct, FC SAN 백엔드, HA 클러스터 구성.
ROI 측정 팁: 각 오프로드 단계 도입 전후로 fio, iperf3, perf를 사용하여 성능과 CPU 사용률을 측정하세요. 오프로드의 가치는 "CPU 사용률 감소 × 서비스 처리량 증가"로 평가할 수 있습니다. CPU 사용률이 이미 20% 이하라면 추가 오프로드보다 스토리지/네트워크 대역폭 확장이 더 효과적입니다.

async_tx XOR/PQ 오프로드 프레임워크

async_tx는 Linux 커널의 비동기 트랜잭션 프레임워크로, RAID 5/6에서 사용하는 XOR 및 PQ(Reed-Solomon) 연산을 DMA 엔진 또는 CPU에서 투명하게 실행합니다. md RAID의 쓰기 경로에서 핵심적인 역할을 하며, DMA 엔진이 있으면 자동으로 하드웨어 가속을 활용합니다.

async_tx_submit() 구조와 DMA 엔진 연동

async_tx_submit()은 비동기 작업의 제출과 완료 추적을 관리합니다. DMA 엔진의 트랜잭션 descriptor를 채널에 제출하고, 완료 콜백을 등록하여 비동기 파이프라인을 구성합니다.

/* crypto/async_tx/async_tx.c */
void async_tx_submit(struct dma_chan *chan,
                     struct dma_async_tx_descriptor *tx,
                     struct async_submit_ctl *submit)
{
    struct dma_async_tx_descriptor *depend_tx = submit->depend_tx;

    /* 의존 관계 설정: 이전 연산 완료 후 실행 */
    if (depend_tx) {
        tx->parent = depend_tx;
        spin_lock_bh(&depend_tx->lock);
        list_add_tail(&tx->parent_node, &depend_tx->tx_list);
        spin_unlock_bh(&depend_tx->lock);
    }

    /* 완료 콜백 설정 */
    tx->callback = submit->cb_fn;
    tx->callback_param = submit->cb_param;

    /* DMA 엔진 채널에 작업 제출 */
    dmaengine_submit(tx);

    /* 보류된 작업 시작 (실제 HW 전송 트리거) */
    dma_async_issue_pending(chan);
}

async_tx의 의존 관계 체인은 RAID 5/6의 read-modify-write 또는 reconstruct-write 패턴에서 연산 순서를 보장합니다. 예를 들어, RAID 6 쓰기 시 "P 패리티 XOR" → "Q 패리티 PQ" → "디스크 쓰기" 순서가 콜백 체인으로 자동 보장됩니다.

XOR/PQ 가속 지원 DMA 엔진 목록

DMA 엔진XORPQmemcpy플랫폼커널 드라이버
Intel IOAT (CB DMA)지원지원지원Xeon (Sandy Bridge~)ioatdma
Intel DSA미지원미지원지원Xeon (Sapphire Rapids~)idxd
Marvell XOR v2지원지원지원Armada 7K/8K, CN9xxxmv_xor_v2
Marvell XOR v1지원미지원지원Armada 370/XP/38xmv_xor
Freescale RAID Engine지원지원지원QorIQ P/T 시리즈fsl-raideng
Microchip PolarFire지원미지원지원PolarFire SoC FPGAmpfs-dma
Hisilicon SEC미지원미지원지원Kunpeng 920hisi_sec2
Intel DSA와 XOR: DSA는 IOAT의 후속이지만, XOR/PQ 연산 지원이 제외되었습니다. DSA는 memcpy/memfill/CRC에 특화되어 있으며, RAID XOR 가속이 필요하면 별도의 RAID 컨트롤러 또는 CPU의 AVX-512 VPCLMULQDQ 명령어를 사용해야 합니다. ARM 기반 NAS(Synology DS1621xs+의 Marvell Armada 등)에서는 mv_xor 엔진이 자동으로 async_tx에 등록됩니다.

async_xor() 핵심 경로 상세

커널 소스 분석: async_xor() — RAID 5 패리티 연산 내부

/* crypto/async_tx/async_xor.c (상세 분석) */
struct dma_async_tx_descriptor *
async_xor(struct page *dest, struct page **src_list,
          unsigned int offset, int src_cnt, size_t len,
          struct async_submit_ctl *submit)
{
    struct dma_chan *chan;
    struct dma_device *device;

    /* 1단계: XOR 기능 DMA 채널 탐색 */
    chan = async_tx_find_channel(submit, DMA_XOR,
            &dest, 1, src_list, src_cnt, len);
    device = chan ? chan->device : NULL;

    if (device && src_cnt <= device->max_xor) {
        /* 2단계: DMA XOR 경로 */
        struct dma_async_tx_descriptor *tx;
        dma_addr_t dma_dest, dma_src[IOAT_NUM_SRC_TEST];
        unsigned long dma_flags = 0;

        /* 페이지 → DMA 주소 변환 */
        dma_dest = dma_map_page(device->dev, dest,
                    offset, len, DMA_BIDIRECTIONAL);
        for (int i = 0; i < src_cnt; i++)
            dma_src[i] = dma_map_page(device->dev,
                    src_list[i], offset, len,
                    DMA_TO_DEVICE);

        /* DMA XOR descriptor 준비 */
        tx = device->device_prep_dma_xor(chan,
                dma_dest, dma_src, src_cnt,
                len, dma_flags);

        /* 3단계: 비동기 제출 (콜백 체인) */
        async_tx_submit(chan, tx, submit);
        return tx;
    }

    /* 4단계: SW 폴백 — CPU XOR (SIMD 최적화) */
    if (submit->flags & ASYNC_TX_XOR_ZERO_DST)
        memset(page_address(dest) + offset, 0, len);

    xor_blocks(src_cnt, len,
        page_address(dest) + offset, srcs);

    return NULL;
}
코드 설명
  • 핵심async_xor() 상세 경로: (1) async_tx_find_channel()DMA_XOR 기능을 가진 DMA 채널을 탐색합니다. IOAT, mv_xor 등이 등록되어 있으면 매칭됩니다. (2) DMA 경로에서는 소스/대상 페이지를 DMA 주소로 매핑하고, device_prep_dma_xor()로 HW descriptor를 준비합니다. (3) async_tx_submit()으로 DMA 엔진에 제출하고, 완료 시 콜백이 호출되어 다음 연산(디스크 쓰기)이 트리거됩니다. (4) DMA 엔진이 없으면 xor_blocks()가 CPU에서 XOR을 수행합니다. 이때 커널은 부팅 시 벤치마크한 최적의 XOR 알고리즘(AVX-512, SSE2, NEON 등)을 자동 선택합니다.

RAID 5/6 쓰기 시 async_tx 호출 흐름

md RAID 5/6의 쓰기 경로에서 async_tx가 호출되는 전체 흐름을 살펴봅니다. 스트라이프 단위로 패리티가 계산되며, 비동기 콜백 체인이 전체 과정을 조율합니다.

  1. raid5_make_request(): bio를 받아 스트라이프 해시 테이블에서 해당 stripe_head를 찾습니다.
  2. handle_stripe(): 스트라이프 상태를 분석하여 읽기/쓰기/패리티 연산을 결정합니다.
  3. ops_run_compute5(): RAID 5 패리티를 계산합니다. 내부에서 async_xor()를 호출합니다.
  4. ops_run_compute6_1()/ops_run_compute6_2(): RAID 6의 P/Q 이중 패리티를 계산합니다. async_gen_syndrome()을 호출합니다.
  5. ops_complete_compute(): 패리티 연산 완료 콜백입니다. 스트라이프를 "쓰기 준비" 상태로 전환합니다.
  6. ops_run_io(): 데이터와 패리티를 디스크에 기록합니다.
async_tx RAID 쓰기 흐름 async_tx RAID 5/6 쓰기 흐름 RAID write bio handle_stripe() async_xor() 패리티 연산 DMA XOR Engine CPU xor_blocks() completion callback → ops_run_io() 스트라이프 처리 상세 타임라인 1. 데이터 읽기 기존 데이터 + 패리티 로드 2. XOR/PQ 연산 async_xor / async_gen_syndrome 3. 콜백 완료 stripe READY 상태 전환 4. 디스크 쓰기 데이터 + 패리티 I/O 제출 5. 완료 bio endio 반환 DMA XOR: CPU 사용률 <5%, async 파이프라인으로 I/O 중첩 가능 CPU XOR: AVX-512/SSE2/NEON 자동 선택, 부팅 시 벤치마크

NAS 보안 강화 체크리스트

NAS는 기업의 핵심 데이터를 저장하므로 다층적 보안이 필수입니다. 물리 보안부터 네트워크, 인증, 감사, 랜섬웨어 방어까지 포괄적인 보안 강화 전략을 정리합니다.

물리 보안

네트워크 보안

# NAS 방화벽 기본 설정 (nftables)
nft add table inet nas_filter
nft add chain inet nas_filter input { type filter hook input priority 0\; policy drop\; }

# 루프백 허용
nft add rule inet nas_filter input iif lo accept

# 기존 연결 허용
nft add rule inet nas_filter input ct state established,related accept

# 관리 VLAN (vlan100)에서만 SSH 허용
nft add rule inet nas_filter input iifname "vlan100" tcp dport 22 accept

# 데이터 VLAN (vlan200)에서 서비스 포트 허용
nft add rule inet nas_filter input iifname "vlan200" tcp dport { 445, 2049, 3260 } accept

# RDMA 포트 허용 (RoCEv2)
nft add rule inet nas_filter input iifname "vlan200" udp dport 4791 accept

# fail2ban SMB jail
cat >> /etc/fail2ban/jail.d/smb.conf << 'EOF'
[smb]
enabled  = true
port     = 445
filter   = smb
logpath  = /var/log/samba/log.%m
maxretry = 5
bantime  = 3600
EOF

인증과 접근 제어

감사(Audit) 로깅

# auditd NAS 데이터 디렉토리 감사 규칙
auditctl -w /srv/nas-data -p rwxa -k nas_file_access

# Samba 감사 모듈 설정
# smb.conf [share] 섹션
# vfs objects = full_audit
# full_audit:prefix = %u|%I|%m|%S
# full_audit:success = connect disconnect mkdir rmdir open read write rename unlink
# full_audit:failure = connect
# full_audit:facility = local5
# full_audit:priority = notice

암호화 계층 조합 가이드

NAS에서 여러 암호화 계층을 조합할 수 있지만, 성능 영향과 키 관리 복잡도를 고려해야 합니다.

조합보호 범위성능 영향키 관리적합 시나리오
SED 단독물리 도난0%TCG Opal (단순)물리 보안만 필요, 최고 성능
dm-crypt (LUKS2)물리 도난 + OS 우회10-30%LUKS2 키슬롯범용 NAS, 유연한 키 관리
SED + fscrypt물리 + 다중 사용자 격리5-15%Opal + 파일별 키멀티 테넌트 NAS
dm-crypt + SMB3 암호화물리 + 네트워크 도청20-40%LUKS2 + Kerberos규정 준수 (금융/의료)
SED + kTLS물리 + 네트워크 (HW가속)0-5%Opal + TLS 인증서고성능 + 전구간 암호화

랜섬웨어 방어

NAS는 랜섬웨어의 주요 타겟입니다. 다층 방어 전략으로 데이터를 보호합니다.

# ZFS 불변 스냅샷 생성
zfs snapshot tank/nas-data@backup-2024-01-15
zfs hold keep tank/nas-data@backup-2024-01-15
# hold가 설정된 스냅샷은 zfs destroy로 삭제 불가

# 자동 스냅샷 (systemd timer)
# /etc/systemd/system/zfs-snapshot.timer
[Timer]
OnCalendar=*:0/15   # 15분마다
Persistent=true

# Btrfs 읽기 전용 스냅샷
btrfs subvolume snapshot -r /srv/nas-data \
    /srv/.snapshots/nas-data-$(date +%Y%m%d-%H%M%S)

# 스냅샷 보존 정책 (30일 이상 자동 삭제)
find /srv/.snapshots -maxdepth 1 -mtime +30 -exec \
    btrfs subvolume delete {} \;
⚠️ 관리자 계정 보호: 랜섬웨어가 NAS 관리자 권한을 획득하면 스냅샷까지 삭제할 수 있습니다. 관리자 계정에는 반드시 2FA를 적용하고, 스냅샷 관리 권한을 별도의 서비스 계정으로 분리하세요. ZFS hold 기능은 zfs release 명령 없이는 삭제할 수 없으므로, hold 키 이름을 별도로 관리합니다.

NAS 보안 강화 종합 체크리스트

범주항목구현 방법우선순위
물리 보안디스크 암호화SED TCG Opal 2.0필수
TPM 자동 잠금해제systemd-cryptenroll --tpm2권장
물리 잠금Kensington Lock, 랙 잠금권장
시리얼 콘솔 보호BIOS 비밀번호, 콘솔 비활성화선택
네트워크VLAN 분리관리/데이터 VLAN 격리필수
방화벽nftables, 필요 포트만 허용필수
fail2banSSH, SMB, Web UI jail필수
SMB1 비활성화server min protocol = SMB3필수
kTLS 암호화SMB3 + kTLS HW 오프로드권장
인증KerberosAD/FreeIPA 연동높음
2FAgoogle-authenticator, FIDO2높음
LDAP 중앙 관리sssd + OpenLDAP/AD권장
최소 권한POSIX/NFSv4 ACL, no_root_squash 금지필수
감사auditd파일 접근/권한 변경 로깅높음
SMB 감사vfs_full_audit 모듈권장
원격 로그rsyslog → 별도 로그 서버필수
랜섬웨어 방어불변 스냅샷ZFS hold, Btrfs readonly필수
3-2-1 백업Air-gapped + WORM필수
파일 스크리닝ClamAV, vfs_virusfilter권장
이상 탐지대량 변경 감지 → 세션 차단권장
암호화저장 데이터SED 또는 dm-crypt LUKS2필수
전송 데이터SMB3 암호화, NFS krb5p높음
키 관리KMIP, HashiCorp Vault엔터프라이즈

보안 강화 자동화 스크립트

#!/bin/bash
# NAS 보안 강화 자동 점검 스크립트
echo "=== NAS 보안 점검 ==="

# 1. SMB1 비활성화 확인
echo -n "[SMB1] "
if smbclient -L localhost -m NT1 2>&1 | grep -q "NT1 disabled"; then
    echo "OK - SMB1 비활성화"
else
    echo "WARNING - SMB1이 활성화되어 있습니다!"
fi

# 2. SSH root 로그인 비활성화 확인
echo -n "[SSH] "
if grep -q "^PermitRootLogin no" /etc/ssh/sshd_config; then
    echo "OK - root 로그인 비활성화"
else
    echo "WARNING - root 로그인이 허용되어 있습니다!"
fi

# 3. fail2ban 상태 확인
echo -n "[fail2ban] "
if systemctl is-active fail2ban >/dev/null 2>&1; then
    echo "OK - fail2ban 활성"
else
    echo "WARNING - fail2ban이 비활성 상태입니다!"
fi

# 4. 방화벽 규칙 확인
echo -n "[방화벽] "
if nft list ruleset 2>/dev/null | grep -q "policy drop"; then
    echo "OK - 기본 정책 drop"
else
    echo "WARNING - 방화벽 기본 정책이 accept입니다!"
fi

# 5. SED 상태 확인
echo -n "[SED] "
for dev in /dev/sd?; do
    if sedutil-cli --query $dev 2>/dev/null | grep -q "Locked = Y"; then
        echo -n "$dev:잠금 "
    fi
done
echo ""

# 6. 스냅샷 보호 확인
echo -n "[스냅샷] "
hold_count=$(zfs holds -r tank 2>/dev/null | grep -c "anti-ransom" || echo 0)
echo "보호된 스냅샷: $hold_count개"

# 7. 원격 로그 전송 확인
echo -n "[원격 로그] "
if grep -q "^@@" /etc/rsyslog.conf 2>/dev/null; then
    echo "OK - 원격 로그 전송 설정됨"
else
    echo "WARNING - 원격 로그 전송이 설정되지 않았습니다!"
fi

echo "=== 점검 완료 ==="

참고 링크

외부 참고 자료:

NAS HW 오프로드와 관련된 다른 주제를 더 깊이 이해하고 싶다면 다음 문서를 참고하세요.