このトピックでは、Robocopy ツールを使用して、SMB プロトコルを使用する Apsara File Storage NAS (NAS) ファイルシステム間でデータを移行する方法について説明します。
前提条件
ソース SMB ファイルシステムが作成され、データが含まれています。また、ファイルシステム用に仮想プライベートクラウド (VPC) マウントポイントも作成されています。
背景情報
Robocopy は、Windows が提供するディレクトリコピーコマンドです。このコマンドを使用すると、不要な重複ファイルをコピーせずに、同じファイル構造を持つ 2 つのイメージコピーを作成できます。また、日付やタイムスタンプなど、関連するすべてのファイル情報を保持することもできます。
課金
NAS ファイルシステム間のデータ移行には、次の費用が発生します。
Elastic Compute Service (ECS) インスタンスをデータ転送のための中間ノードとして使用する場合、ECS インスタンスの構成に基づいて課金されます。 ECS の課金の詳細については、「課金概要」をご参照ください。
両方の NAS ファイルシステムのストレージ使用量に対して課金されます。ストレージ使用料を相殺するためにリソースプランを購入することをお勧めします。 NAS の課金の詳細については、「課金概要」をご参照ください。
Cloud Enterprise Network (CEN) を使用して VPC を接続する場合、使用する転送ルーターとリージョン間接続に対して課金されます。 CEN の課金の詳細については、「課金」をご参照ください。
準備
NAS ファイルシステム間でデータを移行する場合、ECS インスタンスはソースとターゲットの両方の NAS ファイルシステムにアクセスできる必要があります。そのため、ソースとターゲットの NAS ファイルシステムに同じ Alibaba Cloud 仮想プライベートクラウド (VPC) からアクセスできることを確認する必要があります。
ソースファイルシステムのマウントポイントに関する情報を表示します。
データを移行する前に、ソースファイルシステムのマウントポイント情報と、マウントポイントが属する VPC を記録します。詳細については、「マウントポイントの管理」をご参照ください。
説明ファイルシステムにクラシックネットワークマウントポイントしかない場合は、VPC にマウントポイントを作成する必要があります。詳細については、「マウントポイントの追加」をご参照ください。
ターゲットファイルシステムのマウントポイントを構成します。
ファイルシステムが同じリージョンにある場合
ターゲットとソースのファイルシステムのマウントポイントが同じ VPC に属している場合は、マウントポイント情報を取得してデータを移行できます。詳細については、「データの移行」をご参照ください。
ターゲットとソースのファイルシステムのマウントポイントが異なる VPC に属している場合は、次の 3 つの方法のいずれかを使用してマウントポイントを準備できます。
ターゲットリージョンとゾーンに新しいファイルシステムを作成します。 新しいマウントポイントは自動的に作成されます。 詳細については、「コンソールで汎用型 NAS ファイルシステムを作成する」をご参照ください。
説明SMB プロトコルを使用する従量課金制の汎用 NAS ファイルシステム (容量、パフォーマンス、またはプレミアム) を購入した場合は、ソースマウントポイントと同じ VPC と vSwitch を選択します。ターゲットマウントポイントは自動的に生成されます。新しいファイルシステムが作成された後、リソースプランを購入して料金を相殺し、コストを節約できます。
既存のファイルシステムに新しいマウントポイントを作成します。詳細については、「マウントポイントの作成」をご参照ください。
CEN を使用して、宛先とソースのマウントポイントの VPC を接続します。 詳細については、「CEN を使用して、同一リージョン内の VPC 間で NAS ファイルシステムをマウントする」をご参照ください。
ファイルシステムが異なるアカウントに属しているか、異なるリージョンにある場合
ターゲットとソースのファイルシステムのマウントポイントが同じアカウントまたはリージョンにない場合は、CEN を使用して VPC を接続する必要があります。詳細については、「CEN を使用してアカウントとリージョンをまたいで NAS ファイルシステムをマウントする」をご参照ください。
データの移行
ソースとターゲットのマウントポイントを準備した後、新しい ECS インスタンスを作成し、両方の SMB ファイルシステムを ECS インスタンスにマウントしてから、Robocopy ツールを使用してデータをコピーします。次の手順では、データを移行する方法について説明します。
ソースとターゲットのファイルシステムをマウントします。
重要移行を実行するには、新しい一時的な ECS インスタンスを購入することをお勧めします。既存の ECS インスタンスを使用する場合、移行タスクは、実行中のアプリケーションに割り当てられている CPU とネットワーク帯域幅リソースを消費する可能性があります。
ECS コンソール にログインし、[インスタンスの作成] をクリックします。次に、次のパラメータを構成します。
リージョン: ソースファイルシステムが存在するリージョンを選択します。
ネットワークとゾーン: ソースファイルシステムが存在する VPC、ゾーン、および vSwitch を選択します。
インスタンスタイプ: ほとんどの場合、最小のインスタンスタイプを選択できます。
イメージ: Windows Server バージョンを選択します。 Windows Server 2019 を選択することをお勧めします。
ストレージ: [エラスティック一時ディスク | Apsara File Storage NAS | 専用ブロックストレージクラスタ (オプション)] セクションで [ファイルシステムの追加] をクリックします。次の図は構成例を示しています。
説明ソースとターゲットのマウントポイントが同じ VPC にある場合は、ECS 購入ページで NAS マウント情報を構成できます。 ECS インスタンスが起動すると、ソースとターゲットの NAS ファイルシステムが自動的にマウントされます。
ソースと宛先の マウントポイント が同じ VPC、リージョン、またはアカウントにない場合は、ECS 購入ページでソースファイルシステムのみを設定する必要があります。ECS インスタンスの作成後、宛先ファイルシステムを手動でマウントする必要があります。詳細については、「SMB ファイルシステムをマウントする」をご参照ください。

ECS インスタンスが作成され、ソースとターゲットの NAS ファイルシステムがマウントされたら、次のコマンドを実行して結果を確認します。
net useマウントが成功すると、次の情報が表示されます。ソースファイルシステムはドライブ Z にマウントされ、ターゲットファイルシステムはドライブ Y にマウントされます。
Status Local Remote Network ------------------------------------------------------------------------------ OK Y: \\29e9c24****-eab13.cn-wulanchabu.nas.aliyuncs.com\myshare MicrosoftWindowgNetwork OK Z: \\29fe7f4****-txr31.cn-wulanchabu.nas.aliyuncs.com\myshare MicrosoftWindowgNetworkデータを移行します。
次のコマンドを実行して、ソースファイルシステム (ディスク Z) からターゲットファイルシステム (ディスク Y) にデータを移行します。
robocopy Z:\ Y:\ /e /w:5 /z /mt:32説明指定されたディレクトリ内のデータのみが移行されます。ディレクトリは移行されません。
次の表にパラメータを示します。パラメータの値を実際の値に置き換えます。
パラメータ
説明
/mt
同時スレッド数を指定します。デフォルト値: 8。
有効値: 1 ~ 128。
この例では、マルチスレッドレプリケーションに 32 スレッドを使用しています。
/w
エラーによって発生する 2 回の連続再試行の間隔を秒単位で指定します。
/z
再開可能なアップロードを有効にします。
/e
空のディレクトリを含むすべてのサブディレクトリをコピーします。
/copyall
すべてのファイル情報をコピーします。情報には次の項目が含まれます。
データ
属性
タイムスタンプ
アクセス制御リスト (ACL)
所有者情報
監査情報
説明大量のデータ (たとえば、10 TB を超える何億もの小さなファイル) の移行を高速化したい場合は、Windows ECS インスタンスに最新の Python プログラムをインストールできます。詳細については、「SMB ファイルシステムへのデータ移行を高速化するにはどうすればよいですか?」をご参照ください。
移行結果を確認します。
移行が完了したら、次の Robocopy コマンドを実行して、ターゲットファイルシステムがソースファイルシステムと一致するかどうかを確認します。
ROBOCOPY Z:\ Y:\ /e /l /ns /njs /njh /ndl /fp /log:reconcile.txt次の表にパラメータを示します。必要に応じて置き換えてください。
/e: 空のディレクトリを含む、ディレクトリのみをリストします。
/l: ファイルを変更またはコピーせずに、違いを記録します。
/fp: ログにファイルの完全なパスを含めます。このパラメータは、/ndl パラメータが指定されていない場合にのみ必要です。
/ns: ログにファイルサイズを含めません。
/ndl: ログにフォルダを含めません。
/njs: ログにジョブサマリーを含めません。
/njh: ログにジョブヘッダーを含めません。
/log:reconcile.txt: 移行結果を reconcile.txt ログファイルに書き込みます。ファイルが既に存在する場合は、既存の内容が上書きされます。
アプリケーションを新しいファイルシステムに切り替える
データ移行が完了したら、アプリケーションを古いファイルシステムから新しいファイルシステムに切り替えます。これを行うには、すべての ECS インスタンスとコンテナから古いファイルシステムをアンインストールしてから、新しいファイルシステムをマウントします。
NAS ファイルシステムが ECS インスタンスに直接マウントされている場合:
net useコマンドを実行して、既存の NAS マウント情報を記録します。 NAS ファイルシステムがマウントされているローカルドライブ文字をメモしておきます。コマンドを実行して、古いファイルシステムをアンインストールします。
net use Z: /deleteコマンドのドライブ文字 (Z:) を実際のドライブ文字に置き換えます。
説明net use * /delete コマンドを実行して、Windows にマウントされているすべてのファイルシステムを手動でアンインストールします。
net use * /delete /y コマンドを実行して、Windows にマウントされているすべてのファイルシステムを自動的にアンインストールします。
新しいファイルシステムを元のドライブ文字にマウントします。マウントパラメータの詳細については、「SMB ファイルシステムのマウント」をご参照ください。
NAS にアクセスするアプリケーションを起動して、読み取りと書き込みの操作が成功することを確認します。
auto_mount.bat の自動マウント情報を変更して、古いマウントポイントを新しいマウントポイントに置き換えます。
NAS ファイルシステムが Windows コンテナにマウントされている場合:
既存の YAML 構成ファイルを変更して、古いマウントポイントを新しいマウントポイントに置き換えます。
変更した構成ファイルを使用して、新しいポッドを生成します。新しいファイルシステムがマウントされており、読み取りと書き込みの操作が成功することを確認します。
古いファイルシステムを使用するすべてのポッドを削除します。
アプリケーションを新しいファイルシステムに切り替えた後、古いファイルシステムのデータを少なくとも 1 週間保持します。誤って削除したり、同期が不完全だったりした場合にデータが失われないように、古いファイルシステムからデータをすぐに削除しないでください。
よくある質問
SMB ファイルシステムへのデータ移行を高速化するにはどうすればよいですか?
SMB ファイルシステムに大量のデータを書き込んだり、大量のデータ (たとえば、合計 10 TB を超える、それぞれ約 100 KB の小さなファイルが何億もある) の移行を高速化する必要がある場合があります。この場合、Windows ECS インスタンスに最新の Python プログラムをインストールして、移行を実行できます。次の手順を実行する必要があります。
ダウンロード して最新の Python プログラムをインストールします。
システム環境変数 PATH を Python 実行パス (例: `C:\Python27`) に設定します。
set PATH=%PATH%;C:\python27また、
where pythonコマンドを実行して、Python のインストールパスを表示することもできます (次の図を参照)。
次の `migration.py` スクリプトを Alibaba Cloud ECS インスタンスのローカルディレクトリ (例: `C:\`) にコピーします。
#!/usr/bin/python # 必要なモジュールをインポートします import os import random import string import sys, getopt import datetime import time # コマンドを実行する関数 def execute_cmd(cmd): print('\tコマンドを実行しています: %s' % cmd) count = 0 rc = 0 while (count < 3*60): rc = os.system(cmd) if (rc != 0): count += 1 time.sleep(1) continue else: break if rc != 0: print('\tコマンドの実行に失敗しました: %s. rc:%d' %(cmd, rc)) return # サブディレクトリを移行する関数 def migrate_subdirs(srcPath, dstPath, rangeBegin, rangeEnd, ignoreFile): currTimeStr = datetime.datetime.now().strftime("%Y-%m-%d_%H:%M:%S") print('サブディレクトリ範囲[%s, %s] の %s から %s への移行を %s に開始します。\n' %(srcPath, dstPath, rangeBegin, rangeEnd, currTimeStr)) index = 0 for entry in os.listdir(srcPath): if os.path.isdir(os.path.join(srcPath, entry)): if index >= rangeBegin and index <= rangeEnd: srcSubDir = srcPath + "\\" + entry dstSubDir = dstPath + "\\" + entry print('\t%d 番目のディレクトリ %s から %s への移行を開始します。' %(index, srcSubDir, dstSubDir)) cmd = "robocopy \"" + srcSubDir + "\" \"" + dstSubDir + "\" /e /w:5 /z /mt:32" if ignoreFile.strip(): cmd += " /XF \"" + ignoreFile + "\"" cmd += " >> robocopy.log" execute_cmd(cmd) print('\t%s から %s への移行が完了しました。\n' %(srcSubDir, dstSubDir)) index += 1 print('サブディレクトリ範囲[%s, %s] の %s から %s への移行を %s に完了しました。\n' %(srcPath, dstPath, rangeBegin, rangeEnd, datetime.datetime.now().strftime("%Y-%m-%d_%H:%M:%S"))) # 通常ファイルを移行する関数 def migrate_regfiles(srcPath, dstPath, ignoreFile): currTimeStr = datetime.datetime.now().strftime("%Y-%m-%d_%H:%M:%S") print('%s から %s への通常ファイルの移行を %s に開始します。\n' %(srcPath, dstPath, currTimeStr)) for entry in os.listdir(srcPath): if os.path.isfile(os.path.join(srcPath, entry)): print('\t%s の %s から %s への移行を開始します。\n' %(entry, srcPath, dstPath)) cmd = "attrib -R \"" + dstPath + "\\\\" + entry + "\"" execute_cmd(cmd) cmd = "copy \"" + srcPath + "\\\\" + entry + "\" \"" + dstPath + "\" /Y" if ignoreFile.strip(): cmd += " /XF \"" + ignoreFile + "\"" cmd += " >> robocopy.log" execute_cmd(cmd) print('\t%s の %s から %s への移行が完了しました。' %(entry, srcPath, dstPath)) print('%s から %s への通常ファイルの移行を %s に完了しました。\n' %(srcPath, dstPath, datetime.datetime.now().strftime("%Y-%m-%d_%H:%M:%S"))) def main(argv): srcPath = '' dstPath = '' range = '' ignoreFile = '' try: opts, args = getopt.getopt(argv,"hs:d:r:i:f",["srcPath=","dstPath=","range=","ignore="]) except getopt.GetoptError: print('migration.py -s <ソースパス> -d <ターゲットパス> [-r 開始インデックス:終了インデックス | -f] [-i 無視するファイル]') print('例: migration.py -s x:\pic -d z:\pic [-r 0:100]') sys.exit(2) subdironly = False fileonly = False for opt, arg in opts: if opt == '-h': print('migration.py -s <ソースパス> -d <ターゲットパス> [-r 開始インデックス:終了インデックス | -f] [-i 無視するファイル]') sys.exit() elif opt in ("-s", "--srcPath"): srcPath = arg elif opt in ("-d", "--dstPath"): dstPath = arg elif opt in ("-r", "--range"): range = arg subdironly = True elif opt in ("-f", "--file"): fileonly = True elif opt in ("-i", "--ignore"): ignoreFile = arg if not srcPath.strip() or not dstPath.strip(): print('migration.py -s <ソースパス> -d <ターゲットパス> [-r 開始インデックス:終了インデックス | -f] [-i 無視するファイル]') sys.exit() if subdironly and fileonly: print('migration.py -s <ソースパス> -d <ターゲットパス> [-r 開始インデックス:終了インデックス | -f] [-i 無視するファイル]') sys.exit() if not fileonly: if not range.strip(): rangeBegin = 0 rangeEnd = sys.maxsize-1 else: rangeBegin, rangeEnd = (int(x) for x in range.split(":")) if rangeBegin < 0 or rangeEnd >= sys.maxsize or rangeEnd < rangeBegin: print('migration.py -s <ソースパス> -d <ターゲットパス> [-r 開始インデックス:終了インデックス | -f] [-i 無視するファイル]') print('例: migration.py -s x:\pic -d z:\pic -r 0:99') sys.exit() migrate_subdirs(srcPath, dstPath, rangeBegin, rangeEnd, ignoreFile) if not subdironly: migrate_regfiles(srcPath, dstPath, ignoreFile) if __name__ == "__main__": main(sys.argv[1:])データを移行します。コマンド形式は次のとおりです。
python ./migration.py -s <ソースパス> -d <ターゲットパス> [-r 開始インデックス:終了インデックス | -f] [-i 無視するファイル]。次の表に、コマンドの主なパラメータを示します。
パラメータ
説明
-s <ソースパス>
ソースファイルシステムのマウントポイントのディレクトリを指定します。たとえば、
-s Z:\は、ソースファイルシステムのマウントポイントのディレクトリがドライブ Z のルートディレクトリであることを示します。-d <ターゲットパス>
ターゲットファイルシステムのマウントポイントのディレクトリを指定します。たとえば、
-d Y:\は、ターゲットファイルシステムのマウントポイントのディレクトリがドライブ Y のルートディレクトリであることを示します。-r 開始インデックス:終了インデックス
移行するファイルの範囲を
開始インデックスから終了インデックスまで指定します。たとえば、-r 1:100は、1 から 100 までのファイルが移行されることを示します。-f
ソースファイルシステムディレクトリの最初のレベルにある通常ファイルのみを移行することを指定します。
ソースファイルシステムディレクトリのすべてのファイルが移行され、範囲制限は無視されます。
-i 無視するファイル
移行する必要のないソースファイルシステムディレクトリのファイルを指定します。たとえば、
-i ignored.txtは、ignored.txtという名前のファイルが移行されないことを示します。説明デフォルトでは、-r または -f パラメータを設定する必要はありません。スクリプトは、すべてのサブディレクトリで Robocopy を順番に実行し、次に最初のレベルにある通常ファイルをコピーします。複数のクライアントの CPU とネットワークリソースを使用して、異なるサブディレクトリの移行を同時並行的に高速化し、すべてのクライアントが同じソースディスクにアクセスできるようにする場合は、移行するサブディレクトリの範囲を指定できます。たとえば、最初のクライアントは
-r 0:9999を使用でき、2 番目のクライアントは-r 10000:19999を使用できます。たとえば、ソースファイルシステムの `Z:\` ディレクトリからターゲットファイルシステムの `Y:\` ディレクトリにデータを移行するには、次のサンプルコマンドを使用します。
python ./migration.py -s Z:\ -d Y:\