ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

CoreDNS kubernetes 插件完全指南:从 Corefile 配置到集群内 DNS 服务发现

CoreDNS kubernetes 插件完全指南:从 Corefile 配置到集群内 DNS 服务发现 后端网络云原生【免费下载链接】corednsCoreDNS is a DNS server that chains plugins项目地址https://gitcode.com/gh_mirrors/co/coredns点击查看免费下载导读本文围绕 plugin/kubernetes/README.md 展开系统讲解 CoreDNS 的kubernetes插件它如何实现 Kubernetes 的 DNS-Based Service Discovery Specification、如何在 Corefile 中配置集群接入与各类过滤/响应选项、如何借助forward插件实现 stubDomains 与 upstreamNameservers以及 zonal 拓扑寻址、autopath、metadata、metrics 等进阶特性。读完本文你将能够独立编写可运行的 kubernetes 插件配置理解其 informer 缓存与启动同步机制并掌握排查常见行为差异NXDOMAIN vs NODATA、SERVFAIL、负缓存等的源码级依据。插件概述kubernetes插件使 CoreDNS 直接从 Kubernetes 集群中读取 zone 数据Service、Endpoint、Pod、Namespace 等实现 Kubernetes 官方 DNS-Based Service Discovery Specification 中的DNSSchemaVersion常量。在集群中运行 CoreDNS 时它可以作为 kube-dns 的直接替代品在集群外运行时也可通过远程 API endpoint 接入同一套配置。stubDomains 与 upstreamNameservers 的能力由forward插件配合实现见下文示例。需要注意该插件在每个 Server Block 中只能使用一次。这一点在 setup.go 中有强制校验——kubernetesParse循环中对重复出现返回plugin.ErrOnce。从查询处理看插件实现了plugin.Handler接口handler.go对 A/AAAA/TXT/CNAME/PTR/MX/SRV/SOA/NS 等类型分发到plugin.A、plugin.SRV等通用后端函数AXFR/IXFR 直接返回Refused其余类型通过一次“伪 A 查询”区分 NODATA 与 NXDOMAIN。同时它实现了transfer.Transfer接口xfr.go因此 zone 传输需要由transfer插件启用见下文。语法与配置选项基础语法kubernetes [ZONES...]仅写插件名而不带任何参数时插件默认使用 Server Block 声明的 zone它会处理该 zone 内的所有查询并以 in-cluster 方式连接 Kubernetes使用集群 ServiceAccount。默认行为下不为 Service 提供 PTR 记录也不为 Pod 提供 A 记录。如果指定了ZONES...则声明插件对这些 zone 具有权威性。完整配置块kubernetes [ZONES...] { endpoint URL tls CERT KEY CACERT kubeconfig KUBECONFIG [CONTEXT] apiserver_qps QPS apiserver_burst BURST apiserver_max_inflight MAX namespaces NAMESPACE... namespace_labels EXPRESSION labels EXPRESSION pods POD-MODE endpoint_pod_names ttl TTL noendpoints fallthrough [ZONES...] ignore empty_service multicluster [ZONES...] zonal startup_timeout DURATION }这些指令的解析实现在 setup.go 的ParseStanza中下面逐一说明其语义、约束与源码依据。集群连接与认证指令参数说明源码依据endpointURL指定远程 k8s API 地址省略则以 in-cluster 方式连接。设置了kubeconfig时本选项被忽略。可以传多个地址但只有第一个会被使用setup.go 会打印 deprecation 警告kubernetes.gotlsCERT KEY CACERT远程连接的 TLS 证书、私钥与 CA 文件in-cluster 连接未指定 endpoint时忽略同上kubeconfigKUBECONFIG [CONTEXT]用 kubeconfig 文件认证远程集群CONTEXT 可选缺省使用 kubeconfig 中的当前 context支持 TLS、用户名/密码或 token 认证kubeconfig中的集群地址优先setup.go连接建立的核心逻辑在getClientConfigkubernetes.go无 endpoint 时走rest.InClusterConfig()否则用clientcmd.NewNonInteractiveDeferredLoadingClientConfig组装。两种路径都会设置ContentType application/vnd.kubernetes.protobuf与带 CoreDNS 版本、git commit、平台信息的 UserAgent。API 服务器限流保护 apiserver指令说明apiserver_qps QPS客户端到 API server 的每秒最大请求数QPS 限流防止压垮 apiserverapiserver_burst BURST允许超过 QPS 的瞬时突发请求上限apiserver_max_inflight MAX同时进行中的最大并发请求数in-flight 上限三个参数都必须 0setup.go。实现上kubernetes.goQPS/Burst 写入rest.Config的标准限流字段apiserver_max_inflight则通过WrapTransport包装一层信号量RoundTrippernewMaxInflightRoundTripperkubernetes.go请求到达时在信号量上阻塞上下文取消则立即返回错误。命名空间与标签过滤指令说明namespaces NAMESPACE...只暴露列出的命名空间省略则暴露全部namespace_labels EXPRESSION只暴露匹配标签选择器的命名空间例如namespace_labels istio-injectionenabledlabels EXPRESSION只暴露匹配标签选择器的 Kubernetes 对象例如labels environment in (staging, qa),applicationnginx标签选择器语法遵循 Kubernetes 官方 Labels and Selectors再在InitKubeCache中转换为labels.Selector传给 informerkubernetes.go。互斥约束namespaces与namespace_labels不能同时设置解析器会直接报错setup.go。setup_test.go中用namespaces foo barnamespace_labels istio-injectionenabled的用例验证了该错误setup_test.go。服务发现过滤与响应控制指令说明pods POD-MODE设置基于 IP 的 Pod A 记录处理模式详见下表endpoint_pod_names用 endpoint 指向的 Pod 名作为 A 记录中的 endpoint 名称ttl TTL自定义响应 TTL默认 5 秒合法范围 [0, 3600]0 表示禁止缓存noendpoints关闭 endpoint 记录服务禁用 endpoint watch所有 endpoint 查询与 headless service 查询返回 NXDOMAINfallthrough [ZONES...]命中权威 zone 的查询返回 NXDOMAIN 时继续沿插件链向下传递ignore empty_service对没有任何 ready endpoint 的 Service 返回 NXDOMAIN让查询 pod 继续在搜索路径中寻找例如另一集群中的同名服务multicluster [ZONES...]按 MCS-API 定义多集群 zone需安装 ServiceImport/ServiceExport CRD且插件必须对这些 zone 具有权威性zonal为 headless service 启用 zone 作用域名称并发布kubernetes/zone元数据标签见“Zonal Names”一节startup_timeout DURATION启动时等待 informer 缓存同步的超时时间默认 5 秒pods三种模式模式行为disabled默认不处理 Pod 请求一律返回 NXDOMAINinsecure不查证 k8s直接按请求中的 IP 构造 A 记录与通配符 SSL 证书配合时存在被恶意利用的风险为与 kube-dns 向后兼容而保留verified仅当同命名空间存在 IP 匹配的 Pod 时返回 A 记录需要对全集群 Pod 建立 watchCoreDNS 内存中保留每个 Pod 的 IP、名称、命名空间与标签且所有 Pod 状态变化都会流式同步到 CoreDNS因此会占用额外内存并增加 apiserver 负载pods取值非法时解析器报错wrong value for pods: %s, must be one of: disabled, verified, insecuresetup.go。Pod 记录查找逻辑见findPodskubernetes.goinsecure模式只校验 IP 可解析、命名空间已暴露verified模式通过APIConn.PodIndex(ip)反查 Pod 缓存并校验命名空间。注意 Pod watch 默认关闭仅当pods verified时initPodCache才为 truekubernetes.goPod informer 才会启动controller.go。ttl约束超出 [0, 3600] 直接报错ttl must be in range [0, 3600]setup.go默认值常量defaultTTL 5定义在 kubernetes.go。fallthrough语义查询在插件权威 zone 内结果为 NXDOMAIN 时若配置了该选项查询将沿插件链继续传递给下游插件不列 zone 则对所有权威 zone 生效列出如in-addr.arpa、ip6.arpa则只对列出的 zone 生效。handler 中通过k.Fall.Through(state.Name())判断handler.go。ignore empty_service实现findServices中对非 ExternalName、非 headless 的 Service 统计 EndpointSlice 中的 ready 地址数为 0 则跳过NXDOMAINkubernetes.go。multicluster约束所有多集群 zone 必须出现在插件的权威 zone 列表中否则报错is not authoritative for the multicluster zone ...setup.go。启用后插件会额外创建 MCS API 客户端并 watch ServiceImport 与带multicluster.kubernetes.io/service-name标签的 EndpointSlicekubernetes.go、controller.go查询走findMultiClusterServiceskubernetes.goSRV 记录可携带clusterId维度。zonal与noendpoints互斥zone 作用域名称依赖 endpoint 缓存二者同开是配置错误setup.go。同时启用zonal后 informer 使用EndpointSliceToEndpointsWithZones转换额外记录每个 endpoint 的拓扑 zonecontroller.go。endpoint_pod_names名称选择规则默认优先使用 endpoint 的 hostname否则用 endpoint IP 的连字符形式如1-2-3-4.my-service.namespace.svc.cluster.local.启用本指令后hostname 缺省时改用 endpoint 指向的 Pod 名若没有 Pod 或 Pod 名超过 63 字符则退回连字符 IP 形式。实现见endpointHostnamekubernetes.go其中 IPv6 地址会把:替换为-并在尾部补0。Zonal Names基于拓扑 zone 的寻址启用zonal后headless service 额外应答 zone 作用域的名称topology-zone.pin._zone.service.namespace.svc.zone topology-zone.prefer._zone.service.namespace.svc.zone例如us-west-2a.pin._zone.db.prod.svc.cluster.local只返回 EndpointSlicezone字段为us-west-2a的dbendpoints。zone 值是指令左侧所有标签拼接而成Kubernetes zone 标签值本身可含点号如corp.example.com.pin._zone.db.prod.svc.cluster.local选中 zonecorp.example.com。该语法的解析见 parse.go_zone锚点标签zoneLabel位于服务名左侧三个标签处该位置在历史上永远是“查询过长”NXDOMAIN下划线又使其不可能落入任何主机名形态的语法因此不会与现有记录冲突。指令标签只有pin与prefer两个未知指令保持原有的过长 NXDOMAINerrInvalidRequest。pin与prefer的语义差异pin——只返回 zone 本地 endpoints。zone 标签下没有任何 endpoint无论是 zone 已排空还是拼写错误都返回 NODATA“没有 endpoint 属于该 zone”两种情况下答案一致且每个副本回答相同解析失败依旧可见。prefer——有 zone 本地 endpoints 则返回它们否则返回该服务全部 endpoints。一个查询即可完成无需客户端兜底逻辑放宽范围是在名字里选择的绝不会对pin静默放宽。两种指令都应答 A/AAAA 与 SRV过滤发生在 endpoint 选择阶段因此 SRV 记录及其附加段也按 zone 过滤对其他查询类型应答 NODATA且所有副本回答一致。不存在的服务依旧 NXDOMAINClusterIP 与 ExternalName 服务对 zone 作用域名称返回 NXDOMAIN——zone 作用域名称仅为 headless service 定义VIP 拓扑请使用trafficDistribution。实现上findServices中带 zone 标签的名称只要 headless 服务存在就将 err 置 nilNODATA再通过addForZone按ep.Zones[addr.IP]过滤prefer在 zone 为空时回退addForZone()kubernetes.go。需要特别说明它与 Kubernetes Topology Aware Routing 的关系pin/prefer是拓扑寻址原语而非trafficDistribution的扩展。它们基于 endpoint 的物理拓扑 zoneEndpoint.Zone由 EndpointSlice 控制器发布无需 Service 侧 opt-in而不是路由 hintEndpoint.Hints.ForZones仅在 Service 通过trafficDistribution或遗留注解service.kubernetes.io/topology-mode: Auto选择后才存在。因此客户端在名字里指定 zone 拿到的就是实际位于该 zone 的 endpoints。运维注意事项在共享 Service 后的每个副本上都应启用该选项再让客户端使用_zone名称——未启用选项的副本会对这些名称应答 NXDOMAIN客户端会按名称对该否定结果做负缓存负缓存 TTL 遵循 SOA minttl即ttl选项。Zone 作用域名称仅在查询时应答不包含在 zone 传输中。此外zonal 名称在multiclusterzone 内未定义没有任何 zone 的 EndpointSlice 中的 endpoint 不会被任何 zone 选择器匹配。启动与缓存同步机制CoreDNS 启动并启用 kubernetes 插件时会延迟提供服务最多 5 秒可用startup_timeout调整等待连接 Kubernetes API 并同步所有对象 watch。若 5 秒内未完成CoreDNS 照常启动服务插件继续尝试连接与同步此时对尚未同步的 Kubernetes 记录CoreDNS 返回SERVFAIL。该机制在 kubernetes.go 的onStart中实现后台启动dnsControl.Run()controller.go 启动 svc/ep/pod/ns 及可选 svcImport/mcEp 共 6 个 informer每 100ms 轮询HasSynced()每 500ms 打一条 “waiting for Kubernetes API before starting server” 日志超时则警告 “starting server with unsynced Kubernetes API” 并放行。HasSynced是全部启用的控制器同步状态的与运算controller.go。handler 中未同步时对 name error 返回RcodeServerFailurehandler.go。插件对端点的 watch 走discovery.EndpointSlicesAPIcontroller.go 使用discovery.EndpointSlice{}informer这也是“Monitoring Kubernetes Endpoints”一节的实现依据。就绪状态方面插件实现了ready.Readiness接口ready.go与 API 同步完成后向ready插件报告就绪。PTR 记录插件为每个被 Service 选中的 Pod 创建 PTR 记录通过 endpoint 的 IP 反查。若某个 Pod 被多个 Service 选中则每个选中它的 Service 都会生成一条独立的 PTR 记录。相关反向索引epIPIndexEndpointsIP与svcIPIndex/svcExtIPIndex定义在 controller.go反查逻辑见EpIndexReverse、SvcIndexReverse、SvcExtIndexReversecontroller.go。完整配置示例场景一处理cluster.localzone 内所有查询in-cluster 连接并验证 Pod 存在性10.0.0.0/17 cluster.local { kubernetes { pods verified } }该配置同时处理10.0.0.0/17反查 zone 的in-addr.arpaPTR 请求。注意插件要求至少有一个非反向 zoneprimaryZoneIndex检查setup.go。场景二只选择性暴露部分命名空间kubernetes cluster.local { namespaces test staging }场景三CoreDNS 运行在集群外连接远程集群kubernetes cluster.local { endpoint https://k8s-endpoint:8443 tls cert key cacert }场景四多集群MCS-APIkubernetes cluster.local clusterset.local { multicluster clusterset.local }启用 zone 传输zone 传输AXFR/IXFR通过transfer插件启用kubernetes 插件实现了transfer.Transfer接口xfr.goTransfer方法会检查请求 zone 是否为插件权威 zone、生成 SOA随后按记录类型SOA/NS/A/AAAA/SRV/PTR/TXT 等流式输出记录并支持 IXFR 回退serial 相同时只发 SOA。启用方式参见transfer插件文档 plugin/transfer/README.md。注意 zonal 名称仅查询时应答不参与 zone 传输。stubDomains 与 upstreamNameserverskubernetes 插件的 stubDomain 与 upstreamNameserver 能力由forward插件实现。以下配置把example.local转发给10.100.0.10:53stubDomain并用8.8.8.8:53解析不在cluster.local或example.local中的名称upstreamNameservercluster.local:53 { kubernetes cluster.local } example.local { forward . 10.100.0.10:53 } . { forward . 8.8.8.8:53 }上述配置等价于如下 Kube-DNS stubDomains/upstreamNameservers 配置stubDomains: | {“example.local”: [“10.100.0.10:53”]} upstreamNameservers: | [“8.8.8.8:53”]AutoPath服务端搜索路径补全kubernetes 插件可与autopath插件配合在 Kubernetes 集群中实现服务端搜索路径补全。使用前提pods必须设置为verified到达 CoreDNS 的 DNS 报文中的远端 IP 必须是发送请求的 Pod 的 IP。配置示例cluster.local { autopath kubernetes kubernetes { pods verified } }实现见 autopath.goAutoPath方法按请求来源 Pod 的命名空间生成搜索列表ns.svc.zone、svc.zone、zone再接/etc/resolv.conf的搜索项并以空串哨兵结尾。若pods非verifiedinitPodCache为 false则直接返回 nilautopath.go。Pod 反查通过podWithIP完成autopath.go。Metadata查询上下文元数据启用metadata插件后kubernetes 插件发布以下元数据kubernetes/endpoint查询中的 endpoint 名称kubernetes/kind查询中的资源类型pod 或 svckubernetes/namespace查询中的命名空间kubernetes/port-nameSRV 查询中的端口名kubernetes/protocolSRV 查询中的协议kubernetes/service查询中的服务名kubernetes/client-namespace客户端 Pod 的命名空间见下方前提kubernetes/client-pod-name客户端 Pod 的名称见下方前提kubernetes/client-label/label key客户端 Pod 上的某个标签见下方前提kubernetes/client-*系列通过把 DNS 请求报文中的客户端 IP 关联到已知 Pod IP 实现metadata.go 中k.podWithIP(state.IP())因此需要pods verified模式已启用到达 CoreDNS 的报文远端 IP 必须是发送请求 Pod 的 IP。kubernetes/zone标签仅在启用zonal时发布请求的拓扑 zone非 zonal 查询为空。Metrics可观测性与 DNS 编程延迟通过prometheus插件启用监控后kubernetes 插件导出以下指标coredns_kubernetes_dns_programming_duration_seconds{service_kind}——DNS 编程延迟 SLI从 Service/Pod 变化到变化传播到 DNS 服务器可服务的时间。service_kind标签取值cluster_ipheadless_with_selectorheadless_without_selector该指标的实现与注释见 object/metrics.go直方图桶从 1ms 起按 2 倍指数增长约 17 分钟封顶基于 EndpointSlice 的endpoints.kubernetes.io/last-change-trigger-time注解计算延迟EndpointLatencyRecorder。注意端点控制器导出该时间戳依赖主节点与节点间时钟无漂移指标可能因此不够精确。以下为客户端级指标用于监控 apiserver 请求延迟与状态码verb标识 apiserver 请求类型host为 apiserver endpoint标签值会做 UTF-8 清洗见 metrics.gocoredns_kubernetes_rest_client_request_duration_seconds{verb, host}——客户端感知的 apiserver 请求延迟按 verb 与 host 分组coredns_kubernetes_rest_client_rate_limiter_duration_seconds{verb, host}——客户端限流器引入的 apiserver 请求延迟按 verb 与 host 分组coredns_kubernetes_rest_client_requests_total{method, code, host}——apiserver 请求总数按 method、status_code 与 host 分组这些指标通过k8s.io/client-go/tools/metrics的注册适配器接入metrics.go。已知问题DNS 编程延迟指标目前尚不支持headless_without_selector这一 service kind见 README 的 Bugs 一节。常见问题速查现象原因与依据查询返回 SERVFAIL插件尚未与 API 同步启动 5 秒内或连接失败重试中见 handler.go默认无 Pod A 记录pods默认disabled需显式配置verified或insecure配置报 “can only be used once”同一 Server Block 中出现多次 kubernetes 指令见 setup.gonamespaces与namespace_labels同开报错二者互斥见 setup.gozonalnoendpoints报错zone 作用域名称依赖 endpoint 缓存见 setup.goheadless 查询返回 NXDOMAIN可能配置了noendpoints所有 headless 查询均 NXDOMAIN或ignore empty_service无 ready endpoint深入阅读插件文档主体plugin/kubernetes/README.md配置解析与约束setup.go、setup_test.go查询分发与响应handler.go名称解析语法SRV/endpoint/zonalparse.go后端查找逻辑kubernetes.goinformer 缓存与对象索引controller.go、object/相关插件autopathplugin/autopath/README.md、transferplugin/transfer/README.md、forwardplugin/forward/README.md、metadataplugin/metadata/README.md、prometheusplugin/metrics/README.md赞分享后端网络云原生【免费下载链接】corednsCoreDNS is a DNS server that chains plugins项目地址https://gitcode.com/gh_mirrors/co/coredns点击查看免费下载相关推荐CoreDNS k8s_external 插件完全指南将 Kubernetes 服务 ExternalIP 暴露到集群外 DNS 区CoreDNS k8s_external 插件完全指南将 Kubernetes 服务 ExternalIP 暴露到集群外 DNS 区 导读 本文围绕 Core后端网络云原生在 follow-me-install-kubernetes-cluster 中部署 CoreDNS 插件实现 Kubernetes 集群 DNS 服务发现在 follow me install kubernetes cluster 中部署 CoreDNS 插件实现 Kubernetes 集群 DNS 服务发现文档教程云原生CoreDNS 完全指南以插件链为核心的 DNS 服务器与转发器编译、Corefile 配置到多协议部署CoreDNS 完全指南以插件链为核心的 DNS 服务器与转发器编译、Corefile 配置到多协议部署 CoreDNS 是一个用 Go 编写的 DNS后端网络云原生上一篇Windows Defender完全移除终极指南专业级系统安全控制解决方案下一篇如何在浏览器中一键转换图片格式3种主流格式快速转换指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表