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
...
- CoreDNS 监听地址和端口: CoreDNS 配置文件中的
.:53指定了 CoreDNS 的监听地址和端口。这表示 CoreDNS 将监听默认的 DNS 端口 53,以接收 DNS 查询请求。 - 健康检查和就绪状态: 配置中的
health块定义了健康检查相关的配置,其中lameduck 5s表示在关闭 CoreDNS 之前等待 5 秒钟,以确保正在进行的 DNS 查询能够完成。ready表示 CoreDNS 将提供就绪状态检查的端点。 - Kubernetes 集群的 DNS 配置:
kubernetes块定义了对 Kubernetes 集群的 DNS 配置。其中的cluster.local是默认的域名后缀,用于解析集群内的服务和 Pod。pods insecure表示可以通过直接使用 Pod 名称进行 DNS 查询,而不需要完全限定的域名。fallthrough in-addr.arpa ip6.arpa表示对于逆向 DNS 查询(反向解析),将继续使用in-addr.arpa和ip6.arpa域名。ttl 30表示 DNS 解析结果的 TTL(Time to Live)为 30 秒。 - Prometheus 指标暴露:
prometheus :9153表示 CoreDNS 将在端口 9153 上暴露 Prometheus 指标,以供监控和指标收集。 - DNS 解析的转发:
forward . /etc/resolv.conf表示 CoreDNS 将对于除了本地区域的 DNS 查询请求转发到/etc/resolv.conf文件中指定的上游 DNS 服务器。max_concurrent 1000表示最大并发转发请求数为 1000。 - 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对象中。