司机室 發表於 2025-5-31 12:50:00

K8s集群中的DNS服务(CoreDNS)详解

<h2 id="概述">概述</h2>
<p>官网文档:https://kubernetes.io/zh-cn/docs/concepts/services-networking/dns-pod-service/</p>
<p>在 Kubernetes(K8s)中,DNS 服务是实现服务发现和 Pod 通信的核心组件之一,用于解决集群内资源通过域名而非 IP 地址进行访问的需求。本文将详细解析 K8s DNS 服务的原理、组件、配置及应用场景。</p>
<h2 id="k8s-dns的作用">K8s DNS的作用</h2>
<h3 id="服务发现">服务发现</h3>
<ul>
<li>允许 Pod 通过服务名称(Service Name)而非动态变化的 IP 地址访问其他服务,简化网络配置。</li>
<li>支持跨命名空间(Namespace)的服务访问,通过域名后缀区分不同作用域。</li>
</ul>
<h3 id="pod-通信">Pod 通信</h3>
<ul>
<li>每个 Pod 自动获取 DNS 配置,可直接通过主机名(Hostname)或服务名进行通信。</li>
</ul>
<h3 id="解耦服务依赖">解耦服务依赖</h3>
<ul>
<li>服务的 IP 地址变更时,DNS 会自动更新解析结果,避免手动维护 IP 列表。</li>
</ul>
<h2 id="核心组件coredns替代传统-kube-dns">核心组件:CoreDNS(替代传统 kube-dns)</h2>
<p>K8s 早期使用kube-dns作为 DNS 服务器,目前默认采用CoreDNS,因其更轻量、灵活且支持插件机制。</p>
<h3 id="coredns的安装">CoreDNS的安装</h3>
<p>如果使用kubeadm部署集群,CoreDNS 会自动部署在kube-system命名空间下,如果需要进行部署,可以使用下面的文件:</p>
<pre><code>kubectl apply -f https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/dns/coredns/coredns.yaml.base
</code></pre>
<p>部署CoreDNS通常包含</p>
<ul>
<li>StatefulSet/Deployment:定义 CoreDNS Pod 副本。</li>
</ul>
<pre><code>apiVersion: apps/v1
kind: Deployment
metadata:
name: coredns
namespace: kube-system
spec:
replicas: 2# 默认2个副本,确保高可用
selector:
    matchLabels:
      k8s-app: kube-dns# 历史遗留标签,兼容旧版kube-dns
template:
    metadata:
      labels:
      k8s-app: kube-dns
    spec:
      containers:
      - name: coredns
      image: coredns/coredns:v1.10.1# CoreDNS版本
      args: [ "-conf", "/etc/coredns/Corefile" ]
      ports:
      - containerPort: 53
          name: dns
          protocol: UDP
      - containerPort: 53
          name: dns-tcp
          protocol: TCP
      volumeMounts:
      - name: config-volume
          mountPath: /etc/coredns
      volumes:
      - name: config-volume
      configMap:
          name: coredns
          items:
          - key: Corefile
            path: Corefile
</code></pre>
<ul>
<li>Service:暴露 CoreDNS 服务,供集群内 Pod 访问(默认 IP 为10.96.0.10)。</li>
</ul>
<pre><code>apiVersion: v1
kind: Service
metadata:
name: kube-dns
namespace: kube-system
spec:
selector:
    k8s-app: kube-dns
clusterIP: 10.96.0.10# 默认集群IP,Pod的nameserver配置指向此IP
ports:
- name: dns
    port: 53
    protocol: UDP
- name: dns-tcp
    port: 53
    protocol: TCP
</code></pre>
<ul>
<li>ConfigMap:存储 Corefile 配置。</li>
</ul>
<pre><code>.:53 {                              #表示监听所有接口的 53 端口(DNS 标准端口)。
    errors                        # 记录错误日志
    health {
      lameduck 5s               # 健康检查,延迟5秒标记不健康
    }
    ready                           # 提供 readiness 探针端点(/ready),指示 CoreDNS 是否准备好处理请求
    kubernetes cluster.local in-addr.arpa ip6.arpa {
      fallthrough in-addr.arpa ip6.arpa# 未匹配到K8s服务时,透传给下一个插件
      ttl 30                        # DNS记录的TTL时间
    }
    prometheus :9153                # 暴露Prometheus监控指标
    forward . /etc/resolv.conf      # 转发外部域名查询到宿主机的DNS服务器
    cache 30                        # 缓存查询结果30秒
    loop                            # 检测配置循环引用
    reload                        # 自动重新加载配置变更
    loadbalance                     # 对A/AAAA记录进行负载均衡
}
</code></pre>
<h3 id="coredns的组成">CoreDNS的组成</h3>
<ul>
<li>CoreDNS Pod:运行 CoreDNS 服务,监听 DNS 请求(默认端口 53)。</li>
</ul>
<pre><code># kubectl get po -o wide -n kube-system
NAME                           READY   STATUS    RESTARTS      AGE   IP                NODE   NOMINATED NODE   READINESS GATES
coredns-787d4945fb-jb4t9         1/1   Running   1 (2d23h ago)   9d    100.117.144.135   node01   &lt;none&gt;         &lt;none&gt;
coredns-787d4945fb-z47x7         1/1   Running   1 (2d23h ago)   9d    100.117.144.138   node01   &lt;none&gt;         &lt;none&gt;
</code></pre>
<ul>
<li>Service 资源:为 CoreDNS Pod 暴露集群内部服务,名称为kube-dns(或coredns,取决于部署方式),IP 通常为10.96.0.10(集群 IP 范围)。</li>
</ul>
<pre><code># kubectl get svc -n kube-system
NAME       TYPE      CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
kube-dns   ClusterIP   10.96.0.10   &lt;none&gt;      53/UDP,53/TCP,9153/TCP   9d

# kubectl describe svc kube-dns -n kube-system
Name:            kube-dns
Namespace:         kube-system
Labels:            k8s-app=kube-dns
                   kubernetes.io/cluster-service=true
                   kubernetes.io/name=CoreDNS
Annotations:       prometheus.io/port: 9153
                   prometheus.io/scrape: true
Selector:          k8s-app=kube-dns
Type:            ClusterIP
IP Family Policy:SingleStack
IP Families:       IPv4
IP:                10.96.0.10
IPs:               10.96.0.10
Port:            dns53/UDP
TargetPort:      53/UDP
Endpoints:         100.117.144.135:53,100.117.144.138:53
Port:            dns-tcp53/TCP
TargetPort:      53/TCP
Endpoints:         100.117.144.135:53,100.117.144.138:53
Port:            metrics9153/TCP
TargetPort:      9153/TCP
Endpoints:         100.117.144.135:9153,100.117.144.138:9153
Session Affinity:None
Events:            &lt;none&gt;
</code></pre>
<ul>
<li>ConfigMap 配置:通过 ConfigMap 定义 CoreDNS 的解析规则和插件。</li>
</ul>
<pre><code># kubectl describe cm coredns -n kube-system
Name:         coredns
Namespace:    kube-system
Labels:       &lt;none&gt;
Annotations:&lt;none&gt;

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 {
       max_concurrent 1000
    }
    cache 30
    loop
    reload
    loadbalance
}


BinaryData
====

Events:&lt;none&gt;
</code></pre>
<h2 id="coredns域名解析规则">CoreDNS域名解析规则</h2>
<p>K8s集群中Pod之间通过域名互相访问需要遵守特定的规则,规则如下</p>
<pre><code>&lt;service-name&gt;.&lt;namespace&gt;.svc.&lt;cluster-domain&gt;
</code></pre>
<ul>
<li>service-name:表示service的名称</li>
<li>namespace:service所在的命名空间</li>
<li>cluster-domain:集群的域名,默认为<code>cluster.local</code></li>
</ul>
<h4 id="cluster-domain从哪儿获取">cluster-domain从哪儿获取?</h4>
<pre><code># grep clusterDomain /var/lib/kubelet/config.yaml
clusterDomain: cluster.local
</code></pre>
<h2 id="coredns实战案例">CoreDNS实战案例</h2>
<h3 id="验证同一个命名空间下的coredns访问">验证同一个命名空间下的CoreDNS访问</h3>
<p>创建两个Pod和Service</p>
<pre><code>## 第一个Pod和 Service
# cat test-1.yaml
apiVersion: v1
kind: Pod
metadata:
name: dns-target-pod
labels:
    app: dns-test
spec:
containers:
- name: busybox
    image: busybox
    command: ["sh", "-c", "while true; do sleep 3600; done"]
---
apiVersion: v1
kind: Service
metadata:
name: dns-target-service
spec:
type: ClusterIP
selector:
    app: dns-test
ports:
- protocol: TCP
    port: 80
    targetPort: 80

# kubectl apply -f test-1.yaml
pod/dns-target-pod unchanged
service/dns-target-service created

# 第二个Pod和Service
# cat test-2.yaml
apiVersion: v1
kind: Pod
metadata:
name: dns-source-pod
labels:
    app: dns-source-test
spec:
containers:
- name: busybox
    image: busybox
    command: ["sh", "-c", "while true; do sleep 3600; done"]
---
apiVersion: v1
kind: Service
metadata:
name: dns-source-service
spec:
type: ClusterIP
selector:
    app: dns-source-test
ports:
- protocol: TCP
    port: 80
    targetPort: 80

# kubectl apply -f test-2.yaml
pod/dns-source-pod created
service/dns-source-service created

# 检查一下
# kubectl get po,svc
NAME               READY   STATUS    RESTARTS   AGE
pod/dns-source-pod   1/1   Running   0          111s
pod/dns-target-pod   1/1   Running   0          8s

NAME                         TYPE      CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
service/dns-source-service   ClusterIP   10.96.0.192   &lt;none&gt;      80/TCP    81s
service/dns-target-service   ClusterIP   10.96.3.51    &lt;none&gt;      80/TCP    3m56s
</code></pre>
<p>验证DNS</p>
<pre><code># kubectl exec -it pod/dns-source-pod -- sh
/ # nslookup dns-target-service.default.svc.cluster.local
Server:         10.96.0.10
Address:      10.96.0.10:53


Name:   dns-target-service.default.svc.cluster.local
Address: 10.96.3.51
</code></pre>
<h3 id="验证在不同命名空间下的dns访问">验证在不同命名空间下的DNS访问</h3>
<p>示例:</p>
<pre><code># 创建一个新的命名空间
# kubectl create ns coredns
namespace/coredns created
# kubectl get ns coredns
NAME      STATUS   AGE
coredns   Active   15s
</code></pre>
<p>创建Pod和Service进行验证</p>
<pre><code># cat test-3.yaml
apiVersion: v1
kind: Pod
metadata:
name: dns-coredns-pod
namespace: coredns
labels:
    app: dns-coredns-test
spec:
containers:
- name: busybox
    image: busybox
    command: ["sh", "-c", "while true; do sleep 3600; done"]
---
apiVersion: v1
kind: Service
metadata:
name: dns-coredns-service
namespace: coredns
spec:
type: ClusterIP
selector:
    app: dns-coredns-test
ports:
- protocol: TCP
    port: 80
    targetPort: 80

# kubectl apply -f test3.yaml
pod/dns-coredns-pod created
service/dns-coredns-service created

# kubectl get all -n coredns
NAME                  READY   STATUS    RESTARTS   AGE
pod/dns-coredns-pod   1/1   Running   0          4m36s

NAME                        TYPE      CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
service/dns-coredns-service   ClusterIP   10.96.0.119   &lt;none&gt;      80/TCP    4m36s
</code></pre>
<p>进行验证</p>
<pre><code># kubectl exec -it dns-target-pod -- sh
/ # nslookup dns-coredns-service.coredns.svc.cluster.local
Server:         10.96.0.10
Address:      10.96.0.10:53

Name:   dns-coredns-service.coredns.svc.cluster.local
Address: 10.96.0.119
</code></pre>


</div>
<div id="MySignature" role="contentinfo">
    <p>本文来自博客园,作者:huangSir-devops,转载请注明原文链接:https://www.cnblogs.com/huangSir-devops/p/18900643,微信Vac6666666,欢迎交流</p><br><br>
来源:https://www.cnblogs.com/huangSir-devops/p/18900643
頁: [1]
查看完整版本: K8s集群中的DNS服务(CoreDNS)详解