翻訳してみた AWS re:Invent 2018: Building SRE from Scratch at Coinbase during Hypergrowth
Sansan Advent Calander 2018 の4日目の記事です。
先日参加させてもらったre:Invent、超たのしかったっす。
その中で面白かったCoinbase社、及びDataDog社によるSREの取り組みについてのセッションをご紹介したいと思います。
拙い翻訳で心苦しい限りですが、何かしらの気付きになれば幸いです。
本人より許可いただいています。 Thank You so much.
@niallohiggins @phrawzty hello. your SRE session at re:Invent was so great.
— ~/ (@rriifftt) December 3, 2018
I'd like to introduce it in Japanese, is it OK?
SREとは何か
新しいものだから定義は変化し続ける。
その中で多くの誤解があるようだ。
これはSRE?
終わりのない火事場?なりやまないオンコール?トイルへの対応?
これらはSREの仕事ではない。
これらは症状であり、この病気に苦しんでいるのなら治癒する必要がある。
それを治癒するのがSREの仕事である。
Devopsとは?
SREは、すべてではないにしても、devopsのオペレーション、及び文化上の要素を満たすことができる
SRE本にもあるように、SREはdevopsの実装の一つであると言われている。
もし既にdevopsをやっているなら、SREはすぐにフィットするだろう。
Key SRE insight #1
計測し、人、組織、システムを改善する
SREはシステムだけを見るのではなく、インシデント発生時のプロセス、あるいはそれから何を学ぶか、組織のプロセスを改善できるか等の側面からアプローチする必要がある。
そのために常に、全てを計測しなければならない。
Key SRE insight #2
受動的ではなく自発的に。トイルを見つけ出し、それを排除する
自宅に火事が起こったら燃え尽きるまで見ているなんてことはせず、消防士を呼ぶだろう。
あるいは、実際に火事が起こるのは嫌なので発生を検知するために火災報知器を設置するなどの積極的な行動をするだろう。
これは問題が大きくなる前に排除するにあたって有効な手段だ。
受動的ではなく自発的に。これはとてもとても重要だ。
トイルとは?
トイルとはスケールしない手動のオペレーションであり、組織とともにどこまでも成長することがある。
成長するトイルを見逃していては組織の成長は阻害されるだろう。
SREはこの問題に対処する必要がある。
Key SRE insight #3
組織的なフィードバック
例えばデータベースのパフォーマンスがよくない状況においてはデプロイを止めた方がいい時がある。
これは適切なフィードバックがあるからできることであり、システムの信頼性を維持するには必要かつ重要なことだから、コミュニケーションには重点を置くべきである。
トップダウン、ボトムアップの双方で意識されるべきことだ。
Set Early Expectations
SREは新しい概念なので、新しい用語が多くある。
即時的な結果を求めず、ある程度の時間をかけながら始めるのがいいだろう。
でも何から始めればいいか?
Coinbase社では以下の戦略を取ることにした。
Service Level Indicators
何をどう改善すればよいか?何もなければよくわからない。
計測し、現状を理解し、サービスレベルの指標を設定することにした。
作業を進めるときなどには優先度を設定するが、それはどのように設定されるのか、客観的な指標を持つべきである。
その指標にはFour Golden Signalsというフレームが非常に役立つ。
我々はこれらをSLIのコアメトリクスとして採用することにした。
コアメトリクス
データは大量にあるかもしれないが、そのどれもが有用とは限らない。
ビジネスをゴールに向かわせるために本当に大切なメトリクスは何か、それを見極める必要がある。
Four Golden Signals
Four Golden Signalsとは以下のメトリクスである。
- Latency
- Traffic
- Errors
- Saturation
これらはどんなサービスにも適用できる普遍的な指標であると言える。
また、これは後述するが、人、チーム、組織に置いても適用することができる。
Latency
レイテンシーとはクライアントがWebサーバーからレスポンスを受け取るのにどれくらい時間がかかるのかを示すものであり、顧客の経験に直接的な影響がある。
なぜ遅いのか、それはあなたが計測する方法に依存するので難しい問題である。
ロードバランサーで計測するか、クライアント側でラウンドトリップを計測するか、あるいはサーバー側で計測するか、様々なオプションがあるだろう。
実用的な値を計測するにも複雑になりうる。まぁ、これら3つ全てが取れるならかなりいいよね。
Traffic
トラフィックとは作業量、または試行回数を意味する。
トラフィックはビジネスの価値、規模に大きく関係するが、大量のトラフィックに見舞われた時にシステムのどこかで落ちてしまうことがあるだろう。
なので、しきい値を設定する必要がある。
Errors
成功したリクエストと失敗したリクエストの比率をターゲットとして設定するのは簡単だし、効果的だろう。
例えば昨日はサイバーマンデーで、新たな導線を敷き、大量の消費行動が行われたとして、エラーレートが50%であれば使い物にならなず、0.1%であればそれは良い数字であると言えるだろう。
複雑なシステムではエラーが発生するのは当然起こりうることであるから、ゴールはエラーを排除することではなく、エラーをどこまで許容するかを明確にすることである。
また、このエラーレートを低く維持することをビジネス上の重要な目標とすることが望ましい。
Saturation
TrafficとSaturationは何が違うのか?
Trafficは試行の総量であるのに対し、Saturationは使用可能な総量である。
たとえばWebサーバーのメモリ使用量、DBのディスクスペースといったものだ。
これはソフトウェアそのものではないことから、いつでもどこでも起こりうることなので、指標としてこれまた重要なものであると言える。
ただし、Saturationが発生することはトリッキーな事態であるとも言える。
Humans and the Four Golden Signals
Four Golden Signalsは人やチーム、組織にも適用することができる。
Latencyは、人々がブロッカーを待っている時間に例えることができる。
依存関係のあるタスクを待つなどといった状況のことだ。
Trafficはそれより劇的で、スタックしているチケットの数として見ることができる。
Errorについては、人間は誰しも多かれ少なかれミスをする。
何らかの仕組みが必要となることがあるだろう。
Saturationを人という観点から見たときには燃え尽き症候群のようなものがイメージしやすいのではないだろうか。
燃え尽き症候群は大企業にとって大きな課題である。
Start, Then iterate
you can't finish something that you don't start
これらの課題に対するためには、まずはどこからか始めなければならない。
始めるにあたっては完璧である必要はないし、完璧であることはできない。
シンプルに!
繰り返し、フィードバックを与え、得ることが重要だ。ここに魔法はない。
Spreadsheets are simple, right?
さて、システム、ならびに組織にSLIを適用するにはどうすればいいだろうか。
適切なツールを使うことはやはり効果的だろう。
スプレッドシートはいいぞ(突然の金言)
見やすいし、シンプルだし、シェアしやすく、アクセス性もよい。
簡単にコラボレーションできるしオススメ。
サービスごとのFour Golden Signalをカラムに追加することから初めてはどうだろう。
追加サービスがあるのなら行を追加すればいいし、簡単だ。
SLIs: Defining "done"
システムやサービスにSLIを規定し、スプレッドシートを作成し、運用を開始したとする。
そしてFour Golden Signalsの内のいずれかがSLIに抵触したために作業をしたとして、完了したことを我々はどうやって知ればいいだろうか?
そのためには完了した状態を定義しておくとよいだろう。
まず第一に監視システムや、JIRAのチケットに完了したことを報告する。
次にどのようにして完了させたかを説明するためのドキュメンテーションを行う。
これは常に明確なドキュメントでなくてもよい。
なぜならどのようにこの指標を使用しているか、なぜ重要であるのか、誰が気にするべきなのかは必ずしも明白とは言えないからだ。
(結構ゆるめだなーという印象)
ダッシュボードはあなたの友達だが、注意すべきだ。
ダッシュボードには多くの情報があるはずだが、常に十分な情報があるわけではないので、翻弄されないようにした方がよい。
すでにSLI抵触に関するイテレーションが適切に回っている?それなら問題ない。
start somewhere, this is good place to start.
付け加えておくと、大きな障害を避けるためには予測をすることもとても重要だ。
Specification Documentation
SLIの抵触はCriticalな事態だ。
だからこそ、なぜその指標が重要なのかをドキュメントにしておくとよいだろう。
例えば、元々はELBでレイテンシーを計測していたが、やはりモバイルアプリのクライアント側で計測することが最適であるとして、メトリクスを変更したとしよう。
このような時にドキュメントが重要になってくる。
なぜこの指標が重要であるのか、また、それについての将来のロードマップがどのようなものであるのかを話すことができるからである。
SLIの文化を構築するには仕様文書を作成することに非常に大きな価値がある。
やみくもドキュメント化するのではなく、組織の求めるものは何かを念頭に置き、重要なメトリクスをドキュメント化するとよいだろう。
First SLIs, then promises
あなたは顧客のために何を約束しますか?
また、他のチームが約束していることはあなたに依存しますか?
途方もないことかもしれないが、それについて考える必要があるだろう。
でも恐れることはない。良いPM、良いSREはビジネスの価値を知り、問題解決の能力があり、あなたの問いかけに回答してくれるだろう。
その下地を作るためにも計測し、改善し続けるしかない。
なぜこのようなことをしなければならないのか。
数千のメトリクス、重なる工数、難解な問題は山積みだ。
でも答えは一つ、それは約束を守るためだ。
突然の書籍紹介
Thinking in Promises.
http://shop.oreilly.com/product/0636920036289.do
(とてもいい本らしい)
Concerning Promises
promiseには2つのコンポーネントがあり、この場合は人間と機械である。
promiseは人間から機械へ、人間から人間へ、機械から機械へと設定することができる。
それらは常に対等の責任を負う必要はないが、それらの組み合わせの意味を考えることが重要である。
この組み合わせは機能を横断したチーム同士が協力しあっている状態であることが望ましく、より単純な帰結をもたらすだろう。
それは例えばAPIであったり、メッセージキューであったりするかもしれない。
Promises Example
promiseは平易に、明確に明文化すると効果的だ。
それを満たすか、満たさないかがひと目でわかるように。
promiseはSLIに組み込まれることもある。
(SRE本で言うところのSLOがpromiseであるようだ)
例として以下のようなものである。
- response within 50ms
- error rate will be > 1%
- on call 15min
Promise Enumration
各チームはpromiseを列挙したら公式化し、維持なければならない。
また、その機能が果たすべきpromiseを理解していなければならない。
When Promises are Broken...
promiseが破られることは回避できない。
だからこそ、その時に何をすべきか規定しておかなければならない。
インシデントが発生したらどうする?
インシデント発生時のフィードバック方法は規定されている?
継続的なフィードバックは非常に重要である。
Post-Mortems
- blameless post-mortem
- blameless post-mortemがいいネーミングだとは思わないが。。
- https://techbeacon.com/blameless-postmortems-dont-work-heres-what-does
- data driven post-mortem
ポストモーテムには色々とあるが、重要なことは正しい計測、結果の分析、対処である。
そのためには計測した結果を正しく理解し、活用できなければならない。
これができなければポストモーテムはうまく回らないだろう。
Interpreting Incidents
ステークホルダーも交えて共通言語を決定しておくとスムーズに事が運ぶ。
英語なのかフランス語なのか、公式言語は決めておいた方がよい。そのための訓練も重要だ。様々な言語が飛び交う現場は混乱を招くだろう。
また、言うまでもなく発生したインシデントは広く共有すべき。
Mesuring Incident Response
インシデントを定量的、定性的に計測するとよいだろう。
定量的にはインシデントを検知した時間、着手開始時間、リカバリーするまでの時間など。
定性的にはコミュニケーションは適切だったかなど。
これらの継続的なフィードバックは改善に向けて非常に重要である。
富士そば 巣鴨店
富士そばアドベントカレンダー、今年も発見してしまったので2日目に参加させていただきます。
富士そばしゅき度としては、先日まで会社のお金でAWS re:Inventに参加しており、1週間ほどラスベガスにいたのですが、
滞在残り2日くらいになったころから、さて日本に帰ったら何を食べようかとか考えるまでもなく、まぁ富士そばしかないなと思う程度のものです。
というわけで、今回は巣鴨店です。
巣鴨店といえばクッソみたいに泥酔したときに流れ着くことが多く、信頼の終着点として心を置かせていただいている店舗です。
成田からそそくさと巣鴨店に向かうと、そこには衝撃の光景が。
まじかよ。かなしい。
でも駅の反対側に新店舗ができているようでした。
とりあえずよかった。そしてカレーカツ丼がある店舗なのもポイント高いですね。
新店舗だからかテーブル席があり、演歌ぐあいも完璧です。
今回注文したのは渋谷店でよく食している紅生姜ちくわ天そばにしました。
この邪悪さすら感じるビジュアル、最高ですね。
前日の夜から20時間以上なにも食べずに富士そばを狙ってきたこともあり、秒で完食です。
秒だったので正直味とかよくわからなかったですが、この新巣鴨店はカエシが強くなく、やさしい系の出汁だったなーという印象です。
こういうのもいいけど、次は真っ黒なところに行こう、そんな風に思いました。
はい。 こちらからは以上です。
20181121. Aurora Architecture Night メモ
表題のイベントに参加してきました。 ハイパー殴り書きです。Auroraすげーくらいの感想しかなかった。
postgresql compatibility
- pg10 に対応
- RDS Snapshot -> Aurora Migration
- 様々なExtensionをサポート
- GIS
- pgceypto
- plpgsql
- pg_hint_plan
- postgres_fdw
- dblink -> 関数として実装されている
- Aurora -> Redshift
- Redshiftに計算、集計をオフロードするなど
- Aurora -> Redshift
- 相変わらず pg_bigm と textsearch_ja がない
Concurrency
remove log buffer
- WAL Buffer -> buffer がいっぱいになるとワーカーが待たされる
- これがオーバーヘッドになると判断したらしいとか
- ワーカーが直接ストレージにアクセスする
- Durability tracking
- トランザクション管理
- なんだかわからなかったけど、すごそう
- WAL Buffer -> buffer がいっぱいになるとワーカーが待たされる
Checkpoint
- CheckPointがない
- Bufferがないからストレージ直接書き込み
- CheckPointがない
Redoしない
- ?
Vacuum
- XID周回問題
- CloudWatchにメトリクスがある
- freeze map
- 9.6から
- VACUUMすべきタプルを管理
- Aurora には Filesystem がない
- ?
- Intelligent VACUUM Prefech
- VACUUMが86%速い
Scalability
- 各AZに2つずつ、系6つのデーターのコピーを保持
- master / repllica が同じストレージを参照している
- Write のパフォーマンスが一定
- クラッシュリカバリをストレージ側で行う
Auroraの新機能
Backtrack
- 全てのログレコードを保持
- LSN(Logical Sequence Number)が付与されている
- ストレージ側が見せるブロック(LSN?)をヘッドノードに伝えることで制御している
- 最大3日
- 専用の領域を必要とするのでストレージ課金対象
- 常に一貫性のある時間にBacktrackを行う
- Votingが確定していることかな
- 全てのログレコードを保持
Aurora Serverless
- 完全マネージドな感じ
- 設定とかできない
- 軽いロードのDB向け
- proxy endpoint -> Request Router -> NLB -> DB
- ダウンタイムなしの自動スケールアウト
- 0からスケール
- 使わなければインスタンスだけ削除するという設定が可能
- 超かっこいい
parallel query
- クエリをストレージノードの数千のCPUにプッシュダウン
- クエリを分解 -> 分解されたクエリにパラレルクエリコンテキストなるメタデータを付与
- ストレージの台数分並列化する
- 16並列まで?
Aurora Multi Master
- Single Region Multi Master
- Multi Region Multi Master
- ダウンタイム0
- アプリ側に対応が必要
- conflict
- 1つの条件でのみコンフリクト解消のプロセスが発動する
- COMMIT先勝ち
- パーティショニングすることがコンフリクトを軽減するために有効
- Global replication physical
- ちょっと何を言っているのか
- 1sec以下の遅延
- レプリケーション専用インフラが背後に自動で作成
Auroraのなかみ
- キャシュレイヤーの分離
- ヘッドノードにはいるが、DBプロセスにいない
カスタムエンドポイント
- ヘッドノードのまとまりをつくれる
- キャッシュの取り回しのために使うなど
Quoram
ストレージノードが10GBごとの論理ブロックに分割
- なぜ10GBなのかはわからなかった
- protection groupという単位
- Auroraはクォーラムセットとエポックを使用
- ノードの正常性が疑わしい状態になったらエポックが作成される
epoc1 abcdef epoc2 abcdef(?) abcdeg(new) epoc3 abcdef(NG) abcdeg(OK)
- Auroraはデータページを全て送信することでレプリケーションしているわけではない
- 差分のみを送っている
S3のクロスアカウント問題をSTS AssumeRole で解決する
背景
例えばアカウントAにある my-bucket という S3 バケットに対して、アカウントBのリソースからオブジェクトをアップロードした時に、
my-bucket に付与されているバケットポリシーが効かずにハマることがあります。
バケットポリシーでIPアドレス制限だけして他のアカウントのクレデンシャルからアップロードするようなケースです。
アカウントBからオブジェクトをアップロードした場合、
オブジェクトの所有者はアカウントB(バケット所有者のアカウントAとは別のアカウント)になるためバケットポリシーがオブジェクトに適用されません。
例えば、静的ウェブホスティングを有効にしているバケットに、アカウントBからオブジェクトをアップロードしても、
バケットポリシーが適用されないため、アップロードしただけではそのコンテンツは公開できません
(公開するためには、アップロード後にオブジェクトの権限を変更する必要があります)。
この問題を STS Assume Role を使って解決します。
以降、アクセスされる側を アカウントA
、アクセスする側を アカウントB
とします。
アカウントAにIAM Roleを作成する
IAM → Roles → Create Role → Another AWS account を選択して必要事項を入力。
作成する IAM Role は AllowPutToS3
という名前にします。
external id は事前共有鍵のようなもの?。
一致しなければ認証エラーとなるものなので、取扱には注意が必要です。
なお、人間がAssumeRoleをして他AWSアカウントのリソースを触るのならば、セキュリティの観点から MFA を利用した方がよいでしょう。
今回はシステム的にアクセスをしたいので、MFAではなく external id のみで進めてみます。
また、このウィザードからは1つのアカウントしか登録できないので、複数登録したい場合はウィザード完了後にポリシーを編集する必要があります。
IAM Policy
作成した AllowPutToS3 Role に Policy をアタッチします。
今回は S3 への Put のみを許可するポリシーとします。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowPutToS3", "Effect": "Allow", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::my-bucket/*" } ] }
Trust relationships
IAM Role を触ることができるアカウントを指定します。
Trust relationships タブ から Edit trust relationships を選択し、以下の様に設定します。
複数のアカウントから許可したい場合は、ここでアカウントIDを指定することで増やすことができます。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": [ "arn:aws:iam::アカウントBのアカウントID:root", ] }, "Action": "sts:AssumeRole", "Condition": { "StringEquals": { "sts:ExternalId": "hoge" } } } ] }
アカウントBからAssume Roleする
IAM Policy の設定
my-bucket をさわりたいアカウントBのリソースに以下の様なPolicyを設定します。
IAM UserでもGroupでもIAM Roleでもなんでもいいです。
{ "Action": "sts:AssumeRole", "Effect": "Allow", "Resource": "arn:aws:iam::アカウントAのアカウントID:role/AllowPutToS3" }
Credential の取得
上記の IAM Policy が設定されたリソースから Credential を取得します。
以下は AWS CLI での例です。
$ aws sts assume-role \ --role-arn arn:aws:iam::アカウントAのアカウントID:role/AllowPutToS3 \ --role-session-name hoge \ # セッションに付与する任意の名前 --external-id hoge # IAM Role に設定した内容と一致しなければエラー
以下の様なレスポンスが返ってきます。
{ "AssumedRoleUser": { "AssumedRoleId": "**************************", "Arn": "arn:aws:sts::アカウントAのアカウントID:assumed-role/******************" }, "Credentials": { "SecretAccessKey": "*************", "SessionToken": "******************************************************************************************", "Expiration": "2018-03-05T04:45:01Z", "AccessKeyId": "******************" } }
この認証情報をつかってオブジェクトを Put すると、他アカウントからのアクセスでもバケットポリシーが効くようになります。
ややこしいけど便利ですね。
AWS CLI では .aws/config などに必要な設定をすることで自動的に AssumeRole をすることも可能のようです。
とても便利そうですね。
boto3 で AssumeRole したクライアントを作成する実装例
を晒してみます。
微妙に client と resource を選択することができて便利な気がします。
ご査収くださいませ。
AWS Tools for PowerShell で S3 から指定した prefix のオブジェクトをダウンロードする
新しめの AWS Tools for PowerShell では Copy-S3Object
に -KeyPrefix
オプションがあるので、表題のことができそうです。
ツールのバージョンアップ
自分のローカルにインストールされていた Version 3.1**** には -KeyPrefix
オプションがなかったので、以下の手順でバージョンアップしてみます。
- プログラムと機能から AWS Tools for PowerShell を削除
- 管理者権限で起動した PowerShell で
Install-Module -Name AWSPowerShell
を実行- PowerShell version 5 以上
一度ターミナルを閉じてバージョンアップができたか確認します。
PS C:\> Import-Module AWSPowerShell PS C:\> get-Module AWSPowerShell ModuleType Version Name ExportedCommands ---------- ------- ---- ---------------- Binary 3.3.283.0 AWSPowerShell {Add-AASScalableTarget, Add-ACMCertificateTag, Add-ADSConf...
3.1.**** からバージョンアップできました。
やってみる
こんな感じのバケットがあるとして
PS C:\> (Get-S3Object -BucketName my-bucket -Prefix test).Key test/hige_hoge.txt test/hoge_hige.txt test/hoge_hoge.txt
以下の様に実行します。
PS C:\test> Copy-S3Object -BucketName my-bucket -LocalFolder . -KeyPrefix test Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 6/4/2018 3:28 PM test PS C:\test> ls Directory: C:\test Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 6/4/2018 3:28 PM 0 hige_hoge.txt -a---- 6/4/2018 3:28 PM 0 hoge_hige.txt -a---- 6/4/2018 3:28 PM 0 hoge_hoge.txt
いい感じです。
が、↓のようにファイル名の一部まで prefix を指定しようとすると、うまくダウンロードできませんでした。
PS C:\test> Copy-S3Object -BucketName my-bucket -LocalFolder . -KeyPrefix test/hoge Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 6/4/2018 3:30 PM test PS C:\test> ls
ちょっと残念。
boto3 で S3 から指定した prefix のオブジェクトをダウンロードする
というスクリプトを書いたので晒してみます。
$ python download_s3_objects.py --help Usage: download_s3_objects.py [OPTIONS] Options: -p, --profile TEXT -b, --bucket-name TEXT -d, --destination TEXT -P, --prefix TEXT --help Show this message and exit.
こんな感じでファイルが格納されているとして
$ aws s3 ls s3://my-bucket/test/ 2018-06-04 14:46:19 0 hige_hoge.txt 2018-06-04 14:46:26 0 hoge_hige.txt 2018-06-04 14:46:23 0 hoge_hoge.txt
以下の様に使います。
$ python download_s3_objects.py --bucket-name my-bucket --prefix test/hoge downloaded ./hoge_hoge.txt downloaded ./hoge_hige.txt
なお、新しめの powershell なら Copy-S3Object
コマンドレット一発でできそうです。
AWS Tools for PowerShell Reference
追記:
以上です!
list を CSV っぽく置換する
python バージョンは
>>> sys.version '3.6.2 (default, Oct 5 2017, 11:51:36) \n[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.37)]'
です。
やりたいことは
l = ['aoba', 'nene', 'hotaru']
といったリストを
'aoba','nene','hotaru'
というふうにしたい。 (例えば SQL の IN 句を生成したい時など)
単純に join
すると先頭と末尾に '
が付与されない。
>>> print("','".join(l)) aoba','nene','hotaru
しかたなく format を使います。
>>> print("'{}'".format("','".join(l))) 'aoba','nene','hotaru'
こんなんでいいのかわからないけど、やりたいことはできました。