ONTAP SnapMirror 복제 — 관계는 만들었는데 전송이 안 될 때

ONTAP SnapMirror 관계를 만들었는데 목적지에 아무것도 넘어오지 않습니다. 또는 넘어가긴 하는데 원본에 있는 시간당 스냅샷이 DR에는 하나도 없습니다. 둘 다 흔한 상황이고, 원인은 서로 다른 곳에 있습니다.

이 글은 준비 순서를 일부러 틀려가며 어디서 막히는지, 그때 에러가 어디에 찍히는지를 실제 출력으로 확인한 기록입니다. 정책(비동기·동기)과 SnapMirror 라벨이 무엇을 결정하는지도 대조 실험으로 짚었습니다.

SnapMirror 준비 순서 네 단계(인터클러스터 LIF, 클러스터 피어링, SVM 피어링, 관계 생성과 초기화)와 비동기·동기 정책의 차이, 스냅미러 라벨이 붙은 스냅샷만 목적지로 복제된다는 것을 나타낸 그림
준비는 네 칸을 순서대로 쌓아야 한다. 그리고 전송이 시작된 뒤에도 라벨이 없는 스냅샷은 넘어가지 않는다.

이 글의 실습 환경과 범위

이 글은 ONTAP Simulator 9.17.1 기반 가상 랩에서 직접 명령을 실행하고 그 출력을 근거로 작성했습니다. 실제 장비(FAS/AFF)와는 지원 기능·성능·하드웨어 동작에서 차이가 있으며, ONTAP 버전에 따라 명령과 출력이 달라집니다.

구성
스토리지ONTAP Simulator 9.17.1, 2노드 클러스터 cluster1
원본NFS_SVM:nfs_vol1 1GB — 애그리게이트 N2_data
목적지DR_SVM:nfs_vol1_dr 1GB — 애그리게이트 N1_data

확인을 위해 두 번째 클러스터를 하나 더 세웠습니다. 단일 노드짜리 drcluster 입니다. 그래서 이 글의 명령과 출력은 인터클러스터 LIF부터 클러스터 간 SnapMirror까지 전부 실제로 실행한 것입니다.

클러스터구성인터클러스터 LIF
cluster12노드 (원본)192.168.126.24, 192.168.126.25
drcluster1노드 (목적지)192.168.126.60

1. 준비 순서 — 아래에서 위로 쌓는다

실무의 SnapMirror는 다른 사이트의 클러스터로 보냅니다. 그래서 관계를 만들기 전에 네트워크와 신뢰 관계를 먼저 세워야 합니다. 한 칸을 건너뛰면 다음 명령이 거부됩니다.

순서무엇을어디에
1인터클러스터 LIF양쪽 클러스터의 모든 노드
2클러스터 피어링 cluster peer create양쪽 클러스터
3SVM 피어링 vserver peer create원본 SVM ↔ 목적지 SVM
4관계 생성 · 초기화 snapmirror createinitialize목적지 클러스터에서

1-1. ⭐ 인터클러스터 LIF는 클러스터 관리 SVM에 만든다

클러스터끼리 주고받는 트래픽은 데이터 LIF가 아니라 인터클러스터 LIF를 탑니다. NetApp 문서는 “피어링하는 클러스터의 모든 노드에 인터클러스터 LIF를 만들어야 한다”고 명시합니다. [문서확인] 한 노드라도 빠지면 그 노드가 관여하는 전송이 실패합니다.

여기서 가장 헷갈리는 것이 -vserver 에 무엇을 넣느냐입니다. LIF가 올라갈 자리는 특정 노드의 포트인데, -vserver 는 노드가 아니라 관리 LIF들이 올라가 있는 클러스터 관리 SVM 입니다.

cluster1::> vserver show -fields vserver,type

vserver      type
------------ -----
NFS_SVM      data
cluster1     admin      <-- 인터클러스터 LIF 는 여기에
cluster1-01  node       <-- 여기가 아니다
cluster1-02  node

노드 SVM을 넣으면 이렇게 거부됩니다.

cluster1::> network interface create -vserver cluster1-01 -lif ic_wrong -service-policy default-intercluster -home-node cluster1-01 -home-port e0d -address 192.168.126.26 -netmask 255.255.255.0

Error: command failed: LIF creation on a Node Vserver is disallowed.

노드는 -home-node 로 지정하고, -vserver 에는 클러스터 관리 SVM을 넣습니다. 둘을 같은 것으로 착각하기 쉬운데, 에러 메시지(LIF creation on a Node Vserver is disallowed)가 이유를 정확히 말해주지 않아서 한 번은 걸립니다.

제대로 만들면 이렇습니다. 노드가 둘이므로 두 개를 만듭니다.

cluster1::> network interface create -vserver cluster1 -lif ic_lif_01 -service-policy default-intercluster -home-node cluster1-01 -home-port e0d -address 192.168.126.24 -netmask 255.255.255.0

cluster1::> network interface create -vserver cluster1 -lif ic_lif_02 -service-policy default-intercluster -home-node cluster1-02 -home-port e0d -address 192.168.126.25 -netmask 255.255.255.0

cluster1::> network interface show -role intercluster

            Logical    Status     Network            Current       Current Is
Vserver     Interface  Admin/Oper Address/Mask       Node          Port    Home
----------- ---------- ---------- ------------------ ------------- ------- ----
cluster1
            ic_lif_01    up/up    192.168.126.24/24  cluster1-01   e0d     true
            ic_lif_02    up/up    192.168.126.25/24  cluster1-02   e0d     true

만들 때 이런 경고가 같이 나옵니다. 랩처럼 포트가 하나뿐이면 넘어가도 되지만, 운영에서는 페일오버 그룹을 제대로 잡아야 노드 하나가 빠져도 인터클러스터 경로가 유지됩니다.

Warning: The configured failover-group has no valid failover targets for the
         LIF's failover-policy. To view the failover targets for a LIF, use the
         "network interface show -failover" command.

핵심 인자는 -service-policy default-intercluster 입니다. 이 정책이 실제로 무엇을 여는지 보면 이렇습니다.

cluster1::> network interface service-policy show -vserver cluster1 -policy default-intercluster

                   Vserver: cluster1
               Policy Name: default-intercluster
         Included Services: intercluster-core, management-https,
                            backup-ndmp-control

문서 기준으로 인터클러스터 LIF는 intercluster-core 서비스를 제공하는 LIF이고, 보통 이 기본 서비스 정책으로 만듭니다. [문서확인] 위 출력이 그 정의를 그대로 보여줍니다.

방화벽도 같이 봐야 합니다. 문서는 양방향으로 시작되는 TCP 통신이 포트 11104, 11105 에서 열려 있어야 하고, 로컬의 모든 인터클러스터 LIF가 원격의 모든 인터클러스터 LIF와 통신할 수 있어야 한다고 못박습니다. [문서확인] 방화벽이 한 방향만 열려 있어 피어링이 안 되는 사례가 여기서 나옵니다.

1-2. 클러스터 피어링 — 패스프레이즈를 주고받는다

원본 클러스터에서 상대의 인터클러스터 IP를 주고 패스프레이즈를 발급받습니다.

cluster1::> cluster peer create -address-family ipv4 -peer-addrs 192.168.126.60 -generate-passphrase

Notice:
        Passphrase: d4yviqpFBiTgroE9A1GEiMbh
        Expiration Time: 8/28/2026 13:04:29 +09:00
        Intercluster LIF IP: 192.168.126.24
        Peer Cluster Name: drcluster

        Warning: make a note of the passphrase - it cannot be displayed again.

패스프레이즈에는 만료 시각이 있습니다. 기본 1시간이고, 다시 보여주지 않습니다. 상대 클러스터 담당자가 따로 있다면 그 안에 전달해야 합니다.

이제 목적지 클러스터에서 같은 패스프레이즈로 수락합니다. 여기서 한 번 걸립니다.

drcluster::> cluster peer create -address-family ipv4 -peer-addrs 192.168.126.24,192.168.126.25 -passphrase <패스프레이즈>

Error: invalid argument "-passphrase"

-passphrase 는 명령줄 인자로 받지 않습니다. 명령을 치면 ONTAP이 프롬프트로 되물어서 입력받습니다. 스크립트로 자동화하려면 이 방식이 막히므로 REST API(POST /api/cluster/peers)를 쓰는 편이 낫습니다. -peer-cluster-name 도 존재하지 않는 인자입니다.

$ curl -sk -u "admin:***" -X POST "https://<목적지 관리 IP>/api/cluster/peers" -H "Content-Type: application/json" -d '{ "remote": { "ip_addresses": ["192.168.126.24","192.168.126.25"] }, "authentication": { "passphrase": "<패스프레이즈>" } }'

⭐ 양쪽에서 각각 확인한다

cluster1::> cluster peer show

Peer Cluster Name         Cluster Serial Number Availability   Authentication
------------------------- --------------------- -------------- --------------
drcluster                 1-80-000011           Available      ok


drcluster::> cluster peer show

Peer Cluster Name         Cluster Serial Number Availability   Authentication
------------------------- --------------------- -------------- --------------
cluster1                  1-80-000008           Available      ok

한쪽만 보고 넘어가면 안 됩니다. Availability: AvailableAuthentication: ok양쪽 클러스터에서 각각 확인합니다. 한쪽만 정상인 상태로 진행하면 SVM 피어링이나 전송에서 뒤늦게 막히고, 그때는 원인이 여기라는 걸 떠올리기 어렵습니다.

-instance 로 보면 경로와 암호화까지 드러납니다.

cluster1::> cluster peer show -instance

                       Peer Cluster Name: drcluster
           Remote Intercluster Addresses: 192.168.126.60
      Availability of the Remote Cluster: Available
                     Remote Cluster Nodes: drcluster-01
                   Remote Cluster Health: true
                 Unreachable Local Nodes: -
    Authentication Status Administrative: use-authentication
       Authentication Status Operational: ok
            IPspace for the Relationship: Default
Encryption Protocol For Inter-Cluster Communication: tls-psk
  Algorithm By Which the PSK Was Derived: jpake

인터클러스터 통신은 tls-psk 로 암호화되고, 그 사전 공유 키는 jpake 로 유도됩니다. 아까 주고받은 패스프레이즈가 여기에 쓰입니다. Unreachable Local Nodes 가 비어 있는지도 같이 봐야 합니다 — 여기에 노드 이름이 찍히면 그 노드의 인터클러스터 LIF에 문제가 있다는 뜻입니다.

2. SVM 피어링 — 없으면 여기서 즉시 거부된다

여기부터는 랩에서 직접 실행한 결과입니다. 클러스터가 하나라 1·2단계 없이 목적지 SVM과 DP 볼륨을 만들고 바로 관계를 걸어봤습니다.

cluster1::> vserver create -vserver DR_SVM -aggregate N1_data -rootvolume DR_SVM_root -rootvolume-security-style unix
[Job 82] Job succeeded: Vserver creation completed.

cluster1::> volume create -vserver DR_SVM -volume nfs_vol1_dr -aggregate N1_data -size 1GB -type DP
[Job 83] Job succeeded: Successful

cluster1::> snapmirror create -source-path NFS_SVM:nfs_vol1 -destination-path DR_SVM:nfs_vol1_dr -type XDP

Error: command failed: Vservers "NFS_SVM" and "DR_SVM" are not peered. Either
       they are not in a Vserver peer relationship, the "Peer State" of the
       relationship is not "peered", the "snapmirror" application is not
       supported by the relationship or "NFS_SVM" is not the local name for the
       peer-vserver.

이 에러는 친절한 편입니다. 명령이 즉시 거부되고 원인 후보 네 가지를 다 적어줍니다. 특히 “snapmirror 애플리케이션이 지원되지 않는다” 는 경우 — 피어 관계는 있는데 -applications snapmirror 를 빼먹었을 때입니다.

cluster1::> vserver peer create -vserver NFS_SVM -peer-vserver DR_SVM -applications snapmirror
Info: "vserver peer create" command is successful.

cluster1::> vserver peer show

            Peer        Peer                           Peering        Remote
Vserver     Vserver     State        Peer Cluster      Applications   Vserver
----------- ----------- ------------ ----------------- -------------- ---------
DR_SVM      NFS_SVM     peered       cluster1          snapmirror     NFS_SVM
NFS_SVM     DR_SVM      peered       cluster1          snapmirror     DR_SVM

같은 클러스터 안이라 바로 peered 가 됐습니다. 그런데 클러스터가 다르면 여기서 멈춥니다. 같은 명령을 drcluster 의 SVM을 상대로 걸어봤습니다.

cluster1::> vserver peer create -vserver NFS_SVM -peer-vserver DR2_SVM -peer-cluster drcluster -applications snapmirror
Info: [Job 87] 'vserver peer create' job queued

cluster1::> vserver peer show
Vserver     Peer Vserver  State          Peer Cluster   Applications
----------- ------------- -------------- -------------- ------------
NFS_SVM     DR_SVM        peered         cluster1       snapmirror
NFS_SVM     DR2_SVM       initializing   drcluster      snapmirror

같은 관계인데 보는 쪽에 따라 상태 이름이 다릅니다. 요청한 쪽에서는 initializing, 수락해야 하는 쪽에서는 pending 으로 보입니다. 원본 클러스터만 들여다보면 “초기화 중인가 보다” 하고 기다리게 되는데, 실제로는 상대 쪽 승인을 기다리는 중입니다.

drcluster::> vserver peer show
Vserver     Peer Vserver  State      Peer Cluster   Applications
----------- ------------- ---------- -------------- ------------
DR2_SVM     NFS_SVM       pending    cluster1       snapmirror

drcluster::> vserver peer accept -vserver DR2_SVM -peer-vserver NFS_SVM
Info: [Job 34] 'vserver peer accept' job queued

수락하고 나면 양쪽 모두 peered 가 됩니다.

cluster1::>  NFS_SVM   DR2_SVM   peered   drcluster   snapmirror
drcluster::> DR2_SVM   NFS_SVM   peered   cluster1    snapmirror

클러스터 간에서는 -peer-cluster 인자가 하나 더 필요하다는 것도 차이입니다. 같은 클러스터 안이면 생략합니다.

3. ⭐ 목적지는 DP 볼륨 — 그런데 create 는 성공한다

이 글에서 가장 볼 만한 지점입니다. 일반 RW 볼륨을 목적지로 지정해봤습니다.

cluster1::> volume create -vserver DR_SVM -volume wrong_dr -aggregate N1_data -size 1GB
[Job 84] Job succeeded: Successful

cluster1::> snapmirror create -source-path NFS_SVM:nfs_vol1 -destination-path DR_SVM:wrong_dr -type XDP
Operation succeeded: SnapMirror create for the relationship with destination "DR_SVM:wrong_dr".

cluster1::> snapmirror initialize -destination-path DR_SVM:wrong_dr
Operation is queued: SnapMirror initialize of destination "DR_SVM:wrong_dr".

둘 다 성공했다고 답합니다. 타입이 틀렸는데 경고 한 줄 없습니다. 실패는 몇 초 뒤 다른 곳에 찍힙니다.

cluster1::> snapmirror show -destination-path DR_SVM:wrong_dr -fields state,status,healthy,last-transfer-error

source-path      destination-path state      status healthy last-transfer-error
---------------- ---------------- ---------- ------ ------- -----------------------------------------------------------
NFS_SVM:nfs_vol1 DR_SVM:wrong_dr  Broken-off Idle   false   Destination DR_SVM:wrong_dr must be a data-protection volume.

명령 두 개가 모두 “성공”이라고 답했는데 결과는 Broken-off 입니다. 진짜 원인은 last-transfer-error 필드에만 있고, snapmirror show 를 옵션 없이 치면 이 필드가 안 나옵니다. 그래서 “관계는 있는데 왜 전송이 안 되지” 상태로 한참 헤매게 됩니다.

cluster1::> snapmirror show -fields state,status,healthy,unhealthy-reason,last-transfer-error

4. 세 번째 함정 — 스케줄은 베이스라인을 대신 해주지 않는다

cluster1::> snapmirror create -source-path NFS_SVM:nfs_vol1 -destination-path DR_SVM:nfs_vol1_dr -type XDP -schedule hourly

cluster1::> snapmirror show -fields state,status,healthy,schedule

source-path      destination-path   schedule state         status healthy
---------------- ------------------ -------- ------------- ------ -------
NFS_SVM:nfs_vol1 DR_SVM:nfs_vol1_dr hourly   Uninitialized Idle   true

스케줄이 hourly 로 붙어 있는데도 Uninitialized 입니다. 베이스라인 전송은 스케줄이 해주지 않습니다. snapmirror initialize 를 한 번 직접 쳐야 하고, 그 뒤부터 스케줄이 증분을 돌립니다.

$ sudo dd if=/dev/urandom of=/mnt/ontap-nfs/dataA.dat bs=1M count=100

cluster1::> snapmirror initialize -destination-path DR_SVM:nfs_vol1_dr

cluster1::> snapmirror show -fields state,status,healthy,last-transfer-size,last-transfer-duration
source-path      destination-path   state        status healthy last-transfer-size last-transfer-duration
---------------- ------------------ ------------ ------ ------- ------------------ ----------------------
NFS_SVM:nfs_vol1 DR_SVM:nfs_vol1_dr Snapmirrored Idle   true    102.5MB            0:0:24

4-1. 클러스터 간이면 경로 표기가 달라진다

피어링이 끝났으니 실제로 클러스터를 넘어 걸어봤습니다. 관계는 목적지 클러스터에서 만듭니다.

drcluster::> volume create -vserver DR2_SVM -volume nfs_vol1_xc -aggregate DR_data -size 1GB -type DP

drcluster::> snapmirror create -source-path cluster1://NFS_SVM/nfs_vol1 -destination-path drcluster://DR2_SVM/nfs_vol1_xc -type XDP -policy MirrorAllSnapshots

Operation succeeded: SnapMirror create for the relationship with destination "DR2_SVM:nfs_vol1_xc".

경로가 SVM:볼륨 에서 클러스터://SVM/볼륨 로 바뀝니다. 같은 클러스터 안이면 앞의 짧은 형식을 쓰고, 클러스터를 넘으면 긴 형식을 씁니다. 이걸 모르고 짧은 형식으로 치면 상대 클러스터의 SVM을 못 찾습니다.

초기화하면 인터클러스터 LIF를 타고 실제로 넘어갑니다.

drcluster::> snapmirror initialize -destination-path DR2_SVM:nfs_vol1_xc

drcluster::> snapmirror show -fields state,status,healthy
source-path      destination-path    state        status       healthy
---------------- ------------------- ------------ ------------ -------
NFS_SVM:nfs_vol1 DR2_SVM:nfs_vol1_xc Snapmirrored Transferring true

그런데 이 전송이 한참 동안 끝나지 않았습니다. snapmirror show 만 보면 Transferring 에서 멈춘 것처럼 보이고, last-transfer-size이전 전송 값이라 움직이지 않습니다. 이럴 때 봐야 하는 건 -instance 입니다.

drcluster::> snapmirror show -destination-path DR2_SVM:nfs_vol1_xc -instance

                      SnapMirror Policy: MirrorAllSnapshots
                           Mirror State: Snapmirrored
                    Relationship Status: Transferring
                      Transfer Snapshot: hourly.2026-08-28_0705   <-- 지금 넘기는 스냅샷
                      Snapshot Progress: 15.52MB
                         Total Progress: 15.53MB
                    Snapshot Checkpoint: 2.79MB
                        Newest Snapshot: daily.2026-08-28_0010
                      Exported Snapshot: daily.2026-08-27_0910
                                Healthy: true
                         Transfer Error: -
                     Last Transfer Size: 18.59KB   <-- 직전 전송 값. 지금 것이 아니다

진행 중인 전송의 양은 Total Progress 에 있습니다. last-transfer-size끝난 전송의 크기라 진행 중에는 갱신되지 않습니다. 둘을 혼동하면 “전송이 멈췄다”고 오판합니다. Transfer Error 가 비어 있고 Total Progress 가 늘고 있으면 느린 것이지 멈춘 것이 아닙니다.

느린 이유는 정책에 있었습니다. MirrorAllSnapshots 는 이름 그대로 원본의 스냅샷을 전부 넘깁니다. 원본에 시간당 스냅샷이 쌓여 있으면 그 개수만큼 순차로 전송합니다. Transfer Snapshot 필드가 지금 어느 스냅샷을 넘기는 중인지 알려줍니다.

최신 상태만 필요하다면 MirrorLatest 를 쓰면 베이스라인이 훨씬 짧습니다. “스냅샷 이력까지 DR에 둘 것인가”가 정책 선택의 실제 기준이고, 그 대가가 이 시간입니다.

한 가지 더 — SnapMirror 라이선스는 양쪽 클러스터에 각각 필요합니다. 새로 세운 drcluster 에는 라이선스가 없어서 따로 넣어야 했습니다. 원본에만 있으면 되는 것이 아닙니다.

drcluster::> system license show -package SnapMirror
There are no entries matching your query.

drcluster::> system license add -license-code <SnapMirror 키>
License for package "SnapMirror" and serial number "1-81-...4082368507" installed.

5. 정책 — 비동기냐 동기냐를 여기서 정한다

SnapMirror의 동작은 관계에 붙은 정책이 결정합니다. 9.17.1에 기본 제공되는 정책을 그대로 옮기면 이렇습니다.

cluster1::> snapmirror policy show -fields policy,type

vserver  policy                    type
-------- ------------------------- -------------------------
cluster1 MirrorAllSnapshots        async-mirror
cluster1 MirrorLatest              async-mirror
cluster1 DPDefault                 async-mirror
cluster1 XDPDefault                vault
cluster1 DailyBackup               vault
cluster1 MirrorAndVault            mirror-vault
cluster1 Asynchronous              mirror-vault
cluster1 Unified7year              mirror-vault
cluster1 Sync                      sync-mirror
cluster1 StrictSync                strict-sync-mirror
cluster1 AutomatedFailOver         automated-failover
cluster1 AutomatedFailOverDuplex   automated-failover-duplex
17 entries were displayed.
구분타입
비동기async-mirrorDR용 미러. 원본 상태를 그대로 따라간다
vault백업용. 라벨이 붙은 스냅샷을 오래 보관한다
mirror-vault둘을 합친 것. 최신 상태 + 라벨 스냅샷 보관
동기sync-mirror복제 실패 시 클라이언트 I/O는 계속된다
strict-sync-mirror복제 실패 시 클라이언트 I/O도 실패시킨다

NetApp 문서는 이 차이를 이렇게 정리합니다 — Sync 모드에서는 애플리케이션 I/O가 주 스토리지와 보조 스토리지에 병렬로 전달되고, 보조 쪽 쓰기가 어떤 이유로든 완료되지 않아도 애플리케이션은 주 스토리지에 계속 쓸 수 있습니다. 반면 StrictSync 모드는 보조 쪽 쓰기가 실패하면 애플리케이션 I/O를 실패시켜 양쪽이 항상 동일하도록 보장합니다. [문서확인]

StrictSync는 “데이터 일치”를 위해 “서비스 중단”을 감수하는 선택입니다. 금융 원장처럼 한 건도 어긋나면 안 되는 데이터가 아니면 보통 Sync를 씁니다.

실제로 걸어보면 상태 표시가 다르다

같은 원본에 동기식 관계를 하나 더 만들어 비동기와 나란히 놓아봤습니다.

cluster1::> volume create -vserver DR_SVM -volume sync_dr -aggregate N1_data -size 500MB -type DP
cluster1::> snapmirror create -source-path NFS_SVM:nfs_vol1 -destination-path DR_SVM:sync_dr -policy Sync
cluster1::> snapmirror initialize -destination-path DR_SVM:sync_dr

cluster1::> snapmirror show -fields state,status,policy,policy-type,lag-time

source-path      destination-path   policy-type        policy         state        status healthy lag-time
---------------- ------------------ ------------------ -------------- ------------ ------ ------- --------
NFS_SVM:nfs_vol1 DR_SVM:nfs_vol1_dr mirror-vault       MirrorAndVault Snapmirrored Idle   true    0:2:31
NFS_SVM:nfs_vol1 DR_SVM:sync_dr     sync-mirror        Sync           Snapmirrored InSync true    0:0:0

동기식은 statusInSync 이고 lag-time0:0:0 입니다. 비동기식은 Idle 이고 다음 전송까지 lag가 쌓입니다. 동기식 관계에서 InSync 가 아니면 그 자체가 경보입니다 — 비동기의 Idle 과는 의미가 완전히 다릅니다.

참고로 관계를 만들 때 -policy 를 지정하지 않으면 기본값이 붙습니다. 위 첫 줄이 그 경우로, MirrorAndVault 가 자동으로 선택됐습니다. 의도한 정책이 맞는지 snapmirror show -fields policy 로 한 번은 확인하는 편이 좋습니다.

6. ⭐ 라벨 — 왜 hourly 스냅샷은 DR에 없는가

정책 안을 열어보면 SnapMirror 라벨이라는 항목이 나옵니다. 이게 어떤 스냅샷을 복제할지를 정합니다.

cluster1::> snapmirror policy show -policy MirrorAndVault -instance

       SnapMirror Policy Name: MirrorAndVault
       SnapMirror Policy Type: mirror-vault
              Create Snapshot: true
        Total Number of Rules: 3

 Rules:
 SnapMirror Label       Keep Preserve Warn Schedule Prefix     Retention Period
 ---------------------- ---- -------- ---- -------- ---------- ----------------
 sm_created                1 false       0 -        -                         -
 daily                     7 false       0 -        -                         -
 weekly                   52 false       0 -        -                         -

규칙이 셋입니다 — SnapMirror가 스스로 만드는 스냅샷(sm_created), 그리고 라벨이 daily 인 것 7개, weekly 인 것 52개. 이 목록에 없는 라벨은 복제 대상이 아닙니다.

그럼 원본의 스냅샷 정책은 어떤 라벨을 붙이고 있을까요.

cluster1::> snapshot policy show -policy default -instance

     Snapshot Policy Name: default
    Schedule       Count  Prefix        SnapMirror Label
    -------------- -----  ------------- ------------------
    hourly             6  hourly        -                   <-- 라벨이 없다
    daily              2  daily         daily
    weekly             2  weekly        weekly

기본 스냅샷 정책의 hourly 에는 SnapMirror 라벨이 없습니다. 그래서 시간당 스냅샷을 아무리 많이 찍어도 DR에는 하나도 넘어가지 않습니다. 설정이 잘못된 게 아니라 기본값이 원래 그렇습니다.

대조 실험 — 라벨만 다른 스냅샷 두 개

변수를 하나만 남기고 확인했습니다. 같은 시점에, 라벨만 다르게 스냅샷 두 개를 만들었습니다.

cluster1::> snapshot create -vserver NFS_SVM -volume nfs_vol1 -snapshot label_daily_test -snapmirror-label daily
cluster1::> snapshot create -vserver NFS_SVM -volume nfs_vol1 -snapshot label_none_test

cluster1::> snapshot show -vserver NFS_SVM -volume nfs_vol1 -fields snapshot,snapmirror-label
vserver volume   snapshot         snapmirror-label
------- -------- ---------------- ----------------
NFS_SVM nfs_vol1 label_daily_test daily
NFS_SVM nfs_vol1 label_none_test  -
cluster1::> snapmirror update -destination-path DR_SVM:nfs_vol1_dr

cluster1::> snapshot show -vserver DR_SVM -volume nfs_vol1_dr -fields snapshot,snapmirror-label
vserver volume      snapshot                                     snapmirror-label
------- ----------- -------------------------------------------- ----------------
DR_SVM  nfs_vol1_dr snapmirror.394e013e-…_2153774456.…_110500     -
DR_SVM  nfs_vol1_dr label_daily_test                              daily
DR_SVM  nfs_vol1_dr snapmirror.394e013e-…_2153774456.…_112747     -

label_daily_test 는 넘어갔고 label_none_test 는 넘어가지 않았습니다. 데이터도, 시점도, 크기도 같습니다. 다른 것은 라벨 하나뿐입니다.

실제로 원본에는 hourly 스냅샷이 6개 있었지만 목적지에는 SnapMirror가 만든 것과 라벨 붙은 것만 있었습니다. “DR에 시간당 복구 지점이 있을 것”이라고 믿고 있다가 사고 때 발견하면 늦습니다.

시간당 스냅샷도 DR에 두고 싶다면 두 가지를 맞춰야 합니다 — 원본 스냅샷 정책의 해당 스케줄에 라벨을 붙이고, SnapMirror 정책에 그 라벨 규칙을 추가합니다.

# 1) 원본 스냅샷 정책의 hourly 스케줄에 라벨을 붙인다
cluster1::> snapshot policy modify-schedule -policy <정책> -schedule hourly -newsnapmirror-label hourly

# 2) SnapMirror 정책에 그 라벨 규칙을 추가한다
cluster1::> snapmirror policy add-rule -vserver cluster1 -policy <정책> -snapmirror-label hourly -keep 6

둘 중 하나만 하면 안 됩니다. 라벨만 붙이고 정책에 규칙이 없으면 여전히 안 넘어가고, 규칙만 있고 라벨이 없으면 대상이 없습니다. [문서확인] NetApp 문서도 “복제할 스냅샷에 지정하는 SnapMirror 라벨은 원본의 스냅샷 정책에서 지정한다”고 설명합니다.

파라미터 이름에 함정이 있습니다. 라벨을 새로 만들 때snapshot policy create -snapmirror-label1 이지만, 기존 스케줄을 고칠 때-snapmirror-label 이 아니라 -newsnapmirror-label 입니다. 앞의 이름으로 치면 Error: invalid argument "-snapmirror-label" 이 납니다 — 9.17.1에서 직접 확인했습니다.

7. 전송량 — 스냅샷을 기준점으로 삼는다

$ sudo dd if=/dev/urandom of=/mnt/ontap-nfs/dataB.dat bs=1M count=10

cluster1::> snapmirror update -destination-path DR_SVM:nfs_vol1_dr

cluster1::> snapmirror show -fields last-transfer-size,last-transfer-duration,lag-time
source-path      destination-path   last-transfer-size last-transfer-duration lag-time
---------------- ------------------ ------------------ ---------------------- --------
NFS_SVM:nfs_vol1 DR_SVM:nfs_vol1_dr 10.25MB            0:0:14                 0:0:31
동작전송량시간
베이스라인 (100MB 파일)102.5MB24초
10MB 추가 후 update10.25MB14초
breakresync3.53KB즉시

전체를 다시 보내지 않습니다. 두 볼륨이 공통으로 가진 스냅샷이 기준점이고 그 뒤 변경분만 갑니다. 그래서 스냅샷을 함부로 지우면 안 됩니다 — 공통 스냅샷이 사라지면 증분이 끊기고 베이스라인부터 다시 해야 합니다.

lag-time목적지가 원본보다 얼마나 뒤처져 있는지입니다. 이 값이 스케줄 주기보다 계속 커지면 전송이 못 따라가고 있다는 뜻입니다. 모니터링에서 실제로 봐야 하는 값이 이것입니다.

8. ⭐ 복제가 되어도 서비스는 안 된다

cluster1::> volume show -vserver DR_SVM -volume nfs_vol1_dr -fields type,size,used,state,junction-path
vserver volume      size state  junction-path used    type
------- ----------- ---- ------ ------------- ------- ----
DR_SVM  nfs_vol1_dr 1GB  online /nfs_vol1_dr  101.6MB DP

cluster1::> network interface show -vserver DR_SVM
There are no entries matching your query.

데이터는 101.6MB가 들어와 있고 junction까지 걸려 있는데, DR SVM에는 데이터 LIF가 하나도 없습니다. 복제 트래픽은 인터클러스터 경로로 도는 일이라 데이터 LIF가 없어도 잘 돕니다. 하지만 재해가 나서 이걸 서비스로 올릴 때는 LIF·export policy·DNS가 전부 새로 필요합니다.

“SnapMirror 걸어놨으니 괜찮다”가 위험한 이유입니다. 데이터는 안전해도 서비스는 준비되어 있지 않습니다. 전환 절차를 문서로 만들어두고 한 번은 실제로 해봐야 합니다.

9. break 와 resync — 전환 리허설

cluster1::> snapmirror break -destination-path DR_SVM:nfs_vol1_dr

cluster1::> volume show -vserver DR_SVM -volume nfs_vol1_dr -fields type
vserver volume      type
------- ----------- ----
DR_SVM  nfs_vol1_dr RW      <-- DP 에서 RW 로 바뀌었다

cluster1::> snapmirror show -fields state,healthy
source-path      destination-path   state      healthy
---------------- ------------------ ---------- -------
NFS_SVM:nfs_vol1 DR_SVM:nfs_vol1_dr Broken-off true

Broken-off 인데 healthy: true 입니다. 3절의 실패한 관계도 Broken-off 였지만 그때는 healthy: false 였습니다. 같은 상태 이름이 정상 전환일 수도, 장애일 수도 있습니다. 둘을 가르는 것이 healthy 필드입니다.

cluster1::> snapmirror resync -destination-path DR_SVM:nfs_vol1_dr

cluster1::> snapmirror show -fields state,last-transfer-size
source-path      destination-path   state        last-transfer-size
---------------- ------------------ ------------ ------------------
NFS_SVM:nfs_vol1 DR_SVM:nfs_vol1_dr Snapmirrored 3.53KB

3.53KB만 오갔습니다. 공통 스냅샷이 아직 양쪽에 있어서 그 차이만 맞추면 되기 때문입니다. 볼륨 타입도 RW에서 DP로 되돌아갑니다.

다만 break 이후 목적지에 쓴 데이터는 resync 때 버려집니다. 재해 전환 후 목적지에서 계속 서비스했다면 그 변경분을 살려야 하므로, 원본 쪽을 목적지로 삼는 역방향 관계를 만들어 되돌리는 절차를 씁니다. 이 랩은 목적지에 쓰지 않았으므로 그냥 되돌렸습니다.

덤 — 볼륨을 지워도 공간이 바로 안 돌아온다

cluster1::> volume delete -vserver DR_SVM -volume wrong_dr

Info: Volume "wrong_dr" in Vserver "DR_SVM" will be marked as deleted and
      placed in the volume recovery queue. The space used by the volume will be
      recovered only after the retention period of 12 hours has completed.

지운 볼륨이 12시간 복구 큐에 남고 그동안 공간도 안 돌아옵니다. 실수로 지웠을 때 살릴 수 있다는 뜻이라 좋은 기능이지만, “볼륨 지웠는데 애그리게이트 여유가 그대로”라고 당황하는 자리이기도 합니다. 급하면 volume recovery-queue purge 로 즉시 비웁니다.

정리 — 전송이 안 될 때 점검 순서

증상확인
인터클러스터 LIF가 안 만들어진다-vserver노드가 아니라 클러스터 관리 SVM을 넣었는지 (LIF creation on a Node Vserver is disallowed)
클러스터 피어링이 안 된다인터클러스터 LIF가 모든 노드에 있는지. 포트 11104·11105 양방향
cluster peer show 가 한쪽만 정상양쪽 클러스터에서 각각 Availability·Authentication 확인. -instanceUnreachable Local Nodes 도 비어 있어야 한다
SVM 피어가 initializing 에서 안 변한다초기화 중이 아니라 상대 승인 대기다. 목적지에서 vserver peer accept
snapmirror create 가 거부된다vserver peer showpeered 인지, snapmirror 애플리케이션이 있는지. 클러스터 간이면 경로를 클러스터://SVM/볼륨
클러스터 간인데 라이선스 오류SnapMirror 라이선스는 양쪽 클러스터에 각각 필요하다
Uninitialized 에서 안 변한다베이스라인은 스케줄이 안 해준다. snapmirror initialize 직접 실행
Broken-off + healthy false-fields last-transfer-error 로 사유 확인. 목적지 볼륨 타입이 첫 후보
Broken-off + healthy true정상. break 로 전환된 상태
동기식인데 InSync 가 아니다그 자체가 경보. 비동기의 Idle 과 의미가 다르다
특정 스냅샷이 DR에 없다라벨. 원본 스냅샷 정책의 라벨 ↔ SnapMirror 정책 rule 을 맞춘다
Transferring 에서 멈춘 것 같다-instanceTotal Progress 를 본다. last-transfer-size직전 전송 값이라 안 움직인다
베이스라인이 유난히 오래 걸린다정책이 MirrorAllSnapshots스냅샷을 전부 넘긴다. 최신만 필요하면 MirrorLatest
전송은 되는데 계속 밀린다lag-time 추이. 스케줄 주기보다 커지면 못 따라가는 것
복제는 되는데 접속이 안 된다network interface show -vserver <DR SVM> — 데이터 LIF가 아예 없을 수 있다

SnapMirror에서 헷갈리는 대부분은 “명령이 성공을 보고했는데 실제로는 안 되고 있는” 구간에서 나옵니다. createinitialize 도 성공이라고 답한 뒤 last-transfer-error 에만 진실이 남아 있었고, 라벨이 없는 스냅샷은 에러 없이 조용히 복제되지 않았습니다. state 하나만 보지 말고 healthy·last-transfer-error·lag-time 을 같이 보는 습관이 시간을 아껴줍니다.

같은 볼륨을 다루는 다른 글도 함께 보시면 도움이 됩니다 — 파일을 지워도 용량이 안 줄어드는 글은 이 글의 증분 전송이 무엇 위에 서 있는지를 설명해주고, NFS 마운트가 access denied로 거부될 때는 재해 전환 후 목적지를 서비스로 올릴 때 다시 만나는 문제입니다.

참고 문서ONTAP peering basics · ONTAP peering prerequisites · Create cluster peer relationships · Create intercluster SVM peer relationships · SnapMirror synchronous disaster recovery · Define a rule for a SnapMirror policy · snapmirror policy create (CLI)

댓글 남기기