Cloud Storage のベスト プラクティス

はじめに

このページには、Cloud Storage のドキュメントの他のページから抜粋したベスト プラクティスの概要が含まれています。ここに挙げたベスト プラクティスは、Cloud Storage を使用するアプリケーションを構築するときに留意すべきことをすばやく参照するために役立ちます。商用アプリケーションをリリースする場合には、次のベスト プラクティスを遵守してください。

これから Cloud Storage を使い始めるという方には、このページから開始することはおすすめしません。このページは Cloud Storage の基本的な使い方を説明したものではないためです。新たに始める方には、クイックスタート: Console の使用またはクイックスタート: gsutil ツールの使用から開始することをおすすめします。

命名

  • 名前についての要件と考慮事項については、バケットの命名オブジェクトの命名のトピックをご覧ください。

  • 多数のバケットが必要な場合は、GUID か同等のものをバケット名に使用し、名前の衝突を処理するための再試行ロジックをコードに含め、バケットを相互参照するためのリストを保持してください。もう一つの方法は、ドメイン名付きのバケットを使用し、バケット名をサブドメインとして管理することです。

  • ユーザー ID、メールアドレス、プロジェクト名、プロジェクト番号、個人を特定可能な情報(PII)をバケット名に使用しないでください。バケットの存在を誰でも調べることができます。同様に、オブジェクト名に PII を使用する場合にも十分に注意してください。オブジェクト名は、オブジェクトの URL に表示されます。

  • 並行して多数のファイルをアップロードする場合は、タイムスタンプ ベースのファイル名などのシーケンシャルなファイル名を使用しないでください。シーケンシャルな名前を持つファイルは連続して保存されるため、同じバックエンド サーバーにヒットする可能性があります。このようなとき、スループットが制限されます。最適なスループットを達成するために、シーケンス番号のハッシュをファイル名の一部として追加して、連続しないようにしてください。詳細については、リクエスト レートとアクセス配信のガイドラインをご覧ください。

トラフィック

  • Cloud Storage に送信されるトラフィック量の簡単な見積もりを行います。特に、以下の点を考えてください。

    • 1 秒あたりのオペレーションの回数。バケットとオブジェクトの両方について、また作成、更新、削除オペレーションについて、1 秒あたりにオペレーションを何回行うか。

    • 帯域幅。どれだけの量のデータをどれだけの期間内に送信するか。

    • キャッシュ制御。オブジェクトに Cache-Control メタデータを指定すると、頻繁にアクセスするオブジェクトの読み込みレイテンシを改善できます。Cache-Control などのオブジェクトのメタデータの設定方法については、メタデータの表示と編集をご覧ください。

  • トラフィックのスパイクが最小になるようにアプリケーションを設計します。アプリケーションのクライアントの中に、更新を行うものがある場合は、1 日の中で分散させてください。

  • Cloud Storage には、リクエスト レートについての上限はありませんが、高いリクエスト レートに対応するようスケーリングする際のパフォーマンスが最善になるように、リクエスト レートおよびアクセス配信のガイドラインに従ってください。

  • 特定の操作にはレート制限があることに注意し、それに従ってアプリケーションを設計してください。

  • エラーが発生した場合:

    • 再試行方式の一環として指数バックオフを使用して、大量のトラフィック バーストによる問題を避けてください。

    • 新しい接続を使用して再試行し、可能であればドメイン名を再度解決してください。こうすれば、再試行すると同じパスを通り、最初のリクエストがヒットしたのと同じ異常コンポーネントにヒットする「サーバー固定性」を回避することができます。

  • アプリケーションでレイテンシが問題になる場合には、ヘッジされたリクエストを使用します。ヘッジされたリクエストを使用すると、再試行が高速化され、テール レイテンシを削減できます。これによってリクエストの期限が早まって、リクエストが早期にタイムアウトになる可能性はありません。詳細については、https://www2.cs.duke.edu/courses/cps296.4/fall13/838-CloudPapers/dean_longtail.pdf を参照してください。

  • 顧客がアプリケーションに期待するパフォーマンス レベルを理解しましょう。この情報は、新しいバケットを作成するときストレージ オプションとリージョンを選ぶのに役立ちます。

リージョンとデータ ストレージのオプション

  • 高い頻度で提供され、高可用性が求められるデータには、Standard Storage クラスを使用します。このクラスでは、価格は高くなりますが、最高の可用性が提供されます。

  • アクセス頻度が低く、やや低い可用性でも許容できるデータは Nearline Storage クラス、Coldline Storage クラスまたは Archive Storage クラスを使用して保存できます。

  • データは、アプリケーションのユーザーに最も近いリージョンに保存します。たとえば、EU のデータの場合は EU バケットを選択し、米国のデータの場合は US バケットを選択します。詳しくは、バケットのロケーションを指定するをご覧ください。

  • ユーザーデータのロケーションを選ぶ際には、コンプライアンス要件に留意してください。ユーザーがデータを提供するロケーションについての法的な要件があるかどうかを考慮する必要があります。

セキュリティ、ACL、アクセス制御

  • 最も重要な注意事項は、認証情報を絶対に共有しないことです。各ユーザーは異なる認証情報を持つ必要があります。

  • HTTP プロトコルの詳細を印刷すると、OAuth 2.0 トークンなどの認証情報がヘッダー内に表示されます。メッセージ ボードにプロトコルの詳細を投稿する必要がある場合や、トラブルシューティングのために HTTP プロトコルの詳細を提供する必要がある場合は、出力の一部として表示される認証情報を削除または無効にするようにしてください。

  • 可能な場合は、データ転送時に常に TLS(HTTPS)を使用します。これにより、ネットワーク経由でのデータ転送時に認証情報やデータが保護されます。たとえば、Cloud Storage API にアクセスするには、https://storage.googleapis.com を使用します。

  • サーバー証明書を検証する HTTPS ライブラリを必ず使用するようにします。サーバー証明書を検証しない場合、アプリケーションが中間者攻撃などを受けやすくなります。一般に使用されている実装言語の HTTPS ライブラリには、デフォルトではサーバー証明書の検証を行わないものもありますのでご注意ください。たとえば、バージョン 3.2 よりも前の Python ではサーバー証明書の検証は組み込まれていないか、部分的にしかサポートされていません。アプリケーションでサーバー証明書の検証を行うには、サードパーティのラッパー ライブラリを使用する必要があります。

  • アプリケーションがデータにアクセスする必要がなくなった場合は、認証情報を無効にする必要があります。Google のサービスや API で認証情報を無効にするには、Google アカウント権限にログインし、不要なアプリケーションをクリックして [アクセス権を削除] をクリックします。

  • 認証情報は安全に保存するようにします。これには、環境や認証情報の保存場所に応じてさまざまな方法があります。たとえば、認証情報を構成ファイル内に保存している場合は、不正アクセスを防止するため、そのファイルに適切な権限を設定するようにしてください。Google App Engine を使用している場合は、StorageByKeyName を使用して認証情報を保存します。

  • Cloud Storage リクエストは、バケットとオブジェクトを名前で参照します。その結果、ACL によって不正な第三者がバケットやオブジェクトを操作できないようにしていても、第三者がバケット名やオブジェクト名を使用してリクエストを試行し、エラー レスポンスからバケットやオブジェクトの存在を確認できます。したがって、バケット名やオブジェクト名の情報が漏洩することも考えられます。バケット名やオブジェクト名のプライバシーが心配な場合は、次のような予防策を講じる必要があります。

    • 推測しにくいバケット名やオブジェクト名にする。たとえば、「mybucket-gtbytul3」のような無作為なバケット名であれば、不正な第三者が名前を容易に推測したり、他のバケット名を想像したりできなくなります。

    • バケット名やオブジェクト名の一部に機密情報を含めないようにする。たとえば、バケット名として mysecretproject-prodbucket の代わりに somemeaninglesscodename-prod を指定します。一部のアプリケーションでは、機密性の高いメタデータをオブジェクト名の中にエンコードするのではなく、x-goog-meta などのカスタム Cloud Storage ヘッダー内に保持するほうが有用な場合があります。

  • 多数のユーザーを明示的に列挙するのではなく、グループを使用します。これによりスケーラビリティが向上するだけでなく、多数のオブジェクトのアクセス制御を一度に更新するための非常に効率的な手段も提供されます。さらに、ACL を変更するためにオブジェクトごとにリクエストを発行しなくて済むため、コストが低くなります。

  • オブジェクトをバケットに追加する前に、デフォルト オブジェクト ACL が要件に合わせて設定されていることを確認します。これにより、個別のオブジェクトについて ACL を更新する時間を大幅に節約できます。

  • バケットの ACL とオブジェクトの ACL は互いに独立しています。つまり、バケットの ACL はそのバケット内のオブジェクトの ACL には影響を与えません。バケットに対する権限を持たないユーザーが、バケット内のオブジェクトに対する権限を持つことが可能です。たとえば、バケットを作成してグループ A のみにバケット内のオブジェクトを一覧表示する権限を付与してから、そのバケットにオブジェクトをアップロードしてグループ B のみにそのオブジェクトへの READ アクセスを許可できます。グループ B はオブジェクトを読み取ることはできますが、バケットの内容を表示したり、バケットに関するタスクを実行したりすることはできません。

  • Cloud Storage のアクセス制御システムには、オブジェクトが一般公開で読み取り可能であることを指定する機能が含まれています。この一般公開権限のもとで書き込むオブジェクトすべてについて、それが意図したものであることを確認してください。いったんインターネットに公開したデータは、多くの場所にコピーされるため、この権限のもと書き込まれたオブジェクトに対する読み取り制御を事後に設定しても事実上無意味です。

  • Cloud Storage のアクセス制御システムには、バケットが一般公開で書き込み可能であることを指定する機能が含まれています。この方法でバケットを構成することはさまざまな目的で便利ですが、この権限は使用しないことをおすすめします。不正なコンテンツ、ウィルスなどのマルウェアの配布に悪用される可能性があり、バケットの所有者はバケットに保存されたコンテンツに対する法的および金銭的な責任を問われることになります。

    Google アカウントを持たないユーザーが安全にコンテンツを利用できるようにする必要がある場合は、署名付き URL の使用をおすすめします。署名付き URL を使用すると、オブジェクトへのリンクを提供できます。アプリケーションの利用者は、オブジェクトにアクセスするために Cloud Storage での認証を必要としません。署名付き URL を作成するときには、アクセスの種類(読み取り、書き込み、削除)と期間を制御します。

  • gsutil を使用する場合は、追加の推奨事項をご覧ください。

データのアップロード

  • XMLHttpRequest(XHR)コールバックを使って最新の進捗状況を取得する際、進捗が円滑でない場合でも、接続をいったん閉じて再度開くという操作は行わないでください。これを行うと、ネットワークの輻輳時に不適切な正のフィードバック ループができます。ネットワークが輻輳している場合、XHR コールバックはアップロード ストリームからの確認応答(ACK / NACK)処理の背後に未処理のまま残ることがあり、この状況で接続を閉じて再度開くと、最も余裕がない状況にもかかわらずより多くのネットワーク キャパシティを使用します。

  • アップロード トラフィックについては、適度に長いタイムアウトを設定することをおすすめします。優れたエンドユーザー エクスペリエンスのために、アプリケーションの XHR コールバックが長時間呼び出されない場合に、クライアント ステータス ウィンドウを更新してメッセージ(「ネットワークが輻輳しています」など)を表示するようなクライアント側のタイマーを設定できます。このような状況が発生した場合、接続を閉じて再試行することはしないでください。

  • Compute Engine インスタンスを、再開可能なアップロードを開始するために Cloud Storage への POST を行うプロセスとともに使用する場合は、Compute Engine インスタンスを Cloud Storage バケットと同じロケーションで使用する必要があります。次に geo IP サービスを使って、顧客のリクエストのルーティング先となる Compute Engine のリージョンを取得することで、地理上の地域にトラフィックを局所化できます。

  • 再開可能なアップロードでは、再開可能なセッションが作成されたリージョンにそのセッションが留まっている必要があります。こうすることでセッション状態の読み書き時に生じるリージョン間トラフィックを削減でき、再開可能なアップロードのパフォーマンスが向上します。

  • できるだけ転送を小さなチャンクに分解せず、コンテンツ全体を 1 つのチャンクでアップロードしてください。チャンクへの分割を避けることにより、固定のレイテンシ コストがなくなり、スループットが向上するとともに、Cloud Storage に対する QPS が減ります。

    チャンクでアップロードすることを検討すべき状況としては、ソースデータが動的に生成される場合や、クライアントにリクエスト サイズの制限がある場合(多くのブラウザではこれが当てはまります)、クライアントがリクエスト全体をメモリにロードしてからでないと 1 つのリクエストでバイトをストリーミングできない場合が挙げられます。クライアントがエラーを受信する場合、commit オフセットをサーバーに問い合わせ、そのオフセットから残りのバイトのアップロードを再開できます。

  • content-encoding: gzip と圧縮形式の content-type の両方を含むコンテンツをアップロードすると予期しない動作が発生する可能性があるため、この操作はできるだけ避けてください。

データの削除

  • アプリケーション ソフトウェアまたはユーザーがある時点で誤ってデータを削除または上書きする心配がある場合は、Cloud Storage の次の機能を利用してデータを保護してください。

  • 数十万個以上のオブジェクトを一括削除する場合は、処理に非常に時間がかかるため、gsutil の使用を避けてください。代わりに、以下のいずれかの方法を選択します。

    • Cloud Console では、最大数百万個のオブジェクトをバックグラウンドで一括削除できます。また、Cloud Console は、Cloud Console の使用時にフォルダの一部として表示される共通の接頭辞を共有しているオブジェクトのみを一括削除する場合にも使用できます。

    • オブジェクトのライフサイクル管理では、任意の数のオブジェクトを一括削除できます。バケット内のオブジェクトを一括削除するには、条件が Age に 0 に設定され、アクションが Delete に設定されているライフサイクル構成ルールを設定します。削除の処理中に、影響を受けるバケットのオブジェクトの一覧表示が影響を受ける可能性があります

オブジェクトの一覧表示

バケットから多数のオブジェクトを削除した直後、一時的に、オブジェクトの一覧表示が非常に遅くなる場合があります。これは、削除されたレコードが、基になるストレージ システムからすぐには削除されないため、オブジェクトの一覧表示で返すオブジェクトを検索するとき、削除されたレコードをスキップする必要があることが原因です。

最終的に、削除されたレコードは、基になるストレージ システムから削除され、オブジェクトの一覧表示のパフォーマンスは再び正常になります。これには、通常、数時間かかりますが、数日かかる場合もあります。

ワークロードを設計するとき、最近の削除が多いオブジェクトの範囲の一覧表示を避けるようにする必要があります。たとえば、オブジェクトの一覧表示と削除を繰り返してバケットからオブジェクトを削除しようとする場合は、各リクエストで先頭から一覧表示を再開するのではなく、オブジェクトの一覧表示のレスポンスで返されたページトークンを使用して、次の一覧表示のリクエストを発行するようにしてください。各リクエストで、削除された直後のオブジェクトをすべてスキップする必要があるため、オブジェクトの一覧表示が遅くなります。特定の接頭辞のオブジェクトを多数削除した場合、削除の直後は、その接頭辞のオブジェクトを一覧表示しないようにしてください。

ウェブサイトのホスティング

クロスオリジン リソース シェアリング(CORS)のトピックでは、他のウェブサイトでホストされているスクリプトが Cloud Storage バケットに格納されている静的リソースにアクセスできるようにする方法について説明されています。逆のシナリオは、Cloud Storage でホストされているスクリプトに、Cloud Storage の外部のウェブサイトでホストされている静的リソースへのアクセスを許可する場合です。後者のシナリオでは、ウェブサイトは CORS ヘッダーを提供して、アクセスが storage.googleapis.com のコンテンツに許可されます。

特定のバケットをこのデータアクセス専用にすることをおすすめします。これにより、サイトによって静的リソースが誤ってすべての storage.googleapis.com に過度に公開されることを防ぎます。たとえば、mybucket という名前のバケットをデータアクセス専用にしたい場合は、ウェブサイトで CORS ヘッダー Access-Control-Allow-Origin: https://mybucket.storage.googleapis.comAccess-Control-Allow-Origin: https://storage.googleapis.com の代わりに提供するようにしてください。