拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Kubernetes服务发现核心:CoreDNS架构原理与实战配置指南

1. 项目概述为什么Kubernetes离不开自己的DNS在Kubernetes集群里服务发现是个基础到不能再基础却又至关重要的问题。想象一下你部署了一个名为my-api的微服务它可能会因为扩缩容、节点故障或滚动更新其Pod的IP地址随时都在变。如果另一个服务my-frontend需要通过IP来调用my-api那简直就是一场运维灾难你需要不断更新配置这完全违背了云原生的弹性与自动化理念。这就是Kubernetes内置DNS服务存在的核心价值。它不是一个可选项而是集群的“神经系统”负责将稳定的服务名Service Name解析为动态变化的Pod IP地址。默认情况下从Kubernetes 1.13版本开始这个“神经系统”的核心组件就是CoreDNS。它取代了早期的kube-dns以其更高的性能、更灵活的插件化架构成为了Kubernetes服务发现的官方标准。简单来说没有CoreDNSKubernetes集群内的服务间通信将退回到原始的、手动维护IP地址的“石器时代”集群的自动化管理和微服务架构的优势将无从谈起。无论你是刚接触k8s的开发者还是负责维护生产集群的运维工程师深入理解CoreDNS的工作原理、配置和排错都是构建稳定、可观测的云原生应用的必修课。2. CoreDNS在Kubernetes中的架构与核心原理2.1 CoreDNS的核心工作流程要理解CoreDNS首先要明白它在Kubernetes集群中扮演的角色。它不是一个独立于集群外的传统DNS服务器而是一个以Pod形式运行在kube-system命名空间下的集群附加组件。其工作流程可以概括为以下几个核心步骤监听与查询接收CoreDNS Pod通过一个名为kube-dns的Service对外暴露服务其ClusterIP通常是10.96.0.10可配置。集群内所有Pod的/etc/resolv.conf文件中的nameserver都被配置指向这个IP。当Pod内的应用程序发起一个DNS查询例如查询my-api.default.svc.cluster.local时请求首先到达CoreDNS。插件链处理这是CoreDNS设计的精髓。它不像传统DNS服务器那样有固定的处理逻辑而是通过一个可配置的插件链Plugin Chain来处理请求。一个查询请求会像流水线一样依次经过配置文件中启用的各个插件。每个插件可以决定是直接响应、修改请求、转发请求还是将请求传递给下一个插件。与Kubernetes API交互对于Kubernetes集群内的域名查询最关键的一个插件是kubernetes插件。当查询的域名匹配集群内服务域名格式如.svc.cluster.local时kubernetes插件会向Kubernetes API Server发起查询获取对应Service、Pod或Endpoints的真实IP地址信息。响应返回kubernetes插件从API Server获取到IP信息后将其封装成标准的DNS响应报文沿原路返回给发起查询的Pod。对于集群外的域名如www.example.comCoreDNS通常会配置forward插件将查询请求转发到上游的DNS服务器如宿主机配置的DNS或公共DNS8.8.8.8。这个流程确保了服务名的解析是完全动态的、实时的与Kubernetes的资源状态保持严格一致。2.2 关键配置文件解析CorefileCoreDNS的所有行为都由一个名为Corefile的配置文件驱动。在Kubernetes中这个配置文件通常以一个ConfigMap的形式存在名为coredns位于kube-system命名空间。我们可以通过kubectl get configmap coredns -n kube-system -o yaml来查看其内容。一个典型的默认配置如下apiVersion: v1 data: Corefile: | .:53 { errors health { lameduck 5s } ready kubernetes cluster.local in-addr.arpa ip6.arpa { pods insecure fallthrough in-addr.arpa ip6.arpa ttl 30 } prometheus :9153 forward . /etc/resolv.conf cache 30 loop reload loadbalance } kind: ConfigMap我们来逐段拆解这个核心配置.:53这定义了一个服务器块Server Block监听所有网卡.的53端口DNS标准端口。errors将错误日志打印到标准输出。health提供健康检查端点默认在http://localhost:8080/health。ready提供就绪检查端点当所有插件加载完成后该端点返回200 OK。这对于Kubernetes的Readiness Probe很重要。kubernetes cluster.local ...这是核心插件。它告诉CoreDNS负责解析cluster.local及其子域如svc.cluster.local以及反向解析域in-addr.arpa,ip6.arpa的查询。pods insecure启用Pod的DNS记录格式为pod-ip.namespace.pod.cluster.local。insecure选项意味着即使Pod没有关联的Service也会为其创建A记录。在生产环境中出于安全考虑有时会省略此选项或使用pods verified模式。fallthrough如果查询的域名在kubernetes插件域内但未找到记录则将查询“坠落”到插件链中的下一个插件例如forward插件处理。ttl 30为DNS记录设置生存时间TTL为30秒。较短的TTL有助于客户端更快地感知到后端Pod IP的变化。prometheus :9153在9153端口暴露Prometheus格式的指标方便监控CoreDNS的性能和查询量。forward . /etc/resolv.conf这是处理集群外域名的关键。它将所有未在kubernetes插件域内匹配的查询用.表示转发到CoreDNS Pod内/etc/resolv.conf文件中定义的上游DNS服务器。这通常是宿主机或自定义的DNS。cache 30启用缓存缓存时间为30秒可以显著减少对上游DNS和Kubernetes API的重复查询压力。loop检测到简单的DNS转发循环时发出警告并停止CoreDNS进程。reload允许自动重新加载Corefile。当ConfigMap内容更改后CoreDNS会在一段时间后自动加载新配置无需重启Pod。loadbalance对于同一个服务名有多个后端IP即Service对应多个Pod的情况以轮询round-robin方式返回IP地址实现基本的DNS负载均衡。理解这个Corefile是掌握CoreDNS配置和故障排查的基础。3. Kubernetes中的DNS域名解析规则详解在Kubernetes集群内DNS解析有一套完整的命名规范。理解这些规则是进行服务调用和问题诊断的前提。3.1 完整的服务域名格式一个Service在集群内拥有一个完整的、可被DNS解析的域名Fully Qualified Domain Name, FQDN。其标准格式为service-name.namespace-name.svc.cluster.localservice-name你定义的Service资源名称例如my-api。namespace-nameService所在的命名空间例如default。如果调用方Pod与被调用的Service在同一个命名空间可以省略命名空间及之后的部分直接使用service-name。svc.cluster.local这是Kubernetes集群的默认集群域Cluster Domain。在大多数部署中它默认为cluster.local但也可以在kubelet或kube-apiserver的启动参数中通过--cluster-domain进行自定义。示例 假设在production命名空间下有一个名为redis-master的Service。在production命名空间内的Pod可以直接使用redis-master来访问它。在其他命名空间如default的Pod则需要使用完整的FQDNredis-master.production.svc.cluster.local。3.2 Pod的DNS策略与解析配置每个Pod都可以通过dnsPolicy字段来指定其DNS配置策略这直接影响Pod内/etc/resolv.conf文件的生成。主要有以下几种策略ClusterFirst默认这是最常用的策略。Pod的/etc/resolv.conf中的nameserver会被设置为集群DNS服务CoreDNS的ClusterIP。任何不匹配cluster.local后缀的DNS查询都会被CoreDNS转发到上游DNS服务器。apiVersion: v1 kind: Pod metadata: name: busybox spec: dnsPolicy: ClusterFirst # 默认值通常无需显式指定 containers: - name: busybox image: busybox:1.28 command: [sh, -c, sleep 3600]ClusterFirstWithHostNet对于使用主机网络hostNetwork: true的Pod如果希望它仍然使用集群DNS则需要指定此策略。因为使用主机网络的Pod默认会继承宿主机的/etc/resolv.conf。DefaultPod直接从其运行的节点上继承DNS配置。即Pod内的/etc/resolv.conf文件与节点上的文件一致。这通常意味着Pod会使用宿主机配置的公共DNS或企业内网DNS而无法解析集群内的Service域名。None此策略允许你通过dnsConfig字段完全自定义Pod的DNS配置。它提供了最高的灵活性。apiVersion: v1 kind: Pod metadata: name: custom-dns-pod spec: dnsPolicy: None dnsConfig: nameservers: - 8.8.8.8 - 1.1.1.1 searches: - ns1.svc.cluster.local - my.dns.search.suffix options: - name: ndots value: 2 - name: edns0nameservers自定义DNS服务器列表。searchesDNS搜索域列表。当查询的主机名不是FQDN时系统会依次尝试附加这些搜索域。Kubernetes默认会为Pod添加namespace.svc.cluster.local、svc.cluster.local和cluster.local等搜索域。optionsDNS解析器选项。其中ndots尤为重要它指定了一个域名中必须包含的点号.数量少于这个数量的查询会先尝试附加搜索域。默认值为ndots:5在Kubernetes环境下过高的ndots值可能导致不必要的搜索域查询影响解析效率。有时为了优化会将其设置为2或3。3.3 Headless Service与StatefulSet的特殊解析对于无头服务Headless Service即spec.clusterIP: None和StatefulSetDNS解析行为有所不同这对于有状态应用至关重要。Headless Service当查询一个Headless Service的域名时CoreDNS返回的不是一个单一的ClusterIP而是该Service后端所有Pod的IP地址列表。这允许客户端直接与Pod通信常用于实现自定义的负载均衡或主从选举等场景。StatefulSetStatefulSet管理的Pod拥有稳定的、可预测的网络标识。其Pod主机名的格式为statefulset-name-ordinal。同时每个Pod会获得一个唯一的DNS记录pod-name.service-name.namespace.svc.cluster.local。这使得在StatefulSet的Pod之间可以通过固定的DNS名称相互发现例如在Redis Sentinel或MongoDB副本集中非常有用。4. CoreDNS的部署、配置与优化实操4.1 部署与基础检查在通过kubeadm等工具部署的Kubernetes集群中CoreDNS通常是默认安装的。你可以通过以下命令检查其状态# 检查CoreDNS的Deployment和Pod状态 kubectl get deployment coredns -n kube-system kubectl get pods -l k8s-appkube-dns -n kube-system -o wide # 检查CoreDNS的Service kubectl get svc kube-dns -n kube-system # 查看CoreDNS的配置ConfigMap kubectl get configmap coredns -n kube-system -o yaml # 查看CoreDNS Pod的日志排查启动或运行时错误 kubectl logs -f deployment/coredns -n kube-system如果CoreDNS没有运行或者你想自定义部署可以参考官方提供的部署清单。但更常见的操作是修改其ConfigMap来调整行为。4.2 自定义CoreDNS配置常见场景场景一添加自定义域名解析如解析内网服务假设公司内网有一个数据库域名为internal-db.corp.comIP为10.10.10.100。我们希望集群内所有Pod都能通过这个域名访问它。我们可以修改CoreDNS的ConfigMap添加hosts插件。编辑ConfigMapkubectl edit configmap coredns -n kube-system在Corefile的服务器块中添加hosts插件。注意插件顺序通常hosts插件应放在kubernetes插件之前以确保优先使用静态映射。Corefile: | .:53 { errors health ready # 添加hosts插件定义静态映射 hosts { 10.10.10.100 internal-db.corp.com # 可以添加更多映射 fallthrough } kubernetes cluster.local in-addr.arpa ip6.arpa { pods insecure fallthrough in-addr.arpa ip6.arpa } prometheus :9153 forward . /etc/resolv.conf cache 30 loop reload loadbalance }fallthrough指令表示如果hosts插件中没有找到匹配项则继续执行插件链中的下一个插件即kubernetes或forward。场景二配置上游DNS服务器默认情况下CoreDNS使用Pod内的/etc/resolv.conf通常是宿主机的DNS配置作为上游转发器。如果你想指定特定的上游DNS比如使用8.8.8.8和114.114.114.114可以修改forward插件forward . 8.8.8.8 114.114.114.114 { max_concurrent 1000 prefer_udp }这里max_concurrent限制了最大并发查询数prefer_udp表示优先使用UDP协议。场景三启用日志记录以调试DNS查询在排查DNS问题时启用查询日志非常有用。可以添加log插件log这会将所有经过CoreDNS的查询日志打印到标准输出。在生产环境中为了避免日志量过大可以结合filter插件或仅在有问题的Pod上临时启用。4.3 性能优化与监控调整缓存时间cache插件的TTL值默认30秒可以根据集群服务变更频率调整。对于极其稳定的服务可以适当增加缓存时间如300秒以减少API Server压力。对于频繁变更的服务保持较低TTL。监控CoreDNS利用其内置的prometheus插件暴露的指标进行监控是关键。你需要部署Prometheus并配置抓取kube-system命名空间下CoreDNS Pod的9153端口。需要关注的指标包括coredns_dns_request_count_total总请求数按类型A AAAA SRV等和区域zone区分。coredns_dns_request_duration_seconds请求延迟分布。coredns_dns_response_rcode_count_total响应码计数NOERROR NXDOMAIN SERVFAIL等SERVFAIL增多通常意味着上游或API Server问题。coredns_panic_count_totalCoreDNS进程崩溃次数。资源请求与限制确保为CoreDNS的Deployment设置合适的资源请求和限制防止其因资源不足被驱逐或OOMKilled。通常建议内存从128Mi起步根据负载调整。resources: limits: memory: 256Mi cpu: 200m requests: memory: 128Mi cpu: 100m副本数与反亲和性对于生产集群至少运行2个CoreDNS Pod副本以确保高可用。并配置Pod反亲和性让它们调度到不同的节点上避免节点故障导致DNS服务完全中断。spec: replicas: 2 strategy: type: RollingUpdate affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: k8s-app operator: In values: - kube-dns topologyKey: kubernetes.io/hostname5. 常见DNS问题排查与修复实录在实际运维中DNS问题是导致Pod网络连通性故障的常见原因。下面是一个系统性的排查流程和常见问题案例。5.1 系统性排查流程当遇到服务间无法通过域名通信时可以按照以下步骤排查检查Pod本身网络与DNS配置# 进入出问题的Pod或启动一个临时调试Pod如busybox kubectl exec -it problem-pod-name -- sh # 检查DNS配置 cat /etc/resolv.conf # 正常应看到 nameserver 指向集群DNS IP (如 10.96.0.10) # 测试基础网络连通性 ping 10.96.0.10 # 测试是否能ping通CoreDNS Service IP nc -zv 10.96.0.10 53 # 测试53端口是否可达 # 使用nslookup或dig进行DNS查询测试 nslookup kubernetes.default.svc.cluster.local # 或安装dig后使用 dig 10.96.0.10 kubernetes.default.svc.cluster.local short检查CoreDNS服务状态# 确认CoreDNS Pod是否Running且Ready kubectl get pods -n kube-system -l k8s-appkube-dns # 查看CoreDNS Pod日志是否有错误 kubectl logs -n kube-system deployment/coredns --tail50 # 确认kube-dns Service是否存在且Endpoints正常 kubectl get svc kube-dns -n kube-system kubectl get endpoints kube-dns -n kube-system检查Kubernetes网络插件CNIDNS依赖底层网络。确保Calico、Flannel等CNI插件工作正常Pod IP分配和路由没有问题。检查Node节点DNS配置CoreDNS的forward插件依赖节点DNS。检查节点/etc/resolv.conf确保上游DNS服务器可达且没有配置错误。5.2 典型问题案例与解决方案案例一Pod内/etc/resolv.conf的ndots值过高导致解析延迟症状应用调用内部服务域名时偶尔出现超时但直接使用完整FQDN如service.namespace.svc.cluster.local则正常。 原因分析Pod内/etc/resolv.conf默认options ndots:5。当应用查询一个包含少于5个点如redis-master的域名时解析器会依次尝试附加所有搜索域如redis-master.default.svc.cluster.localredis-master.svc.cluster.localredis-master.cluster.local等直到成功或全部失败。这会增加不必要的查询次数和延迟。 解决方案在Pod或Deployment的dnsConfig中降低ndots值或鼓励应用使用完整的FQDN。spec: dnsPolicy: None dnsConfig: options: - name: ndots value: 2案例二CoreDNS Pod内存不足OOMKilled症状CoreDNS Pod频繁重启kubectl describe pod显示原因为OOMKilled。 原因分析查询量过大、缓存设置不当或存在内存泄漏的插件可能导致内存使用量激增。 解决方案增加CoreDNS Pod的内存限制limits.memory。检查并优化Corefile配置例如减少不必要的日志输出log插件调整缓存大小。监控内存使用趋势排查是否有异常的查询流量如DNS放大攻击。案例三无法解析集群外域名如公网域名症状Pod内可以解析kubernetes.default.svc.cluster.local但无法解析www.baidu.com。 排查步骤进入Pod尝试dig 10.96.0.10 www.baidu.com。如果失败说明CoreDNS的上游转发有问题。检查CoreDNS ConfigMap中的forward插件配置确认其指向的上游DNS服务器如/etc/resolv.conf或指定的IP是否可达且正确。登录到CoreDNS Pod所在节点检查节点的网络连通性和DNS配置。检查网络策略NetworkPolicy是否阻止了CoreDNS Pod或节点向上游DNS服务器53端口的出口流量。案例四Headless Service解析返回多个IP但连接失败症状通过nslookup查询Headless Service域名能返回所有Pod IP但应用连接其中某些IP时失败。 原因分析DNS只负责解析不检查Pod的健康状态。返回的IP中可能包含处于NotReady状态的Pod。 解决方案应用端需要实现连接重试和健康检查机制。或者考虑使用readinessProbe并结合publishNotReadyAddresses: false的Service此配置控制不健康的Pod IP是否从Service的Endpoints中移除从而影响DNS解析结果。5.3 调试工具箱准备一些常用的调试镜像和命令能极大提升效率# 1. 启动一个包含dig, nslookup, curl等工具的临时调试Pod kubectl run dns-debug --imagebusybox:1.28 --restartNever --rm -it -- sh # 2. 在Pod内进行DNS查询 nslookup kubernetes.default.svc.cluster.local dig dns-service-ip service-name.namespace.svc.cluster.local A # 3. 从集群外部测试Service需要kubectl端口转发或Ingress # 通常用于测试ClusterIP类型的Service是否工作正常 # 4. 检查CoreDNS的Prometheus指标 # 假设已配置Prometheus可以在Grafana中查看或直接查询 # 例如查询最近5分钟SERVFAIL错误率 sum(rate(coredns_dns_response_rcode_count_total{rcodeSERVFAIL}[5m])) by (pod) / sum(rate(coredns_dns_response_rcode_count_total[5m])) by (pod)DNS问题排查往往需要耐心从Pod内部到CoreDNS自身再到上游和底层网络逐层缩小范围。掌握CoreDNS的原理和这些排查工具能让你在遇到服务发现故障时快速定位并解决问题保障集群的稳定运行。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门