GoogleにおけるRelease Engineeringとは

SRE(Site Reliability Engineering)が叫ばれて久しいですが、Googleがこの度Site Reliability Engineeringに関する書籍をWeb上で無料で公開したので早速かいつまんで読んでみた。きっとそのうち日本語化されてオライリーのebook上に並ぶのでしょう。

とりあえずRelease Engineeringの章に目を惹かれて興味深かったので斜め読みしてみた。

リリースエンジニアの役割とは

Googleではリリースエンジニアの役割について以下のように定義している。

Googleにはコードの変更を本番環境に反映する時間やビルドを構成するファイルの中で利用される機能に関する統計といった様々なメトリクスをレポートするツールがあり、これらのほとんどはリリースエンジニアによって考案され開発されたものだ。ベストプラクティスはリリースプロセスのすべての要素がカバーされていることだ。 例えば、コンパイラフラグ、ビルド識別タグのフォーマット、さらにビルドに必要ないくつかのステップが含まれる。開発チームはリリース作業に時間を費やすのではなく、機能やユーザーのためになることに集中しやすくするためにリリースツールが常に正確に動作するようにしておき、適切にドキュメント化されていることが重要だ。

リリースエンジニアの本質は開発チームが機能に集中できるような仕組みを継続的に作るということ。さらに、リリースの所要時間のメトリクス等も見ているということは、成果物を実際に届けるまでの時間を短くすることに価値があるということを示しており、それを突き詰めれば単位時間でのリリース回数も増える。前にAmazonが1時間に1000回デプロイするという話が話題になったことがあったが、Googleには継続的にそれを担保するためにリリース技術専門のロールがあるということ。

リリースエンジニアリングによる哲学

リリースエンジニアリングが持つべき哲学として以下の4要素が挙げられている。

Self-Service Model

スケール(規模化)をするためにはチームは自立してなければならない。各チームが独自のリリースプロセスを実行できるようにするベストプラクティスとツールを開発している。数千人のエンジニアとプロダクトが存在しているが、リリース頻度と時期はそれぞれのチームに委ねられているため迅速なリリースを達成できる。エンジニアが手を下すことが最小限なリリースプロセスになっており、多くのプロジェクトでは自動化されたビルドシステムと導入用ツールを組み合わせることで自動的に構築されリリースされる。

Googleくらいの規模になるとガチッとリリースのフローが固められてそうな印象もあるのだが、むしろリリースプロセスは各プロジェクトで独自に選択されており、リリースエンジニアリングはツールとベストプラクティスを提供するということに専念しているという印象。

High Velocity

我々は頻繁にリリースすればバージョン間の変更が少なくなるという考え方を採用している。このアプローチはテストやトラブルシューティングを容易にする。あるチームでは1時間毎にビルドを行っており、リリースの選択はテスト結果とビルドに含まれる機能に基づいている。別のチームではPush on Greenなリリースモデルを採用しており、テストが通ったビルドは全てデプロイされている。

短いサイクルでのリリースを徹底している。今のプロジェクトもそこそこ細切れスタイルのリリースをやっているけれど、たまに大きめの開発が入ってくることもあり、かつそれが様々なシステムやサービスと連携することもありリリースが大きくなってしまいがちなのが課題。

Hermetic Builds

Hermetic密閉されたの意味らしい。

ビルドツールは一貫性と再現性を保証できるものでなくてはならない。2人の開発者がそれぞれ別のマシンであるリポジトリの同じリビジョン番号でビルドしても、同じ成果物が期待される。我々のビルドは密閉されており、マシンローカルなライブラリや様々なソフトウェアの影響をうけることはない。その代わりにビルドはライブラリの依存関係のようにビルドツールの既知のバージョンに依存することになる。ビルドプロセスは自己で完結せねばならず、外部サービスに依存してはならない。

本番環境で動作するソフトウェアの不具合を修正したいといっても、古いリリースを再び構築することは難しい。我々はこの作業を元のビルドと同じリビジョンで再構築しその時点以降でされた変更を含めることで実現できる。この戦略をcherry pickingと呼ぶ。我々のビルドツールはビルド中のリポジトリのリビジョンに基づいてバージョン付けされている。それゆえに、先月作成されたプロジェクトにおいてチェリーピックを必要とする場合、互換性が保たれていなかったり期待していない機能が含まれている可能性があるので当月のバージョンのコンパイラは利用しない。

密閉性というか最近で言えばポータビリティという単語がしっくりくるのではないか。どこの環境でも同じ動作を期待できるようにしなくてはならない。また、ビルドはその時点で利用したビルドツールに依存する。ツールの特定のバージョンに依存することで再現性を保っている。たしかに、ビルド対象がバージョニングされていてもビルドツールが進んでしまっていて再現できないみたいなことを昔やってしまったことがある。再現性という意味では最近はコンテナもあるし、CIサービスも充実しているのでこれを担保するのは決して難しくはなくなった。

Enforcement of Policies and Procedures

セキュリティとアクセスコントロールを行うレイヤーにおいて、リリースするときに特定の操作を実行できるユーザーを決定する。ゲート制御には以下のようなものがある。

コードの変更を承認する(この操作はコードベースに散在する設定ファイルによって管理されている) リリースプロセスの中で実行されるアクションの指定 新しいリリースの作成 統合の提案(特定のリビジョンでビルドを実行する要求)とチェリーピックの承認 新しいリリースをデプロイする プロジェクトのビルド設定を変更する

コードベースのほぼ全ての変更はレビューが必要となり、開発者のワークフローに統合されたアクションである。我々の自動リリースシステムはリリースに含まれる全ての変更をレポートし、その内容はビルド成果物と共にアーカイブされる。SREが新しいリリースにどのような変更が含まれているかを理解することで、リリースで問題が発生した際のトラブルシューティングを迅速に行えるようにしている。

ゲート制御?という訳でいいのかわからないが、リリースやチェリーピックにおけるオペレーションとユーザーのロールが適切に設定されている模様で、おかしなリリースがされないような仕組みが作られている。仕組みもそうだけど、例えば常に迅速にレビューができるような体制にするのはすごく大変な印象がある。日々の開発において、やむなくセルフマをせざるを得ない状況が自分たちの場合は起きているので、そういうのはいくら自信があっても後ろ髪を引かれる思いである。この辺りは開発における組織論として非常に興味深い。 

上記実現のための手法

その次に、上記の哲学を実現するための具体的な手法が述べられている。継続的インテグレーションやテスト、パッケージング、デプロイ方法、高速にリリースするためのワークフローのアーキテクチャ等についてであるが、詳細長過ぎるの実際に読んでみてほしい。

Start Release Engineering at the Beginning

最後に、リリースエンジニアを始めるにあたってという項がある。グサグサと刺さってきたので紹介しておきたい。

リリースのエンジニアリングは後になってから考慮されることが多かった。プラットフォームやサービス規模、複雑性が増すほど変化させていかなければならない。

チームは開発サイクル開始時に、リリースエンジニアリングリソースのリソースを設定すべきだ。後になってからリリースシステムを改修するのではなく、早期に適切なプラクティスとプロセスを定着させるほうが安くつく。

開発者・SRE・リリースエンジニアが協調して作業することが不可欠だ。リリースエンジニアはコードをどのようにビルドして展開されるかを理解しておかなくてはならない。 また開発者は、リリースエンジニアが扱うように、フェンス上に結果を構築して丸投げすべきではありません。

うう、非常に刺さりますね。リリースプロセスの重要性は皆わかっていても、どれだけ最初に楽なプロセスを作るかにコミットできるケースはなかなか少ない。ここで言うとこの初期投資は、ガチガチに作り込むのではなく変化に適用しやすいものを作るというか、60点を100%の力で作っておいて常に変化していけよって言う感覚だと思う。

最後にはこのように書かれていた。

リリースエンジニアリングは若い領域のため、プロジェクトの初期段階でリリースエンジニアリングを計画してもリソースが立てられるとは限らない。ゆえに、リリースエンジニアリングを検討する際は、サービスのライフサイクル全体、特に初期においてその役割があることを考慮しておくべきだろう。

というわけで皆さん、リリースエンジニアリング頑張りましょう💪