为什么要引入DNS
在kubernetes中每一个service都会被分配一个虚拟IP,每一个Service在正常情况 下都会长时间不会改变,这个相对于pod的不定IP,对于集群中APP的使用相对是稳定的。但是Service的信息注入到pod目前使用的是环境变量的 方式,并且十分依赖于pod(rc)和service的创建顺序,这使得这个集群看起来又不那么完美,于是kubernetes以插件的方式引入了DNS 系统,利用DNS对Service进行一个映射,这样我们在APP中直接使用域名进行引用,避免了之前的变量泛滥问题,也避免了创建顺序的尴尬局面。
kubernetes中的DNS
kubernetes中以插件的方式使用skydns作为DNS服务器。并且引入了一个另外一个组件kube2sky用来创建和删除域名解析记录。它目前仅支持两种解析A记录、SRV记录,在集群中对于域名的创建遵循一个规则:
对于A记录:
每一个Service都会对应一个A记录,命名规则为:
SERVICENAME.NAMESPACENAME.svc.CLUSTERDOMAIN
- SERVICENAME:每个Service的名字
- NAMESPACENAME:Service所属的namespace的名字
- svc:固定值
- CLUSTERDOMAIN:集群内部的域名
PS:由于老版本的原因,用户应该避免创建名为svc的namespace,否则会有你意想不到的事情发生
对于SRV记录:
每一个服务端口和服务协议会对应一个SRV记录,命名规则为:
_PORTNAME._PORTPROTOCOL.SERVICENAME.NAMESPACENAME.svc.CLUSTERDOMAIN
- _PORTNAME:服务端口名字
- PORTPROTOCOL:服务端口的协议类型
后面的四段和上面A记录的规则一致
解析特点:
从上面可以看出,我们的域名是又臭又长,看起来很不爽。但是在kubernetes集群中,我们在解析的时候不是必须完全输入完才可以解析。
在同一个命令空间下如果我们引用的话,只需要引用对应的Service的名字
如果引用了非同一命名空间下的Service,那么我们只需要加上其对应的命名空间的名字即可。
例如:
a命名空间(namespace)下有个Service:s1 App: a1,b命名空间(namespace)下有个Service:s2 App: a2
现在App a1中需要使用a1 和 a2,那么只需要写出 a1 和 a2.b即可。反过来a2也是这样。
工作原理:
简要画一个图来表示
kube2sky在启动的时候需要指定集群的域名,需要指定etcd的API接口,需要指定kube-apiserver的接口地址,启动之后 kube2sky会通过apiserver监听所有service的创建、删除、修改等操作,在etcd中写入对应的域名解析记录。另一方面 kubernetes集群中,kubelet需要配置skydns的解析地址,在kubelet创建的每一个container时,都会将dns指向到 skydns,在container中进行解析时,解析请求会发送到skydns,skydns会通过etcd中的解析记录进行查找返回对应的解析结果。
安装与配置:
概况
- kube-apiserver: 10.10.2.120:8080
- etcd: 10.10.2.120:4001
- 集群域名: coocla.org
1. 编译kube2sky和skydns
大家可以直接下载我已经编译好的kube2sky、skydns
编译skydns
需要把skydns运行在哪台机器上,就把编译后的skydns拷贝到哪台机器上即可,下面的kube2sky也一样,我这里就运行在编译的这台机器上,
编译kube2sky
2. 配置skydns
- dns-addr: 指定skydns启动时的监听地址
- ttl: 指域名的缓存的超时时间,单位秒
- domain: 集群中的私有域名,这里如果不指定,默认为skydns.local. ,注意最后的一个点
- nameservers:域名转发的dns列表,用来解析集群外部的域名
关于etcd的集群这里我采用集群原本存在的,详情可以参考:Kubernetes技术学习之—搭建kubernetes集群。因此这里不再赘述etcd的搭建过程
3. 启动skydns
4. 启动kube2sky
5. 配置kubelet
指定kubelet的集群域名及集群内部的DNS(skydns)地址
在kubelet的配置文件(/etc/kubernetes/kubelet)中KUBELET_ARGS添加以下两个参数:
重启kubelet以使配置生效。
6. 验证
验 证方法:创建一个新的namespace,在default的namespace中创建两个Pod,一个为nginx server,一个为client1,在新的namespace中创建一个pod为client2,为default namespace中的nginx server创建一个service,分别使用client1和client2对新创建的service进行A记录和SRV记录解析,并解析外部域名的解 析地址。
# cat valid_skydns.yaml
在service创建的过程,我看可以看到kube2sky的日志如下:
接下才我们首先验证Service对应的A记录是否正常:
从上图可以看出跨namespace时则至少需要加上service所在的namespace。
我们再来验证SRV记录的解析:
最后验证集群外部的域名解析:
至此可以看出skydns + kube2sky已经正常的工作在kubernetes集群中。
查看原文:http://www.zoues.com/index.php/2016/02/27/dcos%e4%b9%8bskydns/