この記事は Retty Advent Calendar 2020 15日目の記事です。
どうも。エンジニアの @pikatenor です。今年は小ネタでいきます。
早速本題ですが、CoreDNS のことは皆様ご存知でしょうか。おそらく Kubernetes 絡みで聞いたことあるという方も多いと思います。
CoreDNS は CNCF によってホストされている OSS の DNS サーバーで、昨年1月には充分成熟したとして Graduated プロジェクトに位置づけられました。開発の主体をみても分かるように、Kubernetes の DNS Service として利用されることが多く、Kubernetes 1.11 からは kube-dns に代わり標準の実装として採用*1されています。
とはいえこの CoreDNS、単独で使ってもなかなか便利なやつなので、今回はぼちぼちと例を挙げながら紹介していく記事になります。
インストールと使い方
CoreDNS は Go で書かれており、単一バイナリの形式で GitHub のリリースページにて配布されています。インストールはダウンロードしてお好きなところに配置するだけです。
$ ./coredns -help Usage of ./coredns: -conf string Corefile to load (default "Corefile") -dns.port string Default port (default "53") -pidfile string Path to write pid file -plugins List installed plugins -quiet Quiet mode (no initialization output) -version Show version
デフォルトでは起動したディレクトリ内の Corefile
ファイルを設定ファイルとして読み込みます。
さて、設定ファイルの書き方の前に CoreDNS の基礎的な考え方について解説します。
CoreDNS は単独ではほとんど何も行いません。与えられたクエリにどう応答するかや、ロギング・ロードバランシングなどの処理も含めて、全てはプラグインに委ねられます。CoreDNS のコアのお仕事は DNS クエリを解釈し、設定ファイルに記述されたプラグインへ受け渡すところまでです。CoreDNS という名前なのにガワしかないとはこれいかに。
しかしそんなプラガブルなアーキテクチャのおかげで柔軟な設定ができるのが CoreDNS の魅力です。設定ファイルは次のように記述します。
# <ホストゾーン>:<リッスンポート> { # プラグイン # プラグイン { # プラグイン個別の設定 # } # } . { log whoami }
上記では入力クエリを標準出力に吐く log プラグインと、全てのクエリに対してリクエストを送ってきたクライアント自身の IP アドレスを返す whoami プラグインを指定しています。リッスンポートは省略した場合デフォルトの UDP 53 が使われます。デフォルトポートは -dns.port
オプションで上書きできます。
以降はポートとして 1053 番を利用します。
ゾーン別に設定を書き分けることもできます。例えば example.com
ゾーンに対しては個別の設定を適用したい場合、
.:1053 { log forward . 1.1.1.1 } example.com:1053 { log whoami }
のように書けば、
$ ./coredns -conf ./Corefile .:1053 example.com.:1053 CoreDNS-1.8.0 linux/amd64, go1.15.3, 054c9ae [INFO] 127.0.0.1:47336 - 34552 "A IN retty.me. udp 49 false 4096" NOERROR qr,rd,ra 85 0.00843798s [INFO] 127.0.0.1:54759 - 25644 "A IN example.com. udp 52 false 4096" NOERROR qr,aa,rd 91 0.00009736s
$ dig retty.me -p 1053 @127.0.0.1 ; <<>> DiG 9.16.7 <<>> retty.me -p 1053 @127.0.0.1 ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50149 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;retty.me. IN A ;; ANSWER SECTION: retty.me. 12 IN A 54.64.106.126 retty.me. 12 IN A 54.65.49.141 ;; Query time: 6 msec ;; SERVER: 127.0.0.1#1053(127.0.0.1) ;; WHEN: Tue Dec 15 08:40:07 JST 2020 ;; MSG SIZE rcvd: 85 $ dig example.com -p 1053 @127.0.0.1 ; <<>> DiG 9.16.7 <<>> example.com -p 1053 @127.0.0.1 ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63123 ;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 3 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ; COOKIE: b7ce4118f738e4e6 (echoed) ;; QUESTION SECTION: ;example.com. IN A ;; ADDITIONAL SECTION: example.com. 0 IN A 127.0.0.1 _udp.example.com. 0 IN SRV 0 0 37338 . ;; Query time: 0 msec ;; SERVER: 127.0.0.1#1053(127.0.0.1) ;; WHEN: Tue Dec 15 08:40:09 JST 2020 ;; MSG SIZE rcvd: 114
example.com に対してのみ whoami プラグインが使われ、他のゾーンのクエリは forward プラグイン により 1.1.1.1 へ転送されます。プラグインは一部の例外*2を除き上から順に適用されます。
プラグインの有効化
公式プラグインについては in-tree で CoreDNS チーム自身がメンテナンスしており、それらは標準で配布されているバイナリに含まれています。公式プラグインの一覧はこちらです。
それ以外の外部プラグインを利用する場合は、CoreDNS を手動でビルドする必要があります。とはいえ手順は単純です。
CoreDNS のビルドには Go 1.12 以上が必要です。
$ git clone https://github.com/coredns/coredns $ cd coredns $ make
これだけで ./coredns
が完成します。プラグインを有効化してビルドする際は、plugin.cfg
に プラグイン名:Go パッケージ
の形で追記します。
試しに CoreDNS チームがプラグイン開発の際の例として作った example プラグイン を有効化してみると
$ echo 'example:github.com/coredns/example' >> plugin.cfg $ make $ ./coredns -plugins Other plugins: ... dns.etcd dns.example dns.file ...
example プラグインが有効になっているのが分かります。
設定例
# /etc/hosts の内容を答える . { errors loop reload hosts { reload 1s fallthrough } forward . /etc/resolv.conf cache 30 } # ファイルを個別に指定することも可能 . { hosts /var/tmp/hoge.hosts }
まあ hosts プラグインの説明まんまなんですが。/etc/hosts 形式でパッと書いて答える DNS サーバーをサクッと用意できると便利なシーンは多いですよね。hosts プラグインはクエリされたホスト名が見つからない場合 fallthrough オプションがないと下流のプラグインにクエリを流さず打ち切ってしまうのでそこだけ注意です。例では hosts ファイルになかった場合システムの /etc/resolv.conf に従い他の DNS サーバーに投げます。
またその他ですが、
などのプラグインを用いています。cache 以外はまあ大体の場合において入れておいて問題はないだろうというプラグインです。
結び
というわけで CoreDNS の簡単な紹介でした。結局いい例が浮かばず /etc/hosts というシンプルな例しか挙げられませんでしたが、dnsmasq などと比較しても設定ファイルの明快さ柔軟性、Go 製バイナリであることによる取り回しの良さなど一定の便利さを得られると思います。
明日の Retty Advent Calendar は EKS でアレをソレする話です。ご期待下さい。