CoreDNS 概述

  • CoreDNS 是 k8s 的核心插件,提供了 DNS 和 Serviec Discover 功能;

    • Serviec Discover 可以动态发现 endpoint 中的 pod 列表,从而实现动态添加和删除相关解析记录。
  • CoreDNS 将传统的DNS服务直接提供一个云原生解决方案,他支持从apiserver动态加载相关的service及端点信息,并自动生成资源记录。

k8s 历史采用的服务注册和发现的总线有三代:

  • SkyDNS –> KubeDNS –> CoreDNS(now)

参考文档:

CoreDNS 配置文件

# kubectl get configmap coredns -n kube-system -o yaml
apiVersion: v1
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
    }
kind: ConfigMap
...
  1. CoreDNS 监听地址和端口: CoreDNS 配置文件中的 .:53 指定了 CoreDNS 的监听地址和端口。这表示 CoreDNS 将监听默认的 DNS 端口 53,以接收 DNS 查询请求。
  2. 健康检查和就绪状态: 配置中的 health 块定义了健康检查相关的配置,其中 lameduck 5s 表示在关闭 CoreDNS 之前等待 5 秒钟,以确保正在进行的 DNS 查询能够完成。ready 表示 CoreDNS 将提供就绪状态检查的端点。
  3. Kubernetes 集群的 DNS 配置: kubernetes 块定义了对 Kubernetes 集群的 DNS 配置。其中的 cluster.local 是默认的域名后缀,用于解析集群内的服务和 Pod。pods insecure 表示可以通过直接使用 Pod 名称进行 DNS 查询,而不需要完全限定的域名。fallthrough in-addr.arpa ip6.arpa 表示对于逆向 DNS 查询(反向解析),将继续使用 in-addr.arpaip6.arpa 域名。ttl 30 表示 DNS 解析结果的 TTL(Time to Live)为 30 秒。
  4. Prometheus 指标暴露: prometheus :9153 表示 CoreDNS 将在端口 9153 上暴露 Prometheus 指标,以供监控和指标收集。
  5. DNS 解析的转发: forward . /etc/resolv.conf 表示 CoreDNS 将对于除了本地区域的 DNS 查询请求转发到 /etc/resolv.conf 文件中指定的上游 DNS 服务器。max_concurrent 1000 表示最大并发转发请求数为 1000。
  6. DNS 缓存和其他功能: cache 30 表示启用 DNS 缓存,并设置缓存的 TTL 为 30 秒。loop 表示启用 DNS 循环查询,以支持循环引用的 DNS 配置。reload 表示启用动态配置重载。loadbalance 表示启用负载均衡功能。

CoreDNS & Pod

CoreDNS

# kubectl get pod -n kube-system -l k8s-app=kube-dns
NAME                       READY   STATUS    RESTARTS       AGE
coredns-65c54cc984-8sfk8   1/1     Running   35 (43h ago)   104d
coredns-65c54cc984-fpv5f   1/1     Running   35 (43h ago)   104d

# kubectl describe svc -n kube-system kube-dns 
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 # 默认为10.96.0.10
IPs:               10.96.0.10
Port:              dns  53/UDP
TargetPort:        53/UDP
Endpoints:         10.244.0.74:53,10.244.0.75:53
Port:              dns-tcp  53/TCP
TargetPort:        53/TCP
Endpoints:         10.244.0.74:53,10.244.0.75:53
Port:              metrics  9153/TCP
TargetPort:        9153/TCP
Endpoints:         10.244.0.74:9153,10.244.0.75:9153
Session Affinity:  None
Events:            <none>

Pod

  • Kubelet会为创建的每一个容器于/etc/resolv.conf配置文件中生成DNS查询客户端依赖到的必要配置;
    • 相关的配置信息源自于kubelet的配置参数;
    • 各容器的DNS服务器由clusterDNS参数的值设定,它的取值为kube-system名称空间中的Service对象kube-dns的ClusterIP,默认为10.96.0.10;
    • DNS搜索域的值由clusterDomain参数的值设定,若部署Kubernetes集群时未特别指定,其值将为cluster.local、svc.cluster.local和NAMESPACENAME.svc.cluster.local
  • 下面的示例取自集群上的一个随机选择的Pod中的容器。
# kubectl exec -it  demoapp-65bc49b76-c5fst -- sh
[root@demoapp-65bc49b76-c5fst /]# cat /etc/resolv.conf 
nameserver 10.96.0.10
search default.svc.k8s.xiangzheng.com svc.k8s.xiangzheng.com k8s.xiangzheng.com
options ndots:5


# 上述search参数中指定的DNS各搜索域,是以次序指定的几个域名后缀,它们各自的如下所示。 
<ns>.svc.<zone> # 附带有特定名称空间的域名,例如default.svc.cluster.local;
svc.<zone># 附带了Kubernetes标识Service专用子域svc的域名,例如svc.cluster.local;
<zone> # 集群本地域名,例如cluster.local(默认值)

Service 默认资源记录类型

  • CoreDNS 对于每个Service对象,都会具有以下3个类型的DNS资源记录。

A & AAAA

  • 根据ClusterIP的地址类型,为IPv4生成A记录,为IPv6生成AAAA记录;
  • service_name –> service_ip
# A
<service>.<ns>.svc.<zone>. <ttl>  IN  A  <cluster-ip>

# AAAA
<service>.<ns>.svc.<zone>. <ttl> IN AAAA <cluster-ip>

范例

环境说明

# kubectl describe service demoapp-svc 
Name:              demoapp-svc
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=demoapp
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.99.152.124
IPs:               10.99.152.124
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.1.13:80,10.244.1.14:80,10.244.1.15:80
Session Affinity:  None
Events:            <none>


# 在不同的名称空间中创建pod测试
# kubectl create ns testns
namespace/testns created
# kubectl run testpod --image=ikubernetes/demoapp:v1.0 -n testns
pod/testpod created

测试

# kubectl exec -it -n testns testpod -- sh


# 获取zone(k8s.xiangzheng.com)
[root@testpod /]# cat /etc/resolv.conf 
nameserver 10.96.0.10
search testns.svc.k8s.xiangzheng.com svc.k8s.xiangzheng.com k8s.xiangzheng.com
options ndots:5


# 测试
[root@testpod /]# nslookup -q=a demoapp-svc.default.svc.k8s.xiangzheng.com
Server:		10.96.0.10
Address:	10.96.0.10#53

Name:	demoapp-svc.default.svc.k8s.xiangzheng.com
Address: 10.99.152.124

[root@testpod /]# curl demoapp-svc.default.svc.k8s.xiangzheng.com
iKubernetes demoapp v1.0 !! ClientIP: 10.244.1.16, ServerName: demoapp-65bc49b76-n8rv9, ServerIP: 10.244.1.15!
[root@testpod /]# curl demoapp-svc.default.svc.k8s.xiangzheng.com
iKubernetes demoapp v1.0 !! ClientIP: 10.244.1.16, ServerName: demoapp-65bc49b76-t782v, ServerIP: 10.244.1.14!
[root@testpod /]# curl demoapp-svc.default.svc.k8s.xiangzheng.com
iKubernetes demoapp v1.0 !! ClientIP: 10.244.1.16, ServerName: demoapp-65bc49b76-c5fst, ServerIP: 10.244.1.13!
[root@testpod /]# curl demoapp-svc.default.svc.k8s.xiangzheng.com


# coredns内部生成的解析记录格式:
demoapp-svc.default.svc.k8s.xiangzheng.com. 30 IN A  10.99.152.124

SRV

  • 主要负责端口解析
  • 为每个定义了名称的端口生成一个SRV记录,未命名的端口号则不具有该记录
_<port>._<proto>.<service>.<ns>.svc.<zone>. <ttl>  IN  SRV  <weight> <priority>  <port-number>  <service>.<ns>.svc.<zone>.

PTR

  • service_ip –> service_name
  • 对于每个给定的A记录(例如a.b.c.d)或AAAA记录(例如a1a2a3a4:b1b2b3b4:c1c2c3c4:d1d2d3d4:e1e2e3e4:f1f2f3f4:g1g2g3g4:h1h2h3h4)都要生成PTR记录,它们各自的格式如下所示:
# A
<d>.<c>.<b>.<a>.in-addr.arpa.  <ttl>  IN  PTR <service>.<ns>.svc.<zone>.

# AAAA
h4.h3.h2.h1.g4.g3.g2.g1.f4.f3.f2.f1.e4.e3.e2.e1.d4.d3.d2.d1.c4.c3.c2.c1.b4.b3.b2.b1.a4.a3.a2.a1.ip6.arpa <ttl> IN PTR <service>.<ns>.svc.<zone>.

范例

环境说明

# kubectl describe service demoapp-svc 
Name:              demoapp-svc
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=demoapp
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.99.152.124
IPs:               10.99.152.124
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.1.13:80,10.244.1.14:80,10.244.1.15:80
Session Affinity:  None
Events:            <none>


# 在不同的名称空间中创建pod测试
# kubectl create ns testns
namespace/testns created
# kubectl run testpod --image=ikubernetes/demoapp:v1.0 -n testns
pod/testpod created

测试

# kubectl exec -it -n testns testpod -- sh


# 获取zone(k8s.xiangzheng.com)
[root@testpod /]# cat /etc/resolv.conf 
nameserver 10.96.0.10
search testns.svc.k8s.xiangzheng.com svc.k8s.xiangzheng.com k8s.xiangzheng.com
options ndots:5


# 正向解析获取到serviceIP
[root@testpod /]# nslookup -q=a demoapp-svc.default.svc.k8s.xiangzheng.com
Server:		10.96.0.10
Address:	10.96.0.10#53

Name:	demoapp-svc.default.svc.k8s.xiangzheng.com
Address: 10.99.152.124


# 反向解析获取到serviceIP对应的name
[root@testpod /]# nslookup -q=ptr 10.99.152.124
Server:		10.96.0.10
Address:	10.96.0.10#53

124.152.99.10.in-addr.arpa	name = demoapp-svc.default.svc.k8s.xiangzheng.com.


# coredns内部生成的解析记录格式:
124.152.99.10.in-addr.arpa. 30   IN  PTR  demoapp-svc.default.svc.k8s.xiangzheng.com.

范例 - 1

  • 例如,在default名称空间中创建Service对象demoapp-svc的地址为10.97.72.1,且为TCP协议的80端口取名http,对于默认的cluster.local域名来说,此它会拥有如下3个DNS资源记录。
# A记录:
demoapp-svc.default.svc.cluster.local. 30 IN A  10.97.72.1

# SRV记录:
_http._tcp.demoapp-svc.default.svc.cluster.local. 30 IN SRV 0 100 80 demoapp-svc.default.svc.cluster.local.

# PTR记录:
1.72.97.10.in-addr.arpa. 30     IN      PTR     demoapp-svc.default.svc.cluster.local.

zone 获取方法

方法一

  • 进入到pod容器中查看
# kubectl exec -it -n dev myapp-759cc967fc-x9wz4 -- bash

# cat /etc/resolv.conf
nameserver 10.96.0.10
search dev.svc.k8s.xiangzheng.com svc.k8s.xiangzheng.com k8s.xiangzheng.com
options ndots:5

方法二

  • 通过apiserver静态pod的配置信息查看
# kubectl get pod -n kube-system kube-apiserver-k8s-master-1 -o yaml |grep issuer
    - --service-account-issuer=https://kubernetes.default.svc.k8s.xiangzheng.com

方法三

  • 查看集群初始化配置文件中的 ClusterConfiguration.networking.dnsDomain

注意事项

  • CoreDNS配置文件中的转发策略(forward XXX{XXX})一定要指向企业内部的DNS服务器,而非公网的DNS,否则一些内网域名将无法解析
    • 如:数据库存放在外部,而数据的访问都是从企业内部的DNS服务器来进行名字解析从而进行访问的

其他说明

  • 使用默认注入的环境变量仅在同一名称空间中创建的Pod对象可以互相访问
基于环境变量:

(1)Kubernetes Service环境变量
Kubernetes为每个Service资源生成包括以下形式的环境变量在内一系列环境变量,在同一名称空间中创建的Pod对象都会自动拥有这些变量:
 {SVCNAME}_SERVICE_HOST
 {SVCNAME}_SERVICE_PORT

default名称空间:创建的demoapp Service,意味着default名称空间下的每个Pod内部会被自动注入DEMOAPP_SERVICE_HOST:ClusterIP, DEMOAPP_SERVICE_PORT=80



(2) Docker Link形式的环境变量
Docker使用--link选项实现容器连接时所设置的环境变量形式,具体使用方式请参考Docker的相关文档。在创建Pod对象时,kubernetes也会把与此形式兼容的一系列环境变量注入到Pod对象中。