K8s DNS #
DNS 策略 #
- Default
- The Pod inherits the name resolution configuration from the node that the pods run on
- ClusterFirst
- Any DNS query that does not match the configured cluster domain suffix, such as
“www.kubernetes.io”
, is forwarded to the upstream nameserver inherited from the node.
- Any DNS query that does not match the configured cluster domain suffix, such as
- ClusterFirstWithHostNet
- For Pods running with hostNetwork, you should explicitly set its DNS policy “ClusterFirstWithHostNet”
- None
- It allows a Pod to ignore DNS settings from the Kubernetes environment.
- All DNS settings are supposed to be provided using the dnsConfig field in the Pod Spec.
“
Default
” is not the default DNS policy.If dnsPolicy is not explicitly specified, then “
ClusterFirst
” is used.
参考:
k8s 中域名是如何被解析的 #
在 k8s 中,一个 Pod 如果要访问相同 Namespace 下的 Service(比如 user-svc),那么只需要 curl user-svc
。
如果 Pod 和 Service 不在同一域名下,那么就需要在 Service Name 之后添加上 Service 所在的 Namespace(比如 beta),curl user-svc.beta
。
那么 k8s 是如何知道这些域名是内部域名并为他们做解析的呢?
无论是在 宿主机 或者是在 k8s 集群中,DNS 解析会依赖这个三个文件
/etc/host.conf
/etc/hosts
/etc/resolv.conf
/etc/resolv.conf #
resolv.conf 是 Pod 在 dnsPolicy: ClusterFirst
的情况下,k8s 为其自动生成的。
在该 Pod 内请求的所有的域名解析都需要经过 DNS Service
进行解析,不管是集群内部域名还是外部域名。
每行都会以一个关键字开头,然后跟配置参数。
在集群中主要使用到的关键词有 3 个
- nameserver 定义 DNS 服务器的 IP 地址(Kube-DNS 的 Service IP)
- search 定义域名的搜索列表,当查询的域名中包含的
.
的数量少于 options.ndots 的值时,会依次匹配列表中的每个值 - options 定义域名查找时的配置信息
nameserver、search 和 options 都是可以通过 dnsConfig 字段进行配置的,详细参考官方文档
例如
nameserver 10.250.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
nameserver #
nameserver 所对应的地址正是 DNS Service 的 Cluster IP(该值在启动 kubelet
的时候,通过 clusterDNS
指定)。
search 域 #
search 域默认包含了 namespace.svc.cluster.local
、svc.cluster.local
和 cluster.local
三种。
当我们在 Pod 中访问 a
Service 时( curl a
),会选择 nameserver 10.250.0.10 进行解析,然后依次带入 search 域进行 DNS 查找,直到找到为止。
$ curl a
a.default.svc.cluster.local
显然因为 Pod 和 a Service 在同一 Namespace 下,所以第一次 lookup 就能找到。
如果 Pod 要访问不同 Namespace(例如: beta )下的 Service b ( curl b.beta ),会经过两次 DNS 查找,分别是
$ curl b.beta
b.beta.default.svc.cluster.local # Not Found
b.beta.svc.cluster.local # Found
正是因为 search 的顺序性,所以访问同一 Namespace 下的 Service, curl a 是要比 curl a.default 的效率更高的,因为后者多经过了一次 DNS 解析。
$ curl a
a.default.svc.cluster.local # Found
$ curl a.default
b.default.default.svc.cluster.local # Not Found
b.default.svc.cluster.local # Found
options #
ndots #
ndots:5,表示:
- 如果需要 lookup 的 Domain 中包含少于 5 个
.
,那么将会被当做非绝对域名, - 如果需要查询的 Domain 中包含大于或等于 5 个
.
,那么就会被当做绝对域名。
如果是绝对域名则不会走 search 域,
如果是非绝对域名,就会按照 search 域中进行逐一匹配查询, 如果 search 走完了都没有找到,那么就会使用原域名进行查找。
优化外网域名解析 #
在真正解析 http://iftech.io 之前,经历了
iftech.io.default.svc.cluster.local
-> iftech.io.svc.cluster.local
-> iftech.io.cluster.local
-> iftech.io
这样也就意味着前 3 次 DNS 请求是浪费的,没有意义的。
直接使用绝对域名 #
这是最简单直接的优化方式,可以直接在要访问的域名后面加上 .
如:iftech.io.
,这样就可以避免走 search 域进行匹配。
配置 ndots #
比如配置 ndots:1
,iftech.io.
就会使用原域名进行查找。
CoreDNS vs KubeDNS #
在 kube-dns 中,一个 pod 内使用了数个容器:kubedns、dnsmasq 和 sidecar。
- kubedns 容器监视 Kubernetes API 并基于 Kubernetes DNS 规范提供 DNS 记录,
- dnsmasq 提供缓存和存根域支持,
- sidecar 提供指标和健康检查。
此设置会导致一些问题随着时间的推移而出现。首先,dnsmasq 中的安全漏洞导致过去需要发布 Kubernetes 安全补丁。 此外,由于 dnsmasq 处理存根域,但 kubedns 处理 External Services,因此你无法在外部服务中使用存根域,这非常限制该功能(参阅 dns#131)。
在 CoreDNS 中,所有这些功能都在一个容器中完成 —— 该容器运行用 Go 编写的进程。 启用的不同插件来复制(并增强)kube-dns 中的功能。
为什么 pod 是 coredns,service 是 kube-dns? #
其实是 CoreDNS
CoreDNS is default from K8S 1.11. For previous installations it’s kube-dns.
看 image
,其他都是 metadata,不重要
$ k describe pod coredns-6967fb4995-76trs -n kube-system | grep -i "image"
Image: registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:1.3.1
问题详情
$ k cluster-info
Kubernetes master is running at https://192.168.99.102:8443
KubeDNS is running at https://192.168.99.102:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
$ k get po -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-6967fb4995-76trs 1/1 Running 6 32d
coredns-6967fb4995-grnzj 1/1 Running 6 32d
etcd-minikube 1/1 Running 3 32d
kube-addon-manager-minikube 1/1 Running 3 32d
kube-apiserver-minikube 1/1 Running 3 32d
kube-controller-manager-minikube 1/1 Running 3 32d
kube-proxy-z765q 1/1 Running 3 32d
kube-scheduler-minikube 1/1 Running 3 32d
storage-provisioner 1/1 Running 5 32d
$ k 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 32d
$ k 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=KubeDNS
Annotations: prometheus.io/port: 9153
prometheus.io/scrape: true
Selector: k8s-app=kube-dns
Type: ClusterIP
IP: 10.96.0.10
Port: dns 53/UDP
TargetPort: 53/UDP
Endpoints: 172.17.0.2:53,172.17.0.3:53
Port: dns-tcp 53/TCP
TargetPort: 53/TCP
Endpoints: 172.17.0.2:53,172.17.0.3:53
Port: metrics 9153/TCP
TargetPort: 9153/TCP
Endpoints: 172.17.0.2:9153,172.17.0.3:9153
Session Affinity: None
Events: <none>
参考:
叶王 © 2013-2024 版权所有。如果本文档对你有所帮助,可以请作者喝饮料。