CoreDNS
CKA Domain 3 — CoreDNS 在 Kubernetes 中的角色、配置与故障排查
概述
CoreDNS 是 Kubernetes 集群的默认 DNS 组件(自 K8s v1.13 起替代 kube-dns),负责提供集群内的服务发现功能。它为 Pod 和 Service 提供 DNS 解析,使得可以通过域名而不是 IP 地址进行通信。
Pod DNS 解析流程
Pod → <service>.<namespace>.svc.cluster.local → CoreDNS → Service ClusterIP
完整域名格式:
| 格式 | 说明 |
|---|---|
<service> | 同命名空间内,直接用 Service 名称即可 |
<service>.<namespace> | 跨命名空间访问 |
<service>.<namespace>.svc | 指定 svc 子域 |
<service>.<namespace>.svc.cluster.local | 完整 FQDN |
<pod-ip>.<namespace>.pod.cluster.local | Pod 的 DNS 记录(默认不启用) |
# 验证 DNS 解析
kubectl run test-dns --image=busybox:1.28 --rm -it --restart=Never -- nslookup kubernetes.default.svc.cluster.local
# 或者使用 nslookup 解析同一命名空间的 Service
kubectl run test-dns --image=busybox:1.28 --rm -it --restart=Never -- nslookup my-svc
Pod 的 DNS 记录
# Pod 的 DNS 名称(如果启用了 pod 记录)
<POD-IP-WITH-DASHES>.<NAMESPACE>.pod.cluster.local
# 示例:IP 为 10.244.1.5 的 Pod
10-244-1-5.default.pod.cluster.local
CoreDNS ConfigMap 配置
CoreDNS 的配置存储在 kube-system 命名空间的 ConfigMap 中:
kubectl get configmap -n kube-system coredns -o yaml
默认配置
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
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
}
配置项说明
| 插件/指令 | 说明 |
|---|---|
errors | 记录 DNS 错误日志 |
health | 健康检查端点 :8080/health |
ready | 就绪检查端点 :8181/ready |
kubernetes | Kubernetes DNS 解析核心插件 |
prometheus | 指标暴露 :9153/metrics |
forward | 上游 DNS 转发(. 表示所有域名) |
cache | DNS 缓存 |
loop | 检测 DNS 循环 |
reload | 自动重载配置变更 |
loadbalance | 轮询负载均衡 A/AAAA 记录 |
自定义 DNS 配置
添加自定义 stubDomain
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
health
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
# 自定义域名解析
example.com {
forward . 192.168.1.1
}
# 内部私有域名
internal.company.com {
forward . 10.0.0.10 10.0.0.11
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
Pod 的 dnsPolicy
定义 Pod 的 DNS 策略:
apiVersion: v1
kind: Pod
metadata:
name: dns-test-pod
spec:
dnsPolicy: ClusterFirst # 默认值
containers:
- name: busybox
image: busybox:1.28
command: ["sleep", "3600"]
| 策略 | 说明 |
|---|---|
ClusterFirst | 默认策略,先查询 CoreDNS,未命中则转发上游 DNS |
Default | Pod 继承节点 DNS 配置(/etc/resolv.conf) |
None | 忽略默认 DNS,使用 dnsConfig 自定义 |
ClusterFirstWithHostNet | 用于 hostNetwork: true 的 Pod |
Pod 的 dnsConfig 自定义
当 dnsPolicy: None 时,使用 dnsConfig 完全自定义:
apiVersion: v1
kind: Pod
metadata:
name: custom-dns-pod
spec:
dnsPolicy: None
dnsConfig:
nameservers:
- 1.1.1.1
- 8.8.8.8
searches:
- default.svc.cluster.local
- svc.cluster.local
- cluster.local
options:
- name: ndots
value: "2"
- name: edns0
containers:
- name: busybox
image: busybox:1.28
command: ["sleep", "3600"]
CoreDNS 故障排查
# 查看 CoreDNS Pod 状态
kubectl get pods -n kube-system -l k8s-app=kube-dns
# 查看 CoreDNS 日志
kubectl logs -n kube-system -l k8s-app=kube-dns
# 查看 CoreDNS ConfigMap
kubectl get configmap -n kube-system coredns -o yaml
# 重启 CoreDNS(修改配置后)
kubectl rollout restart -n kube-system deployment/coredns
# 检查 CoreDNS 服务
kubectl get svc -n kube-system kube-dns
# 检查 CoreDNS 资源使用
kubectl top pods -n kube-system -l k8s-app=kube-dns
常见问题排错
# 1. 测试 DNS 解析
kubectl run test --image=busybox:1.28 --rm -it --restart=Never -- nslookup kubernetes.default
# 2. 如果 nslookup 失败,测试 CoreDNS 是否可达
kubectl run test --image=busybox:1.28 --rm -it --restart=Never -- wget http://<coredns-svc-ip>:8080/health
# 3. 检查 DNS 超时
kubectl run test --image=busybox:1.28 --rm -it --restart=Never -- sh
# 在容器内
cat /etc/resolv.conf
# 输出类似:
# nameserver 10.96.0.10
# search default.svc.cluster.local svc.cluster.local cluster.local
# options ndots:5
# 4. 全链路 DNS 测试(从 Pod 内)
kubectl run dig-pod --image=nicolaka/netshoot --rm -it --restart=Never -- dig kubernetes.default.svc.cluster.local
关键排查点
| 排查项 | 命令 |
|---|---|
| CoreDNS Pod 是否运行 | kubectl get pods -n kube-system -l k8s-app=kube-dns |
| Service Endpoints 是否正常 | kubectl get endpoints -n kube-system kube-dns |
| DNS 配置是否正确 | kubectl exec <pod> -- cat /etc/resolv.conf |
| 集群 DNS 域名 | kubectl get configmap -n kube-system coredns -o yaml |
| CoreDNS 内存/CPU | kubectl top pods -n kube-system -l k8s-app=kube-dns |
🧪 完整操作实例:测试 Pod DNS 解析并自定义 CoreDNS
场景描述
验证集群 DNS 解析正常工作,然后通过修改 CoreDNS ConfigMap 配置自定义 stubDomain,使集群内可以解析内部私有域名。
前置条件
- 集群正常运行,CoreDNS Pod 处于 Running 状态
- kubectl 已配置好集群访问
操作步骤
Step 1: 验证基础 DNS 解析
# 使用 busybox 测试 Kubernetes Service 的 DNS 解析
kubectl run dns-test --image=busybox:1.28 --rm -it --restart=Never -- nslookup kubernetes.default
# 预期输出:
# Server: 10.96.0.10
# Address: 10.96.0.10:53
# Name: kubernetes.default.svc.cluster.local
# Address: 10.96.0.1
# 测试完整 FQDN
kubectl run dns-test2 --image=busybox:1.28 --rm -it --restart=Never -- nslookup kubernetes.default.svc.cluster.local
# 预期输出:同上,显示 ClusterIP 10.96.0.1
# 查看 Pod 的 DNS 配置
kubectl run check-dns --image=busybox:1.28 --rm -it --restart=Never -- cat /etc/resolv.conf
# 预期输出:
# nameserver 10.96.0.10
# search default.svc.cluster.local svc.cluster.local cluster.local
# options ndots:5
Step 2: 检查 CoreDNS 组件状态
# 查看 CoreDNS Pod
kubectl get pods -n kube-system -l k8s-app=kube-dns
# NAME READY STATUS RESTARTS AGE
# coredns-7d8f9c7b8c-abc12 1/1 Running 0 10m
# coredns-7d8f9c7b8c-def34 1/1 Running 0 10m
# 查看 CoreDNS Service
kubectl get svc -n kube-system kube-dns
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 10m
# 查看 CoreDNS ConfigMap 当前配置
kubectl get configmap -n kube-system coredns -o yaml
# 预期输出:包含 Corefile 配置段
Step 3: 创建自定义 stubDomain
# 备份当前配置
kubectl get configmap -n kube-system coredns -o yaml > coredns-backup.yaml
# 修改 ConfigMap,添加自定义域解析
kubectl edit configmap -n kube-system coredns
# 在编辑器中,将 Corefile 修改为添加以下段落:
# 修改后的 Corefile(添加到 kubernetes 块下方,forward 块上方):
# 自定义内部域名
internal.example.com {
forward . 192.168.1.100
}
# 自定义 stub 域名
mycompany.local {
forward . 10.0.0.53
}
# 或者直接用 kubectl patch 修改:
cat <<EOFPATCH | kubectl patch configmap -n kube-system coredns --type merge -p "$(cat)"
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
}
internal.example.com {
forward . 192.168.1.100
}
mycompany.local {
forward . 10.0.0.53
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
EOFPATCH
# 预期输出:configmap/coredns patched
Step 4: 重启 CoreDNS 使配置生效
# 检查 reload 插件是否生效(等待自动重载,最多 30 秒)
# 或手动重启强制生效
kubectl rollout restart -n kube-system deployment/coredns
# 预期输出:deployment.apps/coredns restarted
# 等待 CoreDNS Pod 重新就绪
kubectl rollout status -n kube-system deployment/coredns
# 预期输出:deployment "coredns" successfully rolled out
# 验证新 Pod 已就绪
kubectl get pods -n kube-system -l k8s-app=kube-dns
# 预期输出:新的 Pod,状态 Running,RESTARTS 列为 0 或 1
Step 5: 验证自定义域名解析
# 测试自定义 internal.example.com 解析
kubectl run test-stub --image=busybox:1.28 --rm -it --restart=Never -- nslookup internal.example.com
# 预期输出:
# Server: 10.96.0.10
# Address: 10.96.0.10:53
# Name: internal.example.com
# Address: 192.168.1.100
# 测试 mycompany.local 解析
kubectl run test-stub2 --image=busybox:1.28 --rm -it --restart=Never -- nslookup mycompany.local
# 预期输出:
# Server: 10.96.0.10
# Address: 10.96.0.10:53
# Name: mycompany.local
# Address: 10.0.0.53
# 确认原生 K8s DNS 解析仍然正常
kubectl run test-k8s --image=busybox:1.28 --rm -it --restart=Never -- nslookup kubernetes.default
# 预期输出:成功解析到 10.96.0.1
验证结果
# 从 Pod 内查看完整的 DNS 解析链路
kubectl run dig-pod --image=nicolaka/netshoot --rm -it --restart=Never -- dig internal.example.com +trace
# 预期输出:DNS 解析链路从根域到最终 IP
# 查看 CoreDNS 日志,确认自定义域查询被正确处理
kubectl logs -n kube-system -l k8s-app=kube-dns --tail=20 | grep "internal.example.com"
# 预期输出:显示查询日志(如启用 errors 插件)
# 清理测试资源
kubectl delete pod dig-pod --force --grace-period=0 2>/dev/null || true
# 恢复原始 CoreDNS 配置(如有备份)
# kubectl apply -f coredns-backup.yaml
# kubectl rollout restart -n kube-system deployment/coredns
考试提示
-
CoreDNS ConfigMap 在 kube-system 命名空间,名称为
coredns -
修改配置后必须重启 CoreDNS(
kubectl rollout restart)或等待 reload 自动生效 -
.:53块是默认服务器块,处理所有未匹配的域名;自定义块在匹配域名时优先 -
forward 顺序重要:自定义块内的 forward 只用于该域名,而
.块的 forward 处理所有其他域名 -
排查 DNS 问题四步法:①
kubectl get pods -n kube-system -l k8s-app=kube-dns②kubectl logs③ 检查 ConfigMap ④ 用 netshoot/dig 逐层排查 -
busybox:1.28的 nslookup 最稳定;新版本 busybox 可能缺失 nslookup 命令 -
https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/
-
https://kubernetes.io/docs/tasks/administer-cluster/dns-custom-nameservers/
-
https://kubernetes.io/docs/tasks/administer-cluster/coredns/