re:annkara

日々学んだことを書き留めておく。

ISUCON9 振り返り

go言語を初めて一月ほどのコンビで初のISUCONに参加してきました。
自分がインフラ周りを担当して、もう一人がアプリ担当という役割分担でしたが最終的に342位でフィニッシュでした。

やったこと

  • サーバの複数台構成
    nginx&web(1台) + MySQL(1台) の2台構成という中途半場な形ではあるものの、複数台構成を手間取らず実装できたのは良かった。
    本当は、nginx(1台) + web(1台) + MySQL(1台) というそれぞれ専用サーバとして稼働させることを試してみたのだけど、403 {"error":"IP address is not allowed"}というエラーが発生し、時間をかけても解消できなかったので、2台構成に戻してしまった。
    discord の感想戦見てると、同じような現象が発生している人もいたんだけど、あれは何がいけなかったんだろう。。。

  • netdata/alp の導入
    サーバメトリクスの収集として、ぶっつけで netdata をインストールしてリソースの可視化を行っていた。
    また、nginx のログフォーマットを TSLV に変えて、alp で解析できるようにしていた。
    このおかげで最初はDBサーバのCPUリソースがかなり消費されているなというのが把握できたし、エンドポイント毎の応答時間なども把握できた。
    ただ把握できただけで、アプリケーションの修正に繋げられなかったのが悔やまれる。。。

  • nginx の設定変更 gzip 圧縮の有効化や、HTTP2の設定を入れてみた。
    正直効果あったかといわれると、たぶんない気がするし、HTTP2の設定を有効にすると画像ファイルの取得に404が返ってきてしまったので速攻で戻した。

やりたかったこと

  • デプロイフローの整理
    ビルド&デプロイをすべて手動でやってしまってたので、無駄な時間が発生していたと思う。
    ここらへんは完全に準備不足。

  • マニュアルの理解
    アプリケーションの特性だったり、スコアの算出方法だったりをちゃんと把握すべきだったと思う。
    キャンペーンの仕組みや、外部APIの存在などさっと把握したくらいだったので、それがスコアにどのように影響するかちゃんと理解しておくべきだった。

  • アプリケーションの修正
    N+1 問題の解消は最低限しておきたかった。
    この辺は経験値が不足している。

  • DBにインデックス貼る
    /initialize にアクセスのたびに、DBの初期化が走っていたので、スクリプトを直してインデックスを貼るなどをちゃんとしておきたかった。。。

まとめ

反省する点は他にもたくさんあるけど、とにかく参加して良かったし、非常に楽しかったです。
ISUCON での悔しさは、ISUCONでしか返せないので、来年はレベルアップしてリベンジしてやりたいと思います。

kubectl plugin マネージャの krew を Windows 10 で利用するときの注意点

kubectl plugin 機構について前回のブログにまとめていた際に、プラグインマネージャである krew について触れてなかった。

なので触ってみようと思って、インストールしてみたらちょっとハマったところがあったので、krew のことをざっくりと触れつつまとめおきたいと思う。

reannkara.hatenablog.com

krew とは

kubectl plugin を管理するプラグインマネージャのことで、kubectl plugin 機構を利用して Go で実装されている。

GitHub - kubernetes-sigs/krew: 📦 Package manager for kubectl plugins

kubectl krew help で実行可能なコマンドを見てみると、プラグインの検索やインストール、削除、krew でインストールされたプラグインの一覧などを見ることができ一通りの操作がサポートされている。

$ kubectl krew help
krew is the kubectl plugin manager.
You can invoke krew through kubectl: "kubectl krew [command]..."

Usage:
  krew [command]

Available Commands:
  help        Help about any command
  info        Show information about a kubectl plugin
  install     Install kubectl plugins
  list        List installed plugins
  remove      Uninstall plugins
  search      Discover kubectl plugins
  update      Update the local copy of the plugin index
  upgrade     Upgrade installed plugins to newer versions
  version     Show krew version and diagnostics

Flags:
  -h, --help      help for krew
  -v, --v Level   log level for V logs

Use "krew [command] --help" for more information about a command.

ハマったところ

krew をインストールするときに Windows の開発者モードを有効にしておくか、管理者権限でインストールコマンドを実行しないと以下のようなエラーが発生する。

$ ./krew-windows_amd64.exe install --manifest=./krew.yaml --archive=./krew.zip
Installing plugin: krew
...
A required privilege is not held by the client.
F0811 16:39:00.732515   23444 root.go:52] failed to install some plugins: [krew]

これは krew 自体の問題というよりは、Windows が開発者モードを有効にしていないと、管理者権限を持たないユーザにシンボリックリンクを作成させないという仕様のためらしい。

具体的には以下の issue で golang/go で議論されていた。

どうやら Windows 10 Creators Update で非管理者権限でもシンボリックリンクを作成できるようになったことに合わせて、Go の方でも対応を入れようという話だったらしい。

話の本旨からはそれてしまうけど、issue を眺めていると、今まで動いてなかったものがいきなり動いてしまい当時の仕様を変更してしまうことへの懸念だったり、セキュリティへのリスクなどいろいろと議論されていて、非常に興味深かった。

結局は、Go はマルチプラットフォームをサポートを目指す言語であり、Windows だけ挙動が異なるのを避けたい思いだったり、別のissueをあげて、この変更の影響に比べたら取るに足らないことだよみたいなことを言ってたりして、マージされていた。

github.com

krew のインストーラとしては以下の箇所で os.Symlink関数 が利用されている。

krew 自体をインストールするときだけではなくて、他のプラグインをインストールするときにもこの実装が利用されるので、プラグインをインストールするときには管理者権限で実行するか、開発者モードを有効にしないといけない。

github.com

まとめ

kubectl plugin や krew も最近出てきたものなので色々と改善する余地があるものの、自分で機能を拡張できたりするのは非常に面白いし自分も何かしらの形で貢献していきたい。

参考リンク

時間があるときに読んでおきたい。 blogs.windows.com

Windows API
SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE というフラグを Go の方でデフォルトで有効にした。
docs.microsoft.com

たまたま見つけた、Windows 向けの低レベルなAPI を提供する準標準ライブラリなのかな?? godoc.org

redis-cli を弄って単一の Redis クラスターを構築する

ほとんどないとは思うが*1、シングル構成のRedisクラスタが欲しくなった際に、以下のようにコマンドを実行してもエラーが発生する。

annkara@annkara:~/src/redis-5.0.5/src$ ./redis-cli --cluster create 127.0.0.1:6379
[ERR] Wrong number of arguments for specified --cluster sub command

どうやら、redis-cli コマンド内で引数のチェックをしているようなので、チェックを回避するようにして単一マスターノードのクラスタが構築できるか試してみる。

対象の Redis のバージョンは 5.0.5 を利用しており、ソースコードは公式サイトからダウンロードしてきている。

redis.io

とりあえず、エラーメッセージを出力している個所を探してみる。

2050 static clusterManagerCommandProc *validateClusterManagerCommand(void) {
2051     int i, commands_count = sizeof(clusterManagerCommands) /
2052                             sizeof(clusterManagerCommandDef);
2053     clusterManagerCommandProc *proc = NULL;
2054     char *cmdname = config.cluster_manager_command.name;
2055     int argc = config.cluster_manager_command.argc;
2056     for (i = 0; i < commands_count; i++) {
2057         clusterManagerCommandDef cmddef = clusterManagerCommands[i];
2058         if (!strcmp(cmddef.name, cmdname)) {
2059             if ((cmddef.arity > 0 && argc != cmddef.arity) ||
2060                 (cmddef.arity < 0 && argc < (cmddef.arity * -1))) {
2061                 fprintf(stderr, "[ERR] Wrong number of arguments for "
2062                                 "specified --cluster sub command\n");
2063                 return NULL;
2064             }
2065             proc = cmddef.proc;
2066         }
2067     }
2068     if (!proc) fprintf(stderr, "Unknown --cluster subcommand\n");
2069     return proc;
2070 }

2059行目か2060行目のチェックに該当してエラーメッセージが出力されていそう。
チェック処理についてもう少し理解を深めるために、clusterManagerCommandDef型を見てみる。

2006 typedef struct clusterManagerCommandDef {
2007     char *name;
2008     clusterManagerCommandProc *proc;
2009     int arity;
2010     char *args;
2011     char *options;
2012 } clusterManagerCommandDef;
2013
2014 clusterManagerCommandDef clusterManagerCommands[] = {
2015     {"create", clusterManagerCommandCreate, -2, "host1:port1 ... hostN:portN",
2016      "replicas <arg>"},
2017     {"check", clusterManagerCommandCheck, -1, "host:port",
2018      "search-multiple-owners"},
2019     {"info", clusterManagerCommandInfo, -1, "host:port", NULL},
2020     {"fix", clusterManagerCommandFix, -1, "host:port",
2021      "search-multiple-owners"},
2022     {"reshard", clusterManagerCommandReshard, -1, "host:port",
2023      "from <arg>,to <arg>,slots <arg>,yes,timeout <arg>,pipeline <arg>,"
2024      "replace"},
2025     {"rebalance", clusterManagerCommandRebalance, -1, "host:port",
2026      "weight <node1=w1...nodeN=wN>,use-empty-masters,"
2027      "timeout <arg>,simulate,pipeline <arg>,threshold <arg>,replace"},
2028     {"add-node", clusterManagerCommandAddNode, 2,
2029      "new_host:new_port existing_host:existing_port", "slave,master-id <arg>"},
2030     {"del-node", clusterManagerCommandDeleteNode, 2, "host:port node_id",NULL},
2031     {"call", clusterManagerCommandCall, -2,
2032         "host:port command arg arg .. arg", NULL},
2033     {"set-timeout", clusterManagerCommandSetTimeout, 2,
2034      "host:port milliseconds", NULL},
2035     {"import", clusterManagerCommandImport, 1, "host:port",
2036      "from <arg>,copy,replace"},
2037     {"help", clusterManagerCommandHelp, 0, NULL, NULL}
2038 };

clusterManagerCommandDef は構造体で、2014行目で定義されている clusterManagerCommands 配列を見てみると、Redis クラスタを操作するコマンド名や関数ポインタ、引数の数などを保持するための構造体であることがわかる。

arity という英単語を初めて見たのだけど、関数が受け取る引数の数の事を言うらしい。今回は create コマンドなので、-2 となっている。
改めて条件文にもどってみると、2060行目のチェック処理に該当することがわかる。 つまり、Redis クラスタを構成する際には、3台以上のノードの IP:PORT 番号が必要となる。クラスタと言っているので当たり前といえば当たり前だが。。。

## redis-cli --cluster create 127.0.0.1:6379 のコマンドを実行するとき
## cmddef.arity = -2
## argc = 1 (create コマンドに渡される引数の数)2055行目の int argc = config.cluster_manager_command.argc の値
2059 if ((cmddef.arity > 0 && argc != cmddef.arity) ||
2060     (cmddef.arity < 0 && argc < (cmddef.arity * -1))) {

なので、1ノードの設定でも通せるように修正し、もう一度コンパイルして、コマンドを実行してみる。

annkara@annkara:~/src/redis-5.0.5/src$ ./redis-cli --cluster create 127.0.0.1:6379
*** ERROR: Invalid configuration for cluster creation.
*** Redis Cluster requires at least 3 master nodes.
*** This is not possible with 1 nodes and 0 replicas per node.
*** At least 3 nodes are required.

Redis クラスタは最低3台のマスターノードが必要だと至極まっとうなエラーが返される。
どうやら他にもチェックをしている個所があるらしい。。。

4578 /* Cluster Manager Commands */
4579
4580 static int clusterManagerCommandCreate(int argc, char **argv) {

        /* 省略 */

4628     if (masters_count < 3) {
4629         clusterManagerLogErr(
4630             "*** ERROR: Invalid configuration for cluster creation.\n"
4631             "*** Redis Cluster requires at least 3 master nodes.\n"
4632             "*** This is not possible with %d nodes and %d replicas per node.",
4633             node_len, replicas);
4634         clusterManagerLogErr("\n*** At least %d nodes are required.\n",
4635                              3 * (replicas + 1));
4636         return 0;
4637     }

clusterManagerCommandCreate関数できっちりとマスターノード台数のチェックがされているのでこれも回避する。

リトライするととりあえず成功する。

annkara@annkara:~/src/redis-5.0.5/src$ ./redis-cli --cluster create 127.0.0.1:6379
>>> Performing hash slots allocation on 1 nodes...
Master[0] -> Slots 0 - 16383
M: c4ba607158e6288e4a07e19f748dc210be0cd1fc 127.0.0.1:6379
   slots:[0-16383] (16384 slots) master
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join

>>> Performing Cluster Check (using node 127.0.0.1:6379)
M: c4ba607158e6288e4a07e19f748dc210be0cd1fc 127.0.0.1:6379
   slots:[0-16383] (16384 slots) master
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

値の設定・取得くらいの簡単な確認しかしてないけど、とりあえず単一マスターのRedisクラスタを構築することができた。

結局自分の環境では3台のマスターノードを準備して、クラスタ構成を構築したので実際には運用してないけど、とりあえずのメモ書きとして残しておく。

*1:私の場合はRedisクライアントがRedisクラスタしか対応しておらず、かつ検証環境でもとりあえず稼働するRedisクラスタがあればよいという状況だった。

kubectl plugin 機能を利用してkubectl コマンドを拡張する

最近 kubectl コマンドを拡張したいと思い、調べてみたら kubectl plugin 機構で機能拡張できることを知ったので、公式ドキュメントをベースにまとめておこうと思う。

kubectl plugin 機構とは

kubectl v1.12 以上のバージョンで使用できる、kubectl のサブコマンドを自前で実装できる plugin 機構のこと。

実行可能ファイル(シェルスクリプトやbatファイル、goで実装したバイナリなど)を PATH 上に配置し、kubectl-SUBCOMMANDというようなファイル名にすれば、kubectl SUBCOMMAND を実行した際に、kubectl が PATH上を検索し実行するような仕組みとなっている。

現状、v1.15 がリリースされており、機能としても stable となっているが、windwos で実行すると現状以下のエラーが返ってくる。

$ kubectl.exe version
Client Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.0", GitCommit:"e8462b5b5dc2584fdcd18e6bcfe9f1e4d970a529", GitTreeState:"clean", BuildDate:"2019-06-19T16:40:16Z", GoVersion:"go1.12.5", Compiler:"gc", Platform:"windows/amd64"}

$ cat kubectl-echo.bat
echo "HELLO"

$ kubectl.exe echo
not supported by windows

v1.15 のバージョンにおいてはどうやら Windows 向けの実装が入っていなかったが、このプルリクエストがすでにマージされているので、次のバージョンでは利用できそう。

Replace syscall.Execve with exec.Command. by sawlanipradeep · Pull Request #76227 · kubernetes/kubernetes · GitHub

リンク先から入手できる v1.16 のアルファ版リリースを試してみると、実行できているのできっと大丈夫なはず。

kubernetes/CHANGELOG-1.16.md at master · kubernetes/kubernetes · GitHub

$ kubectl-1.16.exe echo

"HELLO"

制約事項

kubectl に既に存在するコマンドをオーバライドすることはできないため、kubectl-version といったコマンドを実装しても、実装したプラグインは実行されず、もともと存在するコマンドが実行される。

$ cat kubectl-version.bat
echo "kubectl version"

$ kubectl-1.16.exe version
Client Version: version.Info{Major:"1", Minor:"16+", GitVersion:"v1.16.0-alpha.1", GitCommit:"704790e0412842e782904f1c2e7123112a9aab2c", GitTreeState:"clean", BuildDate:"2019-07-17T01:06:25Z", GoVersion:"go1.12.7", Compiler:"gc", Platform:"windows/amd64"}

なので、例えば kubectl-create-foo みたいなコマンドを実装し、kubectl create foo というように実行しても、自前で実装したコマンドは実行されない。

実装方法

上述の通り、スクリプトやbatファイル、実行バイナリなどを実装し、実行権限を付与し、PATH上に配置すればあとは kubectl がよしなにしてくれる。

kubectl の実装上、環境変数は kubectl 実行時の環境変数を引き継いでくれるし、パラメータもスクリプト実行時のように渡すことができる。
この編の仕組みは、上で貼ったプルリクエストのリンクを参照すると理解できるかもしれない。

時間があれば自分でもまとめておきたいと思う。

サブコマンドの検索ルール

サブコマンドの検索は最長一致で検索するようになっている。

つまり、実行コマンドが kubectl foo bar baz arg1 --flag=value arg2 だった場合には、kubectl-foo-bar-baz-arg1 という実行可能ファイルを検索し、--flag=value arg2 というパラメータは、kubectl-foo-bar-baz-arg1 にそのまま渡される。

仮に kubectl-foo-bar-baz-arg1 という実行可能ファイルが PATH 上から見つからなかった場合には、kubectl-foo-bar-baz という実行可能ファイルを検索し、arg1 --flag=value arg2というパラメータがサブコマンドに引き渡される。

最終的にサブコマンドが見つからない場合には、通常の kubectl コマンドのエラーが表示される。

ちなみに、すでにインストールされているプラグインを表示するには kubectl plugin list を実行する。
自前で実装したプラグインも、PATH 上に配置されていれば表示される。

sub-command

サブコマンド名に - を利用したい場合には、実行可能ファイル名に _ を利用する。

kubectl foo-bar を実行する際には、ファイル名は kubectl-foo_bar とすればよい。
また、kubectl foo_bar を実行しても、kubectl-foo_bar が実行される。

今のところ、これができることの良さがあまり実感できていない。

実行ファイル名被り

同一名の実行ファイルが別々の PATH 上のディレクトリに配置されている際には、常に最初に見つかったサブコマンドが実行される。
これは kubectl plugin list を実行すれば、そのような警告が表示されるため気づくことができる。

PATHを変更すればよいが、実際にはあまり気にしたくないと思うので名前が被らないようにするのが良いかと思う。

もう少しややこしい問題として、kubectl-foo-barkubectl-foo-bar-baz といった実行ファイルが同一ディレクトリ上に配置されていた場合がある。

kubectl foo bar の場合は kubectl-foo-bar
kubectl foo bar baz の場合は kubectl-foo-bar-baz が実行されることになる。

ややこしいので、あまり自分で実装することはなさそうな気がしている。

k8s.io/cli-runtime パッケージ

今まで見てきたように、kubectl plugin 機構を利用すれば、シェルスクリプトやbatファイルを利用してプラグインを拡張することができる。

ただ、その場合にはパラメータは単純にスクリプトに渡されるだけなので、パラメータの解析などは自前で行う必要があるし、kubectl コマンドをラップするだけになってしまう。

もう少し機能効いた拡張機能を実装したい場合には、kubectl の実装にも利用されている k8s/cli-runtime を利用して Go言語で実装すると良い。ただ、サンプルの実装がGitHubにあるとは言え、ちょっとハードルが高いなと感じてしまったので、簡単なものを作ってみたら再度まとめておきたいと思う。

参考

公式ドキュメント kubernetes.io

今年のKubeCon/CloudNativeConでkubectl plugin についての講演があったので載せておく。 www.youtube.com

krewというプラグインマネージャの話とか記述されたりしています。 qiita.com

低レイヤープログラミング

@dekokunさんや@DQNEOさんに触発されて、低レイヤのプログラミングに興味が湧いてきている。

dekotech.dekokun.info qiita.com

最初は9ccの写経をしていたのだけど、途中からTCP/IPの理解を深めたいなと思って積読していたソースコードで体感するネットワークの仕組み ~手を動かしながら基礎からTCP/IPの実装までがわかるを写経し始めて、やっと第二章まで終えた。

この本の面白いところは、ネットワークのL2レイヤ(イーサネットフレーム)のデータの送受信から自前で実装するという点で、普段ならカーネルがやってくれている部分を実装を通じて理解することができる点だと思う。

第二章が終わった段階では、ホスト上のNICを利用しつつも仮想的なMACアドレスIPアドレスを持つ仮想ホストが実装され、ARP、ICMPなどのL3レイヤまでのプロトコルが実行できる。

イーサネットARP、IP、ICMPとネットワークの低レイヤから高レイヤにかけて段階的に実装していくと、階層化されたネットワークというものを実感できるし、高レイヤのプロトコルはヘッダ情報が複雑化する分、表現力が増すし実装も複雑になるのだなと思った。

例えば、イーサネットレイヤにおけるデータ転送できる最大サイズは1500バイト(もちろん変更できる)に対して、IPレイヤにおけるパケット最大サイズは65535バイトで、その際にはパケットのフラグメンテーションが発生して、1500バイト毎にパケットが分割されて転送されるみたいな。

TCPの実装にはまだ取り組めてないけど、TCPとなるとピア間の接続状態の管理だとか、輻輳制御だとか再送機能だとかもっとできることが増えるのでその分実装も難しくなるんじゃないかなと思っている。これはそのうちちゃんと取り組みたい。

この本自体は実装がメインでネットワークの仕組みだとか、コードの説明だとかあまり載っていないのでネットワークを初めて学ぶような人とか、C言語初心者ですみたいな人には向かない本だと思う。

かといって自分もC言語バリバリ書けるとかではなく、なんとなく読める程度であとはググればなんとなくわかるくらいなので、何冊かC言語の本読んで簡単なサンプルが書ければ大丈夫なんじゃないかと思う。ネットワークに関する知識はどうだろう。基本情報とか応用情報とかの知識があれば大丈夫な気がする。。。

環境面としてはLinuxでやった方がよい。自分はWSLを利用していたけど、コンパイルは通るけど実行はできなかった。多分、socket周りでWindowsがサポートしていないシステムコールを利用しているからだと思う。WSL2は試してないからわからない。そのうちやってみようと思う。

3か月間いろいろアウトプットさぼってきたので、これを機に定期的にブログ書いていきたいなー

【読書メモ】3月に読んだ本

3月に読んだ記憶があるのは以下の3冊。

PythonによるTCP/IPソケットプログラミング

タイトル通りでPythonを利用したソケットプログラミングの基本的な部分を説明している。本当に基本的なことだけを説明しているので、詳細を知りたい場合には別の書籍なりを参照する必要がある。

書籍じゃないけど、id:y_uukiさんの以下のブログだったり、 blog.yuuk.io

id:momijiameさんの以下のブログがよいと思う。 blog.amedama.jp

独学プログラマー Python言語の基本から仕事のやり方まで

独学でプログラマを目指す人向けの本。

前半はPythonの構文の説明で、後半はコードを書く際に必要となる周辺知識(Bash、バージョン管理、チーム開発など)やプログラマとしてキャリアを始める際のアドバイスなどが記載されている。

この本もプログラマに必要なスキルを網羅的記述しているもので、各領域の知識やスキルを深掘りしていくには別個で学んでいく必要があると思う。

Goならわかるシステムプログラミング

従来であればC言語で説明されるシステムプログラミングを、Go言語を利用して説明している。

OSが提供する機能(プロセス管理、メモリ管理、ファイルシステム、ネットワークなど)や、OSが提供するAPIをGo言語ではどのようにして利用しているかなど記述しているので、Go言語に入門した後でもう少し踏み込んで学びたい人には良いのではないかと思った。

私自身はGoで実装した経験があまりないので、もう少し実装経験を積んだら読み返したいと思った。

2月、3月と結構だらだら過ごしてしまったので、4月からもう少しアウトプット増やしていきたい。

【読書メモ】入門 監視

入門 監視 ―モダンなモニタリングのためのデザインパターン

入門 監視 ―モダンなモニタリングのためのデザインパターン

だいぶ前に一読していたので、簡単にまとめておく。

ウェブオペレーション ―サイト運用管理の実践テクニック (THEORY/IN/PRACTICE)を読んだ時に、監視とはアラート発砲をすることでモニタリングはメトリクスを収集することで異なる概念だ、みたいな記述を読んでからずっと別物だと考えていたのだけど、そうでは無いことに気づかされた。

本書から言葉を借りるとすると監視とは以下の定義となる。

監視とは、あるシステムやそのコンポーネントの振る舞いや出力を監視し、チェックし続ける行為のことである。

メトリクスやログを収集し、閾値や特定のメッセージ、メトリクスの変化などを監視し、何かエラーが発生したりこれから障害が発生しそうである場合にアラートを発砲する、こういった複合的なシステムの健全性を確認し続ける行為のことを監視というのだと本書を読んで気づくことができた。

システムの監視というと、アプリケーション開発者というよりはシステム運用者の役割であるという認識が一般的であると思われているが、監視というのは特定の誰かがやるべきことではなく、そのサービスに関わる全ての人が監視に対して責務を持つべきである。

サーバ側のシステムメトリクスに問題が無い状態であろうと、あるページが絶えずHTTPのステータスコード500を返している状態は健全な状態であるとは言えず、そういった場合にはアプリケーション開発者も監視に対して責務を負うべきなのだ。

しかし、開発側も運用側もサービスの監視に対して責務を持つとなると、縦割り組織(開発は開発チーム、運用は運用チームみたいな)だとそういった意識を持ちづらいような気がする。この解決策としてDevOpsといった考え方を取り入れることもできる気がするけど、自分の周りを見てみるとなんだか難しそうな気がする。

エンジニアのスキルというか学習意欲だとかそういったものに依存する部分が大きいと思うからだ。また、SRE(Site Reliability Engineerの方)といった役割にしても、システムの健全性・監視をSREという新しい役割に負ってもらっているという感じがするので、本書が目指すような監視像とはちょっと違う気もしている。

個人的な理想は、開発も運用も同一のサービスを提供する同一のチームで協調していくことなのかなと思っているのだけど、実際にそういった働き方をしている人から話を聞いたわけでは無いのでちょっと聞いてみたい。

本書の感想からだいぶ逸れてしまったけど、開発者だろうと運用者だろうとシステムの健全性を保つという行為自体はエンジニアであれば誰しもが意識すべきことだと思うので、是非とも一読して欲しい本です。