Files
obsidian/infra/data/nas-storage.md
kaffa ba30121962 NAS eth2 USB 2.5GbE 카드 교체 (rev 17 → rev 14, USB 4-1 → 2-2)
- ethtool: 2500 Mb/s Full Duplex 정상 협상
- iperf v2 (MTU 9000): TX 2.26 Gbit/s, RX 2.45 Gbit/s (이론 91%/98%)
- DSM ifcfg가 슬롯 기반으로 eth2 자리 자동 매핑 → 이름/IP/MTU 승계
- watchdog 그대로 유효, 새 카드도 RTL8157 계열이므로 LPM 재발 모니터링 대상
2026-05-20 15:41:31 +09:00

14 KiB
Raw Blame History

title, updated, tags
title updated tags
NAS StorageClass (NFS + iSCSI) 2026-05-20 eth2 USB 2.5GbE 카드 교체 반영 (rev 17 → rev 14, USB 4-1 → 2-2, 라인레이트 재검증)
infra
k3s
storage
nfs
iscsi
synology

개요

Synology NAS(DS916+)를 K3s NFS/iSCSI StorageClass로 사용. Longhorn(로컬 블록)과 병행하여 파일 저장소, 웹소스 등 대용량/RWX 워크로드에 사용.

NAS 정보

항목
모델 Synology DS916+ (Braswell, x86_64, Linux 3.10.108)
bond0 (eth0+eth1, 1G×2) 192.168.9.100 — 관리/SMB/DSM 웹
eth2 (USB 2.5G, RTL8157, r8152) 192.168.205.100 — NFS/iSCSI 데이터 플레인, MTU 9000. 현재 카드: chip rev 14, MAC c8:4d:44:27:a9:63, USB 포트 2-2 (2026-05-20-nas-eth2-replacement)
디스크 11TB (사용 2%)
NFS export /volume1/k3s-nfs
NFS 옵션 rw,async,no_wdelay,crossmnt,no_root_squash,insecure_locks,sec=sys,anonuid=1025,anongid=100

K3s 노드는 모두 192.168.205.0/24 서브넷에 참여하고 있음 (2026-04-14 검증):

노드 출구 NIC src IP
incus-kr1 enp7s0 (PCIe 2.5G) 192.168.205.214
incus-kr2 enx803f5dd34c9f (USB 2.5G) 192.168.205.135
incus-hp2 ens2 192.168.205.134

K3s 설정

항목
StorageClass nfs (default 아님, 명시 지정 필요)
Provisioner nfs-subdir-external-provisioner (Helm)
Namespace nfs-provisioner
NFS 경로 /volume1/k3s-nfs
마운트 옵션 soft,timeo=50,retrans=3
archiveOnDelete true (PVC 삭제 시 데이터 archived- 접두사로 보존)
nodeAffinity 없음 (제약 없이 배포) — 2026-04-14 기준 Deployment에 nodeSelector/affinity 미설정. 3 노드(kr1/kr2/hp2) 전부 192.168.205.0/24 도달 가능해 스케줄 자유

Helm 설치 명령

export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner
helm install nfs-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
  --namespace nfs-provisioner --create-namespace \
  --set nfs.server=192.168.205.100 \
  --set nfs.path=/volume1/k3s-nfs \
  --set storageClass.name=nfs \
  --set storageClass.defaultClass=false \
  --set storageClass.reclaimPolicy=Delete \
  --set storageClass.archiveOnDelete=true \
  --set nfs.mountOptions[0]=soft \
  --set nfs.mountOptions[1]=timeo=50 \
  --set nfs.mountOptions[2]=retrans=3

PVC 사용 예시

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-data
spec:
  storageClassName: nfs
  accessModes: [ReadWriteMany]
  resources:
    requests:
      storage: 10Gi

성능 (fio 벤치마크, 2026-04-05)

테스트 IOPS 대역폭 레이턴시
Random Read 4K 20.6K 84 MB/s 1.5 ms
Random Write 4K 18.1K 74 MB/s 1.8 ms
Seq Read 1M 263 276 MB/s 30 ms
Seq Write 1M 275 288 MB/s 29 ms

용도별 StorageClass 선택

용도 StorageClass 이유
DB (PostgreSQL, etcd, Redis) longhorn 저레이턴시 블록 필요
파일 업로드, 사용자 데이터 nfs 대용량, RWX 지원
웹소스, 정적 파일 nfs 대용량, 여러 Pod 공유
로그, 임시 데이터 longhorn/local-path 빠른 쓰기

파일 소유권

  • no_root_squash 설정으로 root 컨테이너는 소유권 문제 없음
  • 비-root 컨테이너는 Pod securityContext.fsGroup으로 제어

NFS hard vs soft

  • hard: NAS 끊기면 무한 대기 → 서버 먹통
  • soft: 타임아웃 후 에러 반환 → 서버 생존

모든 NFS 마운트는 soft,timeo=50,retrans=3 필수. 인시던트 이력: 2026-04-04-usb-25g-hang

iSCSI StorageClass (democratic-csi)

Synology NAS의 iSCSI를 K3s 블록 스토리지로 사용. democratic-csi가 PVC 생성/삭제 시 자동으로 iSCSI Target + LUN을 관리.

항목
StorageClass synology-iscsi
CSI Driver democratic-csi (Helm)
Namespace democratic-csi
iSCSI Portal 192.168.205.100:3260
Base IQN iqn.2000-01.com.synology:NAS.k3s.
LUN 타입 BLUN (Btrfs thin provisioning)
Volume /volume1
인증 kaffa 계정 (HTTPS API)
자동 관리 PVC 생성 → Target+LUN 생성, PVC 삭제 → Target+LUN 삭제

Helm 설치

values 파일: /tmp/democratic-csi-values.yaml (kr1)

export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
helm repo add democratic-csi https://democratic-csi.github.io/charts/
helm install synology-iscsi democratic-csi/democratic-csi \
  --namespace democratic-csi --create-namespace \
  -f /tmp/democratic-csi-values.yaml

ScsiTarget 서비스의 on-demand 동작 (중요)

DSM의 ScsiTarget 패키지는 LIO(kernel configfs) 기반이며, Target이 0개이면 3260 포트를 LISTEN하지 않는다. 이건 고장이 아니라 LIO의 정상 동작.

  • PVC 없는 상태 → netstat -lnt | grep 3260 비어있음
  • PVC 생성 → democratic-csi가 Synology API로 Target+LUN 자동 생성 → configfs에 Target 등록 → 3260 자동 LISTEN
  • PVC 삭제 → Target/LUN 자동 제거 → Target 0개 되면 3260 닫힘

따라서 "3260 포트가 안 열려있다"만으로 장애 판단 금지. Target 존재 여부 먼저 확인:

# NAS에서
find /sys/kernel/config/target/iscsi -maxdepth 2 -type d
sudo synopkg status ScsiTarget   # "running"이어야 함

2026-04-14 smoke test 결과

단계 결과
PVC 생성 (1Gi, synology-iscsi) → Bound 30초
Target + LUN 자동 생성 OK (democratic-csi → Synology HTTPS API)
3260 LISTEN OK (Target 등록과 동시에)
discovery (kr1/kr2/hp2 전부) OK (양 포털 192.168.205.100 + 192.168.9.100)
PVC 삭제 → PV Released → DeleteVolume → PV gone OK

2026-04-14 이전 며칠간 ScsiTarget이 stop 상태로 방치되어 있었음. 원인 미확인(/var/log/synopkg.log 로그 기준 3/24 부팅 이후 stop 기록 없지만 실제 상태는 stop). 수동 sudo synopkg start ScsiTarget로 복구. 실제 소비자 PVC는 계속 0건이라 서비스 영향 없었음.

전체 StorageClass 요약

StorageClass 방식 용도 HA
longhorn 로컬 NVMe 블록 DB, 고성능 블록 노드 간 레플리카
synology-iscsi NAS iSCSI 블록 블록 스토리지 (NAS) RAID5
nfs NAS NFS 파일 파일, 웹소스, RWX RAID5
local-path 로컬 디스크 캐시, 임시 없음

Jumbo Frame (MTU 9000) 설정 (2026-04-05)

모든 NAS 전용 경로에 MTU 9000 적용. 스위치 포함 전체 경로가 JF 지원.

장비 인터페이스 MTU 설정 위치
kr1 enp7s0 (PCIe 2.5GbE) 9000 /etc/systemd/network/20-enp7s0.network
kr2 enx803f5dd34c9f (USB 2.5GbE) 9000 /etc/systemd/network/30-usb-2g5.network
hp2 ens2 9000 (설정 위치 확인 필요)
NAS eth2 (USB 2.5GbE) 9000 Synology DSM 네트워크 설정

2026-04-14 end-to-end JF 검증

ping -M do -s 8972(DF bit, 9000B 프레임) 전 구간 통과:

경로 결과 avg RTT
kr1 → NAS 2/2 0.46ms
kr2 → NAS 2/2 0.44ms
hp2 → NAS 2/2 0.47ms
kr1 → kr2 2/2 1.09ms
kr1 → hp2 2/2 0.54ms
hp2 → kr2 2/2 0.46ms

스위치 포함 전 경로 9000B fragmentation 없이 통과. 노드 간(kr1↔kr2, kr1↔hp2 등)도 JF 동작 — storage 전용망 외 노드 간 통신에도 활용 가능.

NAS eth2 USB NIC watchdog (2026-04-14)

NAS의 eth2(USB 2.5G, RTL8157)가 USB 3.0 LPM exit latency 미보고 이슈로 간헐적 disconnect 발생 (21일 uptime 기준 2회). 드라이버는 자동 reconnect하지만 인터페이스가 DOWN 상태로 남아 네트워크 서비스 중단.

근본 원인: DSM 3.10.108 커널의 xHCI 호스트 컨트롤러가 LPM U1/U2 exit latency descriptor를 OS에 노출하지 않음 → 링크 절전 복귀 타이밍 불일치 → -71 EPROTO → USB disconnect. DS916+ 하드웨어/커널 조합의 근본적 한계로 드라이버 업데이트·커널 교체로 해결 불가.

대응: cron watchdog

항목
스크립트 /usr/local/bin/eth2-watchdog.sh (root:755)
주기 1분 (root cron, /etc/crontab)
로그 /var/log/eth2-watchdog.log
영속성 /dev/md0 ext4 root, 재부팅 유지 (DSM 메이저 업그레이드 시 재확인 필요)

동작:

  1. /sys/class/net/eth2/operstate 확인
  2. up이 아니면 ip link set eth2 up (IP는 DSM ifcfg-eth2가 자동 할당)
  3. UP 후 IP 없으면 ip addr add 192.168.205.100/24 dev eth2
  4. MTU ≠ 9000 이면 보정

검증 기록

  • 2026-04-14 강제 down 테스트: 1분 내 watchdog 실행 → ip link up → DSM ifcfg 자동 IP 할당 → 정상 복귀 (MTU 9000 유지)
  • Outline 상세 기록: 2026-04-14 / NAS eth2 watchdog 구축 / kappa (id 93baf66b-f003-47a9-9d14-7a66e3dbfde0)
  • RCA 문서: 2026-04-14 / NAS eth2 USB NIC 링크 드롭 원인 조사 / kappa (id db923170-8c16-459d-82ce-46fdc1f0f0d0)
  • 2026-05-20 카드 물리 교체 (chip rev 17 → 14, USB 4-1 → 2-2). 인터페이스 이름/IP/MTU 모두 승계, watchdog 그대로 유효. iperf v2 검증 결과 TX 2.26 Gbit/s, RX 2.45 Gbit/s (이론 91%/98%) — 2026-05-20-nas-eth2-replacement. 새 카드도 동일 RTL8157 계열이라 LPM 이슈 재발 가능, watchdog 발화 빈도 모니터링 대상

kr2 USB NIC 드라이버 (r8152 DKMS)

kr2의 USB 2.5GbE 어댑터(Realtek RTL8157, 0bda:8157)는 커널 기본 cdc_ncm 드라이버로 잡히면 Half Duplex + MTU 1500 제한. DKMS r8152 드라이버(v2.21.4)를 설치하여 Full Duplex + Jumbo Frame 지원.

  • DKMS 패키지: linux-headers-$(uname -r) 설치 시 자동 빌드
  • udev 규칙: /etc/udev/rules.d/50-usb-realtek-net.rules — USB config를 1로 설정하여 r8152가 바인딩
  • 커널 업데이트 시 DKMS가 자동으로 재빌드

주의사항

  • Jumbo Frame은 경로 전체(NIC → 스위치 → NIC)가 지원해야 함. 미지원 스위치가 중간에 있으면 프레임 드롭
  • ping -M do -s 8972 로 end-to-end JF 동작 확인 가능

DSM Reverse Proxy — nas.inouter.com

LAN 전용으로 Synology DSM 웹 UI 접근. nas.inouter.com*.inouter.com 와일드카드 폴백으로 k3s.inouter.com (192.168.9.53, Traefik MetalLB VIP) 로 해석되고, Traefik 에서 이 호스트를 Synology NAS 로 reverse proxy 한다.

항목
Namespace lan-proxies (신규 — LAN-only 리버스 프록시 전용)
Service nas (selector 없는 ClusterIP) + EndpointSlice → 192.168.9.100:5000
Backend Synology DSM HTTP (포트 5000, 평문)
Traefik IngressRoute nas (web entrypoint, redirect → https), nas-tls (websecure entrypoint)
Middleware redirect-https (redirectScheme.scheme=https permanent=true)
TLS 기존 wildcard wildcard-inouter-tls (cert-manager + emberstack reflector 자동 복제)
외부 노출 LAN-only — 와일드카드 *.inouter.com 가 사설 IP 192.168.9.53 로 폴백되므로 인터넷 라우팅 없음

ExternalName 대신 Service+EndpointSlice 사용 이유

요구사항은 "ExternalName Service" 였으나 Kubernetes ExternalName 은 RFC1123 DNS 호스트네임만 허용하고 IP(192.168.9.100)는 거부. 동등한 K8s-native 패턴인 selector-less Service + 수동 EndpointSlice 로 구현. CoreDNS 가 ClusterIP 를 정상 발행하고 kube-proxy 가 EndpointSlice 의 외부 IP 로 분산.

매니페스트

원본: /tmp/nas-reverse-proxy.yaml (heimdall). 핵심 발췌 — 전체 6 객체.

apiVersion: v1
kind: Namespace
metadata:
  name: lan-proxies
  labels:
    purpose: lan-only-reverse-proxy
---
apiVersion: v1
kind: Service
metadata: { name: nas, namespace: lan-proxies }
spec:
  type: ClusterIP
  ports:
    - { name: dsm-http, port: 5000, targetPort: 5000, protocol: TCP }
---
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
  name: nas
  namespace: lan-proxies
  labels: { kubernetes.io/service-name: nas }
addressType: IPv4
ports:
  - { name: dsm-http, port: 5000, protocol: TCP }
endpoints:
  - addresses: [192.168.9.100]
    conditions: { ready: true }
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata: { name: redirect-https, namespace: lan-proxies }
spec:
  redirectScheme: { scheme: https, permanent: true }
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata: { name: nas, namespace: lan-proxies }
spec:
  entryPoints: [web]
  routes:
    - kind: Rule
      match: Host(`nas.inouter.com`)
      middlewares: [{ name: redirect-https }]
      services: [{ name: nas, port: 5000 }]
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata: { name: nas-tls, namespace: lan-proxies }
spec:
  entryPoints: [websecure]
  routes:
    - kind: Rule
      match: Host(`nas.inouter.com`)
      services: [{ name: nas, port: 5000 }]
  tls:
    secretName: wildcard-inouter-tls

동작 검증

curl -sk --resolve nas.inouter.com:80:192.168.9.53  http://nas.inouter.com/   # → 301 https://nas.inouter.com/
curl -sk --resolve nas.inouter.com:443:192.168.9.53 https://nas.inouter.com/  # → 200, 12094B
#   <title>NAS - Synology DiskStation</title>

주의사항

  • LAN-only. *.inouter.com 가 사설 192.168.9.53 으로 가는 한 외부 인터넷에서는 도달 불가. 외부 노출 시 보안/인증 재검토 필요 (Synology DSM 직노출은 CVE 노출면 큼).
  • DSM HTTPS(5001) 도 동일 호스트에서 200 응답하지만 자기서명 인증서 + 이중 TLS 종료라 백엔드는 평문 5000 사용.
  • Traefik 리버스 프록시 패턴은 lan-proxies ns 에 추가 LAN 서비스(예: 스위치/라우터/NAS 부속 UI) 적층 가능.

관련 문서