@dujun
2015-04-03T16:42:26.000000Z
字数 2418
阅读 4965
Kubernetes写书
在前面对Kubernetes的讨论中我们已经知道,每个Kubernetes service都绑定了一个虚拟IP地址(Portal IP),而且Kubernetes最初使用向pod中注入环境变量的方式实现服务发现,但这会带来环境变量泛滥等问题,故需要增加集群DNS服务为每个service映射一个域名。到kubernetes v0.8版本时,DNS作为一个系统可选插件集成到Kubernetes集群中。Kubernetes默认使用(SkyDNS)作为集群的DNS服务器,同时支持forward查找 (A记录)和service查找(SRV记录)。
如果启用了集群DNS选项,则系统会自动创建一个运行SkyDNS域名服务器的pod和一个对外提供集群service域名解析服务的skydns service,并且还会为该service绑定一个稳定的静态IP地址作为入口IP地址。然后,Kubelet被配置成向每个Docker容器传入skydns service的IP地址作为他们的其中一个DNS服务器。每个在Kubernetes集群中定义的service(包括DNS服务器本身对应的service)都会被映射到一个DNS域名,该域名一般由两个部分组成:service所在namespace和service名。默认情况下,一个客户端pod的DNS搜索列表一般包含pod自身的namespace和集群的默认域名集。skydns service的域名搜索过程大致如下(以解析域名foo.bar
为例):
1)搜索客户端pod所在namespace(假设是baz
)中所有的service域名记录,检查是否存在baz.foo.bar
的记录。如果找到,则结束搜索过程,返回该记录对应的IP地址,如果没找到,执行步骤2。
2)搜索namespace foo
中所有的service域名记录,检查是否存在foo.bar
的记录。如果找到,则结束搜索过程,返回该记录对应的IP地址,如果没找到,执行步骤3。
3)在Kubernetes集群系统service域名集中搜索所有的service域名记录,检查是否存在foo.bar
的记录。如果找到,则结束搜索过程,返回该记录对应的IP地址,如果没找到,表示该域名不存在,返回客户端错误信息。
因此,假设有一个名为foo
的service位于集群的bar
namespace中,那么运行在namespace bar
中的pod只需查询DNS记录 foo
就能找到该service,而运行在namespace bar
外的pod(譬如:quux
)就需要查询DNS记录 foo.bar
才能找到该service。
skydns pod中包含3个容器,这三个容器分别运行:skydns,etcd(skydns要用到etcd)和一个连接Kubernetes和skydns的网桥(称为kube2sky)。kube2sky监测Kubernetes主控节点上service对象的更新(kube2sky通过环境变量找到kubernetes-ro service,并调用kubernetes-ro service提供的API来实现),然后向DNS pod中的etcd写入service对象信息,skydns最后会去etcd中读取这些信息。需要注意的是,DNS pod中的etcd实例不会连接到其他已经存在的etcd集群(包括Kubernetes主控节点上的etcd集群)。skydns service可以被所有Kubernetes节点直接访问到,但是Kubernetes节点没有被配置成默认使用集群DNS 服务或搜索集群DNS域名。因此如果想使用集群DNS服务,需在Kubernetes节点上的resolv.conf
文件中显式地将DNS nameserver指向skydns域名服务器。
配置集群DNS最简单的方式是使用cluster/
目录下的自动部署脚本,例如部署在GCE环境中Kubernetes集群在启动之初就创建了SkyDNS pod并使用以下配置文件(见:cluster/gce/config-default.sh
)配置Kubelet。
ENABLE_CLUSTER_DNS=true
DNS_SERVER_IP="10.0.0.10"
DNS_DOMAIN="kubernetes.local"
DNS_REPLICAS=1
以上配置文件启用了集群DNS,并为DNS service绑定了一个IP地址:10.0.0.10
,且该IP地址对应的DNS域名是kubernetes.local
。DNS_REPLICAS
字段表明SkyDNS
的pod副本数为1(该参数传给控制SkyDNS
pod的replication controller)。
如果你不使用cluster/
目录下的自动部署脚本搭建Kubernetes集群(可能你没有Kubernetes支持的IaaS环境),那么你首先需要在kubelet启动时传入以下flag信息。
--cluster_dns=<DNS service ip>
--cluster_domain=<default local domain>
然后,你需要创建DNS server的replication controller和service。读者可以参考skydns-rc.yaml.in和skydns-svc.yaml.in分别作为replication controller和service资源文件的参考。不过,需要注意的是以上两个文件并不是真正的Kubernetes资源文件而是一个saltstack的模板文件,你需要在{{ <param> }}
部分填入你自己的值后才能使用kubectl create
创建replication controller和service对象。