news 2026/9/15 14:06:46

kubeasz 集群 DNS 部署实战:CoreDNS 与 NodeLocal DNSCache 架构解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
kubeasz 集群 DNS 部署实战:CoreDNS 与 NodeLocal DNSCache 架构解析

kubeasz 集群 DNS 部署实战:CoreDNS 与 NodeLocal DNSCache 架构解析

【免费下载链接】kubeasz使用Ansible脚本安装K8S集群,介绍组件交互原理,方便直接,不受国内网络环境影响项目地址: https://gitcode.com/GitHub_Trending/ku/kubeasz

导读

DNS 是 Kubernetes 集群中必须最先部署的基础组件,它为集群中的 Pod 提供集群服务名(SVC)与 Pod hostname 的域名解析能力。本文以 kubeasz 项目为实践载体,系统讲解其内置的 CoreDNS 与 NodeLocal DNSCache 两级 DNS 架构:先说明组件在集群中的作用与选型背景,再给出集成安装、手动部署与验证的完整命令,随后结合仓库中的配置模板与 Ansible 任务源码逐层剖析 Corefile 配置、关键变量与 ipvs/iptables 两种模式的差异,最后列出实战中常见的排错案例,帮助读者在 kubeasz 安装的集群中快速落地并排查集群 DNS 问题。


一、集群 DNS 的角色与选型

在 kubeasz 集群中,DNS 承担两个核心解析任务:

  • 集群服务名 SVC 解析:如nginx.default.svc.cluster.local解析为对应 Service 的 ClusterIP;
  • Pod hostname 解析:通过 headless service 场景下的 pod 记录,或pods insecure模式下的 hostname 解析。

kubeasz 目前推荐并默认部署CoreDNS作为集群 DNS 的实现(历史版本曾基于 kube-dns + dnsmasq + sidecar 三容器方案,对应模板保留在 kubedns.yaml.j2 中作为兼容与迁移参考)。同时,kubeasz 默认启用NodeLocal DNSCache,在集群每个节点上运行一个 DNS 缓存 DaemonSet,以提升 clusterDNS 的查询性能与可靠性。官方测试表明:相比纯 CoreDNS 方案,nodelocaldns + coredns组合能够大幅降低 DNS 查询 timeout 的频次,提升服务稳定性。

说明:原文档中引用的官方 nodelocaldns 说明链接(kubernetes.io 官方文档)可在阅读本文后按需自行检索;本文后续内容均以仓库内实际模板与变量为准。


二、安装集群 DNS:三种方式

kubeasz 已将 CoreDNS 与 NodeLocal DNSCache 自动集成进安装流程,无需单独手工部署。配置模板位于roles/cluster-addon/templates/dns/目录(coredns.yaml.j2nodelocaldns-ipvs.yaml.j2nodelocaldns-iptables.yaml.j2kubedns.yaml.j2)。

1. 随集群一键安装(推荐)

假设集群名为xxxx,在执行ezctl setup全流程安装时,DNS 组件会在第 07 步(集群插件安装)自动完成部署:

# 一键安装整个集群(含 DNS) ezctl setup xxxx all

2. 分步安装

如果集群已就绪,只想单独执行插件安装步骤:

# 只执行第 07 步:安装集群插件(含 coredns、nodelocaldns) ezctl setup xxxx 07

3. 手动安装

kubeasz 在渲染阶段会把模板生成到集群目录{{ cluster_dir }}/yml/下(默认/etc/kubeasz/clusters/xxxx/yml/)。可手动应用生成好的清单文件:

kubectl apply -f /etc/kubeasz/clusters/xxxx/yml/coredns.yaml kubectl apply -f /etc/kubeasz/clusters/xxxx/yml/nodelocaldns.yaml

4. 安装背后的自动化逻辑(源码视角)

从 roles/cluster-addon/tasks/main.yml 可以看到插件的幂等控制方式:

  1. 先执行kubectl get pod --all-namespaces并注册变量pod_info
  2. 只有当pod_info未出现corednsPod 时才import_tasks: coredns.yml
  3. 只有当未出现node-local-dnsPod 时才import_tasks: nodelocaldns.yml

而在 coredns.yml 与 nodelocaldns.yml 中,实际执行的是:

# coredns.yml 核心动作 template: src=dns/coredns.yaml.j2 dest={{ cluster_dir }}/yml/coredns.yaml shell: "{{ base_dir }}/bin/kubectl apply -f {{ cluster_dir }}/yml/coredns.yaml"

两个任务都用when:条件分别受控于配置项:

  • dns_install == "yes":是否安装 CoreDNS(默认开启,见 example/config.yml 中dns_install: "yes");
  • ENABLE_LOCAL_DNS_CACHE|bool:是否启用 NodeLocal DNSCache(默认true)。

此外,nodelocaldns 模板会依据PROXY_MODE自动二选一:

  • PROXY_MODE == 'ipvs'→ 渲染nodelocaldns-ipvs.yaml.j2
  • PROXY_MODE in ["iptables", "nftables"]→ 渲染nodelocaldns-iptables.yaml.j2

两者差异详见下文“四、NodeLocal DNSCache 部署解析”。


三、CoreDNS 部署解析

1. 关键变量与 DNS 服务地址

kubeasz 的 DNS 服务 ClusterIP 并非手工指定,而是由 roles/cluster-addon/vars/main.yml 依据SERVICE_CIDR自动推导,取 Service 网段内第二个可用地址

CLUSTER_DNS_SVC_IP: "{{ SERVICE_CIDR.split('.')[0] }}.{{ SERVICE_CIDR.split('.')[1] }}.{{ SERVICE_CIDR.split('.')[2] }}.{{ SERVICE_CIDR.split('.')[3]|regex_replace('/.*', '')|int + 2 }}"

以默认配置SERVICE_CIDR="10.68.0.0/16"为例,计算得到CLUSTER_DNS_SVC_IP=10.68.0.2——这也解释了后文验证中 Pod 的resolv.confnameserver 10.68.0.2的来源。

其余相关默认值定义在 example/config.yml:

配置项默认值说明
dns_install"yes"是否安装 CoreDNS
corednsVer"__coredns__"CoreDNS 镜像版本(ezdown 渲染时替换为实际版本号)
ENABLE_LOCAL_DNS_CACHEtrue是否启用 NodeLocal DNSCache
dnsNodeCacheVer"__dns_node_cache__"NodeLocal DNSCache 镜像版本
LOCAL_DNS_CACHE"169.254.20.10"节点本地 DNS 监听地址(链路本地地址)
CLUSTER_DNS_DOMAIN"cluster.local"集群 DNS 域名后缀(见 hosts.allinone)

版本号占位符__coredns____dns_node_cache__会在ezdown -D离线下载镜像时被替换为真实版本,这是 kubeasz 离线安装机制的一部分(详见 07-install_cluster_addon.md)。

2. Corefile 核心配置解读

coredns.yaml.j2 中的 ConfigMap 定义了 CoreDNS 的核心行为:

.:53 { errors health { lameduck 5s } ready kubernetes {{ CLUSTER_DNS_DOMAIN }} in-addr.arpa ip6.arpa { pods insecure fallthrough in-addr.arpa ip6.arpa ttl 30 } prometheus :9153 forward . /etc/resolv.conf { max_concurrent 1000 } cache 30 reload loadbalance }

逐项说明:

  • kubernetes cluster.local in-addr.arpa ip6.arpa:接入 Kubernetes API,负责集群域与反向域解析;
    • pods insecure:启用 Pod 记录解析(不做 IP 校验);
    • fallthrough in-addr.arpa ip6.arpa:反向解析不命中时放行给下一插件;
    • ttl 30:集群内记录 TTL 30 秒。
  • forward . /etc/resolv.conf:集群域之外的请求转发给节点/etc/resolv.conf中的上游 DNS(即“默认集成节点 DNS 解析”的实现),max_concurrent 1000限制并发转发数;
  • cache 30:普通记录缓存 30 秒;
  • prometheus :9153:暴露 Prometheus 指标;
  • health/ready:就绪与健康检查端点;
  • loadbalance:对多 A 记录做随机负载均衡。

3. Deployment 与 Service 关键点

  • Service 名称为kube-dnsclusterIP: {{ CLUSTER_DNS_SVC_IP }},即 10.68.0.2),端口 53 UDP/TCP 与 9153 metrics。命名沿用kube-dns是为了兼容旧式 Pod 中写死的kube-dns.kube-system.svc服务名。
  • Pod 标签k8s-app: kube-dns,被 Service selector 选中,这也是 nodelocaldns 中kube-dns-upstreamService 依赖的标签。
  • Deployment 关键配置
    • replicas: 1、RollingUpdate 策略;
    • priorityClassName: system-cluster-critical,保证在资源紧张时优先调度;
    • podAntiAffinity尽量将副本分散到不同节点;
    • 容器镜像为easzlab.io.local:5000/easzlab/coredns:{{ corednsVer }}(离线仓库地址,IfNotPresent);
    • 资源请求cpu: 100m / memory: 70Mi,上限memory: 500Mi
    • 健康检查:liveness 探测/health(8080)、readiness 探测/ready(8181);
    • 安全加固:seccompProfile: RuntimeDefaultallowPrivilegeEscalation: false、仅保留NET_BIND_SERVICE能力、readOnlyRootFilesystem: true

四、NodeLocal DNSCache 部署解析

NodeLocal DNSCache 以 DaemonSet 方式在每个节点运行k8s-dns-node-cache,监听链路本地地址169.254.20.10,作为 Pod 侧 DNS 请求的第一跳缓存,只有未命中的请求才通过force_tcp转发给 CoreDNS,从而显著减少 DNS timeout。

1. 两种模板的差异(ipvs vs iptables/nftables)

从 nodelocaldns-ipvs.yaml.j2 与 nodelocaldns-iptables.yaml.j2 对比可见:

对比项ipvs 模式iptables/nftables 模式
Corefilebind{{ LOCAL_DNS_CACHE }}{{ LOCAL_DNS_CACHE }} {{ CLUSTER_DNS_SVC_IP }}(同时绑定 DNS Service IP)
集群域转发目标forward . {{ CLUSTER_DNS_SVC_IP }}(显式指定)forward . __PILLAR__CLUSTER__DNS__(占位符由启动参数注入)
启动参数-localip{{ LOCAL_DNS_CACHE }}{{ LOCAL_DNS_CACHE }},{{ CLUSTER_DNS_SVC_IP }}

原因:iptables/nftables 模式下,nodelocaldns 需要同时劫持(bind)原kube-dnsService 的 ClusterIP,才能把原本发往10.68.0.2的请求接管到本地缓存;而 ipvs 模式则通过 ipvs 规则天然实现,因此只需绑定本地地址。

2. Corefile 缓存策略

以 ipvs 模板为例:

{{ CLUSTER_DNS_DOMAIN }}:53 { errors cache { success 9984 30 denial 9984 10 } reload loop bind {{ LOCAL_DNS_CACHE }} forward . {{ CLUSTER_DNS_SVC_IP }} { force_tcp } prometheus :9253 health {{ LOCAL_DNS_CACHE }}:8099 }
  • 集群域请求:命中缓存则直接返回(成功记录缓存 9984 条/30 秒,否定记录 9984 条/10 秒);未命中则force_tcpTCP转发给 CoreDNS,避免 UDP 大包分片与超时问题;
  • in-addr.arpa/ip6.arpa:反向域同样走本地缓存与 TCP 转发;
  • .(根域):转发给上游 DNS(__PILLAR__UPSTREAM__SERVERS__),即节点上游;
  • metrics 端口9253,health 端口8099

3. DaemonSet 关键配置

  • hostNetwork: true+dnsPolicy: Default,直连节点网络,不依赖集群 DNS;
  • priorityClassName: system-node-critical
  • tolerations 容忍CriticalAddonsOnlyNoExecuteNoSchedule,保证所有节点(含控制面)都能调度;
  • 需要NET_ADMIN能力以写入 iptables/ipvs 规则;
  • 挂载宿主机/run/xtables.lock以避免并发修改 iptables 时锁冲突;
  • 提供 headless Servicenode-local-dnsclusterIP: None)暴露 9253 端口给 Prometheus 抓取指标。

4. 与 kubelet 的衔接(重要前提)

NodeLocal DNSCache 要真正生效,还需将 kubelet 的--cluster-dns指向169.254.20.10,并配置--cluster-domaincluster.local。在 kubeasz 中,这一衔接由 kubelet-config.yaml.j2 完成;验证时 Pod 内resolv.confnameserver即应指向169.254.20.10(见下文验证章节,若仍为10.68.0.2,则说明 kubelet 未配置 local dns 地址或配置未生效)。


五、验证 DNS 服务

1. 创建测试服务

kubectl run nginx --image=nginx --expose --port=80

确认服务已就绪:

kubectl get pod | grep nginx nginx-7cbc4b4d9c-fl46v 1/1 Running 0 1m kubectl get svc | grep nginx nginx ClusterIP 10.68.33.167 <none> 80/TCP 1m

2. 在测试 Pod 内验证解析

kubectl run test --rm -it --image=alpine /bin/sh If you don't see a command prompt, try pressing enter. / # cat /etc/resolv.conf nameserver 10.68.0.2 search default.svc.cluster.local. svc.cluster.local. cluster.local. options ndots:5 # 测试集群内部服务解析 / # nslookup nginx.default.svc.cluster.local Server: 10.68.0.2 Address 1: 10.68.0.2 kube-dns.kube-system.svc.cluster.local Name: nginx Address 1: 10.68.33.167 nginx.default.svc.cluster.local / # nslookup kubernetes.default.svc.cluster.local Server: 10.68.0.2 Address 1: 10.68.0.2 kube-dns.kube-system.svc.cluster.local Name: kubernetes Address 1: 10.68.0.1 kubernetes.default.svc.cluster.local # 测试外部域名的解析,默认集成node的dns解析 / # nslookup www.baidu.com Server: 10.68.0.2 Address 1: 10.68.0.2 kube-dns.kube-system.svc.cluster.local Name: www.baidu.com Address 1: 180.97.33.108 Address 2: 180.97.33.107 / #

输出要点解读:

  • resolv.confnameserver 10.68.0.2为集群 DNS Service IP,search域与ndots:5由 kubelet 注入;
  • 集群内部名解析返回 ClusterIP:nginx → 10.68.33.167kubernetes → 10.68.0.1(apiserver 集群 IP);
  • 外部域名(www.baidu.com)由 CoreDNS 的forward . /etc/resolv.conf转发至节点上游 DNS 完成解析,多个 A 记录经loadbalance插件随机返回。

若集群启用了 NodeLocal DNSCache 且 kubelet 正确指向169.254.20.10,上述测试中的nameserver应显示为169.254.20.10,解析结果不变。


六、实战排错案例

案例 1:calico 网络下 DNS Pod CrashLoopBackOff(原文档 Note1)

使用 calico 作为网络插件时,安装集群后直接安装 DNS 组件可能出现如下故障:calico 分配 Pod 地址时会从网段的第一个地址(网络地址)开始分配,导致kube-dnsPod 恰好拿到与网络地址冲突的 IP,出现CrashLoopBackOff

故障现象:

$ kubectl get pod --all-namespaces -o wide NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE default busy-5cc98488d4-s894w 1/1 Running 0 28m 172.20.24.193 192.168.97.24 kube-system calico-kube-controllers-6597d9c664-nq9hn 1/1 Running 0 1h 192.168.97.24 192.168.97.24 kube-system calico-node-f8gnf 2/2 Running 0 1h 192.168.97.24 192.168.97.24 kube-system kube-dns-69bf9d5cc9-c68mw 0/3 CrashLoopBackOff 27 31m 172.20.24.192 192.168.97.24

解决办法(临时):删除该 Pod,让其自动重建并获取后续可用 IP:

$ kubectl delete pod -n kube-system kube-dns-69bf9d5cc9-c68mw

案例 2:busybox 内 nslookup 解析异常(原文档 Note2)

使用kubectl run test -it --rm --image=busybox /bin/sh进行解析测试可能会失败——busybox 内置的 nslookup 程序存在已知 bug(例如对SRV记录、搜索域拼接等处理不正确)。因此推荐使用 alpine 镜像(如上文验证章节所示)进行 DNS 解析验证,或改用nslookup之外的diggetent hosts等方式交叉确认。

案例 3:Pod 无法解析(排查路径)

当业务 Pod 报 “could not resolve host” 时,按以下顺序排查:

  1. kubectl get pod -n kube-system -o wide | grep -E 'coredns|node-local-dns':确认两组 Pod 均 Running;
  2. 查看 Podresolv.confnameserver是否为169.254.20.10(启用 nodelocaldns)或10.68.0.2(纯 coredns),search域是否包含cluster.local
  3. 在集群内直接用nslookup测试集群域与外部域,判断是 CoreDNS 不可达还是上游转发失败;
  4. 若为 CoreDNS 异常,kubectl logs -n kube-system <coredns-pod>查看forward错误日志,并确认kube-dnsService 的clusterIPCLUSTER_DNS_SVC_IP一致。

七、小结

在 kubeasz 集群中,DNS 采用“CoreDNS(集群级解析)+ NodeLocal DNSCache(节点级缓存)”两级架构:

  • CoreDNS 通过kubernetes插件解析集群服务与 Pod 记录,通过forward插件代理外部域名;
  • NodeLocal DNSCache 以 DaemonSet 在每个节点缓存并 TCP 转发请求,显著降低 DNS timeout 频次,提升稳定性;
  • 部署完全融入ezctl setup自动化流程,由dns_installENABLE_LOCAL_DNS_CACHE两个开关控制,模板按PROXY_MODE自动选择 ipvs 或 iptables/nftables 变体;
  • 关键配置点集中在 roles/cluster-addon/templates/dns/、roles/cluster-addon/vars/main.yml 与 example/config.yml,Kubelet 侧衔接见 kubelet-config.yaml.j2。

掌握上述部署与验证方法后,即可在 kubeasz 集群中快速交付一个稳定、可观测、可排障的集群 DNS 服务。

【免费下载链接】kubeasz使用Ansible脚本安装K8S集群,介绍组件交互原理,方便直接,不受国内网络环境影响项目地址: https://gitcode.com/GitHub_Trending/ku/kubeasz

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 14:06:06

基于uniapp+Vue3的露营App开发实践:多端适配、地图定位与弱网优化

简介&#xff1a;基于uniapp与Vue框架开发的《露营》App完整项目&#xff0c;面向希望学习跨端应用开发及前后台系统设计的开发者与学生&#xff0c;也非常适合作为课程设计或毕业设计的参考方案。项目基于HBuilder X平台构建&#xff0c;用户端实现了首页、露营信息、露营教程…

作者头像 李华
网站建设 2026/9/15 14:02:49

如何下载 XRay-DINO 权重并加载 xray_dino_vitl16 骨干模型?

如何下载 XRay-DINO 权重并加载 xray_dino_vitl16 骨干模型&#xff1f; 【免费下载链接】dinov2 PyTorch code and models for the DINOv2 self-supervised learning method. 项目地址: https://gitcode.com/GitHub_Trending/di/dinov2 DINOv2 仓库在 2025-12-18 新增了…

作者头像 李华