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

笔记哥 / 05-31 / 42点赞 / 0评论 / 219阅读
## 概述 官网文档: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命名空间下,如果需要进行部署,可以使用下面的文件: ```csharp kubectl apply -f https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/dns/coredns/coredns.yaml.base ``` 部署CoreDNS通常包含 - StatefulSet/Deployment:定义 CoreDNS Pod 副本。 ```csharp 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)。 ```csharp 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 配置。 ```csharp .: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)。 ```csharp [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 coredns-787d4945fb-z47x7 1/1 Running 1 (2d23h ago) 9d 100.117.144.138 node01 ``` - Service 资源:为 CoreDNS Pod 暴露集群内部服务,名称为kube-dns(或coredns,取决于部署方式),IP 通常为10.96.0.10(集群 IP 范围)。 ```csharp [root@master ~]# kubectl get svc -n kube-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kube-dns ClusterIP 10.96.0.10 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: ``` - ConfigMap 配置:通过 ConfigMap 定义 CoreDNS 的解析规则和插件。 ```csharp [root@master ~]# kubectl describe cm coredns -n kube-system Name: coredns Namespace: kube-system Labels: Annotations: 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: ``` ## CoreDNS域名解析规则 K8s集群中Pod之间通过域名互相访问需要遵守特定的规则,规则如下 ```csharp ..svc. ``` - service-name:表示service的名称 - namespace:service所在的命名空间 - cluster-domain:集群的域名,默认为`cluster.local` #### cluster-domain从哪儿获取? ```csharp [root@master ~]# grep clusterDomain /var/lib/kubelet/config.yaml clusterDomain: cluster.local ``` ## CoreDNS实战案例 ### 验证同一个命名空间下的CoreDNS访问 创建两个Pod和Service ```csharp ## 第一个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 80/TCP 81s service/dns-target-service ClusterIP 10.96.3.51 80/TCP 3m56s ``` 验证DNS ```csharp [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访问 示例: ```csharp # 创建一个新的命名空间 [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进行验证 ```csharp [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 80/TCP 4m36s ``` 进行验证 ```csharp [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 ```