service发现是k8s中的一个重要机制,其基本功能为:在集群内通过服务名对服务进行访问,即需要完成从服务名到ClusterIP的解析。
k8s主要有两种service发现机制:环境变量和DNS。没有DNS服务的时候,k8s会采用环境变量的形式,但一旦有多个service,环境变量会变复杂,为解决该问题,我们使用DNS服务。
DNS服务在kubernetes中经历了三个阶段(SkyDNS-》KubeDNS-》CoreDNS):
下面是coredns的配置模板
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: namespace-test
data:
Corefile: |
.:53 {
errors
health
ready
kubernetes cluster.local 10.200.0.0/16 {
pods insecure
upstream 114.114.114.114
fallthrough in-addr.arpa ip6.arpa
namespaces namespace-test
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
CoreDNS的主要功能是通过插件系统实现的。它实现了一种链式插件的结构,将dns的逻辑抽象成了一个个插件。常见的插件如下:
spec:
dnsPolicy: "None"
dnsConfig:
nameservers:
- 1.2.3.4
searchs:
- xx.ns1.svc.cluster.local
- xx.daemon.com
options:
- name: ndots
values: "2"
pod被创建后,容器内的/etc/resolv.conf会根据这个信息进行配置。
之前安装k8s集群的时候就已经安装过CoreDNS,所以这里就不重复讲解安装了,不清楚的小伙伴,可以参考我这篇文章哦:Kubernetes(k8s)安装以及搭建k8s-Dashboard详解
创建nslookup服务
$ cat >busybox.yaml<
查看并验证
$ kubectl create -f busybox.yaml
$ kubectl get pods busybox
$ kubectl exec busybox -- cat /etc/resolv.conf
容器内 resolv 文件的配置
nameserver 10.1.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
ndots:5:如果查询的域名包含的点 “.” 不到 5 个,那么进行 DNS 查找,将使用非完全限定名称(或者叫绝对域名),如果你查询的域名包含点数大于等于 5,那么 DNS 查询,默认会使用绝对域名进行查询。
Kubernetes 域名的全称,必须是 service-name.namespace.svc.cluster.local 这种模式,服务名。
$ kubectl exec -ti busybox -- nslookup kubernetes.default
现在我们来创建一个busybox的pod,测试一下pod内是否可以解析
$ cat >busybox.yaml<
创建并测试解析kubernetes.default
$ kubectl apply -f busybox.yaml
$ kubectl get pods busybox
$ kubectl exec busybox -- cat /etc/resolv.conf
$ kubectl exec -ti busybox -- nslookup kubernetes.default
$ kubectl exec -ti busybox -- nslookup kubernetes.default.svc.cluster.local
cat >dns-Service-Deployment-test001.yaml<
创建
$ kubectl apply -f dns-Service-Deployment-test001.yaml
$ kubectl get pod|grep nginx-old
$ kubectl get svc nginx-svc-old
直接在宿主机上验证
$ nslookup nginx-svc-old.default.svc
发现直接在宿主机上是不能解析域名的。然后用以下yaml创建了一个busybox作为调试工具:
$ cat >dns-Deployment-test002.yaml<
这里用的是截止2021/10/08,busybox的最新镜像。创建好之后,exec进入容器,执行测试命令。
$ kubectl apply -f dns-Deployment-test002.yaml
$ kubectl get pod|grep busybox-deployment
$ kubectl exec -ti busybox-deployment-5bc85cc8d9-gkjgj -- sh
# 访问上面service的域名
$ nslookup nginx-svc-old.default.svc
发现也是无法解析。
根据coredns解析集群内域名原理可知:
服务 a 访问服务 b,对于同一个 Namespace下,可以直接在 pod 中,通过 curl b 来访问。对于跨 Namespace 的情况,服务名后边对应 Namespace即可,比如 curl b.default。DNS 如何解析,依赖容器内 resolv 文件的配置。
查看busybox容器内的resolve.conf文件:
$ kubectl exec -ti busybox-deployment-5bc85cc8d9-gkjgj -- sh
$ nslookup nginx-svc-old.default.svc
$ cat /etc/resolv.conf
这个文件中,配置的 DNS Server,一般就是 K8S 中,coredns的 Service 的 ClusterIP,这个IP是虚拟IP,无法ping,但可以访问。
在容器内发请求时,会根据 /etc/resolv.conf 进行解析流程。选择 nameserver 10.1.0.10 进行解析,然后用nginx-svc-old ,依次带入 /etc/resolve.conf 中的 search 域,进行DNS查找,分别是:
search 内容类似如下(不同的pod,第一个域会有所不同)
search default.svc.cluster.local svc.cluster.local cluster.local
nginx-svc-old.default.svc.cluster.local -> nginx-svc-old.svc.cluster.local -> nginx-svc-old.cluster.local
$ kubectl exec -ti busybox-deployment-5bc85cc8d9-gkjgj -- sh
$ ping nginx-svc-old
$ ping nginx-svc-old.default
直到找到为止。所以,我们执行 ping nginx-svc-old,或者执行 ping nginx-svc-old.default,都可以完成DNS请求,这2个不同的操作,会分别进行不同的DNS查找步骤。
根据以上原理,查看到busybox内的域名/etc/resolv.conf没有问题,nameserver指向正确的kube-dns的service clusterIP。
这下更加怀疑core-dns有问题了。
但查看coredns日志,可以看到并没有报错:
$ kubectl get pod -n kube-system|grep dns
$ kubectl logs -f coredns-7f6cbbb7b8-cn44w -n kube-system
$ kubectl logs -f coredns-7f6cbbb7b8-gf82k -n kube-system
那就说明不是coredns问题了。。
经过一番查找,发现是busybox版本问题。busybox<=1.28.4
发现都说是busybox镜像的问题,从1.28.4以后的镜像都存在这问题。把镜像换成1.28.4试试?修改yaml版本号:
$ kubectl apply -f dns-Deployment-test002.yaml
$ kubectl get pod|grep busybox-deployment
$ kubectl exec -ti busybox-deployment-564c775bbd-g6228 -- sh
$ nslookup nginx-svc-old.default.svc
# exit
$ kubectl get svc
确实可以成功解析域名了。所以这样看还真是busybox版本问题了。
nameserver关键字,如果没指定nameserver就找不到DNS服务器,其它关键字是可选的。nameserver表示解析域名时使用该地址指定的主机为域名服务器。其中域名服务器是按照文件中出现的顺序来查询的,且只有当第一个nameserver没有反应时才查询下面的nameserver,一般不要指定超过3个服务器。
在宿主上/etc/resolv.conf中nameserver如下:
$ kubectl get svc -n kube-system
$ kubectl get pod -n kube-system -o wide|grep dns
$ kubectl exec -ti busybox-deployment-564c775bbd-g6228 -- cat /etc/resolv.conf
$ cat /etc/resolv.conf
后面四个是k8s dns的配置,把后面四个都放到前面来,再验证:
nameserver 10.1.0.10
nameserver 10.244.2.137
nameserver 10.244.2.138
search default.svc.cluster.local svc.cluster.local cluster.local
$ nslookup nginx-svc-old
$ cat /etc/resolv.conf
$ nslookup baidu.com
可以看到现在可以解析了。也不影响外网域名解析,但是最好还是不要指定超过3个服务器。
留言与评论(共有 0 条评论) “” |