発明のための再発明

Webプログラマーが、プログラムの内部動作を通してプログラムを作る時の参考になるような情報を書くブログ(サーバーサイドやDevOpsメイン)

CoreDNSにおけるプラグインチェーンの実装

はじめに

f:id:mrasu:20190217162512p:plain

CoreDNSはサービスディスカバリ機能を持ったDNSです。
CNCFでGraduatedになっているプロジェクトで、KubernetesのデフォルトDNSにもなっています。

この記事では、CoreDNSはプラグイン方式で拡張するようになっているので、その実装を見ていきます。
※ 実装はde2f63d78747b48ae458b8f2c327a01e44cf725cを基にしています。

プラグイン登録

CoreDNSのプラグインは動的にロードするのではなく、Caddyの仕組みを使ってビルド時に組み込まれます。
また、プラグインの実行順序もビルド時に決定されています。
プラグイン情報はzdirectives.goというファイルに定義されていて、zdirectives.goの作成がタスク化されています。
以下のステップを経ることで、プラグインがCoreDNSに組み込まれます。

plugin.cfgに定義

plugin.cfgにはビルドに使用するプラグインと、実行順序が定義されています。
plugin.cfgの内容は以下のようなものです。

metadata:metadata
tls:tls
reload:reload
...
on:github.com/mholt/caddy/onevent

左がプラグイン名で、右がパッケージ名です。
ここに書かれている順番で、プラグインが実行されます。

go generate を実行

go generateは以下のように動きます。

  1. go run directives_generate.goが呼ばれる
  2. zdirectives.goと関連ファイルを作成される

これによって、以下の内容がzdirectives.goに書き込まれます。

var Directives = []string{
    "metadata",
    "tls",
    "reload",
    ...
    "on",
}

このDirectivesが、プラグインの順序を定義しています。

go build を実行

go buildの実行時に、zdirectives.goが使用されます

プラグインチェーンの実行

次は、CoreDNSのプラグインは、実行時の振る舞いについて

開始時に初期化

CoreDNSの開始時に各プラグインを初期化して、zdirectives.goに書かれている順番でプラグインチェーンに登録します

プラグインチェーンの参照

リクエストが来たら、プラグインチェーンにある最初のプラグインが実行されます
server.goh.pluginChain.ServeDNSからプラグインチェーンが開始されます

最初のプラグインを実行

最初のプラグインが実行されます
プラグインはServeDNSというインターフェースを持つので、それが実行されます

後続プラグインの実行

次のプラグインが実行される
plugin#NextOrFailureを呼び出すことで次のプラグインが実行されるので、その関数の前後がプラグイン独自のコードを書く場所です。

まとめ

以上、CoreDNSが実装しているプラグインチェーンを紹介しました。

このブログでは、この記事のようにプログラムを作る時の参考になることを書き続けるつもりです。
もし興味があれば、twitterやブログのフォローしていただけると嬉しいです。