今年からアウトプットすることで内容が頭に入るかなと思って読書メモを書くことにした。

1冊目はプロダクションレディマイクロサービス。 業務でマイクロサービスを開発してるし、興味としてもよりよいマイクロサービスのアーキテクチャ、運用、ベストプラクティスに興味があった。

第1章 マイクロサービス

マイクロサービスの概念

マイクロサービスとは、1つのことだけを非常によくこなす小さなアプリケーションのことです。マイクロサービスは簡単に交換でき、独立に開発、デプロイできる小さなコンポーネントです。(1.1)

ここで「UNIXという考え方」を思い出した。そこでも出てきた好きな考え方だ。小さいシンプルなアプリケーションが協調して動き、大きな仕事を成し遂げる。 スモール・イズ・ビューティフル、1つのプログラムには1つのことをうまくやらせるといった定理だ。 こういう考え方は幅広く適応できるものなのかもしれない。

モノリスでは難しいスケーラビリティーのための並行性とパーティション分割をマイクロサービスは実現できる。

組織について

モノリスからマイクロサービスへの分割の難しさについても書いてあった。サービスの分割だけではなく、その範囲は組織にも及ぶ。

  1. 1チーム1サービス:十分な数の開発者とSREを配置しないといけない。Amazonなんかはこっちなのではないだろうか。
  2. 1チーム複数サービス:チームが特定の製品や業務領域に合わせて組織されており、それらに関連するすべてのサービスを開発する場合にはこれがうまくいくようだ。 自分は新卒からマイクロサービスの開発に関わっているが、こちらのタイプの経験しかない。巨大な組織でない場合はこっちになるではないだろうか。

マイクロサービスとエンドポイントはバージョニングさせない

マイクロサービス開発はペースが速いので、マイクロサービスに異なるバージョンを認めると、クライアントサービスの開発者が自分のコードの中で(古くなり、メンテナンスされてない)特定のバージョンのマイクロサービスを指定するようなことをして、簡単に泥沼にはまることになります。(1.2)

APIエンドポイントのバージョニングも同じような理由から避けなければならないアンチパターンです。(1.2)

やってしまっている…エンドポイントのバージョニング。 しかし完全に納得。バージョニングしているとコードも複雑になるし、だんだんカオスになってくるので解消しよう。

セルフサービス内部ツール

インフラ、アプリケーション、マイクロサービスのように担当する分野の階層が違うチームが存在するとき、

上位レイヤの仕事をするエンジニアが、自分よりも下位のレイヤの何かを設定、構成、利用しなければならないときには、そのエンジニアが使えるセルフサービスツールを用意しなければなりません。(1.3.3.1)

ここでは、例えばサービスを開発するエンジニアがメッセージングに必要なインフラに変更が必要なときには(インフラの詳細な知識がなくても使える)それを実現するツールが必要だと書いてある。 つまり、ブラックボックス化して、そのツールの仕組みと使い方をドキュメント化する。 これをすると、階層の違うチームが自分の階層のサービスやシステム、特に深刻な問題を引き起こしかねないものに大幅な変更を加えられない用にできるメリットもある。

これは納得するとともに、やってないなと思った。たしかに下手なとこはいじれないようにして自分で構成を変更できるようにしたりするのは毎回インフラチームに依頼したりしなくてよくなってよさそう。

開発環境

効率的にマイクロサービスを開発するために、

  1. バージョン管理システム
  2. 開発環境

が必要だと書いてあった。バージョン管理システムは当然Githubなどを使うとして、 特に開発環境は重要で、

開発をすべてローカルに(開発者のノートPCで)行う方法を選んでいる技術組織もありますが、それでは自分が書いたコード変更が本番環境でどのような動きをするかが正確に見えてこないので、デプロイ後に問題を起こすことがあります。(1.3.3.2)

と書いてあった。ここでいう開発環境はマイクロサービスエコシステムがデプロイされた本番環境のミラーを指している。 これはマイクロサービスのためのローカル開発環境の記事でも書いたように、Telepresenceを活用して開発環境に接続して開発しているので問題なさそうだ。

技術的スプロール

マイクロサービスを採用すると、モノリスが抱えるスケーラビリティ、効率の欠如、新テクノロジーへの対応の難しさといった問題は解決するが、 銀の弾丸はなく、引き換えに発生する課題もある。 技術的スプロールとは聞き慣れない言葉だったが、スプロールとは

都市が発展拡大する場合、郊外に向かって市街地が拡大するが、この際に無秩序な開発を行うことをスプロール化と呼ぶ。(wikipedia)

だそうだ。つまりエントロピーの増大だ。マイクロサービス化で個々のサービスは独立しているのでマイクロサービスが100あれば 100種類のプログラミング言語、100種類のデプロイ方法、100種類のライブラリ、100種類の監視、アラート、テスト、機能停止処理方法を持つようなことになりかねない。 これを避けるためには、標準化を進めるしかない。マイクロサービスだからといって、好き勝手にやってるとカオスになるのは納得。

第2章 本番対応

マイクロサービスは小さいサービスが集まって全体の一つのシステムを実現するため、1つのサービスが好き勝手して全体の安定を崩してはいけない。 マイクロサービスを作る際には、何らかの標準が必要になる。 そして、それは

すべてのマイクロサービスに適用できるほど一般的でありながら、定量化でき、測定可能な結果を生み出せる程度には個別的な標準と要件(2.1)

でなければならない。それに本番対応という概念を使い、その原則は

  • 安定性
  • 信頼性
  • スケーラビリティ
  • 耐障害性
  • 大惨事対応
  • パフォーマンス
  • 監視
  • ドキュメント

であり、これらの原則を備えたマイクロサービスは本番トラフィックを任せられる可用性の高いシステムであるというようなことが書いてあった。

スケーラビリティー

これは取り組まないといけないと思っているところで、単純なCPUとかメモリの使用量とかではうまくいかないケースもあるので、もっと柔軟にスケーリングするようにk8sの仕組みも使ってやりたいなというところ。 これはパフォーマンスのところにも書いてあったインフラリソースの効率的な利用にも影響してくるだろう。

ドキュメント

マイクロサービスのアーキテクチャに対する知識や理解は開発者によってまちまちで一致しない。 このような知識や理解の不一致は、機能追加などのときに本番トラフィックの処理を安心して任せられなくなるような重大な欠陥を持ち込み、 マイクロサービスは本番対応を失ってしまう。

その対策として、ドキュメントが重要だということが書いてあった。

アーキテクチャ図、オンボーディング/開発ガイド、リクエストフローとAPIエンドポイントの詳細情報、個々のアラートのオンコールランブックなどの、マイクロサービスに関して必要とされるすべての基本知識(事実)を含めなければなりません。(2.3.7)

理想的にはそうなんだけど、なかなかドキュメント整備は進まない…マイクロサービスってドキュメント書く必要がある情報が多くて大変な感じがする。 ここで書かれているようなマイクロサービス用のドキュメントのテンプレートを自動で生成みたいな楽ができる手段があるといいんだけど。 ドキュメントとコードが乖離しがち。

本番対応の実装

本番対応標準を採用したUberやその他の企業では、本番対応標準の実現、審査は、SRE(サイト信頼性エンジニア、サイトリライアビリティエンジニア)部門が主体となって進めています。一般に、SREはサービスの可用性を守ることを職務としており、マイクロサービスエコシステム全体で本番対応標準を推進していくことは、もともとの職責と非常にうまく適合しています。(2.4)

SREが本番対応チェックリスト用意して満たしているかチェックするみたいな仕組みにするのがいいのかな。こういうのも自動化できるところは自動化したい。

第3章安定性と信頼性

安定性と信頼性のあるデプロイの保証

ホットフィックスはアンチパターンということが書いてあった。バグの修正であっても必ずCI/CDを通る正規のデプロイパイプラインを通らなければならない。

本番環境で障害が起こったときには、本番環境へのデプロイを急ぐのではなく、最後の安定ビルドに戻るようにすべき(3.3.4)

昔の手動デプロイの時代にホットフィックスが障害を起こした事例を思い出した。CI/CD通すの大事。 急いでやったバグ修正本当に大丈夫かというのもあるし、一次対応として問題ないことがわかっているビルドに戻すのは安定性、信頼性を担保するには重要だろう。

非推奨と廃止

マイクロサービスやそのAPIエンドポイントの非推奨、廃止について。

サービスやエンドポイントを完全に廃止、非推奨にする前に、もとのサービスやエンドポイントにまだ送られているリクエストがないかどうかを確認するために、エンドポイントをしっかりと監視する必要があります。(3.6)

古いエンドポイントなどは非推奨を経て廃止する必要があり、その過程には監視の仕組みが不可欠であるということが書いてあった。 今監視はdatadogを使っているが、エンドポイントを非推奨にしたときにサクッとアラートとか飛ばせるようにしておくとよさそう。

第4章 スケーラビリティーとパフォーマンス

垂直スケーリングは、マイクロサービスアーキテクチャの基礎として持続可能でスケーラブルな方法だとは言えません。個々のマイクロサービスが専用ハードウェアを持つような状況ではそれでうまくいくように見えるかもしれませんが、今日のIT業界で使われているDockerやApache Mesosのような新しいハードウェア抽象化とハードウェア分離のテクニックとはうまく適合しません。スケーラブルなアプリケーションを作りたければ、必ず並行性とパーティション分割を増やす方向で最適化を行うべきです。(4.4.2)

ああ、一部垂直スケーリングしかできない構造のあるな…たしかにk8sでスケーリングするときも水平スケーリングの方が筋が良さそうな気がするし、 水平スケーリングできるようにしないといけないな。

第5章 耐障害性と大惨事対応

障害の分類、障害対応の話と、 カオステストやロードテスト(負荷をかけてみるテスト)の自動化などについて書いてあった。 この辺のテストの自動化はまだまだ手つかずなのでいずれやりたい。

第6章 監視

ロギング、ダッシュボード、アラート、オンコールローテーションについて。

ダッシュボードはあんまり活用できてないのでdatadog設定しようと思った。

ダッシュボードにデプロイがいつ行われたかを表示すると、新しいデプロイの導入による問題が見つけやすくなります。そのためにもっとも効果的で役に立つのは、主要メトリックのグラフにデプロイの時刻を表示する方法です。そうすれば、開発者は、デプロイを終えるたびに、グラフをさっと見て、主要メトリックに奇妙なパターンが現れていないかどうかを確かめることができます。(6.4)

たしかに。いつも流れるログ直接見たりしてたけどダッシュボードで可視化してるともっとわかりやすいな。

第7章 ドキュメントと組織的な理解

アーキテクチャレビュー

個々のマイクロサービスについてスケジュールを設定してアーキテクチャレビューを実施することです。優れたアーキテクチャレビューは、サービスのための仕事をしているすべての開発者とSRE(またはその他の運用エンジニア)が一堂に会して、ホワイトボードにサービスのアーキテクチャを描き、そのアーキテクチャを徹底的に評価する会議です。(7.3.1)

こういうのやったことなかった。確かにメンバーによってマイクロサービスへの理解度は異なるし、定期的に開催してアーキテクチャ図を更新するのはよさそう。

本番対応の監査

これもやってないなー付録にチェックリストがついているのでこれを元に作るといいかも。

本番対応チェックの自動化

これは大変そうだけどやるべきだろうな。本にも書いてあったけど、手動だとどうしても後回しになったりする気がする。 一回作ればあとが楽になる類のもの。

さいごに

感想は色々書いたが、マイクロサービスを開発していくうえで参考になる本だった。いくつかアンチパターンをやってしまっていたり未整備なものがあるので改善に取り組んでいきたい。