Анализ исходного кода CoreDNS

Kubernetes

Исходный код CoreDNS основан на версии 1.3.1.

Архитектура

Архитектура CoreDNS реализована на основе фреймворка Caddy, весь проект использует множество подключаемых функций Caddy, общая структура кода относительно понятна и очень удобна для чтения.

Makefile

Сначала взгляните на часть Makefile кода CoreDNS:

Как видно из рисунка,core/plugin/zplugin.goа такжеcore/dnsserver/zdirectives.goфайлы сделаныcoredns.goпройти черезplugin.cfgСгенерировано. в,coredns.goэто файл запуска,plugin.cfgпредставляет собой список настроенных плагинов, плагины по умолчанию следующие:

# Directives are registered in the order they should be
# executed.
#
# Ordering is VERY important. Every plugin will
# feel the effects of all other plugin below
# (after) them during a request, but they must not
# care what plugin above them are doing.

# How to rebuild with updated plugin configurations:
# Modify the list below and run `go gen && go build`

# The parser takes the input format of
#     <plugin-name>:<package-name>
# Or
#     <plugin-name>:<fully-qualified-package-name>
#
# External plugin example:
# log:github.com/coredns/coredns/plugin/log
# Local plugin example:
# log:log

metadata:metadata
tls:tls
reload:reload
nsid:nsid
root:root
bind:bind
debug:debug
trace:trace
health:health
pprof:pprof
prometheus:metrics
errors:errors
log:log
dnstap:dnstap
chaos:chaos
loadbalance:loadbalance
cache:cache
rewrite:rewrite
dnssec:dnssec
autopath:autopath
template:template
hosts:hosts
route53:route53
federation:federation
k8s_external:k8s_external
kubernetes:kubernetes
file:file
auto:auto
secondary:secondary
etcd:etcd
loop:loop
forward:forward
proxy:proxy
erratic:erratic
whoami:whoami
on:github.com/mholt/caddy/onevent

В код по умолчанию включены все существующие плагины, представленные в виде пары ключ-значение.
Посмотрите еще раз на файл запускаcoredns.go:

Код очень простой, простоRunметод, но загруженныйgithub.com/coredns/coredns/core/pluginВсе методы инициализации в пакете.github.com/coredns/coredns/core/pluginТолько один в упаковкеzplugin.goфайл, и этот файл является файлом, сгенерированным Makefile, следующим образом:

// generated by directives_generate.go; DO NOT EDIT

package plugin

import (
	// Include all plugins.
	_ "github.com/coredns/coredns/plugin/auto"
	_ "github.com/coredns/coredns/plugin/autopath"
	_ "github.com/coredns/coredns/plugin/bind"
	_ "github.com/coredns/coredns/plugin/cache"
	_ "github.com/coredns/coredns/plugin/chaos"
	_ "github.com/coredns/coredns/plugin/debug"
	_ "github.com/coredns/coredns/plugin/dnssec"
	_ "github.com/coredns/coredns/plugin/dnstap"
	_ "github.com/coredns/coredns/plugin/erratic"
	_ "github.com/coredns/coredns/plugin/errors"
	_ "github.com/coredns/coredns/plugin/etcd"
	_ "github.com/coredns/coredns/plugin/federation"
	_ "github.com/coredns/coredns/plugin/file"
	_ "github.com/coredns/coredns/plugin/forward"
	_ "github.com/coredns/coredns/plugin/health"
	_ "github.com/coredns/coredns/plugin/hosts"
	_ "github.com/coredns/coredns/plugin/k8s_external"
	_ "github.com/coredns/coredns/plugin/kubernetes"
	_ "github.com/coredns/coredns/plugin/loadbalance"
	_ "github.com/coredns/coredns/plugin/log"
	_ "github.com/coredns/coredns/plugin/loop"
	_ "github.com/coredns/coredns/plugin/metadata"
	_ "github.com/coredns/coredns/plugin/metrics"
	_ "github.com/coredns/coredns/plugin/nsid"
	_ "github.com/coredns/coredns/plugin/pprof"
	_ "github.com/coredns/coredns/plugin/proxy"
	_ "github.com/coredns/coredns/plugin/reload"
	_ "github.com/coredns/coredns/plugin/rewrite"
	_ "github.com/coredns/coredns/plugin/root"
	_ "github.com/coredns/coredns/plugin/route53"
	_ "github.com/coredns/coredns/plugin/secondary"
	_ "github.com/coredns/coredns/plugin/template"
	_ "github.com/coredns/coredns/plugin/tls"
	_ "github.com/coredns/coredns/plugin/trace"
	_ "github.com/coredns/coredns/plugin/whoami"
	_ "github.com/mholt/caddy/onevent"
)

Другой файл, сгенерированный Makefilezdirectives.goследующим образом:

// generated by directives_generate.go; DO NOT EDIT

package dnsserver

// Directives are registered in the order they should be
// executed.
//
// Ordering is VERY important. Every plugin will
// feel the effects of all other plugin below
// (after) them during a request, but they must not
// care what plugin above them are doing.
var Directives = []string{
	"metadata",
	"tls",
	"reload",
	"nsid",
	"root",
	"bind",
	"debug",
	"trace",
	"health",
	"pprof",
	"prometheus",
	"errors",
	"log",
	"dnstap",
	"chaos",
	"loadbalance",
	"cache",
	"rewrite",
	"dnssec",
	"autopath",
	"template",
	"hosts",
	"route53",
	"federation",
	"k8s_external",
	"kubernetes",
	"file",
	"auto",
	"secondary",
	"etcd",
	"loop",
	"forward",
	"proxy",
	"erratic",
	"whoami",
	"on",
}

Два файла, один для загрузки всех подключаемых модулей и выполнения метода инициализации, другой для настройки массива.
назадzplugin.goфайл вgithub.com/coredns/coredns/plugin/autoВзяв пакет в качестве примера, его соответствующий метод инициализации выглядит следующим образом:

Основное выполняемое действие — регистрация автоматического плагина в caddy, а затем добавление метода настройки, который в основном используется для выполнения некоторых операций первоначальной настройки.
Поэтому с помощью этого метода инициализации сгенерированные плагины по очереди регистрируются в caddy.

Инициализация CoreDNS

пройти черезRunМетод входит в процесс инициализации CoreDNS.RunЭтот метод в основном заключается в проверке параметров, уделяя особое внимание пакету, который он вводит.github.com/coredns/coredns/core/dnsserver, соответствующий метод инициализации выглядит следующим образом:

КэддиRegisterServerTypeМетод завершает окончательную регистрацию плагина, где список плагиновDirectivesдаcore/dnsserver/zdirectives.goСодержимое файла содержит ряд информации о подключаемых модулях (порядок подключаемых модулей строго обязателен); иnewContextто естьdnsContextобъект, который реализует интерфейс Caddy Context,
пройти черезMakeServersЗавершите создание dnsServer.

Создание DNS-сервера

CoreDNS имеет множество вариантов создания серверов,

Существует несколько способов DNS, TLS, GRPC и HTTPS. Возьмем в качестве примера режим DNS, введитеNewServerметод, основная функция которого заключается в добавленииpluginChainЦепочка, которой соответствует соответствующий плагинplugin.Handlerметод обхода в обратном порядке,
Предполагая, что загруженные плагины - это ошибки, лог и хост, после обратного порядка, так как плагины добавляются сзади на передhost-->log-->errors, окончательный фактический порядок загрузкиerrors-->log-->host, в том же порядке, как определено.

Выполнение плагина

Все плагины в основном реализуютHandlerинтерфейс,

NameМетод — это название плагина, сосредоточьтесь наServeDNSметод.ServeDNSЕсть три параметра,Contextпредставляет весь контекст,ResponseWriterУказывает, что сообщение возвращается клиенту,dns.Msgпо запросу клиента.
Когда каждый плагин обрабатывает запрос, он вызываетNextOrFailureМетод вызывает следующий плагин для обработки соответствующей логики, то есть цепочек вызовов; вызовWriteMsgМетод завершает вызов завершения, передавая сообщение клиенту.
Если вам нужен пользовательский плагин, он в основном реализованNameа такжеServeDNSметод, а вplugin.cfgОчень удобно добавлять информацию о плагине в соответствующее место, чтобы завершить реализацию пользовательского плагина.

Плагин Kubernetes

Kubernetes также предоставляется в виде подключаемых модулей в CoreDNS, в основном предоставляя внутренние ресурсы в качестве источника разрешения доменных имен.

запускать

Как и другие подключаемые модули, Kubernetes также выполняет init для регистрации подключаемого модуля в caddy, а затем вызываетsetupспособ завершения работы по запуску. посмотриsetupГлавное что делать.

первый звонокkubernetesParseРазберите соответствующую конфигурацию подключаемого модуля Kubernetes, затем вызовитеInitKubeCacheинициализацияkubeClient, во время вызоваnewdnsControllerИнициализируйте dnsController, взаимодействуйте с кластером Kubernetes через dnsController и получите соответствующие данные в кластере; наконец, вызовитеAddPluginДобавьте плагин в конфигурацию в виде связанного списка для завершения инициализации.

бегать

бежать, чтобы достичьServeDNSметод начинается. Главное — ввести разную логику обработки, разбирая разные типы запросов.

путем реализацииServiceBackendЗавершите разрешение доменного имени.
ServicesВ основном в соответствии с конкретным типом запроса, получить все соответствующие услуги;
ReverseВ основном выполняют действия по обратному разрешению доменного имени, то есть получают соответствующее доменное имя через IP;
LookupВ основном используется для поиска вышестоящего DNS-сервера;
RecordsВ основном выполняют работу по разрешению доменных имен и возвращают определенные записи.

Суммировать

Структура кода CoreDNS очень понятна: загрузив пользовательскую последовательность подключаемых модулей во время инициализации, они по очереди внедряются в caddy, а при выполнении выполняются последовательно в соответствии с определенной последовательностью подключаемых модулей, формируя Структура цепного вызова. Вся унифицированная структура кода формируется за счет создания DNSServer и персонализированной реализации нескольких подключаемых модулей.