kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Dependabot の config.yml に「Automatic PR merging」を設定する

Dependabot を使うと「依存パッケージ」の更新を自動化できる.対応言語も幅広く,個人的には JavaScript / Ruby / Python / Docker をよく使っている.最高に便利なんだけど,例えば JavaScript などはリリース頻度が高く,すぐにプルリクエストが溜まってしまう(プルリクエスト数の制限はできる).最近は「Automatic PR merging(プルリクエスト自動マージ機能)」を使うことも多く,設定例を紹介する.

dependabot.com

Dependabot 設定画面

「Automatic PR merging」をすぐに試すなら設定画面を使う.true or false という単純な設定ではなく「ランタイム依存」「開発依存」に対してアップデートレベルを設定できる.さらに特定のパッケージをホワイトリスト形式で設定することもできる.

  • Runtime dependency PRs to merge automatically(ランタイム依存)
    • None
    • Patch updates (security only)
    • Patch updates (all)
    • Minor updates
    • All updates
  • Development dependency PRs to merge automatically(開発依存)
    • None
    • Patch updates (security only)
    • Patch updates (all)
    • Minor updates
    • All updates
  • Whitelisted dependencies to merge automatically (all versions)

参考までに設定画面を載せておく.

f:id:kakku22:20200608102430p:plain

Dependabot config files

Dependabot には「config files」の仕組みもあり,リポジトリに .dependabot/config.yml を置いておくと設定ファイルを GitHub で管理できる.設定ファイルに「Automatic PR merging」を設定する場合は automerged_updates を使う.詳しくは以下の設定項目から選べる.

  • automerged_updates
    • dependency_type
      • development
      • production
      • all
    • update_type
      • security:patch
      • semver:patch
      • semver:minor
      • in_range
      • all
    • dependency_name

dependabot.com

設定例 1 : 全てのプルリクエストを自動マージする

サンドボックス環境など,全てのプルリクエストを自動マージしても大丈夫な場合は dependency_typeupdate_typeall を設定する.今回は JavaScript を前提にする.

version: 1
update_configs:
  - package_manager: javascript
    directory: /
    update_schedule: daily
    automerged_updates:
      - match:
          dependency_type: all
          update_type: all

設定例 2 : マイナーバージョンアップまではプルリクエストを自動マージする

基本的に「メジャーバージョンアップ」だと非互換な更新を含む可能性もあるため,例えば「マイナーバージョンアップまで」ならプルリクエストを自動マージするという戦略もある.その場合は update_typesemver:minor を設定する.

version: 1
update_configs:
  - package_manager: javascript
    directory: /
    update_schedule: daily
    automerged_updates:
      - match:
          dependency_type: all
          update_type: semver:minor

設定例 3 : 特定のパッケージに限定して自動マージする

例えば axiosreact* など,特定のパッケージに限定して自動マージする場合は dependency_name にパッケージ名を設定する.ワイルドカードも使えるため,記述量を減らすこともできる.

version: 1
update_configs:
  - package_manager: javascript
    directory: /
    update_schedule: daily
    automerged_updates:
      - match:
          dependency_name: axios
      - match:
          dependency_name: react*
          update_type: semver:minor

まとめ

Dependabot「Automatic PR merging」を使うとプルリクエストを自動マージできる.今回は「config files」の設定例を紹介した.

なお,自動テストがエラーになった場合にプルリクエストが自動マージされてしまうと困る.ドキュメントに書いてある通り,自動テストを設定している場合は,ステータスを確認する仕組みになっている.実際に CircleCI を使って,一時的に自動テストがエラーになるようにしても自動マージはされなかった.Dependabot will still automatically merge this pull request if you amend it and your tests pass. というコメントもある通り,自動テストを修正すればマージされる.今回は master ブランチ側でテストを直して,プルリクエストに @dependabot rebase とコメントしたらマージされた.

Dependabot will wait until all your status checks pass before merging.

f:id:kakku22:20200604113841p:plain

Dependabot 関連記事

kakakakakku.hatenablog.com

モノリポ時代に知っておくと便利な「git sparse-checkout」

今まで使っていなかった Git コマンドを学んでいく.今回は git sparse-checkout を試す.

git-scm.com

git sparse-checkout とは?

コマンド名にある sparse「わずかな」という意味で,Git リポジトリの「一部」を取得できる.git clone --depth を使ってコミットを刈り取るのではなく,指定したディレクトリを取得する.モノリポ(モノレポ)構成のときに効果的に使える.git sparse-checkout は歴史的な変化もあり,今年になって改善されている.記事を検索すると Git 2.25 より前の git sparse-checkout を紹介した記事が多いように感じたため,今回は Git 2.26.2 を使って試した.

derrickstolee/sparse-checkout-example を使う

git sparse-checkout を試すために,そこそこ大きめな GitHub リポジトリを探していた.以下の GitHub Blog の記事を読んだところ git sparse-checkout を試す手順(Git 2.25 前提)と,サンプルリポジトリが載っていたため,今回は derrickstolee/sparse-checkout-example リポジトリ(モノリポ構成)を使うことにした.

github.blog

github.com

1. 既存リポジトリで git sparse-checkout を使う

まず,既存リポジトリ(git clone をした状態)で git sparse-checkout を使っていく.git clone をして,ファイル数をカウントすると 1585個 となる.ディレクトリ構成は GitHub Blog に載っている画像を見ればすぐ理解できる.tree で簡単に紹介すると,以下のようにモノリポ構成(2階層)になっている.例えば client/android ディレクトリや web/browser ディレクトリなど.

$ git clone git@github.com:derrickstolee/sparse-checkout-example.git
Cloning into 'sparse-checkout-example'...
remote: Enumerating objects: 21, done.
remote: Counting objects: 100% (21/21), done.
remote: Compressing objects: 100% (19/19), done.
remote: Total 1901 (delta 2), reused 11 (delta 1), pack-reused 1880
Receiving objects: 100% (1901/1901), 170.93 MiB | 2.56 MiB/s, done.
Resolving deltas: 100% (177/177), done.
Updating files: 100% (1560/1560), done.

$ cd sparse-checkout-example

$ find . -type f | wc -l
    1585

$ tree -L 2
.
├── LICENSE.md
├── README.md
├── bootstrap.sh
├── client
│   ├── README
│   ├── android
│   ├── electron
│   └── iOS
├── service
│   ├── README
│   ├── common
│   ├── identity
│   ├── items
│   └── list
└── web
    ├── README
    ├── browser
    ├── editor
    └── friends

さっそく,git sparse-checkout init --cone を実行して sparse-checkout を有効化する.--cone オプションはパターンマッチによりディレクトリ探索のパフォーマンスを改善するオプションとして付けておく.直後にファイル数をカウントすると,なんと 30個 に減っている.client/android ディレクトリや web/browser ディレクトリも除外されている.設定は .git/info/sparse-checkout ファイルにあり,意味としては「作業ディレクトリをルートにあるファイルに制限する」となる.

$ git sparse-checkout init --cone
 
$ find . -type f | wc -l
      30

$ tree -L 2
.
├── LICENSE.md
├── README.md
└── bootstrap.sh

$ cat .git/info/sparse-checkout
/*
!/*/

今のままだと重要なコードも除外されているため,例えば「Android アプリを開発するチーム」の場合は,git sparse-checkout set client/android を実行して,ディレクトリを設定できる.実際にファイル数は 56個 になり,client/android ディレクトリを参照できるようになる.

$ git sparse-checkout set client/android

$ find . -type f | wc -l
      56

$ tree -L 2
.
├── LICENSE.md
├── README.md
├── bootstrap.sh
└── client
    ├── README
    └── android

$ cat .git/info/sparse-checkout
/*
!/*/
/client/
!/client/*/
/client/android/

次に「フロントエンドを開発するチーム」の場合は,git sparse-checkout set service web/browser を実行する.すると service ディレクトリと web/browser ディレクトリを参照できるようになる.set は上書きする仕様になっているため,既に client/android ディレクトリは参照できなくなっている.さらに .git/info/sparse-checkout ファイルを見なくても git sparse-checkout list を使えばディレクトリを確認できる.

$ git sparse-checkout set service web/browser

$ find . -type f | wc -l
     636

$ tree -L 2
.
├── LICENSE.md
├── README.md
├── bootstrap.sh
├── service
│   ├── README
│   ├── common
│   ├── identity
│   ├── items
│   └── list
└── web
    ├── README
    └── browser

$ git sparse-checkout list
service
web/browser

なお,Git 2.26 から git sparse-checkout add も使えるため,ディレクトリを追加するときに毎回 git sparse-checkout set をし直していた手順をシンプルにできる.次の手順で add を使っていく.

2. git clone --filter=blob:none --no-checkout と組み合わせる

git clone をするときに --filter=blob:none オプションを付けると,オブジェクトのダウンロードをせずに clone できる(Partial Clone とも言う).さらに --no-checkout オプションを付けると,チェックアウトをせずに clone できる.新しくリポジトリを取得する場合は git clone --filter=blob:none --no-checkout と組み合わせるとオーバーヘッドを減らして,モノリポを管理できる.

$ git clone --filter=blob:none --no-checkout git@github.com:derrickstolee/sparse-checkout-example.git
Cloning into 'sparse-checkout-example'...
remote: Enumerating objects: 13, done.
remote: Counting objects: 100% (13/13), done.
remote: Compressing objects: 100% (12/12), done.
remote: Total 373 (delta 1), reused 7 (delta 1), pack-reused 360
Receiving objects: 100% (373/373), 76.78 KiB | 644.00 KiB/s, done.
Resolving deltas: 100% (18/18), done.

$ cd sparse-checkout-example

$ find . -type f | wc -l
      29

同じように git sparse-checkout init --cone を実行して sparse-checkout を有効化する.今回は add を使って client/android ディレクトリと service ディレクトリと web/browser ディレクトリを参照できるようにする.git sparse-checkout の手順は同じだけど,オブジェクトのダウンロードを後回しにできる点はメリットと言える.

$ git sparse-checkout init --cone

$ git sparse-checkout add client/android

$ git sparse-checkout add service web/browser

$ find . -type f | wc -l
     667

$ tree -L 2
.
├── LICENSE.md
├── README.md
├── bootstrap.sh
├── client
│   ├── README
│   └── android
├── service
│   ├── README
│   ├── common
│   ├── identity
│   ├── items
│   └── list
└── web
    ├── README
    └── browser

まとめ

今まで使っていなかった Git コマンドとして,今回は git sparse-checkout を試した.モノリポ(モノレポ)構成のときに効果的に使える.もし新しくリポジトリを取得する場合は git clone --filter=blob:none --no-checkout と組み合わせるとオーバーヘッドを減らして,素早く clone できる点も覚えておくと良さそう!

Slack で /zoom コマンドを使って Zoom Meeting を作る

Slack に「Zoom App」をインストールすると /zoom コマンドを使って Zoom Meeting を簡単に作れる.Slack から「Join」ボタンを押せばすぐに Zoom Meeting に参加できるため,例えば「クイックコール」をするときなど,便利に使える.

f:id:kakku22:20200601181118p:plain

インストール

「Zoom App」は Slack の「App Directory」からインストールできる.なお,インストール後に /zoom コマンドを使うと,初回は「👉Authorize Zoom」と表示される.Zoom にログインをして権限を付与しておく.

slack.com

/zoom meeting [topic] コマンド

例えば /zoom meeting group1 のように「トピック名」を指定すると,1 Slack Channel の中に複数の Zoom Meeting を作れる.

うまく活用すると「グループディスカッション」にも使える.Zoom に「ブレイクアウトルーム機能」はあるけど,Slack を軸にすることにより,Zoom Meeting ホスト側のセッション時間を気にする必要がなく,無料アカウントで問題なく運用できるようになる.当然ながら「40分」という時間制限はあるけど,もう1度 /zoom コマンドを使って別の Zoom Meeting に参加し直せば OK!

f:id:kakku22:20200601180904p:plain

コマンド一覧

個人的に /zoom コマンドと /zoom meeting [topic] コマンド以外は使わないけど,/zoom help でコマンド一覧を確認できる.

/zoom
/zoom meeting [topic]
/zoom join [meeting id/personal link name]
/zoom join me
/zoom call [@contact/phone number]
/zoom config
/zoom logout

まとめ

Slack に「Zoom App」をインストールすると /zoom コマンドを使って Zoom Meeting を簡単に作れる.「クイックコール」をしたり「グループディスカッション」をしたり,幅広く使えるため,入れておくべし!

リモートモブプログラミングで Git Handover をシュッと実現する「mob」コマンド

「モブプログラミング」を採用すると「全員で同じタスクに取り組む (WIP 1)」ため,複雑な Git ブランチ戦略は必要なくなる.例えば master ブランチと develop ブランチだけで運用することもできる.今回紹介する mob コマンドを使うと,モブセッションで繰り返し行なう「ドライバー(タイピスト)交代」をシュッと実現できる.特に「リモートモブプログラミング」だと GitHub に git push をしてドライバーを交代する(Git Handover と言う)ため,mob コマンドを使うと便利!

mob.sh

インストール

mob コマンドは brew コマンドで簡単にインストールできる.そこそこ頻繁にリリースされているため,定期的に brew upgrade をしておくと良さそう.今回の記事を書いてる間にも v0.0.13v0.0.17 にバージョンアップしていた.

$ brew install remotemobprogramming/brew/mob
$ mob version
v0.0.13

$ brew upgrade remotemobprogramming/brew/mob
$ mob version
v0.0.17

なお mob コマンドは GitHub で OSS になっている.Go で実装されている!

github.com

mob : 基本コマンド

基本的に以下の「基本コマンド 3個」を使えば OK!簡単にワークフローを図解した(GitHub は例として).

  • mob start ... 「モブセッション」を開始する
  • mob next ... 次のドライバーに Git Handover をする
  • mob done ... 「モブセッション」を終了する

f:id:kakku22:20200531164129p:plain

1. mob start

「モブセッション」を開始するときに mob start を実行する.Git リポジトリに remote 設定をしておく必要があるため,リポジトリを clone しておく.mob start を実行すると,自動的に mob-session ブランチが作られて git push まで実行される.

(master) $ mob start
 ✓ git fetch --prune
 ✓ git pull --ff-only
 > create mob-session from master
 ✓ git checkout master
 ✓ git merge origin/master --ff-only
 ✓ git branch mob-session
 ✓ git checkout mob-session
 ✓ git push --no-verify --set-upstream origin mob-session
 > you are mob programming

(mob-session) $ 

2. mob next

開発を進めて,ドライバーを交代するときに mob next を実行する.すると,自動的に git addgit commitgit push が実行される.コミットメッセージはデフォルトだと mob next [ci-skip] となる.最後に master ブランチに切り替わる.

(mob-session) $ mob next
 ✓ git add --all
 ✓ git commit --message "mob next [ci-skip]" --no-verify
 ✓ git push --no-verify origin mob-session
 ✓ git checkout master

(master) $ 

3. mob start

ドライバーを交代したら,もう1度 mob start を実行する.すると,自動的に mob-session ブランチに切り替わり,開発を進められる.モブセッションでは,基本的に mob startmob next を繰り返す.

(master) $ mob start 10
 ✓ git fetch --prune
 ✓ git pull --ff-only
 > rejoining mob session
 ✓ git branch -D mob-session
 ✓ git checkout mob-session
 ✓ git branch --set-upstream-to=origin/mob-session mob-session
 ✓ 10 minutes timer started (finishes at approx. 11:00)
 > you are mob programming
xxxxxxx 5 minutes ago <kakakakakku>

(mob-session) $ 

なお mob start 10 のように引数 minutes を指定すると,自動的にタイマーが起動する.指定した時間が経過すると,Mac の場合は AppleScript (osascript) を使って通知されるようになっている.さらに say コマンドを使って mob next と読み上げてくれる.例えば Mobster など,モブプログラミングに特化したタイマーアプリを使うこともできるけど,mob コマンドに同梱されているのは便利だと思う.

f:id:kakku22:20200531170258p:plain

4. mob done

「モブセッション」を終了するときに mob done を実行する.挙動としては mob-session ブランチを git push をして,さらに master ブランチに git merge までしてくれる.最後に 👉 git commit -m 'describe the changes' と表示されている通り,最終的な git commit はドライバーが行なう.個人的に使うなら mob done は使わずにプルリクエストを作る運用にするかなぁー.

(mob-session) $ mob done
 ✓ git fetch origin --prune
 ✓ git add --all
 ✓ git commit --message "mob next [ci-skip]" --no-verify
 ✓ git push --no-verify origin mob-session
 ✓ git checkout master
 ✓ git merge origin/master --ff-only
 ✓ git merge --squash --ff mob-session
 ✓ git branch -D mob-session
 ✓ git push --no-verify origin --delete mob-session
 👉 git commit -m 'describe the changes'
 
 (master) $ git commit -m'Well done 👍'

 (master) $ git push

Tips 1 : 環境変数を使う

mob config を実行すると,mob コマンドの挙動を決めている環境変数の値を確認できる.

$ mob config
MOB_BASE_BRANCH=master
MOB_WIP_BRANCH=mob-session
MOB_REMOTE_NAME=origin
MOB_WIP_COMMIT_MESSAGE=mob next [ci-skip]
MOB_VOICE_COMMAND=say
MOB_NEXT_STAY=false
MOB_START_INCLUDE_UNCOMMITTED_CHANGES=false
MOB_DEBUG=false

export で上書きできるため,例えば MOB_WIP_BRANCH を設定すれば mob-session 以外のブランチ名も使える.MOB_WIP_COMMIT_MESSAGE を設定すれば mob next [ci-skip] 以外のコミットメッセージも使える. direnv などを使って全員同じ環境変数を export できるようにしておくと良さそう.

$ export MOB_WIP_BRANCH=wip
$ export MOB_WIP_COMMIT_MESSAGE=mob next

(master) $ mob start
overriding MOB_WIP_BRANCH=wip
overriding MOB_WIP_COMMIT_MESSAGE=mob
 ✓ git fetch --prune
 ✓ git pull --ff-only
 > create wip from master
 ✓ git checkout master
 ✓ git merge origin/master --ff-only
 ✓ git branch wip
 ✓ git checkout wip
 ✓ git push --no-verify --set-upstream origin wip
 > you are mob programming

(wip) $ 

Tips 2 : Zoom で画面共有をする

mob share もしくは mob start 10 share のように share を付けると,Zoom で画面共有を設定するダイアログを表示できる.

$ mob share
$ mob start 10 share

f:id:kakku22:20200531172248p:plain

なお share を使う場合は Zoom で「画面共有を開始/停止 (Shift + Command + S)」「グローバルショートカット」を有効化しておく.

f:id:kakku22:20200531172445p:plain

とは言え,今回使った mob コマンド v0.0.17share に対応しているけど,次にリリースされる v0.0.18 では mob share は削除されてしまう.そして mob start 10 shareDEPRECATED になり,将来的に削除されてしまう.実際に使う場面はなさそう.詳しくは GitHub の Releases を見てもらえればと!

まとめ

mob コマンドを使うと Git Handover をシュッと実現できる.特に「リモートモブプログラミング」をするときに便利!

関連記事

慣れた開発環境を使うことを優先し,個人的に Git Handover はリモートモブプログラミングじゃなくても使っていた.詳しくは2年前に公開した資料に載せてある.合わせて読んでもらえると良さそう!

kakakakakku.hatenablog.com

f:id:kakku22:20200531172758p:plain

オブザーバビリティ(可観測性)とは何か?を学べる「Distributed Systems Observability」を読んだ

2019年頃から「オブザーバビリティ (Observability)」もしくは「可観測性」という言葉をよく聞くようになった(本記事では「オブザーバビリティ」という表記に統一する).「マイクロサービス」と同じように「バズワード」の側面があり「オブザーバビリティとは何か?」という質問に対して様々な回答が考えられると思う.

今回は「オブザーバビリティ」の理解を深めるために「Distributed Systems Observability」を読んだ.本書は O'Reilly Media で読むこともできるけど,Humio のサイトから無料でダウンロードすることもできる(メールアドレス登録は必要).著者は Cindy Sridharan となり,肩書は「Distributed Systems Engineer」と書いてあった.

www.humio.com

目次

本書には「オブザーバビリティ」をテーマに気になるトピックが並んでいて,目次を見るだけでも惹き込まれる.日本語訳はなく,個人的に載せているため,参考程度にしてもらえればと!

  1. The Need for Observability(オブザーバビリティの必要性)
  2. Monitoring and Observability(モニタリングとオブザーバビリティ)
  3. Coding and Testing for Observability(オブザーバビリティのコーディングとテスト)
  4. The Three Pillars of Observability(オブザーバビリティの3本の柱)
  5. Conclusion(結論)

1. The Need for Observability

第1章「The Need for Observability」では,「オブザーバビリティ」という用語の整理と必要性を学べる.

まず,大前提として「人によって意味は異なる」と書かれている.例えば,オブザーバビリティを「"ログ/メトリクス/トレース" のことである」と表現する人もいれば「"新しいモニタリング" のことである」と表現する人もいる. そして,本書では「システムにより良い可視性をもたらすこと (bringing better visibility into systems)」は共通していると書かれている.

さらに,以下の項目を理解して設計された「システム特性」こそが「オブザーバビリティ」であると紹介されている.分散システムは完璧に動くことはなく,予測不可能な面もある.デバッグのしやすさは堅牢なシステムをメンテナンスしたり,進化させるために必要と言える.うまく言語化されていると感じた.

  • No complex system is ever fully healthy.
  • Distributed systems are pathologically unpredictable.
  • It’s impossible to predict the myriad states of partial failure various parts of the system might end up in.
  • Failure needs to be embraced at every phase, from system design to implementation, testing, deployment, and, finally, operation.
  • Ease of debugging is a cornerstone for the maintenance and evolution of robust systems.

第1章の最後には「オブザーバビリティは運用の課題だけではない」というトピックもある.モニタリングをしたり,SRE (Site Reliability Engineering) チームが安全にデプロイをすることも重要だけど,それだけでは「オブザーバビリティは達成できない」と書いてある.

2. Monitoring and Observability

まだまだ「オブザーバビリティ」に曖昧さを感じるため,読み進めていく.第2章「Monitoring and Observability」では,オブザーバビリティとモニタリングの関係を学べる.特に最初に載っている図がわかりやすく,参考情報として日本語にした.簡単に書くと,オブザーバビリティは「モニタリングとテストのスーパーセット」であり,モニタリングとテストでは予測できなかった障害に関する情報も提供する.

f:id:kakku22:20200523100752p:plain

次に「どんなメトリクスをアラートに活用すれば良いのか?」というトピックがあり,ザッと箇条書きにすると以下のような内容が紹介されている.個人的に「RED メソッド」は知らなかった.分類はいろいろあるけど,3種類ともシステムを継続的に運用するために必要なメトリクスが揃っていると感じた.

  • SRE 本(6章)に載っている「4大シグナル」
    • レイテンシー
    • トラフィック
    • エラー
    • サチュレーション(飽和)
  • 詳解システムパフォーマンス本に載っている「USE メソッド」
    • 使用率 (Utilization)
    • 飽和 (Saturation)
    • エラー (Errors)
  • Tom Wilkie 提唱の「RED メソッド」
    • リクエストレート (Rate)
    • リクエストエラー (Error)
    • リクエスト期間 (Duration)

また,過去に流し読みをした「SRE 本」「詳解システムパフォーマンス本」に関連しているのも技術領域(トピック)の近さを感じられた.どちらも書評記事を書いてなく,もう1度読み直してまとめないと...あああ!

詳解 システム・パフォーマンス

詳解 システム・パフォーマンス

  • 作者:Brendan Gregg
  • 発売日: 2017/02/22
  • メディア: 単行本(ソフトカバー)

3. Coding and Testing for Observability

第3章「Coding and Testing for Observability」では,「オブザーバビリティ」を実現するために「どんな観点でコーディングとテストを進めれば良いのか?」を検討する指針を学べる.

障害のための「コーディング」

まず,障害を前提に,以下の項目を意識しながらコーディングをするべきと書いてある.日本語訳は参考程度に!

  • Understanding the operational semantics of the application(アプリケーションの運用上の意味を理解する)
  • Understanding the operational characteristics of the dependencies(依存関係の運用上の特性を理解する)
  • Writing code that’s debuggable(デバッグ可能なコードを書く)

1個目「アプリケーションの運用上の意味」に関しては具体例が多く載っている.特に以下の例はアプリケーションを設計する上でとても重要だと思う.DevOps な側面もあるけど,こういった非機能な側面をコーディング時にどこまで検討できるだろう.

  • How a service is deployed and with what tooling(サービスのデプロイ戦略とツール)
  • How an application handles signals(アプリケーションがシグナルをどのように処理するか)
  • How the service is drained off connections when it’s about to exit(サービスのドレイニング)
  • How graceful (or not) the restarts are(再起動がどの程度キレイに行えるか)

3個目「デバッグ可能」の指標としては「将来的に質問ができること」と書いてあり,センスのある表現だと感じた.障害時に原因を分析するだけではなく,過去に遡って傾向を調べることもあるし,今後は「質問する」という表現を使っていく.

障害のための「テスト」

最初に名言が出てくる.個人的な訳になるけど「テストはバグが存在することは示せるけど,バグが存在しないことは示せない」という表現で,これは興味深かった.とは言え,テストにより障害を防ぐことはできるため,可能な限り「本番環境を使ったテスト」も検討するべきと書いてある.

読み進めていくと,途中に「テスト戦略」をマッピングした図が載っている.画像を引用せず,簡単に紹介すると,以下の4フェーズごとにテスト戦略がまとまっている.特に「本番環境を使ったテスト」Deploy / Release / Post-release の3フェーズとなり,ここまで幅広くテストができているアプリケーションがあったら本当にスゴイと思う.

  • Pre-production
    • Unit tests など
  • Deploy
    • Load tests など
  • Release
    • Canarying や Feature flagging など
  • Post-release
    • Chaos testing や A/B tests など

また,本番環境を使ってテストをするためには,第2章で紹介したようなメトリクスを取得し,フィードバックをする仕組みも必要だと書いてある.そして,ロールバックをするなど,異常時にすぐ中止できる仕組みも必要だと書いてある.

4. The Three Pillars of Observability

第4章「The Three Pillars of Observability」では,よく「オブザーバビリティ」の紹介として聞く「ログ/メトリクス/トレース(3本の柱)」の詳細を学べる.必ずしも「3本の柱」を揃えたからと言ってオブザーバビリティを実現したことにはならないけど,より優れたアプリケーションを構築できると書いてある.冒頭には「イベントログ」の紹介もあり,表現次第では「4本の柱」にもなりそう.

なお,New Relic のレポートを読むと「イベント」まで含めた MELT (Metrics, Events, Logs, Traces) という用語を意図的に使っている.自動販売機を例にオブザーバビリティを解説されていて,とてもわかりやすく,合わせて読むと良さそう.

blog.newrelic.co.jp

「ログ」のメリットとデメリット

ログは多くのシチュエーションで使えるし,どんなパッケージにもライブラリがあり,簡単に組み込むことができるメリットがある.逆にパフォーマンスの問題があったり,重要なログをロストする可能性などはデメリットとして挙がっている.また,ログ配信を保証するための仕組みとして RELP (Reliable Event Logging Protocol) という名前が載っている.これは気になる!

en.wikipedia.org

「メトリクス」のメリットとデメリット

メトリクスは定量的な数値から構成されるため,数学的に未来予測ができる点はメリットと言える.また一定期間を過ぎたらメトリクスの解像度を下げる(ダウンサンプリング)こともできる.Prometheus の紹介も少し載っている.ただし,基本的には「ログ」「メトリクス」「単一アプリケーションスコープ」を対象にしているというデメリットもあると書いてある.

kakakakakku.hatenablog.com

「トレース」のメリットとデメリット

複数アプリケーションに対して可視性を高めるためにトレースを活用する.リクエストごとに Unique ID を伝搬しながら実現する.ミドルウェアとしては OpenTracing に準拠した ZipkinJaeger が紹介されている.とは言え,トレースする仕組みを導入したくても,既存のインフラ全てに組み込むのは難しいという課題があり,そこで「サービスメッシュ」の紹介もある.本書は2018年に出版されたこともあり,まだ IstioEnvoy という用語は載っていなかった.今後もし改訂されるなら言及されそう.

まとめ

2019年頃から「オブザーバビリティ」関連の話題をよく聞くため,理解を深めるために「Distributed Systems Observability」を読んだ.

第4章に書いてあった通り,「オブザーバビリティ」「ログ/メトリクス/トレース」情報を揃えて活用することだと理解をしていたけど,そんなに単純なものではなく,技術的にも幅広さが求められることを学べて良かった.当然ながら DevOps とも関連する側面が多く,例えば「スプリントゼロで CI/CD パイプラインを作る」というプラクティスのように「スプリントゼロでオブザーバビリティを導入する」というプラクティスまで応用できると良さそう.

www.humio.com