ニフクラ ブログ

ニフクラ/FJcloud-Vやクラウドの技術について、エンジニアが語るブログです。

ニフクラの新旧オブジェクトストレージ間でデータ移行を行う方法

はじめに

こんにちは。ニフクラ オブジェクトストレージチームです。

ニフクラで提供中のオブジェクトストレージは、2022年4月にサービス内容を刷新しました。
それ以前に提供していたオブジェクトストレージのサービスは「オブジェクトストレージ(旧)」として、2023年01月11日をもってサービス提供が終了します。

オブジェクトストレージサービス サービス刷新とそれに伴う各種サービス提供終了のご案内
https://pfs.nifcloud.com/service/obj_storage_renewal.htm

よって、サービス終了までに、オブジェクトストレージ(旧)から新しいオブジェクトストレージ間でデータ移行を行う必要があります。
本記事では、この新旧2つのストレージサービス間でのデータ移行方法についてご紹介いたします。

ストレージサービス間のデータ移行方法

ニフクラでは、現在オブジェクトストレージ(旧)オブジェクトストレージサービスの2つのストレージサービスがあります。

共にS3互換APIを提供していますが、オブジェクトストレージサービスの方がストレージ利用料金が安く、ライフサイクル管理できるなど、より使いやすくなっていますので、ぜひお早めに移行を進めてください。

オブジェクトストレージ(旧)からオブジェクトストレージサービスへデータを移行する方法は複数ございます。

今回ご紹介する方法は以下のとおりです。

  1. AWS CLI v2 を使用して、転送元オブジェクトをローカルディスクにダウンロードしてから、転送先へアップロードする
  2. rclone を使用して、転送元オブジェクトをメモリーに保存しながら並行して転送先へアップロードする
  3. s3sync を使用して、転送元オブジェクトをメモリーに保存してから、転送先へアップロードする
  4. AWS SDK を使用して、独自の移行プログラムを作成して移行する

データ移行処理ではCPUとメモリー使用量がかなり大きくなりますので、データ移行専用のサーバー(サーバータイプはe-mediumを推奨)を用意してください。
ここでは、オブジェクトストレージ (旧)のeast-2を転送元、オブジェクトストレージサービスのeast-1を転送先として説明します。
今回ご紹介するすべての方法は、弊社から提供されるツールを使用していないため、サポート範囲外となりますことをご了承ください。

なお、オブジェクトストレージ(旧)でサポートされていたACL はオブジェクトストレージサービスではサポートされておらず、デフォルトでは作成したユーザーしかアクセスできない設定になっています(ACLのPrivate相当) 。

このため、必要に応じてデータ移行後にバケットポリシー を使用してアクセス権を設定する必要があります。

方法1: AWS CLI v2を使用する

AWS CLI v2 を使用する方法は、移行対象オブジェクトの合計サイズが小さいときに実施しやすい方法です。

AWS CLI v2と同種のツールとしてS3に特化したS3cmd などがあります。

この方法の長所と短所は以下のとおりです。

長所

・既にAWS CLIを使っているのであれば、使い慣れたツールを使うことができる

短所

・ローカルディスクを使用するため、移行対象オブジェクトの合計サイズが大きいときは不向き
オブジェクトストレージ (旧)とオブジェクトストレージサービスは別システムとなるため、aws s3 sync コマンドで直接バケット名を指定することはできず、 ローカルディスクに一度ダウンロードする必要があります。
ローカルディスクに収まらないサイズのデータを移行するときは、増設ディスクを用意するか、複数回に分けて移行処理を実施する必要があります。

・オブジェクトの各種属性はコピーされない
ユーザー定義メタデータ、Content-Type、Cache-Control、Content-Disposition、Content-Encoding、Content-Languageはコピーされません。
Content-TypeはコピーされるのではなくAWS CLI v2によって拡張子から推測されます。

・バージョニングに対応していない
最新バージョンだけがコピーされます。

ユーザー定義メタデータはコピーされません。
これはアプリケーションによっては致命的な影響を与える可能性がありますので、詳しく説明いたします。

致命的な影響を与える一例を挙げますと、ニフクラ オブジェクトストレージ (旧) SDK for Java で、クライアントサイド暗号化を行っているときは、初期化ベクトルと暗号化された共通鍵がユーザー定義メタデータとして保存されます。(ObjectMetadataモード 使用時のみ。ニフクラ cliの--encrypt オプションはObjectMetadataモードで暗号化を行う。)

ユーザー定義メタデータがコピーされないと、復号に必要な情報が揃わないため、データが事実上消失することになります。

ユーザー定義メタデータはaws s3api head-object で確認することができます。

ユーザー定義メタデータの例

# aws --profile object-storage-old_east --endpoint-url https://jp-east-2.storage.api.nifcloud.com s3api head-object --bucket source-bucket  --key encrypted_data
{
    "AcceptRanges": "bytes",
    "LastModified": "2022-05-26T02:48:40+00:00",
    "ContentLength": 48,
    "ETag": "\"76419e28b113e02d37c9e82e7408d856\"",
    "ContentType": "application/octet-stream",
    "Metadata": {
        "x-amz-iv": "ZZZZZZZZZZZZZZZZZZZZZZZZ",
        "x-amz-key": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
        "x-amz-matdesc": "{}"
    }
}

上記の例では、x-amz-ivは初期化ベクトル、x-amz-keyは暗号化された共通鍵です。
このメタデータがないとクライアントサイド暗号化されたオブジェクトを復号することができません。

クライアントサイド暗号化は極端な例かもしれませんが、ユーザー定義メタデータの消失はシステムにとって致命的な問題に発展する可能性があります。

ユーザー定義メタデータを使っているか、開発者等に必ずご確認ください。

なお、ユーザー定義メタデータだけではなく、Content-Type、Cache-Control、Content-Disposition、Content-Encoding、Content-Languageなども システムに影響を与える可能性がありますので、移行時の要件として確認する必要があります。

実施手順

  1. AWS CLI v2のインストール
  2. AWS CLI v2の設定
  3. 転送元からオブジェクトをローカルディスクにダウンロード
  4. オブジェクトを転送先へアップロード

1 AWS CLI v2のインストール

こちら のページを参考にインストールしてください。

2 AWS CLI v2の設定

最初にAWS CLI v2の設定が必要になります。
AWS CLI v2では複数のアクセスキーを扱うことができるプロファイルという設定項目があります。
以下のコマンドはプロファイルを設定するコマンドです。

オブジェクトストレージ (旧)用 object-storage-old_east というプロファイルを登録。

$ aws configure --profile object-storage-old_east
AWS Access Key ID [None]: (オブジェクトストレージ(旧)のアクセスキー)
AWS Secret Access Key [None]: (オブジェクトストレージ(旧)のシークレットアクセスキー)
Default region name [None]:⏎
Default output format [None]:⏎
$

オブジェクトストレージサービス用にobject-storage-service_eastというプロファイルを登録。

$ aws configure --profile object-storage-service_east
AWS Access Key ID [None]: (オブジェクトストレージサービスのアクセスキー)
AWS Secret Access Key [None]: (オブジェクトストレージサービスのシークレットアクセスキー)
Default region name [None]:⏎
Default output format [None]:⏎
$

3 転送元からオブジェクトをローカルディスクにダウンロード

以下のコマンドで転送元バケット(source-bucket)の全オブジェクトをカレントディレクトリにダウンロードします。

$ aws --profile object-storage-old_east --endpoint-url https://jp-east-2.storage.api.nifcloud.com s3 sync s3://source-bucket .
download: s3://source-bucket/testdata/dir9/data8.dat to testdata/dir9/data8.dat
download: s3://source-bucket/testdata/dir7/data6.dat to testdata/dir7/data6.dat
download: s3://source-bucket/testdata/dir7/data8.dat to testdata/dir7/data8.dat
download: s3://source-bucket/testdata/dir9/data7.dat to testdata/dir9/data7.dat
$

4 オブジェクトを転送先へアップロード

まず最初に転送先にバケット(target-bucket)を作成します。
作成には aws s3api create-bucket コマンドを使用します。aws s3 mb コマンドは使用できません。

$ aws --profile object-storage-service_east --endpoint-url https://jp-east-1.storage.api.nifcloud.com s3api create-bucket --bucket target-bucket

以下のコマンドで、先ほどダウンロードした転送元バケットの全オブジェクトを転送先バケット(target-bucket)にアップロードします。

$ aws --profile object-storage-service_east --endpoint-url https://jp-east-1.storage.api.nifcloud.com s3 sync . s3://target-bucket
upload: testdata/dir9/data6.dat to s3://target-bucket/testdata/dir9/data6.dat
upload: testdata/dir9/data5.dat to s3://target-bucket/testdata/dir9/data5.dat
upload: testdata/dir9/data8.dat to s3://target-bucket/testdata/dir9/data8.dat
upload: testdata/dir9/data7.dat to s3://target-bucket/testdata/dir9/data7.dat
$ 

方法2: rcloneを使用する

rcloneを使用する方法は、ローカルディスクを使用しないので移行対象オブジェクトの合計サイズが大きいときでも実施できる方法です。

この方法の長所と短所は以下のとおりです。

長所

・ローカルディスクを使用しないので、移行対象オブジェクトの合計サイズが大きいときでも適用できる

短所

・Content-Typeのみがコピーされる
ユーザー定義メタデータ、Cache-Control、Content-Disposition、Content-Encoding、Content-Languageはコピーされません。

・バージョニングに対応していない
最新バージョンだけがコピーされます。

実施手順

  1. rcloneのインストール
  2. rcloneの設定
  3. rclone syncの実行

ここではCentOS 7での手順を説明します。

1 rcloneのインストール

以下のコマンドでrcloneをインストールします。

sudo yum install epel-release
sudo yum install rclone

2 rcloneの設定

rcloneではremoteと呼ばれるものを設定します。

オブジェクトストレージ (旧)用にobject-storage-old_eastというremoteを登録。

$ rclone config
No remotes found - make a new one
n) New remote
s) Set configuration password
q) Quit config
n/s/q> n
name> object-storage-old_east
Type of storage to configure.
Enter a string value. Press Enter for the default ("").
Choose a number from below, or type in your own value
 1 / A stackable unification remote, which can appear to merge the contents of several remotes
   \ "union"
 2 / Alias for a existing remote
   \ "alias"
 3 / Amazon Drive
   \ "amazon cloud drive"
 4 / Amazon S3 Compliant Storage Provider (AWS, Alibaba, Ceph, Digital Ocean, Dreamhost, IBM COS, Minio, etc)
   \ "s3"
   .
   .
   .
27 / http Connection
   \ "http"
Storage> 4
** See help for s3 backend at: https://rclone.org/s3/ **

Choose your S3 provider.
Enter a string value. Press Enter for the default ("").
Choose a number from below, or type in your own value
 1 / Amazon Web Services (AWS) S3
   \ "AWS"
   .
   .
   .
10 / Any other S3 compatible provider
   \ "Other"
provider> 10
Get AWS credentials from runtime (environment variables or EC2/ECS meta data if no env vars).
Only applies if access_key_id and secret_access_key is blank.
Enter a boolean value (true or false). Press Enter for the default ("false").
Choose a number from below, or type in your own value
 1 / Enter AWS credentials in the next step
   \ "false"
 2 / Get AWS credentials from the environment (env vars or IAM)
   \ "true"
env_auth> 1
AWS Access Key ID.
Leave blank for anonymous access or runtime credentials.
Enter a string value. Press Enter for the default ("").
access_key_id> (オブジェクトストレージ(旧)のアクセスキー)
AWS Secret Access Key (password)
Leave blank for anonymous access or runtime credentials.
Enter a string value. Press Enter for the default ("").
secret_access_key> (オブジェクトストレージ(旧)のシークレットアクセスキー)
Region to connect to.
Leave blank if you are using an S3 clone and you don't have a region.
Enter a string value. Press Enter for the default ("").
Choose a number from below, or type in your own value
 1 / Use this if unsure. Will use v4 signatures and an empty region.
   \ ""
 2 / Use this only if v4 signatures don't work, eg pre Jewel/v10 CEPH.
   \ "other-v2-signature"
region> 1
Endpoint for S3 API.
Required when using an S3 clone.
Enter a string value. Press Enter for the default ("").
Choose a number from below, or type in your own value
endpoint> https://jp-east-2.storage.api.nifcloud.com
Location constraint - must be set to match the Region.
Leave blank if not sure. Used when creating buckets only.
Enter a string value. Press Enter for the default ("").
location_constraint> ⏎
Canned ACL used when creating buckets and storing or copying objects.

This ACL is used for creating objects and if bucket_acl isn't set, for creating buckets too.

For more info visit https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#canned-acl

Note that this ACL is applied when server side copying objects as S3
doesn't copy the ACL from the source but rather writes a fresh one.
Enter a string value. Press Enter for the default ("").
Choose a number from below, or type in your own value
 1 / Owner gets FULL_CONTROL. No one else has access rights (default).
   \ "private"
 2 / Owner gets FULL_CONTROL. The AllUsers group gets READ access.
   \ "public-read"
   / Owner gets FULL_CONTROL. The AllUsers group gets READ and WRITE access.
 3 | Granting this on a bucket is generally not recommended.
   \ "public-read-write"
 4 / Owner gets FULL_CONTROL. The AuthenticatedUsers group gets READ access.
   \ "authenticated-read"
   / Object owner gets FULL_CONTROL. Bucket owner gets READ access.
 5 | If you specify this canned ACL when creating a bucket, Amazon S3 ignores it.
   \ "bucket-owner-read"
   / Both the object owner and the bucket owner get FULL_CONTROL over the object.
 6 | If you specify this canned ACL when creating a bucket, Amazon S3 ignores it.
   \ "bucket-owner-full-control"
acl> 1
Edit advanced config? (y/n)
y) Yes
n) No
y/n> n
Remote config
--------------------
[object-storage-old_east]
type = s3
provider = Other
env_auth = false
access_key_id = (オブジェクトストレージ(旧)のアクセスキー)
secret_access_key = (オブジェクトストレージ(旧)のシークレットアクセスキー)
endpoint = https://jp-east-2.storage.api.nifcloud.com
acl = private
--------------------
y) Yes this is OK
e) Edit this remote
d) Delete this remote
y/e/d> y
Current remotes:

Name                 Type
====                 ====
object-storage-old_east s3
$

オブジェクトストレージサービス用にobject-storage-service_eastというremoteを登録。

$ rclone config
Current remotes:

Name                 Type
====                 ====
object-storage-old_east s3

e) Edit existing remote
n) New remote
d) Delete remote
r) Rename remote
c) Copy remote
s) Set configuration password
q) Quit config
e/n/d/r/c/s/q> n
name> object-storage-service_east
Type of storage to configure.
Enter a string value. Press Enter for the default ("").
Choose a number from below, or type in your own value
 1 / A stackable unification remote, which can appear to merge the contents of several remotes
   \ "union"
 2 / Alias for a existing remote
   \ "alias"
 3 / Amazon Drive
   \ "amazon cloud drive"
 4 / Amazon S3 Compliant Storage Provider (AWS, Alibaba, Ceph, Digital Ocean, Dreamhost, IBM COS, Minio, etc)
   \ "s3"
   .
   .
   .
27 / http Connection
   \ "http"
Storage> 4
** See help for s3 backend at: https://rclone.org/s3/ **

Choose your S3 provider.
Enter a string value. Press Enter for the default ("").
Choose a number from below, or type in your own value
 1 / Amazon Web Services (AWS) S3
   \ "AWS"
   .
   .
   .
10 / Any other S3 compatible provider
   \ "Other"
provider> 10
Get AWS credentials from runtime (environment variables or EC2/ECS meta data if no env vars).
Only applies if access_key_id and secret_access_key is blank.
Enter a boolean value (true or false). Press Enter for the default ("false").
Choose a number from below, or type in your own value
 1 / Enter AWS credentials in the next step
   \ "false"
 2 / Get AWS credentials from the environment (env vars or IAM)
   \ "true"
env_auth> 1
AWS Access Key ID.
Leave blank for anonymous access or runtime credentials.
Enter a string value. Press Enter for the default ("").
access_key_id> <オブジェクトストレージサービスのアクセスキー>
AWS Secret Access Key (password)
Leave blank for anonymous access or runtime credentials.
Enter a string value. Press Enter for the default ("").
secret_access_key> <オブジェクトストレージサービスのシークレットアクセスキー>
Region to connect to.
Leave blank if you are using an S3 clone and you don't have a region.
Enter a string value. Press Enter for the default ("").
Choose a number from below, or type in your own value
 1 / Use this if unsure. Will use v4 signatures and an empty region.
   \ ""
 2 / Use this only if v4 signatures don't work, eg pre Jewel/v10 CEPH.
   \ "other-v2-signature"
region> 1
Endpoint for S3 API.
Required when using an S3 clone.
Enter a string value. Press Enter for the default ("").
Choose a number from below, or type in your own value
endpoint> https://jp-east-1.storage.api.nifcloud.com
Location constraint - must be set to match the Region.
Leave blank if not sure. Used when creating buckets only.
Enter a string value. Press Enter for the default ("").
location_constraint> ⏎
Canned ACL used when creating buckets and storing or copying objects.

This ACL is used for creating objects and if bucket_acl isn't set, for creating buckets too.

For more info visit https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#canned-acl

Note that this ACL is applied when server side copying objects as S3
doesn't copy the ACL from the source but rather writes a fresh one.
Enter a string value. Press Enter for the default ("").
Choose a number from below, or type in your own value
 1 / Owner gets FULL_CONTROL. No one else has access rights (default).
   \ "private"
 2 / Owner gets FULL_CONTROL. The AllUsers group gets READ access.
   \ "public-read"
   / Owner gets FULL_CONTROL. The AllUsers group gets READ and WRITE access.
 3 | Granting this on a bucket is generally not recommended.
   \ "public-read-write"
 4 / Owner gets FULL_CONTROL. The AuthenticatedUsers group gets READ access.
   \ "authenticated-read"
   / Object owner gets FULL_CONTROL. Bucket owner gets READ access.
 5 | If you specify this canned ACL when creating a bucket, Amazon S3 ignores it.
   \ "bucket-owner-read"
   / Both the object owner and the bucket owner get FULL_CONTROL over the object.
 6 | If you specify this canned ACL when creating a bucket, Amazon S3 ignores it.
   \ "bucket-owner-full-control"
acl> 1
Edit advanced config? (y/n)
y) Yes
n) No
y/n> n
Remote config
--------------------
[object-storage-service_east]
type = s3
provider = Other
env_auth = false
access_key_id = (オブジェクトストレージサービスのアクセスキー)
secret_access_key = (オブジェクトストレージサービスのシークレットアクセスキー)
endpoint = https://jp-east-1.storage.api.nifcloud.com
acl = private
--------------------
y) Yes this is OK
e) Edit this remote
d) Delete this remote
y/e/d> y
Current remotes:

Name                 Type
====                 ====
object-storage-old_east s3
object-storage-service_east s3
$

3 rclone syncの実行

以下コマンドで転送元バケット(source-bucket)から転送先バケット(target-bucket)へ全オブジェクトが転送されます。

rcloneでは転送先バケットは自動的に作成されます。

$ rclone sync -v object-storage-old_east:source-bucket object-storage-service_east:target-bucket
.
.
.
2022/05/27 18:13:24 INFO  : testdata/dir99/data97.dat: Copied (new)
2022/05/27 18:13:24 INFO  : testdata/dir99/data98.dat: Copied (new)
2022/05/27 18:13:24 INFO  : testdata/dir99/data99.dat: Copied (new)
2022/05/27 18:13:24 INFO  : Waiting for deletions to finish
2022/05/27 18:13:24 INFO  :
Transferred:       48.639G / 48.639 GBytes, 100%, 67.012 MBytes/s, ETA 0s
Errors:                 0
Checks:                 0 / 0, -
Transferred:        10000 / 10000, 100%
Elapsed time:    12m23.2s
$

平均5MBオブジェクトが10,000個、計48GBのオブジェクト転送が12分23秒で終わりました。
サーバータイプはe-mediumです。

実際の転送速度はオブジェクト数とオブジェクトサイズなどによって変わりますが、通常はe-mediumで十分と思われます。 また、rcloneはバケット名を指定しないとすべてのバケットの転送をしますので、複数バケットを1回で転送しようとするときにも便利です。

rcloneはオブジェクトを完全に同期させます。
もし転送元にはないオブジェクトが転送先にある場合、そのオブジェクトは転送先から削除されます。
このため誤った操作をするとデータが消失する可能性があります。 --dry-run オブションを指定して問題ないか確認してから本番実行することをおすすめします。

rcloneには他にも便利なオブションがあります。詳細はドキュメントをご参照ください。

方法3: s3syncを使用する

s3sync を使用する方法は、rclone同様ローカルディスクを使用しないので、移行対象オブジェクトの合計サイズが大きいときでも実施できる方法です。

この方法の長所と短所は以下のとおりです。

長所

・サイズが小さいオブジェクト(1KBから20KB)を大量に転送するときは非常に高速
・ユーザー定義メタデータ、Content-Type、 Content-Disposition、Content-Encoding、Content-Languageがコピーされる
ニフクラ オブジェクトストレージ (旧) SDK for Javaなどでクライアントサイド暗号化されたオブジェクトについても、ユーザー定義メタデータが正しく移行できるため、移行時に復号して、再度暗号化するといった中間作業が不要となります。

短所

・サイズが大きいオブジェクトの転送には向いておらず、失敗する可能性がある
おおよその目安として、平均オブジェクトサイズ*ワーカー数(デフォルト16) の物理メモリを使用します。
高速フラッシュドライブをスワップに設定することによってある程度この制限は緩和できますが、このツール自体はサイズが大きいオブジェクトを転送することに最適化されていません。
・バージョニングに対応していない
最新バージョンだけがコピーされます。

s3syncはユーザー定義メタデータがコピーされることがs3syncの大きな特徴です。

s3syncでローカルディスクにダウンロードしたときも、各種属性がファイルシステムの拡張属性(xattr)に保存されるなど、属性のコピーという点が非常に考慮されているツールです。

下記のように各種属性がxattrに保存されます。

$ getfattr -d encrypted_data
# file: encrypted_data
user.s3sync.meta="{\"e_tag\":\"\\\"76419e28b113e02d37c9e82e7408d856\\\"\",\"mtime\":\"2022-05-26T02:48:40Z\",\"content_type\":\"application/octet-stream\",\"content_disposition\":null,\"content_encoding\":null,\"content_language\":null,\"metadata\":{\"X-Amz-Iv\":\"ZZZZZZZZZZZZZZZZZZZZZZZZ\",\"X-Amz-Key\":\"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",\"X-Amz-Matdesc\":\"{}\"},\"acl\":null,\"cache_control\":null,\"version_id\":null,\"storage_class\":null,\"access_control_policy\":null}"

実施手順

  1. s3syncのビルド
  2. s3syncの実行

1 s3syncのビルド

s3syncはソースコードからビルドするかDockerで実行します。

以下はCentOS 7でソースコードからビルドする例です。

sudo yum install epel-release
sudo yum install golang
git clone https://github.com/larrabee/s3sync
cd s3sync
go mod vendor
go build -o s3sync ./cli 

2 s3syncの実行

以下コマンドで転送元バケット(source-bucket)から転送先バケット(target-bucket)へ全オブジェクトが転送されます。

転送先バケットはあらかじめ作成しておく必要があります。

$ ./s3sync \
--se https://jp-east-2.storage.api.nifcloud.com \
--sk (オブジェクトストレージ(旧)のアクセスキー) \
--ss (オブジェクトストレージ(旧)のシークレットアクセスキー) \
--te https://jp-east-1.storage.api.nifcloud.com \
--tk (オブジェクトストレージサービスのアクセスキー) \
--ts (オブジェクトストレージサービスのシークレットアクセスキー) \
s3://source-bucket s3://target-bucket/

INFO[0000] Starting sync
INFO[0844] Pipeline step finished                        ErrorObj=0 InputObj=0 InputObjSpeed=0 OutputObj=10000 OutputObjSpeed=11.83718334253728 stepName=ListSource stepNum=0
INFO[0844] Pipeline step finished                        ErrorObj=0 InputObj=10000 InputObjSpeed=11.83718334253728 OutputObj=10000 OutputObjSpeed=11.83718334253728 stepName=LoadObjData stepNum=1
INFO[0844] Pipeline step finished                        ErrorObj=0 InputObj=10000 InputObjSpeed=11.83718334253728 OutputObj=10000 OutputObjSpeed=11.83718334253728 stepName=UploadObj stepNum=2
INFO[0844] Pipeline step finished                        ErrorObj=0 InputObj=10000 InputObjSpeed=11.83718334253728 OutputObj=0 OutputObjSpeed=0 stepName=Terminator stepNum=3
INFO[0844] Duration: 14m4.79673977s                      durationSec=844.796737497
INFO[0844] Sync Done                                     status=0
$

平均5MBオブジェクトが10,000個、計48GBのオブジェクト転送が14分5秒で終わりました。 サーバータイプはe-mediumです。

s3syncはrcloneと異なりオブジェクトを削除することはありませんが、操作を間違えると古いデータで上書きされてしまう可能性がありますので、注意する必要があります。

s3syncにはほかにも便利なオブションがあります。詳細はドキュメントをご参照ください。

方法4: AWS SDKを使用して、独自の移行プログラムを作成する

AWS CLI v2、rclone、s3synなどでは対応できない特別な要件があるときは、AWS SDK を使用して独自のプログラムを作成することができます。
例えばバージョニングをサポートする必要がある場合は、既存のツールでは対応しきれない可能性があります。

AWS SDKにはリトライ機能などもすべて実装されており抽象化の度合いは比較的高く、少ない労力で独自の転送プログラムを作成することができます。

また、AWS CLI v2、rclone、s3syncはすべてオープンソースでソースコードが公開されていますので、カスタマイズすることも可能です。

データ検証について

移行処理後は正しくデータが移行されたか検証する必要があります。
転送元と転送先でオブジェクトサイズとETagが一致することを確認することは、有効な検証方法の1つです。

マルチパートアップロードではないときのETagはオブジェクトのMD5ハッシュですが、マルチパートアップロード時のETagはオブジェクトのMD5ハッシュではありません。

ETagの一致確認が理想的ですが、マルチパートアップロード時はETagは一致しない可能性がありますので、あらゆるケースに対応できる方法ではありません。

rcloneなどツールによってはマルチパートアップロード時にユーザー定義メタデータにMD5ハッシュを書き込むものもありますが、移行元のMD5ハッシュが分からないと検証はできないので、データ検証で使用できるケースは多くありません。

最低でも転送元と転送先でオブジェクトサイズの一致を確認することをおすすめします。

以下はAWS CLI v2を使用したオブジェクト一覧の出力コマンドで、バケット内の全オブジェクトのオブジェクトサイズが確認できます。

$ aws --profile object-storage-service_east --endpoint-url https://jp-east-1.storage.api.nifcloud.com s3 ls --recursive --summarize s3://target-bucket
2022-05-26 12:00:17   17825796 testdata/dir1/data1.dat
2022-05-26 12:00:17    5242880 testdata/dir1/data2.dat
2022-05-26 12:00:17   19922946 testdata/dir1/data3.dat

オブジェクトストレージの仕様上、最終更新日時はアップロードした日時となりますので、最終更新日時は転送元と異なります。

ETagもAWS CLI v2で出力できますが、JSONで出力されるため必要に応じて加工します。

$ aws s3api list-objects-v2 --profile object-storage-old_east --endpoint-url https://jp-east-2.storage.api.nifcloud.com --bucket source-bucket |jq -r '.Contents[] |[.Size, .ETag, .Key] |@tsv'
17825796    "ca4e308bb5f1645afa9dccf90174f45a-3"    testdata/dir1/data1.dat
5242880 "addc010dee58b36381fccce453f2fa04"  testdata/dir1/data2.dat
19922946    "685a0097a1aa8b6b24ba89ac3e72ad0f-3"    testdata/dir1/data3.dat

s3cmdであれば、もっと簡単に以下のコマンドでETagを出力できます。

$ s3cmd ls --recursive --list-md5 s3://source-bucket
2022-05-26 12:00  17825796   ca4e308bb5f1645afa9dccf90174f45a-3  s3://source-bucket/testdata/dir1/data1.dat

まとめ

ストレージサービス間でのデータ移行方法についてご紹介しました。

それぞれの方法について長所短所があります。

また、移行するデータの容量によってかなり時間がかかるケースもあります。 ネットワーク転送料金(ニフクラでは10TBまで無料)に関しても考慮する必要がでるかもしれません。 移行専用のサーバーをオブジェクトストレージ(旧)と同じリージョンに作成しますと、オブジェクトストレージ(旧)からのダウンロード時のネットワーク転送料金は課金対象外となりますので、料金面でお得になる可能性があります。

それらを認識した上で、ご自分の環境に最適な移行方法を選択してください。