ツールに全幅の信頼を置くべきか?

By 清水 孝郎 - OCTOBER 26, 2022

SHARE:

本文の内容は、2022年10月26日にMarco Bulgariniが投稿したブログ(https://sysdig.com/blog/should-you-trust-tools/)を元に日本語に翻訳・再構成した内容となっております。

私の父は、イタリアに輸入された初期のコンピュータをいくつか使って仕事をしていました。技術者といえば、現場での経験、分厚い技術マニュアルの束、そしてフル装備の道具箱の3本柱で成り立っていた時代です。マニュアルがない、交換部品がない、となると、お客様先から本社まで1日がかりの出張になることも珍しくありませんでした。

Trust tools
現在、状況は大きく変わっているように見えますが、実はそれほど大きくは変わっていません。技術マニュアルは埋め込まれていることが多いし、インターネットという小さなもので、どんな質問にも答えてくれる。そのようなリファレンスに簡単にアクセスできたとしても、経験は決して代え難いものであり、私がこの記事を書いている理由は、まさにこの「道具箱」にあります。

さて、ここで父の道具箱の話に戻ります。私は今でも、父が使っていた道具一式の一部と、格段特別でもないドライバーをいくつか持っています。しかし、いつもより硬いネジを扱うたびに、新型のマグネットチップ、ラバーグリップ、ラチェット機構を喜んで手放し、失敗のない昔のごく普通のデバイスに回帰している自分に気づきます。

一日中インフラをいじっていると、数年前までは父のような道具箱だったのが、今ではソフトウェアエンジニアのような感じになっています。私は日常的にプログラムを追加したり削除したりしていますが、今日まで、その選択が意味するところをほんの少ししか考えていませんでした。

”信じてください、私はエンジニアです” – 午後の間に本番環境を2度壊した方法

Lensの登場です。数十のKubernetesクラスターを管理するために、Lensをもう1年ちょっと使っています。リソースのスペックを深く掘り下げると同時に、リソースのステータスを素早く見て、関連するリソースに移りましょう、という鳥瞰的な視点が気に入っています。本当に速く移りましょうという気持ちにさせてくれるツールです。

いつものように、一日の始まりにElectronベースのアプリを立ち上げる。新しいアップデート?いいね、適用しよう。何事もなく一日を過ごしていたのですが、ある日突然、事件が起こりました。私はその週のオンコールエンジニアなのですが、Podがデータを処理していないというページを受け取りました。ログを見ると、Full GCで止まっています。デプロイ全体をロールバックする理由はありませんが、スケジュールを変更し、関連する開発チームにバグを報告します。ページでPod名を確認し、それを見つけて、”Delete “をクリックします。

ただし、削除されるのはPodではありません。デプロイ全体が消えてしまうのです。信じられない思いが一瞬よぎったかと思うと、今度は:

災害

 --cascade=orphan の削除であることを祈りましょう…。

…いや、違う。すべてのPodが消えました。

あーっ!

"おいおい、バックアップが必要だ、俺はしくじったんだ。"


数人の同僚の助けを借りて、私はすぐに正しいCDパイプラインを起動し、他のオンコールエンジニアと上司にアラートを発しながら、失われたマニフェストを再デプロイしました。復旧後、私はSlackで避けられない羞恥心に耐えながら、インシデントを引き起こした原因と解決するために私がしたことを詳細に説明しました。

濃いコーヒーを飲み、たくさんの罵声を浴びせ、自分の指の数とタイピングの基本能力を迅速に評価した後、私は次のページに戻りました。”Kafka topic has under min in-sync replicas.”(Kafkaトピックは最小の同期レプリカしか持っていません)。

ワーカーノードの迅速な調査で、それが健全でないことがわかったので、そのStatefulSetから新しいノードにPodを移すだけの問題だったのです。そうです、その通りです。リージョンを切り替え、クラスターを切り替え、StatefulSetに入り、Podを探し(簡単です。 NotReady と書かれた⚠️がついたものです)、”Delete “をクリックします。

“これもファットフィンガーはやめましょう。確認ダイアログの名前を確認してください。 pod/kafka-9889hnj…よし、いいぞ。

ただし、消えるのはPodじゃない。StatefulSet全体が消えるんです。

なにー?

そんなはずはない、きっとインターフェースの不具合だ…。

…いいえ すべてのPodが消えました 前と同じように

そんなことがあるのか!?

さて、これは別物であることはすぐにわかりました。デプロイを行ったり来たりして、アプリケーションやお客様がそれに気づくこともあるかもしれません。しかし、データストアがなくなれば、あちこちに波紋が広がります。

"おい、まだオンラインなの? 今度は Kafka で再び起こりました。"

状況は確実に悪化しているにもかかわらず、私は先の教訓を心に留めていました。数秒の間に(間違いなくカフェインを大量に摂取したおかげだ)、私はPRを発行して足りないマニフェストを再デプロイした。PRが適用されている間、他のオンコールエンジニアと上司に連絡を取り、すぐにインシデントを宣言する手続きを開始しました。

数分後、Kafkaは正常な状態に戻り、すべてのブローカー間で完全に同期されました。アプリケーションが安定した状態に収束するのを待つ間、私は自問自答を始めた。どうして午後の間に2回も初歩的なミスを犯してしまったのだろう?そんなに不器用なのか?

Lensの不具合を早くからチェックしていなかったのは、オンコールのせいもあるし、自分の力不足のせいにして安易に逃げようとは思っていなかったからだ。ヒューマンエラーだと思い込んで、その日一日を過ごしていたのです。しかし、ちょっと調べてみると、この厄介なバグに噛まれていたことがわかりました。

https://github.com/lensapp/lens/issues/5492

そして、「今朝の更新だ!」と思いました! 🤦 私はすぐに インシデント チャンネルでアラートを発し (後にエンジニアリング部門全体に伝播されました)、この可能性のある動作を他のユーザーにアラートしました。

反省/振り返り

塵も積もれば山となるで、私は何が起こったのか、特に本番環境でLensを使用することの正当性について自問自答し始めました。

使うべきではなかったのか?

そのための承認を得るべきだったのか?

もしそうなら、システム管理を行うために、王国の鍵にアクセスすることができるソフトウェアの一部を入れることの信頼度を評価するために、どのようなパラメータがあったのでしょうか?

チーム、部署、組織をまたがる明示的かつ強制的な標準化、つまり別の承認プロセスが本当に必要なのでしょうか?

基本に忠実であること

最も簡単な回答は、「物事を複雑にしすぎないで、基本的なツールにこだわる」というものでしょう。しかし、このアプローチには3つの問題があります。

1. “基本”の定義は何でしょうか?(複雑さ)

最初は簡単な質問に見えるかもしれませんが、物事は急速に変化します。kubectl は必要悪で、 Lensk9sOctantその他のダッシュボードは本当に過度な複雑化なのでしょうか?言い方を変えれば、あるツールが単なる手間の軽減ではなく、それ無しでは仕事を遂行できないものになるのはいつなのか?

何十、何百ものKubernetesクラスターを管理したり、本番環境を多くの機能や追加コンポーネントで充実させたりするのに、これらの側面に対処するための特定のツールを使わないで済むとは思えません。技術スタックが低すぎると、より高度な「外部」抽象化(人間が発行したり、人間がスクリプトを書いたりする)が必要になり、あらゆるものと同様に、エラーが発生しやすくなるのです。CustomResourceの処理は、自分で書くよりもistioctlに任せた方が安心です。

2. 生産性はどうでしょうか?(時間)

私にとって、これが試練全体の核心であり、大きなジレンマです。 速く動くことができる一方で、ツールボックスのどれだけを犠牲にすることができまるのでしょうか? 私が直接学んだように、考慮に入れるのが難しい隠れたコストがあります。追加された複雑さと実質的な付加価値のバランスが取れている場合もありますが、線を引くのは簡単ではありません。

ビルドの場合は問題ないのですが、インシデントレスポンスの場合、一刻を争う事態になり、よりスマートなツールでなければ、復旧に時間がかかる可能性があります。意味のあるデータを取得し解釈するために何十ものコマンドを連鎖させる(あるいは適切なノブに触れる)ことで、単純なサービスの低下が本格的な停電に発展する可能性があるのです。

3.”基本的なこと”にも問題がある

どんなに古くても、ツールに噛まれるリスクは常にあります。数ヶ月前、バニラのkubectlでも同じようなシナリオが起こりました。その場合、cURLでプレーンなAPIコールを使用することにフォールバックすることが正当化されたでしょうか?さまざまな OpenSSH の脆弱性が以前の世代のシステム管理者を悩ませていたとき (冗談です、それはまだ私でした)、誰も SSH に疑問を呈したり、Telnet に戻るように促したり、代替手段を探したりしませんでした。

DIY

反対に、「何も信用せず、すべてを自分でビルドする」アプローチもある。

おそらく、より優れた kubectl  やより機能豊富な openssl は必要ないため、ほとんどの場合、それは価値があるとは思いません。 適切なサービスとメンテナンスが必要なオーバーレイには、かなりのリスクが伴います (通常、バックログに積み上げられます)。 より複雑なタスクを実行するために、ビジネス ロジックの抽象化レイヤーを基本的なツールにラップしているだけかもしれません。 それがもたらす影響を認識している限り、それは完全に理にかなっています。 現実的に考えてみましょう。テンプレート エンジンは  gotemplateよりもうまく機能しません。

より良いアプローチ

さて、それでどうでしょう?私が投げかけた多くの質問に対する決定的な答えを持つには程遠いのですが、もし私がこの問題を二度と起こさないように計画しなければならないとしたら(これは自らに課した事後検証の回顧録として捉えてください)、次のようなことを考えるでしょう。

道具箱は標準化するが、選択肢は残す

標準ツールの100%遵守をユーザーに期待するのは、らしくない(そしてちょっと無理がある)。つまり、プロトコルがオープンで、標準が存在するのには理由があり、それはまさにこのことなのです。

もしあなたが規制された業界におらず、コンプライアンスが必須であるなら(上記のようなインシデントがあったら、始末書どころか、もっとひどい目に遭わされていたかもしれません。)、最小限の機能ユニット(チームや部門)全体で共有ツールボックスの使用を義務付け、新しいツールを追加する摩擦をできるだけ減らし、ツールキット自体からのバージョンアップを自動化する方が良いでしょう。こうすることで、すべてのエンジニアが監査可能なツールセットを使用し、かつ一貫性があり、有効性を犠牲にすることなく、確実に使用できるようになります。

いくつかのプロジェクトを活用することで、望ましいバージョン管理を実施することができます。

  • ソース(Git内)で:たとえば、 asdf .tool-versions や、セマンテックなロジックをチェックするために conftest を使用します。
  • デスティネーションでは、OPAKyvernoのようなポリシーエンジン(Kubernetesにのみスコープする場合)を使用します。

要するに、多くのユーティリティを備えた共有のツールボックスをビルドし、それを中心にコラボレーションの文化を作り上げるということです。エッジケースを排除し、主流でよく知られている機器だけを要求するのではなく、オーナーシップとエバンジェリズムを奨励することです。

信頼、しかし検証

ツールの選択は、実際には摩擦がないとはいえ、いくつかの明確な使用基準を持つべきです。これらのパラメータは、第三者審査員による監査に合格するのに十分なものでなければなりません。選考では、以下のような要素が考慮されます:

  • プロジェクトの背後にあるコミュニティの規模や活動レベル。熱心なコミュニティは、問題に対する反応がよく、迅速に行動することができます。
  • リリース頻度と変更リードタイム。リリース頻度が高すぎるプロジェクトでは、ツールボックスのアップデートが多く必要になりますが、リリースの間隔が開きすぎると、修正(または機能)が長い間見つからない可能性があります。
  • ソフトウェアのサプライチェーンの状況です。ソフトウェア部品表はあるか?バイナリは署名されているか?GitHubの main ブランチへの cURL から連鎖した不明瞭な install.sh を要求していないか?

これは、新しいプロジェクトがチームの武器として有用であると考える前に、最低限の調査を行う必要があります。

FOSSを書く

もし社内で構築したツールを必要とするような狭くて特殊なケースにぶつかったら、それをオープンソースにするという初期の目標を持ってプロジェクトを始めましょう。このアプローチには非常に多くの利点があり、数行でまとめるのは難しいのですが、いくつか挙げてみましょう。

  • より良いコードを書くように促される。
  • 透明性のある自動化が要求される。
  • ライフサイクル・メンテナンスは、コミュニティと共有されます。

公開プロジェクトでの共同作業の経験は、スキルアップや知名度の点で非常に貴重ですが、人の自由時間のごく一部に追いやられてしまうことが多いのです。エンジニアに勤務時間中にパブリックプロジェクトに取り組む時間を与えることは、オープンソースへの投資(あるいは単にお返し)の一形態であり、企業ではごく普通のことになるはずです。

次にくるものは?(失敗を受け入れることについて)

かなり不快な経験ではありましたが、今では、ツールが生産性だけでなく、私が管理するあらゆる本番環境の安全性と回復力にどのように影響しているかが、より明確にわかるようになったと思います。前向きに考えると、いくつかのことが起こると思います。

1. ツーリングの必要性を減らす(弾力性を優先させる)

そもそも手動で介入する必要がなければ、私はあのような問題を起こさなかったでしょう。ツールはエンジニアリングが失敗したときに必要です。デプロイは健全でないPodから回復できるべきですし、ネットワークやストレージのパフォーマンスが低下したノードは自動的に排出され、サービス停止になり、新しい(できれば良好な)ものに交換されるべきです。これらはすべて解決された問題であり、私たちはこれらの解決策を実行するために時間と労力を割く必要があります。

2. カオステストの導入(インフラとアプリの結合を評価する)

物事は、最も創造的で厄介な方法で壊れます。前のポイントに続いて、私たちは最も一般的なシナリオを手動で操作することなく管理できるようにする必要があります。つまり、単に故障を想定するだけでなく、故障しても影響がないことをテストすることです。カオスのテストフレームワークの質は大幅に向上しています。もっともらしいシナリオをいくつも想定して、実験を定義し実行することが、かつてないほど簡単にできるようになったのです。

3. ドリルテスト(反応を良くする)

これだけやっても、インシデントは起こります。実際の(非生産的な😄)停電にエンジニアが対応し、機能を復旧させるドリルテストを実施しましょう。MTTRを定義し、測定し、最新のドキュメントを維持し、迅速かつ効果的に実行するためにランブックを最適化します。インシデント管理ポリシーを見直す。そして最後に、難しいことですが、非の打ちどころのない対応文化を広め、間違いを認め、助けを求め、自分の限界をオープンにすることが安全であることを誰もが知っているようにすることです。