【NetApp】SnapMirrorが突如転送できなくなった原因と対応

2022年6月26日

こんにちは、キクです。

業務上NetAppに触れる機会が多いのですが、毎日転送できていたSnapMirrorが急に転送できなくなるという問題に先日遭遇しました。
DR対策の意図でSnapMirrorを採用していることもあり「早急に復旧しないとまずい!!」という程ではなかったのですが、復旧までの一連の作業で学んだことも多かったので記事に残しておこうと思います。

というわけで、今回は『SnapMirrorが突如転送できなくなった原因と対応』をテーマに書いていきたいと思います!

それでは、よろしくお願いします。

動作環境

本記事の内容は下記の環境で実施したものになります
・ONTAP 9.1

注意事項

本記事は僕が経験した内容をもとに記載しておりますが、実行環境や設定などによって動作が異なる場合があります。
そのため『参考程度』にお読みいただけますと幸いです。

そもそもSnapMirrorとは

netapp-snapmirror-basic-1

SnapMirrorは「同一クラスタ内」または「異なるクラスタ間」でデータを複製(Replicate)する機能になります。
SnapMirrorでは「ソース(転送元)となるボリューム」と「ターゲット(転送先)となるボリューム」を指定して「手動」または「スケジュール」によってデータ転送が実施されます。
SnapMirrorについては以下の記事でもう少し詳しく書いているので、ご興味のある方は読んでみてください。
関連記事:【NetApp】SnapMirrorの基本的な概念と設定方法

なぜSnapMirrorが転送できなくなったのか

それでは本題に入っていきましょう。

繰り返しになりますが、今回の問題点は「スケジュール実行により毎日SnapMirror転送していたはずのデータがある日突然転送できなくなってしまった」ということです。
これには大きく2つの原因がありました。

SnapMirrorが転送できなくなった原因

・原因1:ベーススナップショットの消失
・原因2:ボリュームの枯渇

原因1:ベーススナップショットの消失

1つ目の原因は『ベーススナップショットの消失』になります。

ベーススナップショットって何・・・?

突然出てきた言葉なので「?」な方もいるかもしれません。
恥ずかしながら僕も今回の対応を通して「ベーススナップショット」という言葉を初めて聞きました(笑)

既に触れたようにSnapMirrorにはSnapshot技術が活用されています。
「ベーススナップショット」とは、簡単に言ってしまうとSnapMirrorを実現するためのベースとなるスナップショットとなります。
SnapMirrorでは前回の転送データとの差分データのみをターゲット側に転送しますので、そのためには「差分」を把握する必要があります。
このとき利用されるのが「ベーススナップショット」です。

対象ボリュームのスナップショット一覧を確認すると『snapmirror.xxx...YYYY-MM-DD-hhmmss』 という名前のものがあるかと思います。
これが「ベーススナップショット」となります。

ベーススナップショットはSnapMirro設定時に実施する初期化(Initialize)を実行したタイミングで作成されます。
以降のSnapMirrorでは都度ベーススナップショットをソース / ターゲットで更新しながら実施していく形になります。

もしこのベーススナップショットが消失してしまうと「前回どこまでのデータを転送したっけ?」となってしまいSnapMirrorが実施できなくなってしまいます。
今回は次のようなアラートが表示されていたことから、ベーススナップショットが消失していることが発覚しました。

No common Snapshot copy found between srcSVM:srcVOL and dstSVM:dstVOL.

ここでの「commn Snapshot」が「ベーススナップショット」に該当していますので、

「ソース側とターゲット側との間にベーススナップショットがないよ」

と言われてしまっています。
これが原因となりSnapMirrorに失敗するようになってしまっていました。

原因2:ボリュームの枯渇

それではなぜベーススナップショットが消失してしまっていたのか。
それが2つ目の原因となる『ボリュームの枯渇』になります。

Snapshotには「Autodelete」という機能があります。
これは条件にマッチした場合に取得済みのスナップショットを自動的に削除するためのものになります。
早い話、今回はボリュームが枯渇したことでAutodele機能が発動し、その結果ベーススナップショットが削除されてしまったという流れになります。

しかしここで問題点が1つ。
ベーススナップショットは通常のスナップショットとは異なり、データ保護ユーティリティによって内部的にロックされているものとなります。
そのため本来であればAutodelete機能ではベーススナップショットは削除されません。

ではなぜ今回は削除されてしまったのでしょうか。
答えは簡単です。
「ベーススナップショットも削除対象に含んでいいよ」という設定が入ってしまっていたからです。
具体的には以下のコマンドで確認できる「Commitment」という項目になります。

::> volume snapshot autodelete show

Commitmentはデフォルトだと「try」という設定値になっています。
この場合、Autodelete対象としてベーススナップショットは含まれず、ロックされていない通常のスナップショットのみが削除対象となります。

しかし、今回対象ボリュームでは「disrupt」という設定値になってしまっていました。
この設定値の場合には、ベーススナップショットがAutodelete対象に含まれてしまいます。
そうなると今回のように「ベーススナップショット消失」に繋がる可能性も出てきます。

ちなみに、この「Commitment」という項目は何か他の作業に連動して変更されてしまうということがないということが今回の調査で分かりました。
僕自身はこの項目を初めて知ったのですが、過去に(僕以外の管理者によって)意図的に設定されていたということになりますね。
設定内容によるところが大きいですが、Autodeleteの発動にはいくつかの条件が満たす必要があることが分かりました。
今回は以下の条件を満たしたことでAutodeleteが発動していたことが調査により判明しました。

ボリュームが閾値に達し、かつSnapshot reserve(/.snapshot)が100%を超過した

ちなみに、Autodeleteは条件を満たすと即時実行されるということにも分かりました。
Autodeleteについては以下の情報が非常に参考になります。
公式:Snapshotの自動削除の使用方法

少し余談になりますが、僕は調査中に「本当にAutodelete機能で削除されたのだろうか?」と疑問を持ちました。
そこについてはベンダーの方にASUPおよびログを送付し調査を実施していただきました。
関連記事:【NetApp】調査依頼時のAutoSupport送信からログ取得方法まで

ログの内容は長いので一部のみ記載しますが、以下のような内容からAutodeleによってベーススナップショットが削除されていたことが特定できました。

<wafl_volume_snap_autoDelete_1>
  name="snapmirror.xxx...YYYY-MM-DD-hhmmss"
  vol="srcVOL"

対象ボリューム(srcVOL)のベーススナップショットがAutodeleteによって削除されいているのがバッチリ記載されていますね。

どのように復旧したか

最後になりますが、どのようにしてSnapMirrorが実施できるように復旧したのかについて触れていこうと思います。

SnapMirrorが転送できない直接的な原因となっているのは「原因1:ベーススナップショットの消失」になります。
従って、ベーススナップショットが存在する状態に戻してあげる必要があります。

今回の調査で分かったこととしては、一度失われたベーススナップショット自身を復旧することはできないということです。
そのため、最初にベーススナップショットが作成されたときと同様に「SnapMirror関係の初期化(Initialize)」が必要ということが分かりました。

ただ、いきなり初期化を実施してしまうと、ターゲット側の正常なデータを上書きしてしまうことになり「それは避けたい」と思いました。
そのため、今回は新しくターゲットボリュームを作成してSnapMirror関係を新たに作成する方法をとりました。
「A→B」と転送していたものを「A→C」と転送できるようにしたという方が伝わりやすいかもしれません。

こうしておけばB(旧ターゲットボリューム)には手を加えていないので安心です。

実施内容としては新しくSnapMirror関係を作成するだけなので具体的な手順は割愛しますが、次の5ステップを実施した形になります。

作業内容

1. 新規ターゲットとしてボリュームCを作成
2.「ソース:ボリュームA / ターゲット:ボリュームC」の新規SnapMirror関係を設定
3.「ボリュームA → ボリュームC」で問題なくSnapMirror転送ができることを確認
4. 旧SnapMirror関係の解放および削除
5.「旧ターゲット:ボリュームB」の削除

この手順としたことで、新しいSnapMirror関係が問題なく動作することを確認してから旧ターゲットボリュームを削除することができました。
もしいきなり「A→B」で初期化をしてB(旧ターゲットボリューム)に何かあったら嫌だったので、念には念を入れました。

なお、新規SnapMirror関係の作成や旧SnapMirror関係の解放・削除作業については、別の事例を紹介する際に書いた以下の記事が参考になると思うので、ご興味のある方は合わせてご一読ください。
関連記事:【NetApp】ONTAPバージョンの異なるクラスタ間でのSnapMirror逆再同期で苦戦した話

Commitmentの変更は必要?

ちなみに「Commitment:disruptは変更しなくていいのか?」と思われる方もいるかもしれません。
これは設定方針によるのかなと思います。
SnapMirrorはDR対策として非常に重要な要素です。
しかし転送元のソースデータもまた超重要です。

もし仮に「Commitment:try(デフォルト)」としてベーススナップショットが削除されないようにしていた場合、今回ソースボリュームではどのようになっていたでしょうか?
ベーススナップショットは削除されなかったとしてもボリュームが枯渇した状態になってしまうので本来書き込みたいデータがソースボリュームに書き込めなかったかもしれません。
それは困ってしまいますよね。
なのでSnapMirrorが転送できなくなってしまうのは困るけど、ソースボリュームにデータを書き込めないのはもっと困るという場合には「Commitment:disrupt」でもいいのかなと感じました。

そういった経緯もあり今回の対応では「disrupt→try」の変更は実施しませんでした。
まあ「disrupt」である以上、また同じようにSnapMirrorが転送できなくなる可能性は残ってしまいますが、こればっかりは決めの問題かなと思います。

おわりに

いかがだったでしょうか。

今回はSnapMirrorが転送できなくなった原因と対応について書きました。

普段動いているものが急に動かなくなるとドキッとしてしまいますよね。
でも今回一連の調査・対応を通して原因が特定できたり、SnapMirrorの深い部分を知れたのは良かったなと思いました。
みなさんも本記事を通して少しでもSnapMirrorの理解を深めることができていれば嬉しいです。

本記事を最後までお読みいただきありがとうございました。
ではでは!

-NetApp
-