在kubernetes中配置skydns
pmos
8年前
<p>kubernetes中的集群发现有两种方式,一种是 环境变量 ,还有一种就是 dns 服务。对于环境变量,在使用上有一些限制,它依赖于svc和rc的启动顺序: 如果rc先于svc启动,那么pod里面就没有相关svc的环境变量,这种方式违背了kubernetes的理念,即资源之间是解耦的。推荐的方式是使用dns的服务,这篇文章主要关于部署skydns的过程以及其中遇到的问题和采用的方式。</p> <h3>部署</h3> <p>关于skydns如何部署在已有的kubernetes集群中,网上有不少资料可以参考,想要部署一个toy版本可以参考一下。</p> <h3>问题 & 方案</h3> <p>在实际应用的过程中,我需要改变一些配置,其中遇到的坑就记录在此。</p> <p>http vs https</p> <p>网络上所有关于skydns的配置,全都是基于http的。比如下面这一条:</p> <pre> command: - /kube2sky - --kube_master_url=http://10.8.65.48:8080 - -domain=kube.local </pre> <p>kube-apiserver监听了两个端口,一个是对外的https,一个是对内的http,两者提供的服务是一样的。</p> <p>默认的http端口是监听在127.0.0.1:8080上的,对于这个问题,有几个可行的方案:</p> <ol> <li>修改apiserver的配置,让它监听在某个内网ip上,skydns通过内网ip去访问apiserver</li> <li>通过外网ip访问,建立iptables路由规则,将外网的流量转发到127.0.0.1:8080<br> 这个方案需要注意添加ip白名单,防止外网恶意流量的入侵,由于事先并不知道调度器会把dns服务送往哪台机器,需要预先对所有集群机器的ip加白名单。</li> <li>将dns服务通过label绑定在apiserver所在的机器上,直接访问本地外网ip<br> (备注,不确定本地docker里面访问 external_ip:8080 可不可以被转发到 127.0.0.1:8080 ,需要试试。如果不行的话,这条方案直接枪毙。)</li> </ol> <p>但我所遇到的情况更苛刻,kubernetes集群中的机器分布于不同的idc机房,运营商也不全是同一个。这个时候除了自己搭建V*N内网,就没有办法使用内网ip了。由于自己维护V*N内网的成本太大,因此这里就不考虑方案一了。</p> <p>对于方案二,需要预先加很多白名单。之后如果集群有新机器进来,又要加一遍,维护成本也很大,暂时放弃。</p> <p>对于方案三,即使可行,但我也不想把dns服务绑死在某一台机器上,集群调度本身就应该有足够的自由度。</p> <p>想了又想,要不试试使用https的端口吧。但让我失望的是,google到处搜,也没有搜到skydns用https的方案。最后还是在kube2sky的 github主页 找到了某个可能可用的配置选项:</p> <pre> --kube-master-url: URL of kubernetes master. Required if --kubecfg_file is not set. --kubecfg-file: Path to kubecfg file that contains the master URL and tokens to authenticate with the master. </pre> <p>在skydns-rc.yaml中去掉 --kube_master_url ,然后使用 --kubecfg_file ,指向kubeconfig文件,这里我偷个懒使用的是kubelet的配置文件(kubelet.kubeconfig):</p> <pre> apiVersion: v1 kind: Config current-context: kubelet-to-cluster.local preferences: {} clusters: - cluster: certificate-authority: /etc/kubernetes/certs/ca.crt server: https://node-1-master: name: cluster.local contexts: - context: cluster: cluster.local user: kubelet name: kubelet-to-cluster.local users: - name: kubelet user: token: J1j0EhcoCBZBAP20xDR72ta79vPr7j3J </pre> <p>目录挂载</p> <p>在上一部中指定了 --kubecfg_file=/etc/kubernetes/kubelet.kubeconfig 还是不够的,启动的时候会报错,说找不到配置文件。原因是这个路径只是作为一个字符串传进了pod中,pod中并没有这个路径对应的文件,我们还需要做目录的挂载:</p> <pre> # 省略很多配置 volumeMounts: - name: kubernetes-etc mountPath: /etc/kubernetes readOnly: true </pre> <pre> # 省略很多配置 volumes: - name: kubernetes-etc hostPath: path: /etc/kubernetes </pre> <p>在我以为大功告成的时候,结果还是给了我最后一个坑。这个时候kube2sky报了一个错,说无法解析node-1-master。</p> <p>因为集群中所有机器都是以这种短名字命名的,它们对应的ip都配在所有机器的 /etc/hosts 里。而pod中的 /etc/hosts 并不是继承于宿主机的,所以自然就无法解析这些短名字了。最后解决的方法也跟上面一样,把 /etc/hosts 这个文件挂载到skydns的pod中就可以了。</p> <h3>总结</h3> <p>我的方案可能并不是best practice,也非常感谢广大读者可以提出更好的做法,我也会即使更新在博客中,在此谢过了。</p> <p> </p> <p>来自:http://xidui.github.io/2017/02/06/在kubernetes中配置skydns/</p> <p> </p>