【AWS】S3まとめ


どうも、iron千葉です。
S3について、ユーザガイドを見てポイントをまとめました。
ポイントだけ確認したい人、ざっと全体を見たい人におすすめです
S3は奥が深い。


# S3とは？
* インターネットストレージ（平たく言うとgoogleドライブ、evernoteのようなwebブラウザから利用できるストレージ）
* S3はAPIまたはAWS CLIにてプログラムから操作（ファイルのアップロード、ダウンロード、削除）ができる
* 容量制限なし
* データはいつでもダウンロード可能
* 柔軟なアクセス制御ができる（IAM、アクセスコントロール、バケットポリシー）

# S3の概念
## バケット
* バッケットを作成し、その配下にデータを格納する
* バケットはS3の中で一番大きな
* バケットは複数作成できる
* バケットでアクセス制御が可能
* バケット作成時は、配置するリージョンを指定する

## オブジェクト
* オブジェクトは、データ（アップロードファイル）
* オブジェクトは、データ（アップロードファイル）とメタデータ（Content-Type等、ユーザ定義のカスタムメタデータも指定できる）で構成される
	* メタデータはアップロード時にのみ指定できる（アップロード後に修正する場合は、オブジェクトをコピーするときに指定しなおす）
	* オブジェクトをコピーした場合、メタデータも一緒にコピーされる
* オブジェクトは、キーとバージョンIDによってバケット内で一意に特定

## キー
* オブジェクトの固有の識別子
* オブジェクト位は１つのキーを持つ
* オブジェクトはバケット・キー・オブジェクトで一意に特定される

## リージョンとAZ
* S3のバケットをどのリージョン（地域）に作成するのかを指定できる
* S3は3箇所以上のAZに同期される（堅牢性が高い）

## データ整合性モデル
* ３つのデータセンターにデータを同期するため以下の整合性モデルとなる
* 新規ファイルをアップロード時は、「書き込み後の読み込み」整合性→書き込み後すぐ読み込みを行っても問題なく読み込まれる
* 既存ファイルの上書き・削除時は、古いデータを参照または削除ファイルを参照できる状態となり、結果整合性となる→更新後すぐに読み込みを行うと、更新前の情報が返される可能性がある。時間が立つと更新後の状態を返すモデル。
* 実際の動作としては
	* 新しいオブジェクトを Amazon S3 に書き込み、すぐに読み取りを試みます。変更が完全に反映されるまで、Amazon S3は「キーが存在しません」というレポートを表示する場合があります。
	* 新しいオブジェクトを Amazon S3 に書き込み、すぐにバケット内のキーのリストを表示します。変更が完全に反映されるまで、オブジェクトがリストに表示されないことがあります。
	* 既存のオブジェクトを置換し、すぐにそのオブジェクトの読み取りを試みます。変更が完全に反映されるまで、Amazon S3 は古いデータを返す場合があります。
	* 既存のオブジェクトを削除し、すぐにそのオブジェクトの読み取りを試みます。削除が完全に反映されるまで、Amazon S3 は削除済みのデータを返す場合があります。
	* 既存のオブジェクトを削除し、すぐにバケット内のキーのリストを表示します。削除が完全に反映されるまで、Amazon S3 は削除済みのオブジェクトをリストに表示する場合があります。
* オブジェクトのロックをサポートしていない。同時に同じリクエスト（同じファイルを更新等）した場合は、最新のタイムスタンプを持つリクエストが優先される

# S3の機能
## 低冗長化ストレージ(RRS)
* 通常のS3は3箇所のAZでデータをレプリケーションするが、RSSを指定すると2箇所にレプリケーション
* 通常に比べて安価
* 重要でないデータ、再作成できるデータ等を格納するのに利用

## アクセス制御
* S3では3つのアクセス制御がある
	* バケットポリシーは、バケットレベルでのアクセス制御
	* IAMはユーザレベルでのアクセス制御
	* アクセスコントロールリスト（ACL）はオブジェクトレベルでの制御

### バケットポリシー
* バケットポリシーとは、バケットに対して割り当てるアクセス制御用のポリシー（バケットレベルでのアクセス制御を一元管理）※バケット配下のオブジェクトに全て適用される

### IAM
* IAMアカウントを作成し、IAMアカウントに対してS3のアクセス権限を付加できる
* 操作（参照、作成、更新、削除）できるバケットや、オブジェクトを制限できる
* IAMの機能であるフェデレーションを利用して、AWSアカウントを持っていないユーザが一時的にアクセスできるようにすることが可能

### アクセスコントロールリスト
* アクセスコントロール（ACL）は、オブジェクト単位にて制御できる

# バケットの設定可能な項目
* ライフサイクル：オブジェクト作成後1週間後に削除するような設定ができる
* website：静的なWebサーバとして設定できる
* バージョニング：オブジェクトのバージョンを管理できる。誤って上書きした場合に、戻すことができる
* バケットポリシーおよびACL（アクセスコントロールリスト）：バケットレベル、オブジェクトレベルでのアクセス制御ができる
* cors(Cross-Origin Resource Sharing)：クロスオリジンリクエストを許可するようにバケットを設定できる
* バケットに対するタグ付け：バケットに対してタグをつけることで請求レポートで集計できる
* locationの指定：S3を作成するリージョンを指定できる
* S3イベントの通知：S3で発生したイベント（オブジェクト作成、RSSデータ消失）をSNSへプッシュできる
* requestPayment：通常はバケット所有者がS3の通信料金を払う。requestPaymentを利用すると、ダウンロードするユーザに通信料金を請求できる
* DevPay：ダウンロードするコンテンツをユーザに課金させることができる

# バケット
## バケットの制約と制限
* バケット名はリージョン内で一意になる必要がある（S3を利用している全ユーザの中で一意のバケット名を指定する必要がある）※指定したバケット名がDNS名となるた一意になる必要がある
* バケット作成したユーザが所有者となり、他ユーザに委譲できない
* バケット内に作成できるオブジェクト数に制限なし
* バケット内にバケットを作成できない

# オブジェクト

## オブジェクトの構成要素
* キー：オブジェクトを一意にするための名前（ほぼほぼファイル名同等）
* バージョンID：バージョニングを有効にした場合に付加されるID
* 値：データ（ファイル）。0から5TBまでのファイルを格納できる
* メタデータ：オブジェクトの情報を格納するためのキーと値のペア（システムメタデータとユーザにて定義できる独自のメタデータを利用できる）
	* システムメタデータは、オブジェクト作成日、オブジェクトのサイズ、オブジェクトのMD5値、ストレージクラス（Standard?RSS?）、暗号化（SSE-C）状態等を格納している
	* ユーザ定義メタデータ：ユーザ独自に定義できるデータ。例えば、キーを「upload-user」、値を「chiba」で定義することでアップロードしたユーザ名を格納できる
* アクセスコントロール情報：ACL、バケットポリシー、AIMベースのアクセス制御の情報

## バージョニング
* 複数のバージョンのオブジェクトを維持できる（意図的にaaa_20150401.xls、aaa_20150402.xlsなどやらなくても、aaa.xlsでアップロードするだけで複数のバージョンにアクセスできる）
* バージョニングを有効にすることで、誤って上書きしたり、過去の状態のファイルを取得することができる
* デフォルト無効
* バージョニングしている総容量が課金対象（aaa.xlsの場合、バージョン1,バージョン2の2ファイル分課金される）
* バージョニングはバケットレベルで有効・無効を指定できる（オブジェクト単位ではできない）
* 更新の場合は、上書きされず（元のファイルを保持したまま）、別バージョンとして保存される
* 削除（Delete）を実行した場合は、実際にオブジェクトが削除されるわけではなく、”削除した”という情報を最新バージョンとする（なので、元のファイルを復元できる）
* 完全に削除するには、バージョンを指定して削除する（バケット所有者のみが実施できる）※バージョンを指定すると一生復元することができない、削除したオブジェクトの課金もされなくなる
* MFA削除を利用できる。削除やバージョンの有効・無効を変更するときに2要素認証を要求するように設定できる

## ライフサイクル管理
* オブジェクトを自動で削除できる
* オブジェクトを自動でGlacierへアーカイブできる
* ライフサイクルはバケットに対して設定する（オブジェクト単位での設定はできない）
* ライフサイクルは期間をトリガーとして実行する
* 例えば作成後（更新後）、7日後にGlacierへバックアプ、14日後に削除など指定できる
* Glacierにアーカイブされたオブジェクトについて
	* リアルタイムでは利用できない（復元に５時間かかることもある）
	* Glacierにアーカイブされたオブジェクトは、一時的に復元できる（一時的にRRSに復元される、S3のオブジェクトとして元に戻るわけではない）（復元期間を指定し、ダウンロードできる）
	* 復元されたオブジェクトは復元期間を過ぎると削除され、ダウンロードできなくなる
	* ライフサイクルでGlacierへ移動したオブジェクトは、S3からしかアクセス出来ない（Glacierに直接アクセスできない）

## ライフサイクルの設定
* XML形式でライフサイクルを定義し、バケットに割り当てる
* バージョニングが無効な場合：各オブジェクトのバージョンは１つしか無いので、単純に期間やprefix（フォルダのパス）を指定するだけ
* バージョニングが有効な場合：各オブジェクトには最新と、以前のバージョンが存在する。ここでのライフサイクルの対象は、古いバージョン。古いバージョンがGlaceirへアーカイブするタイミング、またはS3から削除するタイミングを指定する
* ライフサイクルは無効・有効を設定できる

## Cross-Origin Resource Sharing
* クロスドメインアクセスを許可できる
* クロスドメインアクセスとは？
	* 例えば、http://example.com/index.htmlへアクセスした場合、別ドメインhttp://test.com/のリソース取得するajax通信を行うことをクロスドメインアクセスと言う
	* 基本的にブラウザでは、セキュリティ上このアクセスを禁止している。理由は、クロスサイトスクリプティングを防止している
	* example.comにクレジットカード番号を送ったつもりなのに、悪意的にtest.comに送られたら困りますよね。
* そこで安全にクロスドメインアクセスを行うための実装がCORS( Cross-Origin Resource Sharing)
* CORSは、XMLHttpRequest(非同期通信を実現するためのjavascriptのオブジェクト)で実現する
* CORSを実装するに当たりサーバ側で設定すること
	* クロスドメインアクセスを許可するオリジンサーバを指定
	* 許可するHTTPメソッド
	* 許可するHTTPヘッダー

## オブジェクトの操作
* アップロード、更新、削除、コピーができる
* バージョニングを有効にした場合は、特定のバージョンをダウンロードできる
* オブジェクトのアップロードは1ファイル最大５GBまで。それ以上の場合は、マルチパートアップロードを利用
* オブジェクトのコピーも５GBまで。それ以上の場合は、マルチパートアップロードを利用
* マルチパートアップロードとは、ファイルを分割してS3へアップロードし、S3上でマージする（分割してアップロードするので、アップロードを中断できたり、並列でアップロードできるので速度が速くなる）

## オブジェクトの共有(署名付き URL)
* デフォルトでは、オブジェクトの所有者のみがアクセスできる
* オブジェクトの所有者は、アクセス制御で他のユーザにアクセスできるように変更できる
* 署名付き URLを作成し、一時的な認証情報を付加することにより、ユーザに期限つきのURLを発行できる
* 署名付き URLを作成時は、ユーザにアクセスを許可くする期間を指定する（期間は、秒で指定）
* 署名付き URLを受けっとったユーザは、誰でもアクセスできるようになる（他のユーザにURLを渡すと、そのユーザもアクセスできる）

## オブジェクトキーのリスト作成（lsコマンド的に一覧表示できる）
* キーはプレフィックス(ディレクトリ)別に作成できる
* バケットに入っているオブジェクトの数によって、リスト作成時間は左右されない（大量のオブジェクトと少量のオブジェクトで速度一緒）
* リスト作成は、1000個取得。それ以上オブジェクトがある場合は、再度リクエストを実施する必要がある（nextリクエスト）

## オブジェクトの削除
* 1回のAPIで1000個まで削除できる(Multi-Object Delete API)※マルチを使用しない場合は、1オブジェクトが削除される
* バージョニングを利用時は、削除するバージョンも指定する
* MFA Deleteとは？オブジェクトの削除時にワンタイムパスワードを入力しないと削除できないようにする
* MFA Deleteを有効にするは、バージョニングを利用している状態で、aws cli等から設定する
* MFA Delete利用時は、削除時にワンタイムパスワードを入力する必要がある

## オブジェクトの復元
* ライフサイクルポリシーにて、Glacierにアーカイブされたオブジェクトを復元する。そうしないとオブジェクトを利用できない
* 利用できるまで約4時間かかる

# アクセス管理
* デフォルトでは、バケット、オブジェクト、ライフサイクル設定等の他の設定は、リソースを作成したAWSアカウントのみ操作権限がある
* アクセスポリシーを作成することにより、他のユーザにアクセス許可を与えることができる
* アクセス管理はリソースベースのポリシー（バケットまたはオブジェクト）、ユーザーベースポリシー（IAMポリシー）からなる
* アクセス管理を整理すると
	* ACL：リソースベースのポリシーで、オブジェクトに対してアタッチする
	* バケットポリシー：リソースベースのポリシーで、バケットに対してアタッチする
	* IAMポリシー：ユーザーベースのポリシーで、IAMアカウントに対してアタッチする
* アクセス許可はS3のリソースに対して行える。S3リソースは以下
	* ライフサイクル
	* 静的ウェブサイト
	* バージョニング
	* バケットポリシー
	* ACL
	* CORS
	* ロギング
	* restore(Glacierにアーカイブされたオブジェクトの操作)

# データの保護
* S3にアップロードされたデータは、リージョン内の複数のデバイスに保存される
* アップロードやコピーを実施した場合、アップロード開始時点で、複数施設に同期が開始される
* 冗長性が喪失した場合、すばやく検出し修復する
* S3に保存しているデータはチェックサムを用いて、データの完成性を定期的に検証している
* データが破損している場合は、冗長データを用いて復元される
* ネットワークトラフィックに対してもチェックサムを行い、パケット損傷を検出している
* オブジェクトの耐久性はイレブンナイン、可用性はイレブンフォー（データが消失する可能性は極めて低いが、オブジェクトに一時的にアクセスできなくなる可能性はある）
* 2拠点で同時にデータが損失しても、データが維持されるようになっている（3拠点で保存されている）
* バージョニングを有効にすることで、ユーザ側の誤操作時のデータ復元もできる

## 暗号化によるデータ保護
* データ転送時の保護
	* SSLを利用する
	* クライアント側での暗号化
* S3上にデータを保管する時のデータ保護
	* サーバサイド暗号化：S3側でデータ保管時に暗号化・複合化する
	* クライアントサイト暗号化：クライアント側でデータを暗号化し、S3へアップロードする

### サーバサイド暗号化の種類
* SSE-S3(サーバサイドエンクリプション-S3)、これはAWSで完全に管理された暗号方式
	* 多要素暗号化機能を備えた一意のキーで暗号（Amazon側で管理）
	* 定期的に更新されるマスターキーで暗号化される
* SSE-KMS：SSE-S3と比べてマスターキー安全にユーザ側で管理できるようになっている
	* 暗号化方式はSSE-S3と同等
	* KMSによるキーを操作した監査ログを取得できる
	* 暗号化キーを保護するマスターキーをユーザー側で操作できる。SSE-S3と比べて鍵の管理をユーザ側で実施できる
	* KMS利用分の追加費用が発生する
* SSE-C
	* データ複合化、暗号化、暗号化キー、等をすべてユーザ側で管理する
	* アップするときに暗号化キーを付与する、Amazon側でオブジェクトと一緒にキーを管理する
	* ダウンロードする場合もキーを指定し、一致した場合のみダウンロードできる

### クライアントサイド暗号化の種類
* S3へ送信前に暗号化する


## 定冗長化ストレージ（RSS）
* アップロード時、またはコピー時にRSSを指定できる
* RSSを利用すると2拠点でのレプリケーション（通常は3拠点）となるが、コスト削減ができる
* 再生可能な画像のサムネイル等で利用する
* 耐久性はフォーナイン（通常はイレブンナイン）となる

## その他のデータ保護
* バージョニングの利用
* MFA Deleteの利用

# S3で静的ウェブサイトのホスティング
* 静的なコンテンツを返すwebサーバとして利用できる
* S3固有のドメイン名でアクセスできる
* 任意のカスタムドメイン名を利用できる
* 静的ウェブサイト利用時でのアセスはSSL接続できない（CloudFrontを利用するとSSLを利用できる）
* 勘違いしやすいポイント
	* オブジェクトへのアクセス方法は2通りある
		* S3のエンドポイントからのアクセス（例：https://s3-ap-northeast-1.amazonaws.com/バケット名/オブジェクト）
		* 静的ウェブサイトからのアクセス（例：http://バケット名.s3-website-ap-northeast-1amazonaws.com/オブジェクト）

## 静的ウェブサイトの設定項目
* インデックスドキュメント：/でアクセス時に返すドキュメント（例：index.html）
* エラードキュメント：4XXの場合のみ、独自のエーラードキュメントを指定できる（それ以外は、S3のデフォルト設定から変更できない）
* リダイレクト：ドメイン名を指定するとリダイレクトしてくれる（XMLを指定して、条件指定でリダイレクトできるように設定もできる）
* オブジェクトによるリダイレクト：オブジェクトのメタデータにリダイレクトヘッダを指定することでリダイレクトもできる
* ウェブサイトを多数のユーザからアクセスできるようにするために：バケット、または公開したいオブジェクトのALCでパブリックの読み取り権限を付加する

# S3のイベント通知の設定
* イベント通知を有効にして、S3で発生したイベントを通知できる（SNS、SQS、Lambdaへ通知できる）
* 通知イベント
	* 新しいオブジェクトを作成した場合
	* RSSでのオブジェクト消失時

# リクエストのルーティングに関するTIPS
* DNSで解決するIPアドレスが変更される場合がある、→DNSキャッシュを短くする

# パフォーマンスの最適化

## リクエストパフォーマンスの最適化
* 毎秒 100 回の PUT/LIST/DELETE リクエストまたは毎秒 300 回の GET リクエストを頻繁に超える場合のみ最適化を考える（以下だったら問題ない）
* リクエストが一貫して増加する傾向がある場合は、バケットを分ける
* 一時的に、毎秒 300 回の PUT/LIST/DELETE リクエストまたは毎秒 800 回の GET リクエストを超えることが予想される場合は、リクエストレートの一時的な制限が発生る可能性があるため、サポートに制限解除してもらう
	* 申請しない場合は、異常とみなされて503 "Slow Down"を返される→リクエストレートを下げれば回避される
* 大量にGETが発生する場合は、CloudFrontの利用を検討する
* GET以外のリクエストも含まれる大量のアクセスの場合
	* プレフィックスにランダムの文字列を入れる→S3ではアルファベット順にインデックスされるため、連続した文字列（例えば20150401、20150402）の場合同じパーティションにオブジェクトが保存される可能性が高い。そのため、大量のアクセスがあった場合I/Oがネックになる。キーをランダムにすることによりパーティションを分けられ、I/Oを分散できる
	* 【例】examplebucket/2013-26-05-15-00-00/cust1234234/photo1.jpg→examplebucket/232a-2013-26-05-15-00-00/cust1234234/photo1.jpg
	* 【例】プレフィックスにIDが含まれる場合は、IDを逆にしてみたり→とにかく連続な文字列にならないようにする

## TCPウィンドウスケーリング
* OS（カーネル）、アプリケーションでウィンドウサイズを設定する。S3側は64KBを超えるウィンドウサイズをサポート

## TCP 選択的送達確認
* パケットが喪失した場合の再送時間が短縮される（SACKブロックに正常に受信したパケットを入れて返せるようになる）
* OS側で有効にする必要があるが、デフォルトで無効の可能性もあるので確認する

# BitTorrent の使用
* S3ではBitTorrentをサポート
* 通常のS3オブジェクトのダウンロードより転送費用が少なくなる→クライアントとクライアント間でもデータ転送が行われるようになるため
* BitTorrentを利用する場合、料金が安くなることはあるが高くなることはない
* オブジェクトが人気であればあるほど、S3転送料金が安くなる→人気がない場合は、BitTorrentを利用しない場合とあまり変わらない
* デフォルトで、BitTorrentでダウンロード可能になっている（特に有効・無効などの設定はない）

# Amazon DevPay
* アクセスがあったIAMアカウントに対して、請求ができる
* 使用量（ストレージ、トランザクション、帯域幅）、月ごとの定額、一括払いを含め、製品に対してどのような金額でも課金できる
* Amazonが請求代行してくれる（カスタマーに請求を行う）
* Amazonが請求を行った後、手数料を引いて残額が支払われる
* Amazonは、Dev Payの使用量を請求する
* カスタマーが請求に対して支払いを行わない場合、カスタマーのS3アクセスを停止する

# アクセスログ
* バケットアクセスのログをS3上に保存できる
* デフォルト無効なので利用する場合は有効にする
* アクセスログはバケット単位で出力、出力先バケット、プレフィックスを指定できる
* 定期的にログをS3に一括で書き込むので、リアルタイム性はない
* S3への書き込みはLog Deliveryという特殊なアカウントで書き込みされる。通常通りこのユーザに書き込み権限を与える必要がある
	※ただし、マネジメントコンソールから有効にした場合は、自動でACLで書き込み許可が付加される
* アクセスログの完全性は保証されない、ベストエフォートで書き込まれる
* アクセスログの有効・無効にするには時間がかかる
	* 有効にした直後のログは記録されない場合もある
	* 無効にした直後のログは記録される場合もある
* カスタムログ情報として、 query-stringをログに保存できる
* 自動で削除されないので、ライフサイクルを設定しておくとよい