在k8s中搭建可解析hostname的DNS服务
2016-01-25更新
上篇文章总结k8s中搭建hbase时,遇到Pod中hostname的DNS解析问题,本篇将通过修改kube2sky源码来解决这个问题。
1 前言
kube2sky在Github上的项目(戳这里)一直在更新,放在DockerHub平台上的镜像滞后较多,有重新构建的必要。虽然新版kube2sky加入了对Pod的DNS解析,域名格式为<pod-ip-address>.<namespace>.pod.<cluster-name>,并不能直接通过hostname来访问对应的Pod。因此对kube2sky源码进行了修改,增加了对pod中容器的hostname的域名解析,以及集群中运行kube-proxy的主机hostname的解析。
2 kube2sky源码修改与解析
修改后的kube2sky.go(戳这里)
kube2sky监控kubernetes中services、endpoints、pods、nodes的变化,将IP地址和域名的对应关系写入到ETCD中;集群中的skyDNS从ETCD中读取这些对应关系进行域名解析。所以kube2sky和skyDNS间唯一的交流方式就是ETCD,增加hostname的解析即往ETCD中增加hostname与IP地址的对应关系。kube2sky通过访问kube-apiserver来获取集群信息,同时通过watch函数来监听IP地址是否发生了变化,如果发生了变化即更新ETCD中的记录。
在源码中有个细节可以注意下:对于传入的--domain参数,如果参数不带最后一点,则程序中会自动加上这一点。即"--domain=domeos.sohu"和"--domain=domeos.sohu."是一样的。
3 制作kube2sky镜像
1) 安装go
$ yum install go
2) 创建相应目录
$ mkdir /tmp/kube2sky
$ export GOPATH=/tmp/kube2sky
$ cd /tmp/kube2sky
3) 编译安装skyDNS
$ go get github.com/skynetservices/skydns
$ cd $GOPATH/src/github.com/skynetservices/skydns
$ go build -v
$ cp $GOPATH/bin/skydns /usr/bin
4) 安装godep
$ go get github.com/tools/godep
$ cp $GOPATH/bin/godep /usr/bin
5) 下载kube2sky编译依赖
$ go get -d github.com/GoogleCloudPlatform/kubernetes/cluster/addons/dns/kube2sky
kube2sky依赖整个k8s项目,因此要在该项目下进行编译。文件很多速度很慢,耐心等待。
结束后会发现报缺少两个依赖包,原因是GFW的存在导致下不下来,因此需要手工下载并放到相应路径下:
| 依赖包 | 下载地址 | 目录位置 | 注意事项 | 
| golang.org/x/net | https://github.com/golang/net | $GOPATH/
 src/golang.org/x/net  | 
要将目录名改一致 | 
| golang.org/x/crypto | https://github.com/golang/crypto | $GOPATH/
 src/golang.org/x/crypto  | 
要将目录名改一致 | 
然后在$GOPATH目录下再执行一次:
$ go get -d github.com/GoogleCloudPlatform/kubernetes/cluster/addons/dns/kube2sky
此时显示已经正常下载。
6) 编译kube2sky
进入 $GOPATH/src/github.com/GoogleCloudPlatform/kubernetes/cluster/addons/dns/kube2sky/ 目录,用之前修改过的kube2sky.go替换此处的kube2sky.go。
使用docker container来编译则直接:make kube2sky。
查看Makefile文件可以发现实际上是使用cgo来编译的,所以也可以直接在主机上编译,但这种编译出来的kube2sky程序与主机平台相关:
$ GOOS=linux GOARCH=amd64 CGO_ENABLED= go build -a -installsuffix cgo --ldflags '-w' ./kube2sky.go
编译完成后在该目录下即生成了kube2sky可执行文件。
7) 创建kube2sky镜像
kube2sky的Dockerfile:
FROM private-registry.sohucs.com/sohucs/base-rh7:1.0
MAINTAINER openxxs <openxxs@gmail.com>
COPY kube2sky.go /
COPY kube2sky /
RUN chmod +x /kube2sky
CMD ["/kube2sky"]
skyDNS的Dockerfile:
FROM private-registry.sohucs.com/sohucs/base-rh7:1.0
MAINTAINER openxxs <openxxs@gmail.com>
COPY skydns /
RUN chmod +x /skydns
CMD ["/skydns"]
构建并放入私有仓库中:
$ cd kube2sky/build/path
$ docker build -t private-registry.sohucs.com/domeos/kube2sky:1.1 . $ docker push private-registry.sohucs.com/domeos/kube2sky:1.1
$ cd skydns/build/path $ docker build -t private-registry.sohucs.com/domeos/skydns:1.0 . $ docker push private-registry.sohucs.com/domeos/skydns:1.0
4 部署skyDNS
启动kubelet时加DNS配置参数:--cluster_dns=172.16.40.1 --cluster_domain=domeos.sohu。这里尝试过加多个--cluster_dns地址,但只有最后加的配置有效。在部署时尝试过service形式部署和HostPort形式部署,对于集群内的域名解析两种方式都可以正常工作。如果希望在主机节点上也使用这套DNS解析,HostPort形式更适合。
1)以service形式部署
与上篇文章的部署方式不同,本文不再将ETCD、kube2sky和skyDNS放在同一个Pod中,而是独立出来。例子如下:
apiVersion: v1
kind: Service
metadata:
name: skydns-svc
labels:
app: skydns-svc
version: v9
spec:
selector:
app: skydns
version: v9
type: ClusterIP
clusterIP: 172.16.40.1
ports:
- name: dns
port:
protocol: UDP
- name: dns-tcp
port:
protocol: TCP
---
apiVersion: v1
kind: ReplicationController
metadata:
name: skydns
labels:
app: skydns
version: v9
spec:
replicas:
selector:
app: skydns
version: v9
template:
metadata:
labels:
app: skydns
version: v9
spec:
containers:
- name: skydns
image: private-registry.sohucs.com/domeos/skydns:1.0
command:
- "/skydns"
args:
- "--machines=http://10.16.42.200:4012"
- "--domain=domeos.sohu"
- "--addr=0.0.0.0:53"
ports:
- containerPort:
name: dns-udp
protocol: UDP
- containerPort:
name: dns-tcp
protocol: TCP
---
apiVersion: v1
kind: ReplicationController
metadata:
name: kube2sky
labels:
app: kube2sky
version: v9
spec:
replicas:
selector:
app: kube2sky
version: v9
template:
metadata:
labels:
app: kube2sky
version: v9
spec:
containers:
- name: kube2sky
image: private-registry.sohucs.com/domeos/kube2sky:1.1
command:
- "/kube2sky"
args:
- "--etcd-server=http://10.16.42.200:4012"
- "--domain=domeos.sohu"
- "--kube_master_url=http://10.16.42.200:8080"
上述yaml文件中创建了服务地址为172.16.40.1的DNS服务,并创建了与之对应的kube2sky和skyDNS的RC。skyDNS中的--machines参数为ETCD的地址,这里直接用k8s集群的ETCD;--domain为域名的后缀;--addr为域名服务的地址和端口。kube2sky中--etcd-server为ETCD地址,--kube_master_url为k8s的apiserver地址。
$ kubectl create -f dns.yaml
$ kubectl get pods | grep -E "skydns|kube2sky"
kube2sky-yylub 1/1 Running 0 1d
skydns-dteml 1/1 Running 0 1d
$ kubectl get service | grep skydns
skydns-svc 172.16.40.1 <none> 53/UDP,53/TCP app=skydns,version=v9 1d
可以看到skyDNS已经正常运行了。
2)以HostPort形式部署
apiVersion: v1
kind: ReplicationController
metadata:
name: skydns
labels:
app: skydns
version: v9
spec:
replicas:
selector:
app: skydns
version: v9
template:
metadata:
labels:
app: skydns
version: v9
spec:
containers:
- name: skydns
image: private-registry.sohucs.com/domeos/skydns:1.0
command:
- "/skydns"
args:
- "--machines=http://10.16.42.200:4012"
- "--domain=domeos.sohu"
- "--addr=0.0.0.0:53"
ports:
- containerPort:
hostPort:
name: dns-udp
protocol: UDP
- containerPort:
hostPort:
name: dns-tcp
protocol: TCP
dnsPolicy: ClusterFirst
nodeName: bx-42-197
hostNetwork: true
restartPolicy: Always
---
apiVersion: v1
kind: ReplicationController
metadata:
name: kube2sky
labels:
app: kube2sky
version: v9
spec:
replicas:
selector:
app: kube2sky
version: v9
template:
metadata:
labels:
app: kube2sky
version: v9
spec:
containers:
- name: kube2sky
image: private-registry.sohucs.com/domeos/kube2sky:1.1
command:
- "/kube2sky"
args:
- "--etcd-server=http://10.16.42.200:4012"
- "--domain=domeos.sohu"
- "--kube_master_url=http://10.16.42.200:8080"
dnsPolicy: ClusterFirst
restartPolicy: Always
HostPort形式并不需要创建service,创建skyDNS时需要设置hostNetwork属性为true,同时设置nodeName以指定skyDNS运行在哪个节点上(例子中指定为bx-42-197的节点上)。在启动kubelet时的--cluster_dns参数值为bx-42-197的IP地址,即--cluster_dns=10.16.42.197。这里要注意skyDNS占用了53端口,因此bx-42-197的53端口必须是可用的。同时,需要手工将skyDNS的服务地址和search域写入到各个node节点的/etc/resolv.conf文件中,内容如下:
nameserver 10.16.42.197
search default.svc.domeos.sohu svc.domeos.sohu domeos.sohu
5 测试
查看ETCD中的相关记录主要有三类:
$ etcdctl --peers=10.16.42.200: ls --recursive /skydns
......
# 这一类为pod的DNS记录,下例中kafka-1-wkfa1为pod的名字,而19d074a1为运行在pod中的一个container的hostname
/skydns/sohu/domeos/kafka--wkfa1
/skydns/sohu/domeos/kafka--wkfa1/19d074a1
......
# 这一类为service的DNS记录
/skydns/sohu/domeos/svc/default/kafka-svc-
/skydns/sohu/domeos/svc/default/kafka-svc-/b56639fb
......
# 这一类为主机的DNS记录
/skydns/sohu/domeos/bx-42-198
/skydns/sohu/domeos/bx-42-198/adc8794b
......
$ etcdctl --peers=10.16.42.200: get /skydns/sohu/domeos/kafka--wkfa1/19d074a1
{"host":"172.28.0.12","priority":,"weight":,"ttl":}
$ etcdctl --peers=10.16.42.200: get /skydns/sohu/domeos/svc/default/kafka-svc-/b56639fb
{"host":"172.16.50.1","priority":,"weight":,"ttl":}
$ etcdctl --peers=10.16.42.200:4012 get /skydns/sohu/domeos/bx-42-198/adc8794b
{"host":"10.16.42.198","priority":10,"weight":10,"ttl":30}
可以看到Pod的hostname和主机节点的hostname被加入了记录,service的DNS记录依旧保留。
通过 docker exec 进入任一运行中的container进行测试:
$ docker exec -it 0d0874df9e15 /bin/sh
# 查看resolv.conf文件,可以看到DNS服务被加进来了
$ cat /etc/resolv.conf
nameserver 172.16.40.1
nameserver 192.168.132.1
search default.svc.domeos.sohu svc.domeos.sohu domeos.sohu
options ndots:
# 测试解析其它container的hostname,解析成功
$ ping kafka--wkfa1 -c
PING kafka--wkfa1.domeos.sohu (172.28.0.12) () bytes of data.
# 测试解析k8s的service,解析成功
$ ping kafka-svc- -c
PING kafka-svc-.default.svc.domeos.sohu (172.16.50.1) () bytes of data.
# 测试解析主机的hostname,解析成功
$ ping bx-- -c
PING bx--.domeos.sohu (10.16.42.198) () bytes of data.
通过hostname访问成功!
在k8s中搭建可解析hostname的DNS服务的更多相关文章
- 在 k8S 中搭建 SonarQube 7.4.9 版本(使用 PostgreSQL 数据库)
		
搭建 SonarQube 和 PostgreSQL 服务 本文搭建的 SonarQube 版本是 7.4.9-community,由于在官方文档中声明 7.9 版本之后就不再支持使用 MySQL 数据 ...
 - K8S中如何跨namespace 访问服务?为什么ping不通ClusterIP?
		
1.K8S中如何跨namespace 访问服务? 2.在Pod中为什么ping不通ClusterIP? 简述: Rancher2.0中的一个用户,在K8S环境中,创建两个namespace,对应用进行 ...
 - 二进制部署1.23.4版本k8s集群-2-安装DNS服务
		
2.安装DNS服务 为什么要安装bind9? K8S中,使用Ingress进行7层流量调度,需要使用域名,进行7层调度. 以前使用绑定host的方法,来进行域名和IP地址的解析. 在K8S里,没有好的 ...
 - k8s中pod内dns无法解析的问题
		
用k8s创建了pod,然后进入pod后,发现在pod中无法解析www.baidu.com,也就是出现了无法解析外面的域名的问题.经过高人指点,做个小总结.操作如下. 一,将CoreDNS 的Confi ...
 - 在k8s中收集jvm异常dump文件到OSS
		
现状 加参数 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=logs/test.dump 可以实现在jvm发生内存错误后 会生成dump文件 方便开 ...
 - k8s中yaml文常见语法
		
在k8s中,所有的配置都是 json格式的.但为了读写方便,通常将这些配置写成yaml 格式,其运行的时候,还是会靠yaml引擎将其转化为json,apiserver 也仅接受json的数据类型. y ...
 - 从harbor部署到在k8s中使用
		
一.概述 harbor是什么呢?英文单词的意思是:港湾.港湾用来存放集装箱(货物的),而docker的由来正是借鉴了集装箱的原理,所以harbor是用于存放docker的镜像,作为镜像仓库使用.官方的 ...
 - k8s 环境搭建
		
转自:https://blog.csdn.net/running_free/article/details/78388948 一.概述 1.简介 官方中文文档:https://www.kubernet ...
 - 如何在 Windows 10 中搭建 Node.js 环境?
		
[编者按]本文作者为 Szabolcs Kurdi,主要通过生动的实例介绍如何在 Windows 10 中搭建 Node.js 环境.文章系国内 ITOM 管理平台 OneAPM 编译呈现. 在本文中 ...
 
随机推荐
- 20155323 2016-2017-2 《Java程序设计》第6周学习总结
			
20155323 2016-2017-2 <Java程序设计>第6周学习总结 教材学习内容总结 串流:衔接数据的来源和目的地就是串流对象. I/O操作主要是指使用Java进行输入,输出操作 ...
 - MFC自动生成代码详解(一)
			
首先声明这篇博客是给MFC刚刚上路的coder准备的,老鸟们就自觉无视我吧! 大家有没有感觉,创建MFC工程时他总会生成一大堆文件一大堆代码.虽然给我们带来了便利,但是调试的时候碰到这些代码总是畏首畏 ...
 - hdu 4993
			
http://acm.hdu.edu.cn/showproblem.php?pid=4993 满足ax + by = c的x,y对数 水题,暴力 #include <cstdio> #in ...
 - JAVA实现WC.exe功能
			
项目要求 实现一个统计程序,它能正确统计程序文件中的字符数.单词数.行数,以及还具备其他扩展功能,并能够快速地处理多个文件. 具体功能要求: 程序处理用户需求的模式为: wc.exe [paramet ...
 - PHP环境的搭建及与nginx的集成
			
1. 去php官网下载最新稳定版(最新其实是7.0,为了兼容性,使用5.6.16) wget http://cn2.php.net/get/php-5.6.16.tar.gz/from/this/m ...
 - 转 UNIGUI安装教程、使用例子
			
转 UNIGUI安装教程.使用例子 http://my.oschina.net/u/582827/blog/203429?p={{currentPage-1}} 转 uniGui安装教程.使用例子 发 ...
 - what is HTTP OPTIONS verb
			
The options verb is sent by browser to see if server accept cross origin request or not, this proces ...
 - sqlserver错误2,error 40
			
打开配置管理器:开始-> sqlserver2014->配置工具->配置管理器 选择sqlserver服务,并将右侧箭头的指向右击设为启动就OK了
 - K8S+GitLab-自动化分布式部署ASP.NET Core(一) 部署环境
			
一.部署流程介绍 开发人员通过Git上传asp.net core 项目到Gilab,并编写好.gitlab-ci.yml , GitLab-Runner 自动拉取代码,然后进行Build,编译,单元测 ...
 - gridview获取选中行索引及当前行数据
			
gridview获取选中行索引及当前行数据 一.非直接绑定数据: <!--前台传值--> <asp:TemplateField HeaderText="操作"&g ...