16boke - 一路博客

4、安装CoreDNS实现Kubernetes的服务发现

Kubernetes DNS服务简介

介绍

域名系统(DNS)是一种用于将各种类型的信息(例如IP地址)与易于记忆的名称相关联的系统。 默认情况下,大多数Kubernetes群集会自动配置内部DNS服务,以便为服务发现提供轻量级机制。 内置的服务发现使应用程序更容易在Kubernetes集群上相互查找和通信,即使在节点之间创建,删除和移动Pod和服务时也是如此。

最近版本的Kubernetes中Kubernetes DNS服务的实现细节已经改变。 在本文中,我们将介绍Kubernetes DNS服务的kube-dns和CoreDNS几个不同的实现版本。 我们一起来看看它们的运作方式以及Kubernetes生成的DNS记录。

Kubernetes DNS服务提供什么?

在Kubernetes版本1.11之前,Kubernetes DNS服务基于kube-dns。 1.11版引入了CoreDNS来解决kube-dns的一些安全性和稳定性问题。

无论处理实际DNS记录的软件如何,两种实现都以类似的方式工作:

  • 创建名为kube-dns的服务和一个或多个Pod。

  • kube-dns服务监听来自Kubernetes API的服务service和端点endpoint事件,并根据需要更新其DNS记录。 创建,更新或删除Kubernetes服务及其关联的pod时会触发这些事件。

  • kubelet将每个新Pod的/etc/resolv.conf名称服务器选项设置为kube-dns服务的集群IP,并使用适当的搜索选项以允许使用更短的主机名:

resolve.conf

nameserver 10.32.0.10 search namespace.svc.cluster.local svc.cluster.local cluster.local options ndots:5

  • 然后,在容器中运行的应用程序可以将主机名(例如example-service.namespace)解析为正确的群集IP地址。

Kubernetes DNS记录示例

Kubernetes服务的完整DNS A记录类似于以下示例:

service.namespace.svc.cluster.local

一个Pod会有这种格式的记录,反映了Pod的实际IP地址:

10.32.0.125.namespace.pod.cluster.local

此外,为Kubernetes服务的命名端口创建SRV记录:

_port-name._protocol.service.namespace.svc.cluster.local

所有这些的结果是内置的,基于DNS的服务发现机制,你的应用程序或微服务可以在其中定位一个简单一致的主机名,并可以访问群集上的其他服务或Pod。

CoreDNS

从Kubernetes 1.11开始,新的Kubernetes DNS服务,CoreDNS已升级为GA。 这意味着它已准备好用于生产,并且将成为许多安装工具和托管Kubernetes提供商的默认集群DNS服务。

CoreDNS,用Go编写且单一进程,它涵盖了以前系统的所有功能: 单个容器解析并缓存DNS查询,响应运行状况检查并提供指标。

除了解决与性能和安全相关的问题之外,CoreDNS还修复了一些其他小错误并添加了一些新功能:

  • 修复了使用stubDomains和外部服务之间不兼容的一些问题

  • CoreDNS可以通过随机化返回某些记录的顺序来增强基于DNS的round-robin负载平衡

  • autopath功能可以在解析外部主机名时提高DNS响应时间,方法是更好地遍历resolv.conf中列出的每个搜索域后缀

  • 如果使用kube-dns的话,10.32.0.125.namespace.pod.cluster.local将始终解析为10.32.0.125,即使pod实际上不存在。 CoreDNS具有“已验证的pod”模式,只有当存在具有正确IP且位于右侧命名空间的pod时,才会成功解析。

1、下载CoreDNS配置文件并修改

Github的路径:https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/dns/coredns/coredns.yaml.base

下载coredns.yaml.base,然后修改“__PILLAR__DNS__DOMAIN__”为“cluster.local”,意思是dns在集群中的域名,修改“__PILLAR__DNS__SERVER__”为集群ip地址(这个需要查看集群的配置)

默认情况下dns服务使用ServiceAccount、 ClusterRole和 ClusterRoleBinding来做认证和捐授权,如果内网不采用认证,可以去掉ServiceAccount、 ClusterRole和 ClusterRoleBinding 部分,同时将Deployment部分删除 serviceAccountName: coredns

2、部署coredns

kubectl create -f coredns.yaml

如果安装kubernetes的时候没有启用kube-apiserver的token认证,此时会报错,提示:“/var/run/secrets/kubernetes.io/serviceaccount/apiserver.key不存在”,需要创建一个serviceaccount账号。

3、创建ServiceAccount和secret

执行kubectl get serviceaccount,如果结果如下:

NAME      SECRETS default   0

说明没有Serviceaccount,需要在apiserver的启动参数中添加:

--admission_control=ServiceAccount,重启kube-apiserver服务,会发现创建了/var/run/kubernetes/apiserver.crt和apiserver.key这两个文件。

接着修改kube-controller-manager服务,添加:

--service_account_private_key_file=/var/run/kubernetes/apiserver.key

然后重启kube-controller-manager服务。

再执行kubectl get serviceaccount,如果结果如下:

NAME      SECRETS default   1

说明创建成功

4、修改node节点的kubelet服务

修改kubelet服务的:KUBELET__DNS_IP="--cluster-dns=10.10.10.111"

KUBELET_DNS_DOMAIN="--cluster-domain=cluster.local"

其中10.10.10.111为我创建corndns的时候设置的集群ip地址,cluster.local为集群域名。

然后重启kubelet服务。

5、测试

这里以《kubernetes权威指南》的javaweb项目来测试,默认情况下tomcat中的web程序访问不了mysql的,因为jsp中配置的以服务名“mysql”来连接mysql服务器,但是由于之前没有配置dns,所以访问失败,错误提示:“Caused by: java.net.UnknownHostException: mysql”。

这里先全部删除创建的mysql-rc.yaml,mysql-svc.yaml、myweb-rc.yaml、myweb-svc.yaml,然后再重新创建。再请求http://192.168.13.126:30001/demo,发现成功访问了。