service注册和域名发现
服务注册:
创建service时,增加相应的 key/value 进入 etcd.
Servicename:clusterip through API-server.
服务发现:
作为服务发现机制的基本功能,在集群内需要能够通过服务名对服务进行访问,这就需要一 个集群范围内的 DNS 服务来完成从服务名到 ClusterIP 的解析。
从 Kubernetes 1.11 版本开始,Kubernetes 集群的 DNS 服务由 CoreDNS 提供。 CoreDNS 是 CNCF 基金会的一个项目,是用 Go 语言实现的高性能、插件式、易扩展的 DNS 服务端。 CoreDNS 解决了 KubeDNS 的一些问题,例如 dnsmasq 的安全漏洞、externalName 不能使 用 stubDomains 设置,等等。
CoreDNS 支持自定义 DNS 记录及配置 upstream DNS Server,可以统一管理 Kubernetes 基 于服务的内部 DNS 和数据中心的物理 DNS。
CoreDNS 没有使用多个容器的架构,只用一个容器便实现了 KubeDNS 内 3 个容器的全部功 能。
当一个service创建之后,在etcd 中,注册servicename:Servicename:clusterip等信息, 然后CoreDns 会在kubernets master 中订阅服务,进行watch list。
当ervice创建之后,kubernetes master通知 CoreDns,建立DNS关系。
Pod会从conredns中查询service,例如:servicename.ns1.svc.cluster.local,找到映射的ip,如:169.169.58.168
查看 CoreDNS 信息
k8s 的 v1.20.5 版本在集群启动时,已经启动了 coreDNS 域名服务。
在部署 CoreDNS 应用前,至少需要创建一个 ConfigMap、一个 Deployment 和一个 Service 共 3 个资源对象。ConfigMap“coredns”主要设置 CoreDNS 的主配置文件 Corefile 的内容, 其中可以定义各种域名的解析方式和使用的插件。
# kubectl get configmap -n kube-system
# kubectl edit configmap coredns -n kube-system
其中,各插件说明:
1. errors:错误信息到标准输出。
2.health:CoreDNS 自身健康状态报告,默认监听端口 8080,一般用来做健康检查。您可以通 过 http://localhost:8080/health 获取健康状态。
3.ready:CoreDNS 插件状态报告,默认监听端口 8181,一般用来做可读性检查。可以通过 http://localhost:8181/ready 获取可读状态。当所有插件都运行后,ready 状态为 200。
4.kubernetes:CoreDNS kubernetes 插件,提供集群内服务解析能力。
5.prometheus:CoreDNS 自身 metrics 数据接口。可以通过http://localhost:9153/metrics 获取 prometheus 格式的监控数据。 forward(或 proxy):将域名查询请求转到预定义的 DNS 服务器。默认配置中,当域名不在 kubernetes 域时,将请求转发到预定义的解析器(/etc/resolv.conf)中。默认使用宿主机的 /etc/resolv.conf 配置。
6.cache:DNS 缓存。
7.loop:环路检测,如果检测到环路,则停止 CoreDNS。
8.reload:允许自动重新加载已更改的 Corefile。编辑 ConfigMap 配置后,请等待两分钟以使 更改生效。
9. loadbalance:循环 DNS 负载均衡器,可以在答案中随机 A、AAAA、MX 记录的顺序。 在下面的示例中为域名“ cluster.local ”设置了一系列插件,包括 errors 、health、kubernetes、 prometheus、forward、cache、loop、reload 和 loadbalance,在进行域名解析时,这些插件 将以从上到下的顺序依次执行。 另外,etcd 和 hosts 插件都可以用于用户自定义域名记录。 下面是使用 etcd 插件的配置示例,将以“.com”结尾的域名记录配置为从 etcd 中获取,并将 域名记录保存在/skydns 路径下
serviceName的DNS解析举例
在centos下,安装必要功能
yum -y install bind-utils k run c5 -it --image=registry.cn-hangzhou.aliyuncs.com/liuyik8s/centos:dns – sh
接下来使用一个带有 nslookup 工具的 Pod 来验证 DNS 服务能否正常工作:
kubectl run curl --image=radial/busyboxplus:curl -i
然后,按回车并执行nslookup kubernets 命令,查看kubernetes集群服务情况
nslookup kubernetes Server10.20.0.10Address 1 10.20.0.10 kube-dns.kube-system.svc.cluster.local Name kubernetes Address 1 10.20.0.1 kubernetes.default.svc.cluster.local
查找同namespace的服务
在 dnsutils 成功启动后,通过 nslookup 进行测试。
查找 defaul 命名空间存在的 mysql 服务。
kubectl run curl --image=radial/busyboxplus:curl -it root@curl:/ $ nslookup test1 Server10.20.0.10 Address 1 10.20.0.10 kube-dns.kube-system.svc.cluster.local Name test1 Address 1 10.20.45.33 test1.default.svc.cluster.local
可以看到,通过 DNS 服务器,成功找到了 test1 服务的 IP 地址:10.20.45.33。
查找不同命名空间的服务
如果某个 Service 属于不同的命名空间,那么在进行 Service 查找时,需要补充 Namespace 的名称,组合成完整的域名。下面以查找 kube-dns 服务为例,将其所在的 Namespace“kube-system”补充在服务名之后,用“.”连接为“kube-dns.kube-system”,即可查询成功:
/ # nslookup kube-dns.kube-systemServer10.96.0.10Address 10.96.0.10#53 Name kube-dns.kube-system.svc.cluster.local Address10.96.0.10
如果仅使用“kube-dns”进行查找,则会失败:
/ # nslookup kube-dnsServer10.96.0.10Address 10.96.0.10#53 ** server can't find kube-dns NXDOMAIN
域名解析过程分析
resolv.conf 文件分析
部署 pod 的时候,如果用的是 K8s 集群的 DNS,那么 kubelet 在起 pause 容器的时候, 会将其 DNS 解析配置初始化成集群内的配置。
比如刚才创建了一个叫 curl 的 pod,它的 resolv.conf 文件如下:
$ kubectl exec -it curl -- sh / # cat /etc/resolv.conf nameserver 10.96.0.10 search default.svc.cluster.local svc.cluster.local cluster.local options ndots:5
在集群中 pod 之间互相用 svc name 访问的时候,会根据 resolv.conf 文件的 DNS 配置 来解析域名,下面来分析具体的过程。
pod 的 resolv.conf 文件主要有三个部分,分别为 nameserver、search 和 option。
而这三 个部分可以由 K8s 指定,也可以通过 pod.spec.dnsConfig 字段自定义。
nameserver
resolv.conf 文件的第一行 nameserver 指定的是 DNS 服务的 IP,这里就是 coreDNS 的 clusterIP
# kubectl get services -n kube-system -o wideNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 24h k8s-app=kube-dns
也就是说所有域名的解析,都要经过 coreDNS 的虚拟 IP 10.96.0.10 进行解析,不论是 Kubernetes 内部域名还是外部的域名。
search 域
resolv.conf 文件的第二行指定的是 DNS search 域。
解析域名的时候,将要访问的域名依次 带入 search 域,进行 DNS 查询。
比如我要在刚才那个 pod 中访问一个域名为 dnsutils 的服务,其进行的 DNS 域名查询的 顺序是: dnsutils.default.svc.cluster.local -> dnsutils.svc.cluster.local -> dnsutils.cluster.local 直到查到为止
options
resolv.conf 文件的第三行指定的是其他项,最常见的是 dnots。
dnots 指的是如果查询的域 名包含的点 “.” 小于 5,则先走 search 域,再用绝对域名;如果查询的域名包含点数大于 或等于 5,则先用绝对域名,再走 search 域。
K8s 中默认的配置是 5。 也就是说,如果我访问的是 a.b.c.e.f.g ,那么域名查找的顺序如下:
a.b.c.e.f.g. -> a.b.c.e.f.g.default.svc.cluster.local -> a.b.c.e.f.g.svc.cluster.local -> a.b.c.e.f.g.cluster.local
如果我访问的是 a.b.c.e,那么域名查找的顺序如下:
a.b.c.e.default.svc.cluster.local -> a.b.c.e.svc.cluster.local -> a.b.c.e.cluster.local -> a.b.c.e
Pod级别DNS配置说明
除了使用集群范围的 DNS 服务(如 CoreDNS),在 Pod 级别也能设置 DNS 的相关策略和配 置。在 Pod 的 YAML 配置文件中通过 spec.dnsPolicy 字段设置 DNS 策略,例如:
apiVersion v1 kind Pod metadata namespace default name dns-example spec containersname test image nginx dnsPolicy"Default"
目前可以设置的 DNS 策略如下。
◎ Default:继承 Pod 所在宿主机的 DNS 设置。
◎ ClusterFirst:优先使用 Kubernetes 环境的 DNS 服务(如 CoreDNS 提供的域名解析服务), 将无法解析的域名转发到从宿主机继承的 DNS 服务器。
◎ ClusterFirstWithHostNet:与 ClusterFirst 相同,对于以 hostNetwork 模式运行的 Pod,应 明确指定使用该策略。
◎ None:忽略 Kubernetes 环境的 DNS 配置,通过 spec.dnsConfig 自定义 DNS 配置。这个 选项从 Kubernetes 1.9 版本开始引入,到 Kubernetes 1.10 版本升级为 Beta 版,到 Kubernetes 1.14 版本升级为稳定版。
以下面的 dnsConfig 为例:
apiVersion v1 kind Pod metadata namespace default name dns-example spec containersname test image nginx dnsPolicy"None" dnsConfig nameservers 1.2.3.4 searches ns1.svc.cluster.local my.dns.search.suffix optionsname ndots value"2"name edns0