RAKSUL TechBlog

ラクスルグループのエンジニアが技術トピックを発信するブログです

サービスを止めずにNFSからS3へ移行した話

こんにちは。ハコベルカーゴのサーバサイドの開発を担当している貞元です。 ハコベルカーゴのインフラはAWSで構築されています。 初期のファイル保存先はNFSが採用されていましたが、負荷が高い時に応答が不安定になることがあり、新しくファイルを保存する際はS3が採用され、NFSとS3が混在する結果となりました。 その負債を解消するためにリリースをする際、サービスを止めずにNFSからS3にファイル保存先を移行しました。その時にとった方法を紹介します。

ハコベルカーゴとは

ハコベルカーゴとは荷物を送りたい荷主と、空いた時間に仕事を受注したい運送事業者を直接つなぐマッチングサービスです。 詳しくはこちらを見てみてくださいね。

インフラ・Webアプリケーションの構成

この話で関係するインフラ・Webアプリケーションの構成は以下のとおりです。

インフラ

  • AWS
    • EC2(Webアプリケーション, NFS)
    • S3

アプリ

  • Ruby on Rails
    • CarrierWave(ファイルアップロード)

問題・改善

上記のようにファイルのアップロード先がNFSとS3が混在しております。 またNFSサーバーはEC2上で動作させていますが、登録ドライバーの増加に伴い負荷が高くなりやすく応答が不安定になることがありアップロードや参照ができないことが発生していました。 そのためNFSを使用するのをやめ、ファイルアップロード先を可用性の高いS3のみに改善することにしました。

ハコベルカーゴは、荷主からは常時注文を受け付けています。 またドライバーも常時運行している状況であるため、サービスを止めないように運用しています。 そのため移行手順は段階的に分け、各手順で問題なく動作していることの確認も含めて約3日おきに実施しました。

移行手順

  1. 移行前
  2. ファイルの保存先をNFSとS3の両方に変更
    1. CarrierWaveのUploaderで保存先をS3に変更gem 'fog-aws'を使用し、storage :fogを指定してS3へアップロード
      class ImageUploader < CarrierWave::Uploader::Base
        storage :fog
      end
    2. storeメソッドをオーバーライドして、NFSにも保存
      class ImageUploader < CarrierWave::Uploader::Base
        storage :fog
      
        def store!(new_file)
          super
      
          FileUtils.mkdir_p(File.dirname(filepath))
          File.binwrite(filepath, file.read)
        end
      end
  3. 過去のファイルをS3へコピー
    1. aws cliにて、S3とファイルを同期
      aws s3 sync \
        --exact-timestamps \
        --cache-control="max-age=864000" \
        /mnt/nfs/path/to/ s3://path/to/
    2. この段階でNFSとS3の両方に同じファイルが存在することになる
  4. ファイル取得先をS3へ変更
  5. ファイルの保存先をS3のみにし、NFSを停止

まとめ

このように段階的に移行することで、サービスを止めることなく移行することができました。 今回のようなNFSからS3への移行だけでなく、他のケースにも応用できます。バックエンドの大きな変更などがある場合には、このような方法を検討してユーザーへのサービス提供を止めないチャレンジをしてみると良いと思います。

ハコベルおよびラクスルではエンジニアリングの力で世界を変えたいエンジニアを絶賛募集中です! 本記事を読んで興味をもっていただいた方はぜひご連絡いただければと思います!