こんにちは!kintone開発チームの田中裕一(@yuichielectric)です。
こちらの記事に引き続き、Velocity Conferenceに参加して、面白かったセッションの内容を紹介しようと思います。
Velocity Conferenceについては前回の記事を参考にしてみてください。
Failure is an option
今回紹介するのは前回と同じ Etsy の Ian Malpass(@indec)さんによる"Failure is an option"というセッションです。
このセッションでは、Etsyでの失敗に対する扱いや、失敗からいかに学ぶかという文化的な話と、その文化を支えるツールが紹介されました。失敗をどう扱うのかという考え方は非常に参考になり、それを恐れるよりもうまく乗りこなすことが重要なのだということがよく分かるセッションでした。
また、スピーカーの方のブログ記事でセッションの書き起こしも公開されています。
失敗は避けられない
Etsyでは、以下のような失敗は避けられないものと考えています。
- バグを入れてしまうこと
- ユーザーが求めていないものを使ってしまうこと
- 予期せぬ障害が発生すること
ただし、致命的な失敗を避け、被害を最小限に留めることはできます。
失敗を避けるために、様々なものを2重、3重にチェックしたり、新たなプロセスを設けたりすることも出来ますが、Etsyではそういったことはせず、スピードと柔軟性を保ち、失敗が起きてもすぐに修正できるようにしています。
継続的デプロイ
そのために重要なのが継続的デプロイです。EtsyではDeployinatorというツールを作っています。このツールでは、Web UIでデプロイができます。
特徴的なのはこのツールからデプロイをするのはエンジニアやオペレーションに限らず、誰でも使えるということです。デザイナやプロダクトマネージャがデプロイすることもあります。こうすることで、直したいと思ったものは自分で直してデプロイすることができるようになります。
このように誰でも簡単にデプロイ出来るようになると、1つのデプロイ当たりの変更が小さくなります。デプロイの変更が小さくなることによって、
- コードレビューがやりやすくなる
- そのデプロイによって何かが失敗しても原因調査がしやすい
というメリットが得られ、失敗のコストを減らすことが出来ます。
自動テスト
バグを防ぐために自動テストを行っていますが、自動テストの数や複雑さが増すほど実行時間は掛かるようになります。自動テストに時間がかかれば掛かるほど、1回のデプロイに時間が増すため、1日にデプロイ出来る回数は限られてきてしまいます。その結果、デプロイしたものにバグが見つかったとしても、修正をデプロイするのに時間が掛かってしまいます。
よって、自動テストの実行に掛かる時間は短くする必要があります。
そのために、Etsyでは以下の2点を行いました(参考)。
- テストを分割して並列実行出来るようにして実行時間を短縮
- 長時間掛かるテストや不安定なテストを削除
テストの削除してしまって良いのだろうかと思うかも知れませんが、デプロイに時間がかかってしまうというコストの割に得られるメリットは低いと判断して削除しています。
また、デプロイする段階になって自動テストが失敗すること自体が好ましくありません。そのため、Tryというツールを作りエンジニアが開発中のコードを専用のサーバーで実行する仕組みを作り、デプロイする前にテストが通るかどうかを確認できるようにしています。
デプロイ後のメトリクス監視
Etsyではすべてのものを計測しており(参考)、そのグラフはダッシュボード化されています(参考)。Etsyではデプロイをした後は、各種のメトリクスがどのように変化するのかをエンジニアが観察するようになっています。
それぞれのグラフにはデプロイしたタイミングに縦線が表示されるため、デプロイのタイミングで何かのメトリクスに大きな変化があった場合はすぐに気づく事が出来ます。
また、ダッシュボードには"Tree-Armed Sweaters"という名前のメトリクスのグラフが含まれています。これはエラーページが表示された回数を表します。似たようなメトリクスとして"Screwed Users"というメトリクスのグラフもあります。これは、ユーザーが何らかの不都合な体験をしたり、処理に時間がかかったりした回数を合算したものです。
デプロイ直後にこれらのメトリクスが急上昇している場合は、デプロイによって何かのバグを入れてしまったとすぐに気づくことが出来ます。
デプロイ後のログ監視
デプロイした後にはログも監視しています。これにはSupergrepというツールを使っています。このツールは、運用環境のログを集約したものをWeb上でストリーミングして表示します。これによって、何かエラーが多発している場合はすぐにバグを入れてしまったことに気づくことが出来ます。また、スタックトレース上のコード行数をGitHubへのリンクにするようになっているので、エラーが起きてスタックトレースが表示されている場合でも、何が原因なのかをすぐに調べることが出来ます。
新機能による運用障害を防ぐ
新機能のコードをデプロイする際には、フィーチャーフラグを使います。これは、ある特定のコードを実行するかどうかを設定ファイルに書いておける仕組みを提供します。
新機能を開発する際は、この仕組みを使って、まずは機能を無効化した状態でその機能に関するコードを少しずつデプロイしていきます。このような無効化されているコードのことをEtsyでは"dark code"と呼んでいます。これは、ユーザーには何の変化も与えないですが、コードを少しずつデプロイしていくことで既存コードの予期せぬ箇所に影響を与えていないかを確認することが出来ます。
また、フィーチャーフラグでは、全ユーザーのうちのある特定の割合のユーザーにのみ機能を提供することも出来ます。この仕組みを使って、ある程度出来てきた機能をまずは全ユーザーの1%に公開してみます。こうすることで、この機能がパフォーマンスリグレッションを起こさないかどうかなどを確認することが出来ます。そして、利用するユーザーの割合を少しずつ増やしていくことで、もし途中で問題が発生したら即座に利用するユーザーの割合を減らしたり、機能を無効化すれば、大きな障害になることもありません。
間違ったものを作る失敗を最小限に留める
ここまでで、新しくデプロイしたコードがバグや障害を引き起こさないような工夫は出来てきました。しかし、新しく機能を作った段階では、その機能が本当にユーザーの問題を解決するかどうかは定かではありません。
それを確認するために、ここでもフィーチャーフラグを使います。フィーチャーフラグは、ある特定のグループのユーザーのみ機能を有効にすることもできます。この仕組みを使って、まずはEtsy社内の同僚に対して機能を有効にしてみます。これによって、社外のユーザーには新しい機能を見せずに、社内の同僚からフィードバックをもらう事が出来ます。
また、新しい機能をユーザーに公開するときにも、一度にすべてのユーザーに公開するのではなく、まずは新しい機能を使いたいユーザーを公募します。これに参加してくれたユーザーのみのグループを作成し、そのグループに対して新しい機能を有効とします。
こうすることで、新しい機能へのフィードバックをもらうことが出来ます。また、もしフィードバックをもらえなかったとしても、ユーザーはいつでもそのグループから離脱して以前の状態に戻ることができるようになっているので、そのグループの離脱者が多いようであれば、その機能は使われないという判断が出来ます。
予期せぬ障害に備える
ここまで説明したような工夫をしても、予期せぬ障害は発生します。その場合、被害を最小限に留めるために、原因となる機能を無効にします。一部の機能が使えなくなるので、最善の策ではありませんが、サービス全体が使えなくなってしまうよりはましです。
このようにして、予期せぬ障害に対してもフィーチャーフラグを使うことによって、被害を最小限にとどめています。
失敗を責めず、そこから学ぶ文化
失敗の被害を最小限に留める方法について話をしてきましたが、それでも失敗をなくすことは出来ません。それであれば、失敗を責めるのではなく、失敗を受け入れ、そこからいかに多くを学ぶかと考えるほうが生産的です(参考)。同じ失敗を2度と繰り返さないようにすればよいのです。
そのため、失敗が起きた後は、振り返りを行い、今後どうするべきかを検討します。そして、この学びを社内の全員で共有しています。
さらに、Etsyでは1年のうちで一番大きな失敗を表彰することもしています。このように、失敗を恐れるのではなく、失敗を受け入れ、そこから学ぶことに注力することで、スピードを保ったまま開発を進めていくことができているのです。
感想
Etsyの失敗に対する考え方についての話でしたが、この根底にある常に失敗から学び、改善し続ける文化が素晴らしいと思いました。このような文化を築くことで、今後もどんどん開発の進め方や使うツールが変化していくのだろうと思います。
僕らも常に改善する文化を目指していますが、まだまだ学ぶべき点が非常に多くありました。参考にしつつ、僕らなりの良い開発文化を築いていけるよう頑張ろう思います!