
SRE偽聖典――ハロウィンの夜、32節を表示するために神を依存性注入した無駄なもの博物館・本館 第二収蔵企画
こんにちは黒パグです🐾
このお話はハロウィン🎃👻のお話ですが言っていることはエンジニア小話です。
初めて触れる方には難しい内容になっていますが、こんな世界もあるんだなと思いながらイラストをお楽しみください。
一部のサイト信頼性エンジニア向けホラーです。
はい。スキの数よりニッチなネタです。
詳細は↓ クリックして遊びにきてね
God exists. Access denied.
神は存在する。しかし権限がない。
ハロウィンの夜に読むなら、ずいぶん都合のいい聖典である。神はいる。話もできる。なのに最後は403で追い返される。
お菓子をもらいに行った先で、入館権限を求められるとは思わなかった。
今夜の案内役
銀白のツインテールに黒い魔女帽子。王冠の飾りと、いつもの気品。足元だけはピンクのスリッパ。
幕島様に、無駄なもの博物館の案内をお願いした。 黒パグの記事にはよく出てきているのでお見知りおきください。
自然哲学や叙事詩、聖典のような文体でSREの格言を並べたら、山は常にデプロイされ、川は持続的にDBを削り、人間は抽象化の塔の中でトイレを見失った。
幽霊に会う前に、トイレの場所を教えてくれ。
展示するのは『SRE偽聖典――我がコンテキストはあふるるなり』。英題はThe Book of Eternal Incidents。全8章と終章、32節の英日対訳がある。
幕島様の衣装も、カボチャも、記事と挿絵のために用意した。Python原本には手を入れていない。

printすればよい
その32節を、Pythonで表示する。
printすればよい。
そこで、全面リファクタリングした。
いや、そこで、じゃないんだよ。
原本は694行。例外型やデータモデルも含め、クラス定義は29個ある。正典をJSONへ分離し、スキーマを検証して、ドメインモデルへ変換する。出力にはSink、翻訳にはTranslationService、容量の見積もりにはCapacityPlanner。
そして神にも、専用のDIコンテナを用意した。
神を直接newするのは、何となく設計が悪そうだからである。
ここまで来ると、神を呼ぶ前に、保守担当者を呼んだほうが早い。

名前を変えたら、神がいない
神はDIコンテナに登録しておく。実際にそこから解決するのは終章だが、その前にもGodという名前は出てくる。
第27節では、Wordという変数を用意したあと、Godを参照してNameErrorが起きる。用意した名前と、参照する名前が合っていない。
降霊の失敗かと思ったら、変数名の問題だった。
創世記における名前変更の影響は、呼び出し元で捕捉される。神が見つからないまま、処理は先へ進む。
なお、4枚目のスライドにあるC#のコードはDIのイメージを示す例で、Python原本の抜粋ではない。第27節の名前参照と、終章でのGodの解決も、別の場面である。

キャッシュ箱に、お菓子を入れる
英語から日本語への翻訳はTranslationServiceが担当する。和訳は、最初からVerseに入っている。
サービスはキャッシュを確認し、なければ和訳を取得して保存する。ところがUnexaminedCacheは、保存した直後に中身を全部消す。
お菓子を入れる。
ふたを閉める。
空になる。
幕島様、困り顔で「お菓子返して?」。
「吟味されざるキャッシュは、保持するに値しない」という第16節を、そのまま実装した結果である。
元の実行記録では、キャッシュミスは33回。正典は32節だが、第31節だけ二回出すので、翻訳も一回増える。保存した和訳が残らないため、その追加分もミスになる。
キャッシュ箱に入れた途端、次の訪問に備えるものがなくなる。ハロウィンの菓子入れとしても、なかなか厳しい仕様だ。

テーブルが来るまで、皿を持って待つ
第23節では、SQLiteに本当にCREATE TABLEを発行する。
Thou preparest a table before me in the presence of mine errors.
汝、わがエラーの前にテーブルを備えたもう。
ありがたい。宴の席には机が要る。
ただし第10節は、そのテーブルへすでにSELECTしている。第15節もEXPLAIN QUERY PLANを発行している。まだ存在しないテーブルを相手にするので、どちらもエラーになる。
第10節で着席しようとしたら、机が届くのは13節後だった。
例外は捕捉され、メトリクスに数えられる。机を早く届ける修正は入らない。そこを直すと、普通に文章を表示するプログラムへ近づいてしまう。
DBはメモリ内SQLiteで、外部サーバーには接続しない。第24節のNo healthy upstreamも、健康でない二つの候補から選ぼうとして発生させた例外だ。
お化け屋敷の裏方まで、本物の障害に付き合う必要はない。

お菓子をくれなきゃ、リトライするぞ
第12節には、朝までのリトライがある。
玄関へ来た魔女が、一度で帰らない。
「お菓子をくれなきゃ、リトライするぞ」
そのいたずら、運用側に効くやつだ。
時計は仮想のものを使う。一回ごとに60秒を進め、朝6時になるまで繰り返す。元の実行記録では222回。
実際に朝まで待つことはなく、処理はすぐ終わる。居座る気迫だけはあるが、夜のほうを早送りした。

当番は起こさず、記録は捨てる
第25節のPagerDutyも、外へ通知しているわけではない。EventBusを通してObserverを呼び、メモリ内のカウンタを増やす。DBにはSEV1を一行記録する。
ハロウィンの仮装で、本物の当番を起こしたら、朝までのリトライでは済まなくなる。
別に、FridayDeployGuardMiddlewareという門番もいる。金曜18時以降の変更で危険を受容した人を記録するが、実行は止めない。
入場者の名前は控える。門は開いている。
この記録は、後で神へ承認を説明する際に効いてくる。だがメトリクスの行き先は別だ。終了時にJSONへ変換し、/dev/nullへ保存する。
幽霊が持っていったように見えるが、捨てたのは自分である。
8枚目のスライドでは門番と通知の仕組みが一緒に描かれている。原本では、金曜の変更を記録する処理と、第25節でObserverを呼ぶ処理は分けて読む。

その承認印、誰のですか
終章になって、DIコンテナからGodを初めて解決する。
神は問う。
「汝、なぜ本番環境にデプロイしたのか」
「承認を得ております」
「誰が承認したのか」
「あなたです」
自分で押した印鑑を、自分で問い詰めている。
承認者と審判者は同じオブジェクト。ここでBlameShiftingErrorが発生し、HTTP 403 Forbiddenという文字列へ変換される。
HTTPサーバーは立っていない。神の認可APIへ問い合わせてもいない。このやり取りとエラーを、画面へ表示している。
挿絵の神は、カボチャの頭と後光を持つ監査役にした。原本のGodに顔はないが、「誰が承認した?」の場面には、妙によく似合った。

あとがきの席がない
CapacityPlannerの見積もり方を、ここで見ておく。
聖典を最初から最後まで、一度黙って実行する。その結果から本文に必要な量を決め、二度目に画面へ出す。お化け屋敷の下見を、全行程で済ませている。
見積もれたのなら、少し余裕を持たせればいい。ところが安全係数は1.0。本文が収まる量だけ、ぴったり確保する。
本文が終わり、Amen.を出力した時点で、論理的な容量は4,178に到達する。
この数は、Pythonの文字列長に改行分を加えたものだ。LLMのトークン数でも、RAMの消費量でもない。
次にAfterwordServiceが「あとがき」を出そうとする。四文字と改行で五つ必要だが、空きはゼロ。出力前にContextOverflowが起きる。
Process exited with code 137
OOMKilled
幕島様が「RAMは空いてる!」と抗議する。空いている。作品が自分で決めた出力容量に、あとがきが入らなかった。
実際のOOMは起きていない。原本はsys.exit(137)を呼んで終了する。関数名は_kernel_oom_killだが、SIGKILLを送る処理はない。名前の仮装だけは本格的だ。
終了時にはatexitも働き、メトリクスを捨てたあとで「――終――」が出る。
あとがきは書けなかったが、終わりの挨拶はできた。

一節、おかわり
Ask, and it shall be given unto you. Retry, and it shall be given unto you twice.
求めよ、さらば与えられん。リトライせよ、さらば二重に与えられん。
第31節は、本当に二度出力する。
ただし失敗を見つけて再試行するのではなく、設定に従って二回呼ぶ。同じ家で、二度お菓子をもらう作戦である。
先ほどのキャッシュミス33回のうち、余分な一回はここに対応する。キャッシュは次の呼び出しまで和訳を持っていない。
閲覧用の聖典には32節を各一回収めた。実行ログでは第31節だけ二回。正典に同じ節が二つあるわけではない。

魔法陣の真ん中に、print
スライドの魔法陣を見ると、真ん中に小さなprintがある。その周囲を、検証、モデル、依存性注入、容量計画といった仕組みが囲んでいる。
キャッシュにも役割がある。例外にも型がある。責務は分かれている。
ただ、やりたいことは、32節を表示することだった。
ハロウィンの飾り付けを始めて、幽霊の受付、魔女の入館証、カボチャの責務分離まで用意してしまった感じがする。飾りを付ける場所より、規約を置く場所のほうが広い。
この作品では、仕組みを増やした結果として起きることも、そのまま展示に含めた。テーブルが遅れて来るのも、保存した和訳が残らないのも、あとがきが入らないのも。

原本は、仮装させない
無駄なもの博物館へ収蔵するにあたり、原本のバイト列は保護し、SHA-256を記録した。解説と展示は別の派生物として作った。
キャッシュを直す、二回の出力を一回にする、あとがき用の余白を足す。どれも、今回は行っていない。
今回の魔女帽子は、原本の外側に置いた。
Web展示は記録からの再生で、Pythonをサーバー上や閲覧者の端末で実行するものではない。容量メーターと終幕パネルは展示演出、標準出力欄は検証で取得した文字列を原本の順に出す部分である。
制作時の確認内容には、原本SHA-256、Python構文、制限付き別プロセス実行、32節の連番と英日対応、第31節だけの二重出力がある。計測あり・なしの標準出力も、バイト単位で一致したと記録している。
実ブラウザの操作、実機のモバイル表示、ブラウザコンソールの確認はUNKNOWNのまま。CSSの画面幅対応やJavaScriptの検査で、その欄を埋めたことにはしない。今回の本文改稿で、実行試験をやり直したわけでもない。

参考資料
Python公式ドキュメント:sys.exit、atexit、sqlite3、subprocessのreturncode。
https://docs.python.org/3.12/library/sys.html#sys.exit
https://docs.python.org/3.12/library/atexit.html
https://docs.python.org/3.12/library/sqlite3.html
https://docs.python.org/3.12/library/subprocess.html#subprocess.CompletedProcess.returncode
閉館
幕島様が、閉じた聖典に顔を伏せている。銀白の髪が机へ流れ、魔女帽子が少し傾いた。
横から小さな幽霊が、キャンディを一つ差し出す。
神へ提出する書類はもうない。あとがきの受付も終わった。
せめてこのキャンディだけは、キャッシュに入れずに持って帰ってほしい。

#SRE #Python #プログラミング #ハロウィン #無駄なもの博物館 #SRE偽聖典 #依存性注入 #技術ネタ #LLM48 #幕島翔子
おまけ
イラスト集





