Qingular

CoreDNS

·CKAk8s练习

CKA Domain 3 — CoreDNS 在 Kubernetes 中的角色、配置与故障排查

← 返回 CKA 练习目录

概述

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.localPod 的 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
kubernetesKubernetes DNS 解析核心插件
prometheus指标暴露 :9153/metrics
forward上游 DNS 转发(. 表示所有域名)
cacheDNS 缓存
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
DefaultPod 继承节点 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 内存/CPUkubectl 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

考试提示