Google Cloud Platform Japan Blog
最新情報や使い方、チュートリアル、国内外の事例やイベントについてお伝えします。
カナリアのおかげで命拾い : CRE が現場で学んだこと
2017年4月18日火曜日
信頼性の高いソフトウェアのリリースでは、何かおかしなことが起こったときにロールバックできることが何より重要です。そしてその方法は
前回の投稿
で説明しました。
ひとたびロールバックを身につけてしまえば、その次は、そもそも何かおかしなことが起こり始めていることをどうやって検知するかを知りたいと思うはずです。その方法の 1 つが、今回のテーマであるカナリア リリースです。
Photo taken by
David Carroll
カナリア リリースのコンセプトは、1913 年に生理学者の
John Scott Haldane
氏が、一酸化炭素を検出するためにカゴの中の鳥を炭鉱に連れて行ったことが始まりです。かよわい鳥は人間よりもこの無臭ガスに敏感で、ガス漏れが起きているとすぐに木から落ちてしまうため、それが炭鉱員にとってその場から離れるべきサインとなるのです。
ソフトウェアにおけるカナリアは通常、バイナリや設定のロールアウトなど、何らかの設定を更新してライブ稼働した際にトラフィックを受信する最初のインスタンスのことを指します。新しいリリースは、まずカナリアのみに行くことになるわけです。
カナリアが実際のユーザー トラフィックを処理するという点が肝で、もし不具合があった場合は実際のユーザーが影響を受けます。そのため、カナリア リリースはデプロイ プロセスの最初のステップであるべきで、テストの最終ステップになっては意味がありません。
カナリア リリースを実装するにあたって最初のステップとなるのは、リリース エンジニアが新しいバイナリのリリースをカナリア インスタンスに対して開始する手動プロセスです。
その後、エンジニアはカナリアを監視し、エラーやレイテンシ、負荷が増加していないことを確認します。すべてうまく進んでいるようであれば、カナリア以外の稼働インスタンスに対してもリリースを開始します。
ところが、Google の SRE チームはこのやり方に疑問を呈しました。モニター グラフを手動で監視するだけでは、新しいリリースのパフォーマンス上の問題やエラー率の増加を検知する際の信頼性が十分ではないというのです。
ほとんどのリリースがうまくいっている場合、リリース エンジニアは問題がないことに慣れてしまい、低レベルの問題が発生してもモニターの異常をノイズだと暗黙的に合理化してしまうのです。実際、不具合のあったリリースを内部事後分析すると、根本的な原因が「リリース エンジニアが気にするほどカナリアのグラフが動いていなかったため」だったことが何度かありました。
そこで Google では自動分析に移行しました。これにより、カナリアのロールアウト サービスがカナリアのタスクを測定し、エラーやレイテンシ、負荷が上昇したことを自動的に検知、ロールバックも自動で行うようになりました(もちろん、これは
ロールバックが安全に実施できる
場合にのみ適用されます)。
もしリリース時にカナリアを実装するのであれば、リリースの問題が見えやすくなるように工夫してください。カナリア タスクにおいてどのようにフォールト トレランスを実装するか、入念に考えるようにしましょう。カナリアがクエリに対して最善の力を尽くすようにしてもいいですが、内部エラーや依存しているサービスからのエラーが発生したときは、問題が生じたことがモニターに「大きな声で鳴いて」表示されるようにしなければなりません(ウェールズの炭鉱員がカナリアを有毒ガスに耐えられるように育てなかったり、カナリアに小型ガス マスクを装着しなかったりしたことには、正当な理由があるのですから)。
クライアントでのカナリア リリース
クライアント ソフトウェアをリリースする場合は、カナリア リリースのメカニズムがクライアントの新バージョンに必要であり、次の質問に答えられるようにしておかなくてはなりません。
ごく少数のユーザーにだけ新バージョンをデプロイするにはどうすればよいのか。
新バージョンがクラッシュを繰り返したり、トラフィックを落としたり、ユーザー エラーを表示したりしたときは、どうやって検知するのか(クエリが発生していないことに対するモニター音はどうするのか)。
2 の解決策は、クライアントが自らバックエンド サービスにクライアントの存在を識別させることです。そこにクライアントの OS やアプリケーションのバージョン ID など、各リクエストの情報が含まれていることが理想です。また、サーバーにこれらの情報をログ化させます。クライアントが自らの存在を明確にカナリアとして識別させることができれば、それに越したことはありません。
そうすれば、クライアントの情報を異なる監視測定基準セットにエクスポートできます。クライアントがクエリ送信できていないことを検知するには、一般的に 1 日または 1 週間の特定の時間の着信トラフィックとして妥当な最も低い量を把握しておき、着信トラフィックがそれ以下になった場合にアラートを発するようにしましょう。
高可用性システムのカナリアに対するアラートのルールは通常、評価期間(問題発生となり、モニターがそのことを音で知らせるまでの時間)を主要システムより長めにしてあります。というのも、トラフィック量が少ないため、標準の通知がノイズとなってしまうからです。いくつかのサービス インスタンスが再スタートしたといったような比較的無害の問題によって、簡単にカナリアのエラー率が上がり、通常アラームのしきい値を超えてしまうのです。
リリースは通常、一部のアクティブ ユーザーを除き、幅広いタイプのユーザーをカバーするようにしなくてはなりません。Android クライアントであれば、Google Play Store が
アプリケーション パッケージ ファイル
(APK)の新バージョンを(実質無作為の)一部ユーザーに向けてデプロイすることを許可します。これは、国ごとに行うことが可能です。
ただし、この手法には制限やリスクがあります。以下では、Android APK のリリースについて考えてみます。
ウェブ クライアント
エンドユーザーが、アプリではなくデスクトップやモバイル ウェブを介してサービスにアクセスする場合は、実行される内容を制御しやすくなります。
UI が JavaScript で管理されている一般的なウェブ クライアントは制御がとても簡単で、アップデートした JavaScript のリソースを、ページが読み込まれるたびにクライアントに配信することも可能です。
しかし、JavaScript やそれに似たリソースをクライアント サイドにキャッシュすると、それ自体はサービス負荷やユーザーのレイテンシと帯域の消費を削減できるために便利なのですが、変更に不具合があったときにはロールバックが難しくなります。前回の投稿で説明したように、簡単で迅速なロールバックを阻害するようなものは、すべて問題なのです。
その解決策の 1 つは、JavaScript ファイルをバージョン付けすることです(最初のリリースを /v1/ のディレクトリに入れ、2 番目のリリースを /v2/ に入れるといった具合です)。そうすれば、ロールアウトでは単にルート ページ内のリソース リンクが変更され、新(または旧)バージョンを参照するようになります。
Android APK のリリース
Android アプリの新バージョンをロールアウトする際は、Play Store 内で
段階的にロールアウト
されたものを利用している既存ユーザーのうち、一定の割合のユーザーに対して行うとよいでしょう。そうすることで、ごく一部の既存ユーザーに新しいリリースを試してもらえます。その後、このリリースに自信が持てるようになれば、徐々に他のユーザーにもロールアウトすればよいのです。
一部ユーザーにリリースする方法では、新リリースを受けることができるユーザーの割合を示します。対象となるユーザーがモバイル デバイスを使って更新の有無を Play Store に問い合わせると、アプリに更新があることがわかり、更新が始まります。
ただし、この方法には以下の問題があります。
更新の対象となるユーザーが、実際にいつ更新を確認するかはわかりません。ユーザーが適切にネット接続できる状況にあれば、通常は 24 時間以内でしょう。ただ、携帯電話や WiFi データ サービスが低速だったり、バイト単位の費用が高額だったりするような国では、そうとも限りません。
ユーザーがモバイル デバイスで更新を許諾するかどうかもわかりません。特に新リリースにおいて追加の許可が必要な場合は、ここが課題となります。
上述したカナリア リリースの手順に従えば、カナリアとなるアクティブ ユーザーの母数が増え、新しいトラフィックの特徴が明確になった時点で、新しいクライアント リリースに問題があるかどうかを判断できます。エラー率は上がったのか、レイテンシはどう変化したか、サーバーへのトラフィックが理由もなく急増していないか、などです。
バージョン v に不具合があるとわかっているアプリをうまく修復する方法は(ロールバックできない場合)、リリース v+1 内にバージョン v-1 というコード部分を構築してリリースし、すぐに 100 % 持ち直すことです。こうすることで、コード内に見つかった問題を修復する時間のプレッシャーから解放されます。
リリースの割合を段階的に増やす
新しいバイナリやアプリを徐々にリリースする場合は、アプリのリリースをどのような割合で増やしていくのか、いつ次に進めばよいのかを決めなくてはなりません。その際、次の点を考慮しましょう。
(カナリアの)最初の段階では、監視やロギングによって問題が明確になるように十分なトラフィックを生成する必要があります。ユーザー数がどれだけなのかにもよりますが、だいたい全ユーザーの 1 % ~ 10 % 程度と考えるとよいでしょう。
各段階で手動の作業が数多く発生し、全体のリリースは遅れます。1 日 3 % ずつ段階的に作業すると、完全にリリースするまで 1 か月かかります。
一気に割合を増加させると(たとえば 10 % から 100 % にするなど)、小規模なトラフィックでは生じなかったトラフィックの大問題が発生する可能性があります。こうした懸念がある場合は、各段階で更新をかけるユーザー数を 2 倍以上増やさないようにしましょう。
新バージョンに問題がないときは、大半のユーザーにすぐにでも使ってもらいたいと考えるのが普通です。ロールバックする場合は、新しいリリースを出すときよりも 100 % 速くロールバックするようにしましょう。
トラフィックのパターンは、通常は日中に最も混雑するなど 1 日を通して変化するものです。そのため、リリース後のトラフィック負荷のピークを把握するには、最低でも 24 時間が必要です。
モバイル アプリの場合、ユーザーが新リリースを取り入れ、有効にして使い出すまでに時間がかかると考えましょう。
Android アプリのアップデートを数日以内に大半のユーザーにロールアウトしたいと考えているのであれば、Play Store の
段階的アップデート
を利用するのがよいかもしれません。10 % に対するロールアウトから開始し、次に 50 % へと増加させ、最後に 100 % にするといった具合です。
次のリリースまで最低 24 時間は空けるようにし、次のステップに進むまでモニターやログを確認するようにしてください。そうすれば、最初のリリースから 72 時間以内にほとんどのユーザーが新しいリリースを取り入れ、大抵の問題は手が終えなくなる前に検知できるはずです。
もしリリースによってサービスのトラフィックが急激に増える危険性があるとわかっているのであれば、10 %、25 %、50 %、100 % といった順番でリリースするか、さらに細かい割合で増加させるようにしましょう。
サービス インスタンスを直接アップデートする内部バイナリ リリースの場合は、1 %、10 %、100 % の順で実施してもよいでしょう。1 % のリリース時には、新リリースに全体的なエラーがないか確認します。たとえば、レスポンスの 90 % がエラーになるようなことはないか、といったことです。
10 % のリリースでは、さらに小さなエラーやレイテンシの増加を見つけ出し、全般的なパフォーマンスに違いが出ないかを確認します。
そして通常は、3 回目で完全にリリースします。パフォーマンスに敏感なシステムの場合、つまり通常 75 % 以上の容量で運用しているような場合ですが、ここに 50 % という段階を追加し、パフォーマンスが落ちていないか詳細に確認しましょう。システムの信頼性に対する目標値が高ければ高いほど、それぞれのステップで問題を検知するのに要する時間は長くなります。
理想的なマーケティングに沿ったリリースのシーケンスが 0 - 100 だとして(つまり全員に新機能を同時リリースします)、信頼性を担当するエンジニアの理想的なリリースのシーケンスが 0 - 0 なのだとしたら(何も変更しなければ問題は起こらないためです)、アプリの正しいリリースのシーケンスは交渉によって決まります。
以上が考慮すべきポイントです。お互いにとって納得のいくロールアウトの方法を決める際に、これらのポイントが理にかなった方法として役に立つことを願っています。
下のグラフは、8 日間のリリース期間という枠の中で、それぞれの戦略がどう作用するかを示しています。
まとめ
私たち Google は、どんな状況でもうまくいくようなソフトウェア リリースの哲学を生み出しました。それは次のとおりです。
ロールバックは早期に行い、頻繁に行うこと : この哲学に従うようにサービスを持っていけば、サービスの平均修復時間(MTTR)を削減できます。
ロールアウトではカナリアを使うこと : どれだけテストや QA を実施したとしても、実稼働のトラフィック上でバイナリ リリースに問題が見つかることは少なくありません。効果的なカナリア戦略を取り入れ、正しく監視することで、問題の平均検知時間(MTTD)が短縮でき、影響を受けるユーザー数も大幅に削減できます。
とはいえ、結局のところ、最も優れたリリースは、その機能がバイナリのロールアウトとは関係なく独自に有効となることかもしれません。この件については、またの機会に。
* この投稿は米国時間 3 月 31 日、Customer Reliability Engineer である Adrian Hilton によって投稿されたもの(投稿は
こちら
)の抄訳です。
- By Adrian Hilton, Customer Reliability Engineer
0 件のコメント :
コメントを投稿
12 か月間のトライアル
300 ドル相当が無料になるトライアルで、あらゆる GCP プロダクトをお試しいただけます。
Labels
.NET
.NET Core
.NET Core ランタイム
.NET Foundation
Access Management
AlphaGo
Anvato
Apache Beam
Apache Maven
API
Apigee
APIs Explore
App Engine
App Engine Flex
App Engine flexible
AppArmor
AppScale
AprilFool
AR
Artifactory
ASP.NET
ASP.NET Core
Attunity
AWS
Big Data
BigQuery
Billing Alerts
Bime by Zendesk
Bitbucket
Borg
BOSH Google CPI
Bower
BreezoMeter
BYOSL
Capacitor
Chromium OS
Client Libraries
Cloud API
Cloud Audit Logging
Cloud Bigtable
Cloud CDN
Cloud Client Libraries
Cloud Console
Cloud Consoleアプリ
Cloud Dataflow
Cloud Dataflow SDK
Cloud Datalab
Cloud Dataprep
Cloud Dataproc
Cloud Datastore
Cloud Debugger
Cloud Deployment Manager
Cloud Endpoints
Cloud Foundry
Cloud Foundry Foundation
Cloud Functions
Cloud Identity
Cloud Jobs API
Cloud KMS
Cloud Load Balancing
Cloud Machine Learning
Cloud monitoring
Cloud Natural Language API
Cloud Networking
cloud Pub/Sub
Cloud Resource Manager
Cloud Resource Manager API
Cloud SDK
Cloud SDK for Windows
Cloud Source Repositories
Cloud Spanner
Cloud Speech API
Cloud SQL
Cloud Storage
Cloud Storage FUSE
Cloud Tools for PowerShell
Cloud Tools PowerShell
Cloud Translation
Cloud Translation API
Cloud Virtual Network
Cloud Vision
CloudBerry Backup
CloudBerry Lab
CloudEndure
Cloudian
CloudML
Cluster Federation
Codelabs
Cohesity
Coldline
Colossus
Compute Engine
Compute user Accounts
Container Engine
Container Registry
Container-Optimized OS
Container-VM Image
CRE
CSEK
Customer Reliability Engineering
Dbvisit
DDoS
Debugger
deep learning
Deployment Manager
Developer Console
Developers
DevOps
Disney
Docker
Dockerfile
Drain
Dreamel
Eclipse
Eclipse Orion
Education Grants
Elasticsearch
Energy Sciences Network
Error Reporting
ESNet
Evernote
FASTER
Fastly
Firebase
Firebase Analytics
Firebase Authentication
Flexible Environment
G Suite
gcloud
GCP 移行ガイド
gcsfuse
GitHub
Go
Go 言語
Google App Engine
Google Apps
Google Certified Professional - Data Engineer
Google Cloud Certification Program
Google Cloud Console
Google Cloud Dataflow
Google Cloud Datalab
Google Cloud Datastore
Google Cloud Endpoints
Google Cloud Explorer
Google Cloud Identity and Access Management
Google Cloud Launcher
Google Cloud Logging
Google Cloud Platform
Google Cloud Resource Manager
Google Cloud Security Scanner
Google Cloud Shell
Google Cloud SQL
Google Cloud Storage
Google Cloud Storage Nearline
Google Cloud Tools for IntelliJ
Google Code
Google Compute Engine
Google Container Engine
Google Data Analytics
Google Data Studio
Google Date Studio
Google Deployment Manager
Google Drive
Google Earth Engine
Google Genomics
Google SafeSearch
Google Service Control
Google Sheets
Google Slides
Google Translate
Google 公認プロフェッショナル
GPU
Gradle
GroupBy
gRPC
HA / DR
Haskell
HEPCloud
HIPAA
Horizon
HTCondor
IaaS
IAM
IBM
IBM POWER9
icon
IERS
Improbable
InShorts
Intel
IntelliJ
Internal Load Balancing
Internet2
IoT
Issue Tracker
Java
JFrog
JFrog Artifactory SaaS
Jupiter
Jupyter
Khan Academy
Komprise
kubefed
Kubernetes
KVM
Landsat
load shedding
Logging
Looker
Magenta
Managed Instance Group
Maps API
Maven
Maxon Cinema 4D
MightyTV
Mission Control
MongoDB
MQTT
MySQL
Nearline
Network Time Protocol
neural networks
Next
Node
NoSQL
NTP
NuGet パッケージ
OCP
OLDISM
Open Compute Project
OpenCAPI
OpenCAPI Consortium
OpenShift Dedicated
Orbitera
Organization
Orion
Panda
Particle
Percona
Pete's Dragon
Pivotal
Pivotal Cloud Foundry
PLCN
Pokemon GO
Pokémon GO
Poseidon
Postgre
PowerPoint
PowerShell
Protocol Buffers
Puppet
Pythian
Python
Raspberry Pi
Red Hat
Regional Managed Instance Groups
Rust
SC16
ScaleArc
Security & Identity
Sentinel-2
Serving Websites
SideFX Houdini
SIGOPS Hall of Fame Award
Site Reliability Engineering
SLA
Slack
SLI
SLO
Snap
Spaceknow
SpatialOS
Spinnaker
Spring
SQL Server
SRE
Stack Overflow
Stackdriver
Stackdriver Debugger
Stackdriver Diagnostics
Stackdriver Error Reporting
Stackdriver Logging
Stackdriver Monitoring
Stackdriver Trace
Stanford
Startups
StatefulSets
Storage & Databases
StorReduce
Streak
Sureline
Sysbench
Tableau
Talend
Tensor Flow
Tensor Processing Unit
TensorFlow
The Carousel
TPU
Trace
Transfer Service
Translate API
Uber
Veritas
Video Intelligence API
Vision API
Visual Studio
Visualization
Vitess
VM
VM Image
VSS
Waze
Webyog
Wide and Deep
Windows Server
Windows ワークロード
Wix
Worlds Adrift
Xplenty
Yellowfin
YouTube
Zaius
Zaius P9 Server
Zipkin
ZYNC Render
アーキテクチャ図
イベント
エンティティ
オンライン教育
クラウド アーキテクト
コードラボ
コンピューティング
サポート
ジッター
ショート動画シリーズ
スタートガイド
ストレージ
セミナー
ソリューション: メディア
データ エンジニア
データセンター
ビッグデータ
ファジング
プリエンプティブル VM
フルマネージド
マイクロサービス
マルチクラウド
ロード シェディング
運用管理
可用性
海底ケーブル
機械学習
月刊ニュース
資格、認定
新機能、アップデート
人気記事ランキング
導入事例
内部負荷分散
認定試験
料金
Archive
2017
4
3
2
1
2016
12
11
10
9
8
7
6
5
4
3
2
1
2015
12
11
10
9
8
7
6
5
4
3
2
1
2014
12
11
10
9
8
6
5
4
3
2
Feed
月刊ニュースレターに
登録
新着ポストをメールで受け取る
Google
on
Follow @GoogleCloud_jp
0 件のコメント :
コメントを投稿