デバッグのための開発 (2025)
Developing for Debugging (2025) (davepacheco.net)
要約
Oxideのコントロールプレーンは、外部DNSと内部DNSの2つの異なるDNSサービスを運用しています。DNSデータの権威ある情報源はCockroachDBであり、NexusコンポーネントがDNS変更を検知し、バックグラウンドタスクを通じてDNSサーバーに伝播させます。このプロセスで何が起こりうるか、そして問題発生時に原因を特定するにはどうすればよいかという問いから、デバッグのための開発という考え方が生まれました。この考え方に基づき、Omicronデバッガー(omdb)が開発され、DNS伝播パイプラインのどこで問題が発生したかを迅速に特定できるようになりました。
全文翻訳
Dave Pacheco's Blog
Written by dap
on June 9, 2025
デバッグのための開発
Oxideのコントロールプレーンは、2つの異なるDNSサービスを運用しています。外部DNSは顧客に公開され、システムの外部向けAPIおよびWebコンソールの場所を示す名前を提供します。内部DNSはシステムの内部ネットワークでのみ動作し、コントロールプレーンのコンポーネントのサービスディスカバリを提供します。これらは同じスタックの別々のデプロイメントを使用しています。基本的な仕組みは以下の通りです。
-
DNSデータの正当な情報源(つまり、DNSサーバーが報告すべき名前とレコード)は、コントロールプレーンのデータベースです。これは強く一貫した分散データベース(CockroachDB)です。
-
コントロールプレーンの中核はNexusと呼ばれるコンポーネントです。DNSの変更を引き起こすべきイベントが発生した場合(例:内部または外部でサービスを提供するコンポーネントが追加または削除された場合):
-
Nexusはまずデータベース内のDNS構成を更新します。
-
Nexus内のバックグラウンドタスクのシーケンスが、更新された構成をサービス中のすべてのDNSサーバーに伝播させます。これらのタスクは、DNSを変更するイベントに応答して実行され、定期的に(一時的な障害やウェイクアップの失敗などに対処するため)実行されます。
-
[画像: Diagram: DNS propagation]
この一連の流れは、変更を引き起こしたイベントに対して非同期ですが、正常に動作しているシステムでは通常数秒で完了します。
しかし、インフラがオフラインになったとき、常にDNSが原因であることは誰もが知っています。そのため、このシステムに取り組むにあたり、私たちは次のようなことを考えました。このプロセスで何が起こりうるか?それが壊れたとき、なぜ壊れたのかをどうやって知るのか?
具体的には、顧客が期待するDNS名が存在しないと報告した場合を考えてみましょう。外部DNSサーバーにクエリしても、レコードが返ってきません。何が問題でしょうか?考えられるのは以下の通りです。
- データベース内のDNSデータが間違っている可能性がある。
- 伝播プロセスが壊れている可能性がある:
- NexusがDNSデータの変更に気づいていないのかもしれない。
- NexusがDNSサーバーのリストを間違っているのかもしれない。(例:システムにサーバーが追加されたが、伝播リストに追加されていない)
- DNSデータからDNSサーバーへの伝播が壊れているのかもしれない。
- 伝播プロセスが停止しているのかもしれない。
- DNSサーバーが、その構成に対して間違ったデータをサービスしている可能性がある。
DNSが間違ったことをしているという報告を受けた場合、これらのすべてを報告できるツールが欲しいと思うのは明白でしょう。
-
データベースには何が入っているか?
- DNS構成の一部となっている名前は何か?
- 最後にいつ、どのNexusによって、なぜ更新されたか?
-
各Nexusインスタンスについて、最後の伝播試行について:
- いつ開始されたか?まだ実行中か?
- どのバージョンのDNS構成を伝播しようとしているか?
- 伝播すべきDNSサーバーのリストをどのように見つけたか?いつそれを決定したか?
- 各サーバーへのDNS構成の伝播の最後の完了試行の結果はどうだったか?
-
各DNSサーバーについて、どのバージョンのDNSデータで動作しているか?
この例は、omdb(Omicronデバッガ)を構築するきっかけとなりました。OmicronはOxideシステムにおけるコントロールプレーンの内部名です。これはDNSデバッガではなくOmicronデバッガと呼ばれます。なぜなら、これは私たちがランタイムでの観測可能性を必要とする唯一のサブシステムではないだろうと考えたからです。
さて、私たちはバックグラウンドタスクと呼ばれる新しい抽象化の形でDNS伝播を構築しました。バックグラウンドタスクには、基本的な観測可能性が組み込まれています。これらは基本的に、いくつかのプロパティを持つ非同期Rust関数です。特定のイベントに応答して呼び出され(アクティブ化され)、常に一定間隔でアクティブ化され、完全なセットは静的に定義されており、任意のステータスペイロード(現在はスキーマレスなJSONオブジェクト)を返すことができます。これらの要素により、omdbは、omdb自体があまり多くのことを知らなくても、DNS伝播に関する有用な概要レポートを生成できます。まず、サーバーから提供される基本的なドキュメントを報告できます。
# omdb nexus background-tasks doc | grep -A1 "dns.*internal"
note: Nexus URL not specified. Will pick one from DNS.
note: using DNS server for subnet fd00:1122:3344::/48
note: (if this is not right, use --dns-server to specify an alternate DNS server)
note: using Nexus URL http://[fd00:1122:3344:102::3]:12221
task: "dns_config_internal"
watches internal DNS data stored in CockroachDB
--
task: "dns_propagation_internal"
propagates latest internal DNS configuration (from "dns_config_internal"
background task) to the latest list of DNS servers (from
"dns_servers_internal" background task)
--
task: "dns_servers_internal"
watches list of internal DNS servers stored in internal DNS
そして、これがステータスです。
# omdb nexus background-tasks show dns_internal
note: Nexus URL not specified. Will pick one from DNS.
note: using DNS server for subnet fd00:1122:3344::/48
note: (if this is not right, use --dns-server to specify an alternate DNS server)
note: using Nexus URL http://[fd00:1122:3344:104::3]:12221
task: "dns_config_internal"
configured period: every 1m
currently executing: no
last completed activation: iter 4500, triggered by a periodic timer firing
started at 2025-06-10T03:31:47.775Z (23s ago) and ran for 1303ms
last generation found: 18
task: "dns_servers_internal"
configured period: every 1m
currently executing: no
last completed activation: iter 4500, triggered by a periodic timer firing
started at 2025-06-10T03:31:47.775Z (23s ago) and ran for 1ms
servers found: 3
DNS_SERVER_ADDR
[fd00:1122:3344:1::1]:5353
[fd00:1122:3344:2::1]:5353
[fd00:1122:3344:3::1]:5353
task: "dns_propagation_internal"
configured period: every 1m
currently executing: no
last completed activation: iter 4502, triggered by a periodic timer firing
started at 2025-06-10T03:31:47.775Z (23s ago) and ran for 876ms
attempt to propagate generation: 18
DNS_SERVER_ADDR LAST_RESULT
[fd00:1122:3344:1::1]:5353 success
[fd00:1122:3344:2::1]:5353 success
[fd00:1122:3344:3::1]:5353 success
これは私がデバッグのために開発すると呼ぶものの、的確な例です。システムを構築する際に、そのどの部分も本番環境で予期せず壊れる可能性があると仮定します。デバッグするために必要な情報を事前に考え、それを本番システムから収集できるようにします。バックグラウンドタスクのような基本的な抽象化に投資することで、DNS伝播の各部分を、これらの小さなステータスレポートが得られるようにファクタリングするのは非常に簡単な作業でした。それにもかかわらず、これだけで、伝播パイプラインのどこが壊れたのかを数秒で正確に判断できます。その結果、機能するだけでなく、デバッグ可能なシステムが生まれます。
ソフトウェアは自己を正当化できるべきである
ソフトウェアが何が間違っているかを教えてくれるのは素晴らしいことです。それが、自分が機能していることを説得力を持って伝えられるなら、さらに素晴らしいことです。
このようなシステムが次のように報告するのは一つのことです。
問題0件
または:
DNS伝播は最新の状態です。
なるほど。しかし、それは本当に真実でしょうか?「問題0件」とは、「このプログラムが認識している問題は0件」という意味です。「最新の状態」は、せいぜい曖昧であり、その言葉が画面に表示されるとすぐに間違っている可能性があります。
上記のシステムは、正しく機能している場合に、より強力で肯定的な証拠を報告します。「DNSバージョン18を伝播しました。これは2025-06-10T03:31:47.775Zに発見したもので、これらの3つのDNSサーバー(2025-06-10T03:31:47.775Zに発見したもの)に伝播し、すべてが2025-06-10T03:31:48.651000Zまでに完了しました。」
これははるかに多くの情報です。多くの場合、これによりDNSが問題ではないと判断できます。たとえそれが別の何かであったとしても、この情報は、何が起こったのかを解明するためのイベントのタイムラインを作成するのに役立ちます。ユーザーが伝播が完了する前にDNSをクエリしたのでしょうか?
その他の利点
このようにソフトウェアを開発することには、他にも多くの利点があります。
-
システムを構築中に
omdbを使用して、自動テストを作成する前に操作やテストを行うことができます。ここでは行いませんでしたが、伝播パイプラインの残りの部分の前にデータベース部分を構築し、omdbを使用してNexusが更新を認識するのを見ることを想像できます。デバッガ駆動開発は、Oxide and Friendsポッドキャストのエピソード全体で取り上げられています。 -
既存のシステムで作業中に
omdbを使用して、その動作を理解することができます。この場合、一部のDNSサーバーがオフラインになった場合に何が起こるかを見ることができます。 -
omdbを使用して、人々にソフトウェアの仕組みを教えることができます。DNSサブシステムのオンボーディングドキュメント(存在しませんが、存在するべきです!)は、DNSの変更とその後の伝播の例をステップバイステップで説明できます。メンターは新しいチームメンバーにそれを見せることができます。デモ(この詳細レベルで)は、千の図に値します。 -
omdbをソフトウェア変更についてコミュニケーションするためのツールとして使用できます。新しいDNSシステムについて人々に伝える代わりに、DNSサブシステムの詳細なシステムデモを10分で行い、DNSの変更が期待どおりに伝播されたことだけでなく、どのように伝播されたかを示し、問題がない場合に何が起こるかさえ示すことができます。
過去の経験から、チームがシステム全体でこれを行うことに成功した場合、デバッグ情報の容易な利用可能性は、サポートコールを処理する際の感情的なトーンを本当に変えることができると言えます。多くの人は、デバッグを、やりたいことからの痛みを伴う気晴らしと見なします。顧客が修正を待っているため、プレッシャーがかかっているときは特にストレスがかかります。多くのストレスは、恐怖と不確実性から生じます。これらのツールを構築すると、より多くの問題を迅速に(そしてより自信を持って)解決できます。顧客が苦しんでいることを知るのは依然としてつらいですが、それを解決する方法を知っていれば、はるかに恐ろしくなくなります。
皮肉なことに、このように構築されたソフトウェアは、このプロセスが開発中にそれらについて考えることを促すため、実行時問題が発生する可能性が低いという直感もあります。それを裏付けるデータはありません。
1。多くのチームメンバーがomdbに多くのコマンドを追加しており、現在ではコントロールプレーンのかなり多くの部分をクエリするためのコマンドがあります。
2。ここでは、プロセスの両端(データベースに不正確なデータがある場合や、DNSサーバーが構成が正しい場合でも間違ったものをサービスしている場合)の問題は、説明を簡単にするために無視しています。これらの問題を観察するためのツールもあり、同様に詳細であり、「正しく機能している」だけではありません。