【読書メモ】システム運用アンチパターン

備忘録として書きます。
筆者以外が読むことを想定していません。すみません。

### この書籍を読んだ方がいい人(筆者の主観)

- システムの運用に関わるエンジニア
- ビジネスサイドとやりとりすることが多い開発チームの人
- 「プロダクトが軌道に乗ってきたのはいいけどインフラチームやビジネスサイドとの調整が多くなってきて辛い」と思っている人

### この書籍を読まなくてもいい人(筆者の主観)

- 業務におけるコーディングの比重が高い人
- 立ち上げ間もないプロダクトやリリース前のプロダクトに参画している人


どちらかと言えば比較的規模が大きめでレガシーなシステムの運用に関わっている人向けの書籍だと思います。

### 1章 DevOpsを構成するもの

#### 内容要約

- DevOpsとはツールの話ではない。人・プロセスの方が優先される。本書はJenkinsやDockerやKubernetesについて解説した書籍ではない。
- DevOpsは4つの柱に支えられている。その柱とは **文化(culture)・自動化(automation)・メトリクス(metrics)・共有(sharing)** である。これら4つを総称してCAMSと呼ぶ。

#### 感想

DevOps = ツールの話だと思っていたので意外でした。DevOpsがツールの問題ではない理由は下記の通りです。

> Jenkinsの最新版をインストールしたり、CircleCIにサインアップしても、しっかりとしたテストスイートがなければ意味がありません。自動テストを価値あるものとして考える文化がなければ、ツールは価値を提供しません。[^1]

要するに、ツールを有効活用できる文化がなければ導入しても意味がないとのことです。基本的には正論だと思います。ただ、「ツールを導入してみたら思ったよりも使いやすかったので自動テストを拡充していこう」みたいにツールの導入がきっかけで文化が変わることもあるような気がします。


### パターナリスト症候群

#### 内容要約

- システムに問題が発生すると対策としてアクセス制限や承認プロセスが追加される。その結果として仕事の進め方やタイミングが特定の人物・チーム(ゲートキーパー)に依存してしまう。
- 承認プロセスを追加する組織は問題を防ぐことに注目し、組織の負担が増えることには着目しない。結果としてリリースのリードタイムが増える・プロセスの品質が低下する等、別の問題が発生する。DevOps組織では手動プロセス追加ではなく自動化を推奨する。
- 手動プロセスを自動化する際はそのプロセスが解決しようとしている懸念事項を考える必要がある。また、自動化の設計にはゲートキーパーが参加することが望ましい。
- 自動処理の設計ではロギング・通知・エラー処理を上手く検討する必要がある。

#### 感想

「手動のプロセスが解決しようとしている懸念事項を考えるべき」というのは2つの理由があると思いました。


1つは当然自動処理を上手く作成するため、もう1つはプロセスを担当していた人やチームとのコミュニケーションを上手く進めるためです。


自分が今まで担当していた作業が自動化されると良く思わない人が多いので、「このプロセスによって何を解決しようとしていましたか？」と丁寧にコミュニケーションをとりながら進めると良さそうです。

### 3章 盲目状態での運用

#### 内容要約

- システムを理解するためにスループット・エラー率・レイテンシの3つのメトリクスが有効である。スループットは一定時間内に処理したリクエスト数・エラー率はリクエスト数に対するエラー数の割合・レイテンシは特定のアクションが完了するまでの時間である。
- 計測対象のメトリクスを決めた後は「健全なメトリクス」を定義する。健全なメトリクスを決めることにビジネスサイドに参加してもらうことは有効である。(例：ダッシュボード画面は早く表示されてほしい。レポート表示は多少遅くても良い等)
- ログはJsonのように構造化して集約すべきである。ログを集約化すると「20台のサーバ全てでリクエストの1%が失敗している」といった状況を可視化することができる。
- ログには **文脈** を盛り込む必要がある。例えばECサイトのログに注文IDを出力する。これにより注文IDでログを絞り込み、その注文に関する文脈を絞り込むことができる。

#### 感想

計測すべきメトリクスを決めるには業務知識が必要になりそうです。例えば給与計算システムであれば締め日はいつ頃なのか・どのようなアルゴリズムで計算するのかを知らないと有効なメトリクスを定義できない気がします。

ログを構造化するというのもメトリクスの話に近いと思いました。(要は何を記録して何を記録しないのかという問題) 

ただ、既存のシステムのログを構造化するならどこから始めればよいのか分かりません。構造化されているログとされていないログが混在して却って調査しづらくなる事態も起こりそう。 

### 4章 情報ではなくデータ

あまりピンと来なかったので割愛します。すみません。

### 5章 最後の味付けとしての品質

#### 内容要約

分量が多いため小分けしてまとめます。

##### 5.1 ~ 5.3： テスト

- テストにはユニットテスト・統合テスト・エンドツーエンドテストの3種類がある。
  - ユニットテスト： 個々のモジュールをテストする。内部実装ではなく振る舞いをテストすべきである。
  - 統合テスト： モジュール間のやり取りや外部システムとの通信をテストする。テストのセットアップに時間がかかる問題がある。
  - エンドツーエンドテスト： ブラウザ操作によりシステムをテストする。
- 自動テストは信頼性が重要であるので、コード以外の原因で失敗する不安定なテストは許容すべきではない。したがってエンドツーエンドテストは最小限にするほうがよい。

##### 5.4 継続的デプロイと継続的デリバリ

- 継続的デプロイ ≠ 継続的デリバリである。前者はメインブランチへのコミットをトリガーとして自動的にリリースすることを指す。後者は **アプリケーションを常にデプロイ可能な状態に保つこと** を指す。
- 継続的デリバリではアプリケーションがデプロイ可能であることを示すために次の一連のステップを自動で実行する。
    - 静的解析
    - ユニットテスト
    - 統合テスト
    - エンドツーエンドテスト
    - アーティファクトのビルド[^2]

##### 5.5 機能フラグ

- フラグやセマフォを用いて **コードのデプロイ** と **機能のリリース** を分けることができる。

#### 感想

エンドツーエンドテストの信頼性が低いのは実務でも実感しています。バグを検出できることよりも外部要因で失敗することの方が多いです。

私は本書を読むまで継続的デリバリ=継続的デプロイと勘違いしていました。

継続的デリバリの目的は自動デプロイではなく、アーティファクトがビルドされている = 静的解析やテストがパスしてデプロイできる状態である ということを担保することだと思いました。 (その状態を実現するためには充実した自動テストが必要なので割とハードルは高そう。)

### 6章 アラート疲れ

飛ばします。ごめんなさい

### 7章 空の道具箱

#### 内容要約

- 自動化によって改善される領域は以下の4点である。
  - 待ち時間： 特に複数部署間で連携が必要な作業は待ちが発生しやすい。それゆえに自動化の恩恵は大きい。
  - 実行時間： 複数のコマンドをまとめて実行する・同じ作業を繰り返し実行する場合は自動化すべきである。
  - 実行頻度： 手動で同じ作業を繰り返すと品質が低下する。また、作業を中断して別のタスクを実行することはコンテキストスイッチが必要になるため効率が悪い。自動化によってコンテキストスイッチを減らすことができる。
  - 実行のばらつき： 手動作業は実行タイミングや実行にかかる時間にばらつきがある。自動化により品質を平準化することができる。
- 手動作業のコストは(実行時間の下限値 ~ 上限値) × 実行回数 でおおまかに見積もる。
- 自動化にかかる時間をプロジェクトの一部として見積りに含める。こうするとツールの構築とテストがプロジェクトに組み込まれてスムーズに進む。
- 問題の性質は単純・困難・複雑・混沌に分類される。タスクの複雑さは専門家ではなく実行する人の観点で分類されるべきである。
- タスク自動化の難易度を識別するプロセスは次のとおりである。
　1. 困難なタスクを一連のシンプルなタスクに分割する
　2. それぞれのシンプルなタスクを評価して間違えた場合の影響を1 ~ 10でランク付けする。
　3. ツールやスクリプトでタスクを確実に実行する難しさを1 ~ 10でランク付けする。
　4. 2と3を軸とした図にタスクを配置して全体的な難易度を評価する。
　5. タスクがプロットされる位置に基づいて手動で実行するか自動で実行するかを決める。

#### 感想

自動化によって実行のばらつきを減らすことができるという観点は今まで持っていませんでした。副次的な効果として、自動化されたプロセスに実行時間のばらつきがあれば何等かのトラブルだと判別できそうです。


### 8章 業務時間外のデプロイ

#### 内容要約

- デプロイ頻度が少ないと1回あたりのデプロイに含まれる変更が増える。変更が増えるとデプロイが失敗するリスクが増える。リスクが増えるとデプロイへの抵抗感が増えてデプロイが減る。さらに1回あたりのデプロイで変更される数が多くなる。これはフィードバックループと呼ばれる。
- アプリケーションとデプロイ用のスクリプトを1つのファイル(これをデプロイアーティファクトと呼ぶ)にまとめることが推奨される。
- OSのパッケージ管理システム(RPMやDEB)を利用してデプロイアーティファクトを作成すると依存関係の管理やWebサーバの再起動等の手順を1つのコマンドに集約できるため、デプロイプロセスのばらつきを抑えることができる。
- 環境ごとに異なる設定はデプロイアーティファクトに含めることが難しい。この問題を解決する主な方法はKVストア・構成管理ツール・設定ファイルへのシンボリックリンクである。

#### 感想

デプロイアーティファクトをRPMを使って作成するという方法は考えたことがありませんでした。
1つのコマンドにデプロイプロセスを全て含めることができることの恩恵は大きそうです。

### 9章 ~ 12章

9章以降は組織文化や採用がテーマでした。現時点ではあまり関心のないテーマなので割愛します。

[^1]: 「システム運用アンチパターン」 P.4
[^2]: アプリケーションコードをデプロイ可能な1つのファイルにまとめたもの