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

概述

官网文档:https://kubernetes.io/zh-cn/docs/concepts/services-networking/dns-pod-service/

在 Kubernetes(K8s)中,DNS 服务是实现服务发现和 Pod 通信的核心组件之一,用于解决集群内资源通过域名而非 IP 地址进行访问的需求。本文将详细解析 K8s DNS 服务的原理、组件、配置及应用场景。

K8s DNS的作用

服务发现

  • 允许 Pod 通过服务名称(Service Name)而非动态变化的 IP 地址访问其他服务,简化网络配置。
  • 支持跨命名空间(Namespace)的服务访问,通过域名后缀区分不同作用域。

Pod 通信

  • 每个 Pod 自动获取 DNS 配置,可直接通过主机名(Hostname)或服务名进行通信。

解耦服务依赖

  • 服务的 IP 地址变更时,DNS 会自动更新解析结果,避免手动维护 IP 列表。

核心组件:CoreDNS(替代传统 kube-dns)

K8s 早期使用kube-dns作为 DNS 服务器,目前默认采用CoreDNS,因其更轻量、灵活且支持插件机制。

CoreDNS的安装

如果使用kubeadm部署集群,CoreDNS 会自动部署在kube-system命名空间下,如果需要进行部署,可以使用下面的文件:

kubectl apply -f https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/dns/coredns/coredns.yaml.base 

部署CoreDNS通常包含

  • StatefulSet/Deployment:定义 CoreDNS Pod 副本。
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 
  • Service:暴露 CoreDNS 服务,供集群内 Pod 访问(默认 IP 为10.96.0.10)。
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 
  • ConfigMap:存储 Corefile 配置。
.: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记录进行负载均衡 } 

CoreDNS的组成

  • CoreDNS Pod:运行 CoreDNS 服务,监听 DNS 请求(默认端口 53)。
[root@master ~]# 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   <none>           <none> coredns-787d4945fb-z47x7         1/1     Running   1 (2d23h ago)   9d    100.117.144.138   node01   <none>           <none> 
  • Service 资源:为 CoreDNS Pod 暴露集群内部服务,名称为kube-dns(或coredns,取决于部署方式),IP 通常为10.96.0.10(集群 IP 范围)。
[root@master ~]# kubectl get svc -n kube-system NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE kube-dns   ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   9d  [root@master ~]# 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:              dns  53/UDP TargetPort:        53/UDP Endpoints:         100.117.144.135:53,100.117.144.138:53 Port:              dns-tcp  53/TCP TargetPort:        53/TCP Endpoints:         100.117.144.135:53,100.117.144.138:53 Port:              metrics  9153/TCP TargetPort:        9153/TCP Endpoints:         100.117.144.135:9153,100.117.144.138:9153 Session Affinity:  None Events:            <none> 
  • ConfigMap 配置:通过 ConfigMap 定义 CoreDNS 的解析规则和插件。
[root@master ~]# kubectl describe cm coredns -n kube-system Name:         coredns Namespace:    kube-system Labels:       <none> Annotations:  <none>  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:  <none> 

CoreDNS域名解析规则

K8s集群中Pod之间通过域名互相访问需要遵守特定的规则,规则如下

<service-name>.<namespace>.svc.<cluster-domain> 
  • service-name:表示service的名称
  • namespace:service所在的命名空间
  • cluster-domain:集群的域名,默认为cluster.local

cluster-domain从哪儿获取?

[root@master ~]# grep clusterDomain /var/lib/kubelet/config.yaml  clusterDomain: cluster.local 

CoreDNS实战案例

验证同一个命名空间下的CoreDNS访问

创建两个Pod和Service

## 第一个Pod和 Service [root@master ~/coredns]# 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  [root@master ~/coredns]# kubectl apply -f test-1.yaml pod/dns-target-pod unchanged service/dns-target-service created  # 第二个Pod和Service [root@master ~/coredns]# 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  [root@master ~/coredns]# kubectl apply -f test-2.yaml pod/dns-source-pod created service/dns-source-service created  # 检查一下 [root@master ~/coredns]# 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   <none>        80/TCP    81s service/dns-target-service   ClusterIP   10.96.3.51    <none>        80/TCP    3m56s 

验证DNS

[root@master ~/coredns]# 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 

验证在不同命名空间下的DNS访问

示例:

# 创建一个新的命名空间 [root@master ~/coredns]# kubectl create ns coredns namespace/coredns created [root@master ~/coredns]# kubectl get ns coredns NAME      STATUS   AGE coredns   Active   15s 

创建Pod和Service进行验证

[root@master ~/coredns]# 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  [root@master ~/coredns]# kubectl apply -f test3.yaml pod/dns-coredns-pod created service/dns-coredns-service created  [root@master ~]# 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   <none>        80/TCP    4m36s 

进行验证

[root@master ~/coredns]# 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 

发表评论

评论已关闭。

相关文章