CoreDNSにおけるクエリ処理方法

そして、それがクラスタドメイン内のKubernetesカスタムDNSエントリにどのように適用されるか。

前の投稿では、KubernetesにおけるカスタムDNSエントリの3つの異なるユースケースについて説明しました。

前の投稿では、最初の2つについて説明しました。この投稿では、3番目のケースを満たすために、`kubernetes`プラグインの`fallthrough`オプションをどのように使用するかを示します。

これがどのように機能するかを理解するために、まずCoreDNSがリクエストを処理する方法を確認する必要があります。これは以前クエリルーティングで説明されていましたが、ここではもう少し詳しく説明します。

CoreDNSがプラグインをチェーンしていることは誰もが知っています。しかし、それは正確にはどういう意味でしょうか?それを知るために、Corefileを解剖し、それがCoreDNSの内部構造にどのように変換されるか、そしてクエリがこれらの内部構造をどのように通過するかを説明します。

このCorefileを考えてみましょう。

coredns.io:5300 {
  file /etc/coredns/zones/coredns.io.db
}

example.io:53 {
  errors
  log
  file /etc/coredns/zones/example.io.db
}

example.net:53 {
  file /etc/coredns/zones/example.net.db
}

.:53 {
  errors
  log
  health
  rewrite name foo.example.com foo.default.svc.cluster.local
  kubernetes cluster.local 10.0.0.0/24
  file /etc/coredns/example.db example.org
  forward . /etc/resolv.conf
  cache 30
}

ここでは、5300と53の2つの異なるポートがあることに注目してください。内部的には、これらの各ポートは`dnsserver.Server`になります。4つのサーバブロック(スタンザ)があるにもかかわらず、実際には2つのサーバしか得られません。CoreDNSは、同じポートに関連付けられたすべてのサーバブロックを収集し、同じ`dnsserver.Server`に結合します。サーバはポート上のクエリを多重化し、ゾーンに応じて異なるプラグインチェーンに渡します。ゾーンに最も具体的に一致するサーバブロックを選択します。サーバブロックが一致しない場合は、`SERVFAIL`が返されます。これは以下の図に視覚的に示されています。

Query Processing

そのため、特定のクエリは正確に1つのプラグインチェーンを通過します。プラグインの順序は、`plugin.cfg`ファイルによってビルド時に決定されますが、これをランタイムで変更可能にするという議論もあります。そのため、`cache`がサーバブロックの最後に表示されていても、プラグインチェーンの最後ではありません。

`.:53`サーバブロックでは、`health`プラグインを定義していますが、図には表示されていません。これは、いくつかの異なるタイプのプラグインがあるためです。「通常の」プラグインはリクエスト処理を実行し、プラグインチェーンに表示されます。しかし、サーバまたはサーバブロックの構成を変更するだけのプラグインがいくつかあります。リクエスト時のロジックがないため、プラグインチェーンには挿入されません。このように動作するプラグインには、`health`、`tls`、`startup`、`shutdown`、`root`プラグインなどがあります。

リクエスト時の処理を実行するプラグインは、リクエストをある程度操作するプラグインとバックエンドプラグインの2つのグループに分類できます。バックエンドプラグインは、ゾーンとレコードデータのさまざまなソースを提供します。`etcd`、`file`、`kubernetes`プラグインはすべてバックエンドの例です。

リクエストを操作しますが、バックエンドではないプラグイン(つまり、ゾーンデータのソースではないプラグイン)は、通常、ロジックを実行した後にクエリを次のプラグインに渡します。たとえば、`rewrite`プラグインはリクエストに変更を加え、その後渡します。結果が後のプラグインから返されると、質問セクションを元に戻しますが(クライアントが文句を言わないように)、応答を保持してクライアントに返します。

特定のバックエンドは通常、そのゾーンの最終的な決定権を持ちます。結果を返すか、クエリに対してNXDOMAINを返します。ただし、場合によってはこれが望ましい動作ではないため、一部のプラグインは`fallthrough`オプションをサポートしています。`fallthrough`が有効になっている場合、レコードが見つからない場合にNXDOMAINを返す代わりに、プラグインはリクエストをチェーンの下に渡します。その後、チェーンの下流のバックエンドがリクエストを処理する機会があります。

Kubernetesの3つのユースケースに関する最初の議論に戻ると、`fallthrough`を使用して3番目のユースケースを満たす方法を理解できるようになりました。そのブログの最初のCorefileを思い出してください。

.:53 {
    errors
    log
    health
    kubernetes cluster.local 10.0.0.0/24
    forward . /etc/resolv.conf
    cache 30
}

これは、標準的なクラスタ内DNSサービス検出を処理します。3番目のユースケースは、既存のクラスタドメインに任意のエントリを追加することです。これを行うには、`cluster.local`ゾーンを処理するための別のバックエンドを定義し、`kubernetes`プラグインで`fallthrough`オプションを構成します。非常に動的なエントリの場合、`etcd`プラグインを使用できます。しかし、デモのために`file`プラグインを使用する方が簡単なので、そうします。

`kubernetes`は`plugin.cfg`で`file`の前にあるため、`kubernetes`で`fallthrough`を使用すると、`kubernetes`が処理しないクエリを`file`が処理することになります。つまり、前のブログで2番目のユースケースを処理したのと同じように、ConfigMapの一部としてゾーンファイルを用意する必要があります。ただし、この場合は、別のゾーン(前のブログの`example.org`)で構成されるのではなく、`file`プラグインは`cluster.local`ドメインを使用するように構成されています。

apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        errors
        log
        health
        kubernetes cluster.local 10.0.0.0/24 {
          fallthrough
        }
        file /etc/coredns/cluster.db cluster.local
        forward . /etc/resolv.conf
        cache 30
    }    
  cluster.db: |
    cluster.local.               IN      SOA     ns.dns.cluster.local. hostmaster.cluster.local. 2015082541 7200 3600 1209600 3600
    something.cluster.local.     IN      A       10.0.0.1
    otherthing.cluster.local.    IN      CNAME   google.com.    

ポッドテンプレートの`config-volume`に`cluster.db`ファイルを追加することを忘れないでください。

      volumes:
        - name: config-volume
          configMap:
            name: coredns
            items:
            - key: Corefile
              path: Corefile
            - key: cluster.db
              path: cluster.db

最後に、CoreDNSに正常に再読み込みするように(実行中の各ポッドに)シグナルを送信します。

$ kubectl -n kube-system exec coredns-461002909-7mp96 -- kill -SIGUSR1 1

では、新しいDNSレコードを試してみましょう。

$ kubectl run -it --rm --restart=Never --image=infoblox/dnstools:latest dnstools
If you don't see a command prompt, try pressing enter.
/ # host kubernetes
kubernetes.default.svc.cluster.local has address 10.0.0.1
/ # host something
something.cluster.local has address 10.0.0.1
/ # host otherthign
Host otherthign not found: 3(NXDOMAIN)
/ # host otherthing
otherthing.cluster.local is an alias for google.com.
google.com has IPv6 address 2607:f8b0:4005:805::200e
google.com mail is handled by 30 alt2.aspmx.l.google.com.
google.com mail is handled by 50 alt4.aspmx.l.google.com.
google.com mail is handled by 40 alt3.aspmx.l.google.com.
google.com mail is handled by 20 alt1.aspmx.l.google.com.
google.com mail is handled by 10 aspmx.l.google.com.
/ #

間違った名前を入力した場合、予想どおりNXDOMAINが表示されることがわかります。ただし、正しい名前は、ゾーンファイルのレコードに解決されます。そのため、クラスタドメインにカスタムエントリを作成する方法ができました。

標準のCoreDNSリリースでは、`kubernetes`プラグインは`file`と`etcd`の前にあります。つまり、クエリを処理する最初の機会が得られます。必要に応じて、その順序を変更するためにCoreDNSを再構築できます。その方法については、MiekのCoreDNSへのプラグインの追加方法に関する投稿をご覧ください。

John Belamaric
公開日: タグ付き カスタム検出DNSドキュメントKube-DNSKubernetesプラグインサービス 使用語数1143語。