本番環境の転送用スクリプトの作成

概要

gsutil を本番環境での大規模なタスク(数 GiB のデータを毎晩アップロード / ダウンロードするなど)に使用する場合は、タスクを確実に実行するうえで役立つヒントがいくつかあります。このセクションでは特に、gsutil の再開可能転送メカニズムに関連して、大規模な本番運用タスクをスクリプト化する方法について説明します。

再開可能な転送のバックグラウンド

まず、gsutil の再開可能な転送メカニズムと、このメカニズムを確実に機能させるために必要なスクリプトの実装方法を理解しておくと便利です。gsutil は、任意のサイズのファイルをダウンロードするときや、構成可能なしきい値(デフォルトのしきい値 8 MiB)を超えるファイルをアップロードするときに、再開可能転送サポートを使用します。断続的なネットワークの問題などが原因で転送が途中で失敗すると、gsutil はランダム化されたバイナリの指数バックオフ / リトライ方式を使用して、10 分間に最大 23 回の転送を実施します。この試行で転送が毎回失敗し、その間に進捗がない場合、gsutil は転送を中止しますが、その際、構成可能な場所に転送のトラッカー ファイルを保持します。デフォルトの保存場所は ~/.gsutil/ です。このファイルには、転送中のバケットとオブジェクトの名前の SHA1 ハッシュと、ファイル名の最後の 16 文字を組み合わせた名前が付きます。このような形で転送が失敗した場合は、しばらくしてから(ネットワークの問題が解決した後など)、gsutil を再実行すると、中断した場所から再開可能転送機能により転送が再開します。

データ転送タスクのスクリプトの作成

このような方法で本番環境の大量のデータ転送をスクリプトで実行するには、未完了のファイル転送を定期的に判別し、gsutil でコピーを実行するスクリプトを作成する必要があります。以下では、このようなスクリプトを実装するための推奨事項を説明します。

  1. 再開可能な転送が 10 分間の間に 23 回連続で失敗し、その間に進捗がない場合、すぐに転送を再試行しても機能する可能性はほとんどありません。30 分おきに実行される cron ジョブを作成し、実行する必要のある転送をそのジョブで判別して転送を実行させるほうが、正常に処理される確率が高いと考えられます。ネットワークに一時的な問題が発生した場合、スクリプトによって中断箇所が特定され、最終的に(ネットワークの問題の解消後に)転送は正常に完了します。

  2. 迅速なデータ転送に依存するビジネスの場合は、ネットワーク監視機能の実装を検討する必要があります。たとえば、小規模なダウンロードを数分間隔で試行するタスクを実装しておき、そのダウンロードの試行が数回(回数は要件に応じて調整)続けて失敗した場合にアラートを生成するようにしておけば、IT 担当者が問題をすばやく調査できます。通常の監視の実装と同様に、アラート生成のしきい値を試しながら適切に設定し、IT 担当者によるアラートの無視につながるような誤判定のアラートを避ける必要があります。

  3. まだ転送が完了していないファイルは、さまざまな方法で判別できます。多数(数千以上など)のオブジェクトが含まれているバケットのリスト取得は避けることをおすすめします。1 つの方法として、オブジェクト名の構造を転送プロセスが反映されるような形にしておき、gsutil で接頭辞にワイルドカードを使用してバケットのリストの一部をリクエストする、という方法があります。たとえば、定期的なプロセスに現在の日付のオブジェクトのダウンロードが含まれる場合、「year-month-day-object-ID」の形式を使用してオブジェクトに名前を付けると、「gsutil ls "gs://bucket/2011-09-27-*"」のようなコマンドを使用してその日のオブジェクトを検索できます。「gsutil ls "gs://bucket/*-2011-09-27"」のようなコマンドを使用するより、ワイルドカードなしの接頭辞を使用する方が効率的です。後者のコマンドでは、実際にはバケット内の全リストをリクエストしてから gsutil 内でフィルタ処理しているのに対し、前者では Google Storage に対して名前が * までの部分で始まるオブジェクトのみを返すようリクエストするためです。

    データ アップロードの場合、スクリプトがファイルをクラウドに正常にコピーしたときに、別の方法でローカル ファイルを処理中領域から完了領域に移動する必要があります。次のようなコマンドを使用すると、この処理を一括して実行できます。

    gsutil -m cp -r to_upload/subdir_$i gs://bucket/subdir_$i
    

    i はシェルのループ変数です。gsutil cp コマンドの実行後に毎回、シェルの $status 変数が 0 になっているかどうかチェックし、コピーが失敗している場合には問題のコピーを戻します。

    この方法では、ファイル システムで残りの作業を記録しています。

  4. 1 個のバケット内に非常に多数(数十万以上)のオブジェクトがある場合は、バケットの一覧表示を使用してオブジェクトを列挙する代わりに、データベースによるオブジェクトの追跡を検討する必要があります。たとえば、このデータベースではダウンロードの状態を追跡できるため、バケットのリスト表示を実行せずに、ローカルでデータベースを検索することで、定期ダウンロード スクリプトによるダウンロードが必要なオブジェクトを判別できます。

  5. 転送に失敗した後で、部分的にダウンロードされた一時ファイルを削除しないようにします。gsutil が中断場所を特定します(さらに、最後にダウンロードされたコンテンツのハッシュを使用してデータの整合性を検証します)。部分的に転送されたファイルを削除すると、進捗状況が失われるため、ネットワークを無駄に利用することになります。

  6. 高速のネットワーク接続を使用している場合は、gsutil -m(マルチスレッド / マルチ処理)オプションを利用することで、大量のファイルを迅速に転送できます。ただし、一部のファイルのダウンロードが失敗していても、gsutil ではどのファイルが正常にダウンロードされたかを追跡しません。たとえば、マルチスレッド転送を利用して 100 ファイルをダウンロードし、そのうち 3 ファイルのダウンロードが失敗した場合、どの転送が失敗したかを判別して転送を再試行する処理は、スクリプト側で行う必要があります。こうしたケースは、前述のように定期的にチェックと実行を行うことで対応できます。

    並列転送(gsutil -m)を使用する場合、使用するスレッド数(.boto 構成ファイルの parallel_thread_count 設定)をいくつか試しながら適切に設定することをおすすめします。デフォルトでは、Linux の場合には 10 スレッドが、他のオペレーティング システムの場合には 24 スレッドが使用されます。この値が最適かどうかは、ネットワークの速度、使用できるメモリ、CPU 負荷などの条件によって変わります。スレッド数を増減させて試しながら、環境に最適なスレッド数を設定してください。