ニフクラ ブログ

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

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

こんにちは、富士通クラウドテクノロジーズ 小林です。

ニフティクラウドには
ニフティクラウドストレージ (旧)
ニフティクラウド オブジェクトストレージ

という2種類のストレージサービスが存在します。
それぞれS3ベースの互換APIであることは変わりませんが、オブジェクトストレージはアップロードの転送量がリージョンに関わらず完全に無料であったり、昨今のデータ増加傾向に合わせたコストメリットが大きい料金設計のサービスになっております。
※ちなみに、両方のサービスともリクエスト量による課金は一切ございません。料金についての詳細はこちらを御覧ください。

この2種類のストレージサービスですが、オブジェクトをそれぞれのサービス間で移行するには少々工夫が必要ですので今回はいくつかやり方をご紹介したいと思います。

方法1. s3fs及びaws cli(syncコマンド)を利用する方法

まず1つ目の方法ですが、s3fsとAWS コマンドラインインターフェイス (以降 AWS CLI) というAWS用のツールを利用します。データの流れは下記のようになります。

クラウドストレージ(旧)→ s3fs → AWS CLI(syncコマンド) → オブジェクトストレージ

導入準備

  • AWS CLIのインストールはこちらをご参照ください。
  • fuseのインストール
# yum groupinstall "Development Tools" 
# wget https://github.com/libfuse/libfuse/releases/download/fuse-2.9.7/fuse-2.9.7.tar.gz
# tar xvfz fuse-2.9.7.tar.gz 
# cd fuse-2.9.7
# ./configure --prefix=/usr
# make
# make install
  • s3fsのインストール
# wget https://github.com/s3fs-fuse/s3fs-fuse/archive/v1.80.tar.gz
# tar xvfz v1.80.tar.gz
# cd s3fs-fuse-1.80
# ./autogen.sh
# ./configure --prefix=/usr
# make
# make install
# echo "APIアクセスキー:シークレットキー"  > ~/.passwd-s3fs 

実行例

クラウドストレージ(旧)の バケットsrcbucket からオブジェクトストレージの バケットdstBucket に転送する場合

  • s3fsマウント
# mkdir /src_dir
# s3fs -f srcbucket  /src_dir -o sigv2 -o url=https://ncss.nifty.com
  • aws cliでsync実行
# aws s3 sync --endpoint-url https://jp-east-2.os.cloud.nifty.com . s3://dstBucket

方法2. aws-sdkを利用したプログラムで移行

方法1で説明したようなツールを使った方式では、実行に関しての細かな制御ができないため、小さな容量のバケットであれば十分ですが、大規模になるに従って確認方法などに不安が残ります。下記の例はS3互換APIであることを利用して、rubyのaws-sdkを使用したプログラムによる移行を行うことものですが、当然途中でログなどを自由に出力できますので、確認もしやすくなります。

require 'aws-sdk-v1'
require 'nokogiri'
require 'yaml'

# migrate_storate_tool.rb
class MigrateStorageTool

    def initialize
        src_storage = AWS::S3.new(
          :access_key_id => ENV['ACCESS_KEY'] ,
          :secret_access_key => ENV['SECRET_KEY'],
          :s3_endpoint => ENV['SRC_ENDPOINT']
        )

        dst_storage = AWS::S3.new(
          :access_key_id => ENV['ACCESS_KEY'] ,
          :secret_access_key => ENV['SECRET_KEY'],
          :s3_endpoint => ENV['DST_ENDPOINT']
        )

        @src_bucket = src_storage.buckets[ENV['SRC_BUCKET_NAME']]
        @dst_bucket = dst_storage.buckets[ENV['DST_BUCKET_NAME']]
    end

    def migrage
        @src_bucket.objects.each do |src_obj|
           put_dst_storage src_obj
        end
    end

private

    def put_dst_storage(src_obj)
       puts "key: #{src_obj.key} "
       data = src_obj.read
       dst_obj = @dst_bucket.objects[src_obj.key]
       dst_obj.write(data, :multipart_threshold => 100 * 1024 * 1024)
       dst_obj.acl = set_src_acl(src_obj)
    end

    def authenticated_users_acl?(acl)
      acl.xpath('//xmlns:URI').to_s.include? "AuthenticatedUsers"
    end

    def public_read_acl?(acl)
      acl.xpath('//xmlns:URI').to_s.include? "AllUsers"
    end

    def private_acl?(acl)
      !public_read_acl?(acl) == !authenticated_users_acl?(acl)
    end

    def set_src_acl(obj)
        src_acl ||= Nokogiri::XML(obj.acl.to_s)
        return :public_read if public_read_acl?(src_acl)
        return :authenticated_read if authenticated_users_acl?(src_acl)
        return :private if private_acl?(src_acl)
        src_acl = nil
        :private
    end
end

ms = MigrateStorageTool.new
ms.migrage

実行方法

  • rubyが実行できる環境に上記コードを配置します。
  • 環境変数で、下記の値を設定しておきます。
    ※アクセスキー・シークレットキーはニフティクラウド・コントロールパネルのアカウント管理ページより取得できます。
export ACCESS_KEY=[アクセスキー]                    #ニフティクラウドAPIのアクセスキー
export SECRET_KEY=[シークレットキー]                #ニフティクラウドのシークレットキー
export SRC_ENDPOINT=ncss.nifty.com                #移行元のストレージエンドポイント(今回はクラウドストレージ(旧))
export DST_ENDPOINT=jp-east-2.os.cloud.nifty.com  #移行先のストレージエンドポイント(今回はオブジェクトストレージ)
export SRC_BUCKET_NAME=bucketname                 #移行元のバケット名
export DST_BUCKET_NAME=bucketname                 #移行先のバケット名
  • その後rubyスクリプトを実行すると、オブジェクトのコピーを行います。
# ruby migrate_storage_tool.rb 

上記プログラムでは、比較的小規模のバケットを想定してるので、エラーハンドリングなど細かい制御など行っておりませんが、データ量などに応じて、通信エラー等発生時のリトライ・一時停止・再開といった処理などを追記すると使い勝手もより向上すると思います。

また今回はaws-sdkのv1を使用したシンプルなサンプルになっていますが、可能であればv2を利用したほうがよりきめ細かいAPI操作を実装できるので移行の際に独自の要件などがある場合はv2を使用した方が良いかもしれません。