インフラチームがお届けするブログリレーです!既に公開されている記事もありますので、こちらから他のメンバーの投稿もぜひチェックしてみてください!

はじめに

この記事では、Storage Gateway(S3 File Gateway)とTransfer Family for SFTPを使用してSFTPとSMBプロトコルどちらも使用できるファイルサーバーを作る方法をご紹介します。

軽く前提知識を整理した後に、環境構築手順の紹介をしていきます。
特にStorage Gatewayについては、ちょっとクセがあったので細かく解説しています。

また、S3 File Gatewayの仕様で気になった点があったため、その点に関する動作検証の結果についても紹介します。

まずは軽く前提知識を整理

Storage Gateway、S3 File Gatewayについて

AWS Storage Gatewayはオンプレミス環境とAWSの間でのファイル送受信を行う際に使用されるサービスです。
Storage Gatewayを使用することで、今までオンプレミス環境で使用していたプロトコルをそのまま利用し、AWS上のストレージにファイルを転送できます。
(ファイル転送の処理そのものを行うサービスではなく、あくまでもプロトコルの差分を吸収するためのゲートウェイとして機能するイメージです)

オンプレ側のプロトコルとしては、SMB、NFS、iSCSIといったよく使用されるものがサポートされています。
AWS上のストレージとしてもS3、EBS、FSx for Windows File Serverといった一般的なものが使用できます。


(引用:https://pages.awscloud.com/rs/112-TZM-766/images/AWS-Black-Belt_2023_AWS-Storage-Gateway_0131_v1.pdf P10)

また、Storage Gatewayは使用するプロトコルによって4種類に分類されます。


(引用:https://pages.awscloud.com/rs/112-TZM-766/images/AWS-Black-Belt_2023_AWS-Storage-Gateway_0131_v1.pdf P11)

このように、Storage Gatewayはユースケースに合わせた使い分けができるサービスになっています。
今回はSMBプロトコルを使用して転送したいため、S3 File Gatewayを使用しています。

さらにStorage Gatewayのサービスを構成する重要な要素としてStorage Gatewayアプライアンスがあります。
その名の通り、Storage Gatewayとして動作するために必要な機能を持ったアプライアンスです。
オンプレミス側のサーバーにStorage Gatewayアプライアンスを導入するか、AWS側にEC2として設置するか、どちらか選ぶ必要があります。


(引用:https://pages.awscloud.com/rs/112-TZM-766/images/AWS-Black-Belt_2023_AWS-Storage-Gateway_0131_v1.pdf P12)

ドキュメントではオンプレミス側に配置することが勧められていますが、オンプレミスでの制約によって導入できない場合はEC2を使用して設置することになります。

なお、FSx File Gatewayについては2024年10月28日以降、新規作成できなくなっているため注意してください。
以下の記事にもあるように、FSx File Gatewayを使わずにFSx for Windows File Serverのファイル共有をクライアントに直接マッピングすることになります。

2024 年 10 月 28 日より、新規のお客様は新しい Amazon FSx File Gateway (FSx File Gateway) を作成できなくなります。このサービスを利用したい場合は、2024 年 10 月 28 日までに FSx File Gateway を作成してください。

https://aws.amazon.com/jp/blogs/news/switch-your-file-share-access-from-amazon-fsx-file-gateway-to-amazon-fsx-for-windows-file-server/

Transfer Family

Transfer FamilyもAWS上にファイル転送をするためのサービスですが、Storage Gatewayとは異なる以下のプロトコルを使用します。

  • SFTP(SSH File Transfer Protocol)
  • FTPS(File Transfer Protocol over SSL/TLS)
  • FTP(File Transfer Protocol)
  • AS2(Applicability Statement 2)

転送先に指定できるAWSサービスとしてはS3とEFSがサポートされています。

また、ファイル転送を補完する機能も提供されています。
例えば、今回使用するSFTPプロトコルではSFTPユーザーの認証情報を登録しておいたり、アクセス可能なディレクトリの設定する必要もあります。
これらの機能もTransfer Familyには具備されており、フルマネージドなSFTPサーバーとして使用することができます。

上記いずれのプロトコルを使用してAWS上にファイルを転送したい際には、有力候補となるサービスです。

なお、手前味噌ではありますが私が以前Transfer Familyについて登壇した際の資料も紹介させていただきます。

Transfer Familyの基本的な内容にも触れていますので、ご興味があれば見ていただければと思います。

DataSync

今回は検証していませんが、上記2つと類似するサービスとしてDataSyncにも少し触れておきます。
DataSyncはオンプレミスとAWSの間のデータ転送に使用するサービスです


(引用:https://pages.awscloud.com/rs/112-TZM-766/images/AWS-Black-Belt_2024_AWS-DataSync_0930_v1.pdf

Storage GatewayやTransfer Familyと似てるように見えますが、DataSyncはデータを転送する処理そのものを機能として提供するサービスです。
一方で、Storage GatewayとTransfer Familyは主にデータを転送するための環境を整備する目的で使用されるサービスです。
なので、Storage GatewayとTransfer Familyを使用する際には、データ転送の処理は別の仕組みを使って実装するのが一般的だと思います。

※厳密には少し異なると思いますが、今回はざっくり理解するために上記のような紹介の仕方をさせていただいています

やってみた

今回はStorage GatewayのS3 File GatewayとTransfer Familyを使用し、SMBとSFTPどっちも使用できるファイルサーバーを作ってみました。
構成図にすると以下のようになります。

SMBクライアントとしてはWindows Server on EC2を使用し、SFTPクライアントとしてはローカルPCを使用しました。

なお、今回は構成簡略化のためにTransfer Familyをパブリックサブネットに配置していますが、商用環境ではプライベートサブネットにおくことを推奨します
パブリックサブネットにあるNLBを前段に設置するなどしておき、SFTPサーバーに直接接続できないような構成にしておく方がセキュアな構成になります。

以降、構築手順と検証内容について順を追って説明していきます

事前準備

まずは以下のようにVPC、サブネット、EC2(Windows Server)、S3バケットを作成しておきます。
(これらの環境準備の手順は割愛させていただきます)

S3 File Gatewayの作成

今回はStorage Gatewayアプライアンスをプライベートサブネットに配置しましたが、その場合は手順に少しクセがありました。
そのため、アプライアンスを作る前後に補足を入れつつ手順を記載していきます。

Storage Gatewayアプライアンスの配置までの手順

まず、今回使用するS3 File Gatewayを作成していきます。

S3 File Gatewayの画面から「ゲートウェイの作成」をクリックし、名前、使用するタイムゾーン、ゲートウェイの種類を選択します

下にスクロールするとStorage Gatewayアプライアンスの作成メニューが表示されます。
オンプレミス側に導入する場合には、以下のように画面上からセットアップのためのテンプレートをダウンロードしておく必要があります。

今回はEC2を使用しますが、その場合にはデフォルト設定でEC2を立ち上げるか、設定をカスタマイズするかどうかを聞かれます。
ここで注意したいのが、Storage Gatewayをプライベートサブネットに配置するのか、パブリックサブネットに配置するのかによって手順が変わるという点です。

デフォルト設定を選択すると、以下のようにパブリックIPを持つサブネットしか選択できないようになります。

今回の検証もそうなのですが、Storage Gatewayアプライアンスをプライベートサブネットに配置したい場合は「設定をカスタマイズ」を選択する必要があります。

上記画面で(オプション)と書かれているところ以外はほぼ必須の要件となっているため、「インスタンスの起動」をクリックした後のEC2インスタンス起動画面で設定を行ってからEC2を起動させます。
EC2の作成が完了したらStorage Gatewayの画面に戻り、チェックボックスにチェックを入れてから「次へ」をクリックします。

少し脱線:なぜデフォルト設定でパブリックサブネットに配置されるのか?

少し話が脱線しますが、デフォルト設定でパブリックIPを要求される理由はStorage Gatewayのアクティベーションキーが関係しているようです。

Storage Gatewayのネットワーク仕様を見ると、以下のような記載があります。

ローカルシステムでストレージゲートウェイのアクティベーションキーを取得するため。ポート 80 は、Storage Gateway アプライアンスのアクティベーションの間のみ使用されます。

https://docs.aws.amazon.com/ja_jp/filegateway/latest/files3/Requirements.html#networks

若干理解しにくい記載の仕方ですが、要するに「Storage Gatewayのアクティベーションキーを取得するために、Storage Gatewayのパブリックなサービスエンドポイントにアクセスする必要がある」ということだと思われます。
つまり、プライベートサブネットにStorage Gatewayアプライアンスを配置する際には、Storage GatewayのVPCエンドポイントを用意しておく必要があるということです。

実際に、公式ドキュメントにもStorage GatewayのVPCエンドポイント作成手順が記載されています。

https://docs.aws.amazon.com/ja_jp/filegateway/latest/files3/gateway-private-link.html

今回もこのドキュメントを参考に、Storage Gateway用のVPCエンドポイントを作成しました。

Storage Gatewayアプライアンスを配置した後の手順

前述の手順でゲートウェイのセットアップを完了させた後に「次へ」をクリックすると、ゲートウェイ接続の設定に移ります。
ここでは「IPアドレス」と「アクティベーションキー」のどちらかを選ぶ必要がありますが、「IPアドレス」を選択するとパブリックIPしか入力できません。
そのため、プライベートサブネットを利用した場合には「アクティベーションキー」を選択する必要があります。

このアクティベーションキーの取得にも少しクセがあります。
今回のようにプライベートサブネットにStorage Gatewayアプライアンスを配置した場合、Storage Gatewayアプライアンスに対してHTTPリクエストを投げ、そのレスポンスからアクティベーションキーを取得する必要があります。

アクティベーションキー取得の手順もドキュメントに記載されており、crulコマンドやスクリプトを使用した手順が記載されています。


(引用:https://docs.aws.amazon.com/filegateway/latest/files3/get-activation-key.html#get-activation-key-linux-curl

そのため、今回はアクティベーションキー取得のためにEC2を別途追加し、以下のような仕組みでアクティベーションキーを取得しました。

以下は実際に実行したコマンドです

$ curl "http://10.XXX.XXX.XXX/?activationRegion=ap-northeast-1&vpcEndpoint=vpce-XXXXXXXXXXXXXXXXX-XXXXXXXX.storagegateway.ap-northeast-1.vpce.amazonaws.com&no_redirect"
XXXXX-XXXXX-XXXXX-XXXXX-XXXXX

上記のようにアクティベーションキーを取得し設定することで、Storage Gatewayの設定を次に進めることができます。

アクティベーションキーの入力ができたら次へ進み、設定内容を確認したら「アクティブゲートウェイ」をクリックします

セットアップの最終ステップに進み、「キャッシュストレージの設定」の欄の読み込みが終わるのをしばらく待ちます。
読み込みが終わったら「設定」をクリックします。

作成したゲートウェイの画面に移動し、ステータスが「実行中」になっていれば完了です。

ファイル共有の作成

先ほどはゲートウェイそのものを作成しましたが、ゲートウェイとS3バケットを連携させる設定を別途追加してあげる必要があります。
そのために、左メニューから「ファイル共有」に移動し「ファイル共有の作成」をクリックします。

連携させるゲートウェイとS3バケット、使用するプロトコル、認証方法を選択します。

認証方法をゲストアクセスにする場合は、「設定」をクリックしてゲストパスワードを設定しておきます。

ちなみに、この場合のユーザー名はsmbguestと設定されます。
私が調べた限りでは日本語版ドキュメントにゲストユーザーのユーザー名が書かれておらず、英語版ドキュメントでしか確認できませんでした。

You can use the following procedure to change the password for the guest user smbguest.
https://docs.aws.amazon.com/filegateway/latest/files3/guest-access.html

「ファイル共有の作成」をクリックするとファイル共有が作成されるので、ステータスが「利用可能」になることを確認します。

これでS3 File Gatewayの設定は完了です!

接続確認

別のVPCに作成したWindows Serverに接続し、SMBでの接続を設定していきます。
Windows Serverでネットワークドライブの割り当て設定画面を開き、フォルダ名を設定します。

なお、上記で設定するフォルダ名はファイル共有の詳細画面の「コマンドの例」から確認できます。

ゲストユーザーの認証情報を入力すると、ファイル共有の設定が完了します。

Transfer Family for SFTPの作成

では次に、Transfer Familyを作成していきます。
なお、Transfer FamilyをVPCに配置し、パブリックアクセス可能な状態にするにはEIPを少なくとも2つ作っておく必要があります。
EIPを作った上でサーバーの作成に取り掛かりましょう。

サーバーの作成

Transfer Familyの画面から「サーバーを作成」をクリックします。

今回はSFTPを使用するので、SFTPを選択して次に進みます。

SFTPユーザーを管理するIDプロバイダーのタイプを選択します。
ユースケースによって様々な設定ができますが、今回はサービスマネージドを選択します。

ネットワーク周りの設定画面に移るので、今回の構成に合わせて設定を入れていきます。

使用するストレージにはS3を選択します。

ログなどの詳細設定に移りますが、今回は全てデフォルトで設定しておきます。

最後に確認画面が出るため、設定内容を確認してから「サーバーを作成」をクリックします。

ステータスがオンラインになれば作成完了です

ユーザーの作成と接続確認

サーバーを作成したら、SFTPユーザーの設定をしていきます。
サーバーの詳細画面の中にユーザーという枠があるので、「ユーザーを追加」をクリックします。

ユーザーの名前やアタッチするIAMロールの設定を入れてユーザーを作成します。
※SSHパブリックキーの欄には、ローカル環境であらかじめ作成しておいたSSHユーザーの公開鍵の中身をコピぺしておきます。

ユーザーの作成まで終わったら接続する準備が整ったので、SFTPクライアントから正常に接続できることを確認します。

$ sftp -i hatakeyama-sftp-test-user hatakeyama-sftp-test-user@s-XXXXXXXXXXXXXXXXX.server.transfer.ap-northeast-1.amazonaws.com
The authenticity of host 's-XXXXXXXXXXXXXXXXX.server.transfer.ap-northeast-1.amazonaws.com (35.XXX.XXX.XXX)' can't be established.
RSA key fingerprint is SHA256:c3hD4zdkHyAJUUMuqpsFqgn56zjydJRMb4TYFWN+Foc.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 's-XXXXXXXXXXXXXXXXX.server.transfer.ap-northeast-1.amazonaws.com' (RSA) to the list of known hosts.
Connected to s-XXXXXXXXXXXXXXXXX.server.transfer.ap-northeast-1.amazonaws.com.
sftp> 
sftp> 
sftp> pwd
Remote working directory: /hatakeyama-test-s3

SFTPとSMBによるファイル転送の挙動確認

今回Storage Gatewayについて調べる中で、気になる仕様を見つけました

If you do want multiple file shares to write to the same Amazon S3 bucket, you must prevent the file shares from trying to write to the same objects simultaneously.
To do this, configure a separate, unique object prefix for each file share. This means that each file share only writes to objects with the corresponding prefix, and doesn’t write to objects that are associated with the other file shares in your deployment. You configure the object prefix in the S3 prefix name field when you create a new file share.

(翻訳)
複数のファイル共有を同じAmazon S3バケットに書き込みたい場合は、ファイル共有が同時に同じオブジェクトに書き込もうとするのを防ぐ必要があります。
これを行うには、各ファイル共有に個別のユニークなオブジェクトプレフィックスを設定します。これは、各ファイル共有が対応するプレフィックスを持つオブジェクトにのみ書き込み、デプロイメント内の他のファイル共有に関連付けられているオブジェクトには書き込まないことを意味します。オブジェクト接頭辞は、新しいファイル共有を作成するときに、S3 接頭辞名フィールドで設定します。

https://docs.aws.amazon.com/filegateway/latest/files3/best-practices.html#prevent-multiple-writes

これは、S3バケット内の特定のパス(フォルダ)に対する書き込みは、一つのゲートウェイからのみ設定するように書かれています。
今回、Storage Gatewayのファイル共有とS3バケットのパスは1対1に対応しているので問題ないように思えます。
しかし、特定のS3バケットのパスに対してStorage GatewayとTransfer Family両方から書き込みをするとどうなるかは不明でした。

なので、Storage GatewayとTransfer Family両方から書き込みをした場合の挙動確認をしてみました。

Storage Gateway経由での書き込みをした場合の挙動

まずはSMBクライアントからS3 File Gatewayを経由し、S3に対して書き込みを行います。
SMBクライアントであるWindows Server上で以下のようなファイルを作成し、共有フォルダに配置してみます。

すると、すぐにS3バケットにも保存されました。

1,2分経過すると、SFTP接続したローカルPCからも書き込まれたファイルが確認できました。

sftp> ls
TestFile_from_smb.txt   
sftp> 
sftp> get TestFile_from_smb.txt
Fetching /hatakeyama-test-s3/TestFile_from_smb.txt to TestFile_from_smb.txt
TestFile_from_smb.txt      
sftp> 
$ cat TestFile_from_smb.txt 
This is a test file from SMB client.

Transfer Family経由での書き込みをした場合の挙動

次に、SFTPクライアントからTransfer Familyを経由し、S3に書き込みを行います。
以下のようなファイルをSFTPクライアントであるローカルPC上に作成し、SFTPコマンドで転送します。

$ cat TestFile_from_sftp.txt 
This is a test file from local SFTP client.
sftp> pwd
Remote working directory: /hatakeyama-test-s3
sftp> 
sftp> put TestFile_from_sftp.txt
Uploading TestFile_from_sftp.txt to /hatakeyama-test-s3/TestFile_from_sftp.txt
TestFile_from_sftp.txt                                                                                                                                               100%   44     2.2KB/s   00:00    
sftp> 

すると、すぐにS3バケットにも保存されました。

しかし、10分ほど待ってもSMBクライアント側からは確認できませんでした。

これはStorage Gatewayのキャッシュに関する仕様が関係しています。
Storage Gatewayにはキャッシュ層が設けられているため、キャッシュ更新が行われないとS3バケット上での更新がSMBクライアント側からは確認できません。


(引用:https://pages.awscloud.com/rs/112-TZM-766/images/AWS-Black-Belt_2023_AWS-Storage-Gateway_0131_v1.pdf P23)

そこで、Storage Gatewayでキャッシュの更新を行います。


更新を行うと、SFTPで転送されてきたファイルをSMBクライアントから確認することができました!

なお、定期的にキャッシュを行うようにする設定も可能です。
今回はファイル共有の設定をカスタマイズしなかったのですが、その場合は以下のように、キャッシュの定期的な更新が行われない設定になります。

この設定を、試しに5分としてみます

キャッシュ定期更新の設定を入れた上で、SFTPクライアントから新たなファイルをSFTPで転送してみます。

$ cat TestFile_from_sftp_v2.txt 
This is a test file from local SFTP client.(v2)
sftp> put TestFile_from_sftp_v2.txt
Uploading TestFile_from_sftp_v2.txt to /hatakeyama-test-s3/TestFile_from_sftp_v2.txt
TestFile_from_sftp_v2.txt                                                                                                                                            100%   48     3.2KB/s   00:00    
sftp> 
sftp> ls
TestFile_from_sftp.txt      TestFile_from_sftp_v2.txt   TestFile_from_smb.txt       
sftp> 

5分後にSMBクライアント側から更新してみると、SFTPで転送し直したファイルを確認することができました!

さいごに

社内に閉じたプライベートな環境ではこのような構成を取ることは少ないと思いますが、社外の環境とファイル連携をする際には活用できる方法だと思います。

また、S3 File Gatewayを使用する際にはキャッシュ更新にも配慮する必要があります。
定期更新の間隔は5分が最短となっているため、リアルタイム性にシビアな要件が求められる環境では作り込みが必要と思われます。

とはいえ、今回紹介した構成を採用することで、今まで使用してきたSFTPサーバーやファイル共有の仕組みを丸っとAWSのマネージドサービスに置き換えることができます。
LambdaやStep Functionsを活用することで、ある特定のユースケースにおけるファイル転送処理を自動化してしまうことも可能だと思います。
どちらもとても良いサービスだと思いますので、ぜひ活用してみてください!

この記事が誰かの役に立ったら嬉しいです。