ablog

不器用で落着きのない技術者のメモ

S3 Object Lock について

たぶんこんな感じ。

S3 Object Lock とは

バージョニングされた過去バージョンを消せなくする機能。オブジェクトの上書きはできるが過去バージョンを消せない。従って、バージョニングを有効化しないと S3 Object Lock を有効化できない。

期間保持と法的保有

バケット*1に対して設定する一定期間オブジェクトバージョンを削除できない「期間保持」とオブジェクトに対して設定する解除するまで永久にオブジェクトバージョンを削除できない「法的保有」がある。
保持期間(Retention period)では過去バージョンを削除できない期間を設定できる。長くは変更できるが、短くはできない。法的保有(Legal hold)はオブジェクトレベルのみの設定でバケットレベルでは設定できず、有効化しているとそのオブジェクトの全過去バージョンを削除できない。s3:PutObjectLegalHold 権限を持つIAMユーザー/ロールで無効化するまでオブジェクトバージョンを削除できない。保持期間(Retention period)と法的保有(Legal hold)の両方を有効化できるが、全過去バージョンを削除できなくなるので法的保有(Legal hold)のみ有効化しているのと同じ動作になる。

期間保持のガバナンスモードとコンプライアンスモード

期間保持には「ガバナンスモード」と「コンプライアンスモード」があり両方共バケットレベルでは設定後に無効化できるが、オブジェクトに対しては「コンプライアンスモード」で作成されたオブジェクトは保持期間を過ぎるまで二度とバージョンを消せなくなる。「コンプライアンスモード」にしたバケットを削除するにはアカウントを解約するしかない。「ガバナンスモード」は明示的に s3:BypassGovernanceRetention 権限*2を付与されたIAMユーザー/ロールでは無効化して削除できる。

利用例

バケットのプロパティで保持期間90日に設定し、Organizations の Service Control Policy(SCP) で子アカウントの s3:PutBucketObjectLockConfiguration と s3:PutObjectRetention を Deny すると、そのバケットに作成されたオブジェクトは90日間削除できない。「コンプライアンスモード」の場合はこの期間はどうやっても削除できない。「ガバナンスモード」の場合は、親アカウントでSCPをデタッチしてs3:BypassGovernanceRetention 権限を持ったIAMユーザー/ロールでオブジェクトの保持期限を無効化して削除することができる。

*1:オブジェクト毎にも設定できる

*2: s3:PutObjectRetention 権限も必要

S3 へのパブリックアクセスを一切禁止する

Amazon S3 Block Public Access で S3 へのパブリック・アクセスを一切禁止する設定例。アカウント全体と各バケット毎の設定があるが、各バケット毎の設定はアカウント全体設定でオーバライドされる。つまり、アカウント全体の設定で禁止していると、バケット単位で許可しても許可されない。

すでにアカウントレベルで全パブリックアクセスを拒否しているため、実際には余分な設定ですが、バケットレベルで制御可能だということは覚えておいてください。バケットレベルでオプションを変更しても、アカウントレベルでの設定は上書きできません。

Amazon S3 Block Public Access – アカウントとバケットのさらなる保護 | Amazon Web Services ブログ

設定例

このアカウントのパブリックアクセスコントロールリスト (ACL) を管理する
  • 新規のパブリック ACL と、パブリックオブジェクトのアップロードをブロックする (推奨) : チェック
  • パブリック ACL を通じて付与されたパブリックアクセスを削除する (推奨) : チェック
このアカウントのパブリックバケットポリシーを管理する
  • 新規のパブリックバケットポリシーをブロックする (推奨) : チェック
  • パブリックポリシーを持つバケットへのパブリックアクセスとクロスアカウントアクセスをブロックする (推奨) : チェック
補足
  • 以下のアクセス権限をIAMユーザーに付与しない、または Organizations の子アカウントについては SCP(Service Control Policy) で S3 Block Public Access の設定変更を禁止できる*1
    • PutAccountPublicAccessBlock … アカウントレベルの設定禁止
    • PutBucketPublicAccessBlock … バケットレベルの設定禁止
  • 新規AWSアカウントを作成すると、デフォルトで S3 Block Public Access はアカウントレベルでは False、バケットレベルでは True*2

意味

新規のパブリック ACL と、パブリックオブジェクトのアップロードをブロックする (推奨)
  • バケットACLで以下の設定がバケットレベル(左画像)でもオブジェクトレベル(右画像)でもできなくなる*3

  • オブジェクトの「公開」もできない。

パブリック ACL を通じて付与されたパブリックアクセスを削除する (推奨)
  • オブジェクトアップロード時にパブリックACLを設定すると、オブジェクトのアップロードは成功するが、パブリックACLは付与されない。



新規のパブリックバケットポリシーをブロックする (推奨)
  • パブリックバケットポリシー("Principal": "*")を設定できない。

  • AWSアカウントIDを指定したクロスアカウントのアクセス許可は可能。

パブリックポリシーを持つバケットへのパブリックアクセスとクロスアカウントアクセスをブロックする (推奨)
  • パブリックバケットポリシーが設定されても、

  • パブリックアクセスは拒否される。

$ aws s3 cp s3://s3-public-block-acl-test/test.txt ./
fatal error: An error occurred (403) when calling the HeadObject operation: Forbidden

補足

RestrictPublicBuckets*4 を True にするとクロスアカウントアクセスが不可になるか?
  • パブリックポリシーを設定しなければクロスアカウントアクセス可能*5
DeleteAccountPublicAccessBlock、DeleteBucketPublicAccessBlock を許可する権限は何か?
  • Put/Delete とも PutAccountPublicAccessBlock、PutBucketPublicAccessBlock の2つの権限があれば可能。逆に禁止する場合は、SCP でこの2つの権限を拒否すれば、Put/DeleteAccountPublicAccessBlock、Put/DeleteBucketPublicAccessBlock を禁止できる。
$ aws s3control delete-public-access-block --account-id 012345678901
An error occurred (AccessDenied) when calling the DeletePublicAccessBlock operation: Access Denied

$ aws s3control put-public-access-block --account-id 012345678901 --public-access-block-configuration "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"
An error occurred (AccessDenied) when calling the PutPublicAccessBlock operation: Access Denied

*1:要検証

*2:新規バケットを作成するとデフォルトで True

*3:チェックして「保存」をクリックすると「エラー アクセス拒否」とメッセージが表示され設定できない

*4:パブリックポリシーを持つバケットへのパブリックアクセスとクロスアカウントアクセスをブロックする

*5:s3 cp でクロスアカウントでバケット間コピーすると "An error occurred (AccessDenied) when calling the UploadPartCopy operation" と怒られる - ablog の通り、コピー先にパブリックポリシーがあっても失敗するので注意

Amazon Linux で AWS CLI をアップデートする

Amazon LinuxAWS CLI をアップデートする手順。

  • 現在のバージョンを確認する。
$ aws --version
aws-cli/1.15.83 Python/2.7.14 Linux/4.14.77-70.59.amzn1.x86_64 botocore/1.10.82
  • AWS CLISDK(boto) をアップデートする。
$ sudo pip install -U awscli
  • アップデート後のバージョンを確認する。
$ aws --version
aws-cli/1.16.84 Python/2.7.14 Linux/4.14.77-70.59.amzn1.x86_64 botocore/1.12.74

文鎮化した S3 バケットを元に戻す

誤ったバケットポリシーを設定したり、バケットポリシーで特定のVPCエンドポイントからのみのアクセスを許可していてそのVPCエンドポイントを消してしまったりしてS3バケットに一切アクセスできず文鎮化してしまった場合の対処法。root アカウントのシークレットアクセスキーを作成して AWS CLI からバケットポリシーを削除して復旧することができる*1

手順

rootアカウントのシークレットアクセスキー作成
  • AWSマネジメントコンソールにrootアカウントでログインする
  • ナビゲーションバー右上のアカウント名を選択し、[セキュリティ認証情報]を選択する。

  • [アクセスキー (アクセスキー ID とシークレットアクセスキー)]-[新しいアクセスキーの作成]をクリックし、[キーファイルのダウンロード]をクリックしてダウンロードする。
文鎮化したS3バケットバケットポリシーを削除
  • ダウンロードしたキーファイルを開いて、AWS CLI に設定する。
$ export AWS_DEFAULT_REGION=ap-northeast-1
$ export AWS_ACCESS_KEY_ID="ROOT_KEY_ID" ★アクセスキーを指定
$ export AWS_SECRET_ACCESS_KEY="ROOT_SECRET_KEY" ★シークレットキーを指定
$ aws s3api delete-bucket-policy --bucket az-private
rootアカウントのシークレットアクセスキー削除
  • ナビゲーションバー右上のアカウント名を選択し、[セキュリティ認証情報]を選択する。
  • [アクセスキー (アクセスキー ID とシークレットアクセスキー)]で[削除]をクリックし、シークレットアクセスキーを削除する。

*1:AWSマネジメントコンソールからはできない

サーバ負荷をシンプルに評価する指標 "sysload"

たしか、4年くらい前にデータベース系のイベントで瀬島さんと横道さんと話しているときにそういうものを作っているとちらっと聞いて気になっていたので、ブログ見たときに sysload は「あの時、聞いたやつだ」と思い出した。

はるか昔kernel 2.6 の頃、Load Average が低めに出てしまうというバグがありました。
当時、弊社では Load Average を監視項目の一つにしていたため、これには大いに困りました。
また、その頃、私は resource monitoring に力を入れていたのですが、以前 blog でも書かせていただいた通り、MySQLのサーバ一台あたり200以上のmetricを収集していたため、「多すぎてどれを見ていいかわからない」といった声が社内から上がっていました。
そういった諸々の問題を解決するため、6年くらい前、私はあれこれ思案して、新しい metric を作成しました。
いまなおその metric は社内で広く普及しており、一定の有用性を示せたかと思いますので、せっかくなのでOSSとして公開させていただくことにしました。
gree/sysload
今回は、その metric と、その metric を生成するためのスクリプトの実装について、解説させていただきます。

6年くらい前に自作した metric がそこそこ有用だと思うので、OSSで公開します | GREE Engineers' Blog

職人芸な繊細な仕事だが、非常にシンプルに収斂していて匠の技を感じた。監視項目は大量にあると見るのが大変なので、如何に最小限の項目でアラートを上げるようにして全てを網羅できるようにできるかがパフォーマンス・エンジニアの腕の見せどころだと思う。*1
sysload は "sys_load_five" 1項目で「CPUバウンドなサーバもdiskバウンドなサーバも、NICからの割り込みが激しいサーバも、とりあえずsysloadさえ監視しておけば、検知できる」というのが美しい。"sys_load_five" は5分間の平均値のため瞬間的なスパイクの影響は受けなくなる、短時間のスパイクも検知したい場合は1分間隔の "sys_load_one"、15秒間隔の "sys_load" もある。「kernel 2.6 の頃、Load Average が低めに出てしまうというバグがあり作られた」とのことだが、CPUバウンドとdiskバウンド以外にネットワークバウンドも検知する点は Load Average にはないが重要な機能が追加されている。「software interrupt を受けているCPUの使用率(NICからの割り込みを受けているCPUの使用率)*2」まで見ているのは匠だと思う。「もちろん、sysloadは万能ではありません」はその通りだが、1項目で負荷の指標を見れるようにしているのは素晴らしく、GREEの環境で実用性も実証されている sysload がOSS公開されて感謝です。

動かしてみる

cpustats.py はこのまま ganglia で sysload を集計するためにも使えるのですが、コマンドラインから実行することも可能です。

6年くらい前に自作した metric がそこそこ有用だと思うので、OSSで公開します | GREE Engineers' Blog

とのことなのでEC2で動かしてみた。

インストール
  • sysload と負荷ツールをダウンロードする。
$ sudo yum -y install git stress 
$ git clone https://github.com/gree/sysload.git
CPU負荷をかけてモニタリングしてみる
  • CPUに負荷をかける。
$ stress --cpu `grep -c 'processor' /proc/cpuinfo` &
  • cpustats.py を実行して sys_load_five をモニタリングする。
$ cd ~/sysload/ganglia
$ python cpustats.py
(中略)
value for sys_load is 100.000
value for sys_load_one is 100.000
value for sys_load_five is 25.000 ★
value for sys_load_fifteen is 8.333
IO負荷をかけてモニタリングしてみる
$ stress --hdd `grep -c 'processor' /proc/cpuinfo` --io `grep -c 'processor' /proc/cpuinfo` &
  • cpustats.py を実行して sys_load_five をモニタリングする。
$ cd ~/sysload/ganglia
$ python cpustats.py
(中略)
value for sys_load is 100.000
value for sys_load_one is 100.000
value for sys_load_five is 26.925 ★
value for sys_load_fifteen is 8.975

sysload/cpustats.py at master · gree/sysload · GitHubのソースはちゃんと読めていないのでまた読みたいと思います(特に「NICからの割り込み」の計上まわり)。

余談

  • B.Gregg の The USE Method はコンピュータのCPU、メモリ、ディスクなどのコンポーネント毎に使用率、サチュレーション、エラーの3つの観点で見ることでボトルネックをシンプルでシステマチックに特定するメソッドだが、sysload は一つの指標に集約していて非常にシンプル。
  • 「sysloadでは、InnoDBのmutexの競合やspinlockやthreadのconcurrencyやdirty pageのflushやその他諸々の監視はできません」については、アクティブセッション数と DB Time + Wait Event が MySQL + InnoDB で取れればどんな性能問題が発生しても時間ベースでシンプルな評価が可能になる。*3

さいごに

今回はmonitoringの話をさせていただきましたが、MySQLでディープなネタが2つくらいありますので、今後、blogなりスライドなりで公開したいなぁと思ってます。興味のある方は気長にお待ち下さい。

6年くらい前に自作した metric がそこそこ有用だと思うので、OSSで公開します | GREE Engineers' Blog

sysload は話を聞いてから4年くらい待ったので、オリンピック周期くらいで公開されることを楽しみにしておりますw

*1:監視は少ない項目で、稼働統計情報としては原因追求できるよう多数の項目を詳細に記録する必要がある

*2:「/proc/interrupts をみて、eth{0,1,2,3} に割り込んでる CPU をチェックする、bonding してると active 側の NIC が eth0 と eth1 で切り替わるので、eth0以外からの割り込みもチェックする、eth{0,1,2,3} からの割り込みをチェックして、割り込まれてるNICごとに CPU をグループ分けする、もし割り込まれてないNICがあれば、結線されてないと考えて、監視対象から外す」といった緻密な実装には驚きました

*3:当り前だが、アクティブセッション数自体を取得できないようなハングは検知できないので、ハング検知は別途行う必要がある

Aurora PostgreSQL互換でフェイルオーバーを高速化する

  • LinuxTCP Keep Alive パラメータ
tcp_keepalive_time = 1
tcp_keepalive_intvl = 1
tcp_keepalive_probes = 5
// Sets internal TTL to match the Aurora RO Endpoint TTL
java.security.Security.setProperty("networkaddress.cache.ttl" , "1");
// If the lookup fails, default to something like small to retry
java.security.Security.setProperty("networkaddress.cache.negative.ttl" , "3");
  • JDBC Driver
    • connectTimeout: ソケットがデータベースに接続を確立するまでの時間
    • loginTimeout: ソケット接続が確立された後、データベースにログインするまでの時間
    • socketTimeout: ソケットが読み取り操作で待機する時間
    • tcpKeepAlive: 設定した TCP キープアライブパラメータが優先される

Aurora MySQL互換のフェイルオーバー

障害挿入クエリ(Fault Injection Queries)
  • INSTANCE はMySQLインスタンスをクラッシュさせる。
  • DISPATCHER はクラスターボリュームに書込むディスパッチャをクラッシュさせる。
  • NODEはMySQLインスタンスとディスパッチャの両方をクラッシュさせ、キャッシュが削除される。

Syntax

ALTER SYSTEM CRASH [ INSTANCE | DISPATCHER | NODE ];

Options
This fault injection query takes one of the following crash types:

  • INSTANCE—A crash of the MySQL-compatible database for the Amazon Aurora instance is simulated.
  • DISPATCHER—A crash of the dispatcher on the master instance for the Aurora DB cluster is simulated. The dispatcher writes updates to the cluster volume for an Amazon Aurora DB cluster.
  • NODE—A crash of both the MySQL-compatible database and the dispatcher for the Amazon Aurora instance is simulated. For this fault injection simulation, the cache is also deleted.

The default crash type is INSTANCE.

Testing Amazon Aurora Using Fault Injection Queries - Amazon Aurora
エンドポイント
  • クラスターエンドポイント(例:mycluster.cluster-************.us-east-1.rds.amazonaws.com)
  • 読み取りエンドポイント(例:mycluster.cluster-ro-************.us-east-1.rds.amazonaws.com)
    • リードレプリカに接続するエンドポイント。
    • 複数のリードレプリカがある場合、いずれかにルーティングする。
    • リードレプリカが存在しない場合はプライマリ DB インスタンスに接続する。
  • カスタムエンドポイント(例:mycluster.cluster-custom-************.us-east-1.rds.amazonaws.com)
    • 任意のインスタンスにルーティングするエンドポイントを作成できる。
  • インスタンスエンドポイント
フェイルオーバーの優先度
  • フェイルオーバーの優先度は、最も高い 0 から最も低い 15 まで設定できる。
  • プライマリインスタンスに障害が発生すると、優先度の高いリードレプリカをプライマリインスタンスに昇格する。
  • 同じ優先度のリードレプリカが複数ある場合は最大サイズのレプリカを昇格する。同じ優先度とサイズのリードレプリカが複数ある場合、任意のレプリカを昇格する。
  • クラスターにリードレプリカがない場合は障害時にプライマリインスタンスが再作成される。

補足

エンドポイントは CNAME
$ dig +noall +ans \
aurora-postgres105.cluster-********.ap-northeast-1.rds.amazonaws.com \
aurora-postgres105.cluster-ro-********.ap-northeast-1.rds.amazonaws.com \
tokyo-1a.cluster-custom-********.ap-northeast-1.rds.amazonaws.com \
aurora-postgres105-a.********.ap-northeast-1.rds.amazonaws.com \
aurora-postgres105-a-ap-northeast-1a.********.ap-northeast-1.rds.amazonaws.com \
aurora-postgres105-c.********.ap-northeast-1.rds.amazonaws.com

aurora-postgres105.cluster-********.ap-northeast-1.rds.amazonaws.com. 5 IN CNAME aurora-postgres105-a.********.ap-northeast-1.rds.amazonaws.com.
aurora-postgres105-a.********.ap-northeast-1.rds.amazonaws.com. 5 IN CNAME ec2-**-***-109-247.ap-northeast-1.compute.amazonaws.com.
ec2-**-***-109-247.ap-northeast-1.compute.amazonaws.com. 604800	IN A **.***.109.247
aurora-postgres105.cluster-ro-********.ap-northeast-1.rds.amazonaws.com. 1 IN CNAME	aurora-postgres105-c.********.ap-northeast-1.rds.amazonaws.com.
aurora-postgres105-c.********.ap-northeast-1.rds.amazonaws.com. 5 IN CNAME ec2-**-***-100-225.ap-northeast-1.compute.amazonaws.com.
ec2-**-***-100-225.ap-northeast-1.compute.amazonaws.com. 604800	IN A **.***.100.225
tokyo-1a.cluster-custom-********.ap-northeast-1.rds.amazonaws.com. 1 IN CNAME aurora-postgres105-a-ap-northeast-1a.********.ap-northeast-1.rds.amazonaws.com.
aurora-postgres105-a-ap-northeast-1a.********.ap-northeast-1.rds.amazonaws.com. 5 IN CNAME ec2-**-**-33-213.ap-northeast-1.compute.amazonaws.com.
ec2-**-**-33-213.ap-northeast-1.compute.amazonaws.com. 604800 IN A **.**.33.213
aurora-postgres105-a.********.ap-northeast-1.rds.amazonaws.com. 5 IN CNAME ec2-**-***-109-247.ap-northeast-1.compute.amazonaws.com.
ec2-**-***-109-247.ap-northeast-1.compute.amazonaws.com. 604800	IN A **.***.109.247
aurora-postgres105-a-ap-northeast-1a.********.ap-northeast-1.rds.amazonaws.com. 5 IN CNAME ec2-**-**-33-213.ap-northeast-1.compute.amazonaws.com.
ec2-**-**-33-213.ap-northeast-1.compute.amazonaws.com. 604800 IN A **.**.33.213
aurora-postgres105-c.********.ap-northeast-1.rds.amazonaws.com. 5 IN CNAME ec2-**-***-100-225.ap-northeast-1.compute.amazonaws.com.
ec2-**-***-100-225.ap-northeast-1.compute.amazonaws.com. 604800	IN A **.***.100.225
エンドポイントの TTL は短い
ストレージノードは同じデータを6つコピーしていない

Auroraでは、データベースボリュームは10GBのデータセグメントで構成されています。 これらのセグメントはプロテクショングループとして複製され、6つのコピーが3つのAZに分散しています。 しかし、6つのコピーはすべて同じではありません。 コピーの半分はフルセグメントで、ボリュームの10GB部分のデータページとログレコードの両方を含んでいます。 残りの半分は、ログレコードのみを含むテールセグメントです。 各AZには、1つのフルセグメントと1つのテールセグメントが含まれています。

ほとんどのデータベースには、REDOログストレージよりもはるかに多くのデータブロックストレージがあります。 フルセグメントとテールセグメントを組み合わせて使用すると、Auroraの物理ストレージに必要な要件がデータベースの6倍から、3倍より少し多い程度になります。 “AZ+1″の障害に耐えるように設計されたシステムでは、これは最小限のレプリケーションファクターです。

Amazon Aurora Under the Hood: クオーラムセットを使ったコスト削減 | Amazon Web Services ブログ

参考

DB クラスターのプライマリインスタンスが失敗した場合、Aurora は以下のいずれかの方法で、新しいプライマリインスタンスに自動的にフェイルオーバーします。

DB クラスターに 1 つ以上の Aurora レプリカがある場合は、障害発生中に 1 つの Aurora レプリカがプライマリインスタンスに昇格されます。障害イベントによって短い中断が発生し、その間例外によって読み取りと書き込みオペレーションが失敗します。ただし、一般的なサービスの復元時間は 120 秒未満であり、多くの場合 60 秒未満で復元されます。DB クラスターの可用性を高めるために、複数のアベイラビリティーゾーン内で少なくとも 1 つ以上の Aurora レプリカを作成することをお勧めします。

各レプリカに優先度を割り当てることで、Aurora レプリカがプライマリインスタンスに昇格される順序をカスタマイズできます。優先度の範囲は、最も高い 0 から最も低い 15 までです。プライマリインスタンスが失敗した場合、Amazon RDS は最も高い優先度の Aurora レプリカを新しいプライマリインスタンスに昇格します。Aurora レプリカの優先度はいつでも変更できます。優先度を変更しても、フェイルオーバーはトリガーされません。

複数の Aurora レプリカで同じ優先度を共有でき、その場合は昇格階層が発生します。複数の Aurora レプリカで同じ優先度を共有する場合、Amazon RDS は最大サイズのレプリカを昇格します。複数の Aurora レプリカで同じ優先度とサイズを共有する場合、Amazon RDS は同じ昇格階層の任意のレプリカを昇格します。

DB クラスターに Aurora レプリカが含まれていない場合、障害イベントの発生時にプライマリインスタンスが再作成されます。障害イベントによって中断が発生し、その間例外によって読み取りと書き込みオペレーションが失敗します。新しいプライマリインスタンスが再作成されると、サービスが回復します。これは、通常は 10 分未満で行われます。Aurora レプリカのプライマリインスタンスへの昇格は、新しいプライマリインスタンスの作成よりもはるかに短時間で実行されます。

Aurora DB クラスターのバックアップと復元の概要 - Amazon Aurora

dev.classmethod.jp
dev.classmethod.jp
https://www.allthingsdistributed.com/files/p1041-verbitski.pdf
atsuizo.hatenadiary.jp
qiita.com
docs.aws.amazon.com