LOADING

Follow me

DCOS之skydns
二月 27, 2016|DCOS

DCOS之skydns

DCOS之skydns

为什么要引入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

# yum install go
# mkdir /tmp/kube2sky
# export GOPATH=/tmp/kube2sky
# cd /tmp/kube2sky 
# go get githu.com/skynetservices/skydns
# cd $GOPATH/src/github.com/skynetservices/skydns
# go build -v
# cp $GOPATH/bin/skydns /usr/bin

需要把skydns运行在哪台机器上,就把编译后的skydns拷贝到哪台机器上即可,下面的kube2sky也一样,我这里就运行在编译的这台机器上,

编译kube2sky

# mkdir /tmp/skydns
# go get github.com/tools/godep
# go get -d github.com/GoogleCloudPlatform/kubernetes/cluster/addons/dns/kube2sky
# cd /go/src/github.com/GoogleCloudPlatform/kubernetes/cluster/addons/dns/kube2sky
# make kube2sky
# cp kube2sky /usr/bin

2. 配置skydns

# etcdctl mk /skydns/config '{“dns-addr”: “10.10.2.120:53”, “ttl”: 3600, “domain”: “coocla.org.”, “nameservers”: [“223.5.5.5:53”, “114.114.114.114:53"]}'
  • dns-addr: 指定skydns启动时的监听地址
  • ttl: 指域名的缓存的超时时间,单位秒
  • domain: 集群中的私有域名,这里如果不指定,默认为skydns.local. ,注意最后的一个点
  • nameservers:域名转发的dns列表,用来解析集群外部的域名

关于etcd的集群这里我采用集群原本存在的,详情可以参考:Kubernetes技术学习之—搭建kubernetes集群。因此这里不再赘述etcd的搭建过程

3. 启动skydns

# skydns -machines=http://10.10.2.120:4001 &

4. 启动kube2sky

# kube2sky -domain=coocla.org -etcd-server=http://10.10.2.120:4001 -kube_master_url=http://10.10.2.120:8080 &

5. 配置kubelet

指定kubelet的集群域名及集群内部的DNS(skydns)地址

在kubelet的配置文件(/etc/kubernetes/kubelet)中KUBELET_ARGS添加以下两个参数:

KUBELET_ARGS="--cluster-dns=10.10.2.120 --cluster-domain=coocla.org"

重启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

apiVersion: v1
kind: Namespace
metadata:
  name: coocla

---
apiversion: v1
kind: Pod
metadata:
  name: nginx-server
  label:
      app: nginx
spec:
  containers:
  - name: nginx
    image: nginx

---
apiVersion: v1
kind: Pod
metadata:
  name: client
spec:
  containers:
  - name: client
    image: busybox
    command:
    - sleep
    - "360000"

---
apiVersion: v1
kind: Pod
metadata:
  name: client-coocla
  namespace: coocla
spec:
  containers:
  - name: client-coocla
    image: busybox
    command:
    - sleep
    - "360000"

---
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  ports:
  - port: 7878
    targetPort: 80
    protocol: TCP
    name: web80
  selector:
    app: nginx
# kubectl create -f valid_skydns.yaml
namespaces/coocla
pods/nginx-server
pods/client
pods/client-coocla
services/web

在service创建的过程,我看可以看到kube2sky的日志如下:

接下才我们首先验证Service对应的A记录是否正常:

14A263E1-B284-43CE-BA2B-B76FFC2160F0

从上图可以看出跨namespace时则至少需要加上service所在的namespace。

我们再来验证SRV记录的解析:

52C7DE3B-8E05-4799-BB99-E413E8A0ADC5

最后验证集群外部的域名解析:

8958A379-638F-43EC-AC79-23A2C3D1A6BA

至此可以看出skydns + kube2sky已经正常的工作在kubernetes集群中。

no comments
Share

发表评论