Kubernetes DNS部署
2016-04-12 15:12
771 查看
在kubernetes中每一个service都会被分配一个虚拟IP,每一个Service在正常情况下都会长时间不会改变,这个相对于pod的不定IP,对于集群中APP的使用相对是稳定的。但是Service的信息注入到pod目前使用的是环境变量的方式,并且十分依赖于pod(rc)和service的创建顺序,这使得这个集群看起来又不那么完美,于是kubernetes以插件的方式引入了DNS系统,利用DNS对Service进行一个映射,这样我们在APP中直接使用域名进行引用,避免了之前的变量泛滥问题,也避免了创建顺序的尴尬局面。
skyDNS: 提供DNS解析服务
etcd:用于skyDNS的存储
kube2sky:连接Kubernetes和skyDNS
(1)kube2sky容器需要访问Kubernetes Master,需要配置Master所在物理主机的IP地址和端口
(2)kube2sky容器和skydns容器的启动参数-domain,设置Kubernetes集群中Service所属的域名,本例中为cluster.local。启动后,kube2sky会监听Kubernetes,当有新的Service创建时,就会生成相应的记录并保存到etcd中。kube2sky为每个Service生成两条记录:
(3)skydns的启动参数-addr=0.0.0.0:53表示使用本机TCP和UDP的53端口提供服务。
创建DNS服务的Service配置文件如下:
注意:skydns服务使用的clusterIP需要我们指定一个固定的IP地址,每个Node的Kubelet进程都将使用这个IP地址,不能通过Kubernetes自动分配。
另外,这个IP地址需要在kube-apiserver启动参数–service-cluster-ip-range指定的IP地址范围内。
–cluster_domain=cluster.local 为DNS服务中设置的域名
修改/etc/kubernetes/kubelet:
或者修改/usr/lib/systemd/system/kubelet.service
创建完成后,查看到系统创建的RC、Pod和Service都已创建成功:
然后我们创建一个普通的Service,以redis-master服务为例:
查看创建出来的Service:
运行kubectl create -f busybox.yaml完成创建。
在该容器成功启动后,通过kubectl exec nslookup 进行测试:
可以看到,通过DNS服务器10.254.0.3成功找到了名为”redis-master”服务的IP地址:10.254.7.160
如果某个Service属于自定义的命名空间,那么进行Service查找时,需要带个namespace的名字。下面以查看kube-dns服务为例:
如果仅使用”kube-dns”来进行查找,则将会失败:
nslookup: can’t resolve ‘kube-dns’
查看多个容器组成的Pod时,要添加-c选项指定容器的名称
查看etcd存储的Service信息
可以看到在skydns键下面,根据我们配置的域名(cluster.local)生成了local/cluster子键,接下来是namespace(default和kube-system)和svc(下面也按namespace生成子键)。
查看redis-master服务对应的键值:
可以看到,redis-master服务对应的完整域名为redis-master.default.cluster.local,并且其IP地址为10.254.7.160。
(2)根据Kubelet启动参数的设置(–cluster_dns),Kubelet会在每个新创建的Pod中设置DNS域名解析配置文件/etc/resolv.conf文件,在其中增加了一条nameserver配置和一条search配置:
通过名字服务器10.254.0.3访问的实际上是skydns在53端口上提供的DNS解析服务。
(3)应用程序就能够像访问网站域名一样,仅仅通过服务的名字就能访问到服务了。
例如,设置redis-slave的启动脚本为:
redis-server –slaveof redis-master 6379
创建redis-slave的Pod并启动它。
之后,我们可以登录redis-slave容器中查看,其通过DNS域名服务找到了redis-master的IP地址10.254.7.160,并成功建立了连接。
通过DNS设置,对于其他Service(服务)的查询将可以不再依赖系统为每个Pod创建的环境变量,而是直接使用Service的名字就能对其进行访问,使得应用程序中的代码更简洁了。
参考资料
书:Kubernetes权威指南 P250
skyDNS: 提供DNS解析服务
etcd:用于skyDNS的存储
kube2sky:连接Kubernetes和skyDNS
1. skydns配置文件
创建DNS服务的RC配置文件,在这个RC配置中包含了3个Container的定义[root@docker1 dns]# cat skydns-rc.yaml | grep -v '#' apiVersion: v1 kind: ReplicationController metadata: name: kube-dns-v9 namespace: kube-system labels: k8s-app: kube-dns version: v9 kubernetes.io/cluster-service: "true" spec: replicas: 1 selector: k8s-app: kube-dns version: v9 template: metadata: labels: k8s-app: kube-dns version: v9 kubernetes.io/cluster-service: "true" spec: containers: - name: etcd image: kube-registry:5000/etcd resources: limits: cpu: 100m memory: 50Mi command: - /usr/local/bin/etcd - -data-dir - /var/etcd/data - -listen-client-urls - http://127.0.0.1:2379,http://127.0.0.1:4001 - -advertise-client-urls - http://127.0.0.1:2379,http://127.0.0.1:4001 - -initial-cluster-token - skydns-etcd volumeMounts: - name: etcd-storage mountPath: /var/etcd/data - name: kube2sky image: kube-registry:5000/kube2sky resources: limits: cpu: 100m memory: 50Mi args: - -domain=cluster.local - -kube_master_url=http://192.168.123.201:8080 - name: skydns image: kube-registry:5000/skydns resources: limits: cpu: 100m memory: 50Mi args: - -machines=http://localhost:4001 - -addr=0.0.0.0:53 - -domain=cluster.local ports: - containerPort: 53 name: dns protocol: UDP - containerPort: 53 name: dns-tcp protocol: TCP volumes: - name: etcd-storage emptyDir: {}
(1)kube2sky容器需要访问Kubernetes Master,需要配置Master所在物理主机的IP地址和端口
(2)kube2sky容器和skydns容器的启动参数-domain,设置Kubernetes集群中Service所属的域名,本例中为cluster.local。启动后,kube2sky会监听Kubernetes,当有新的Service创建时,就会生成相应的记录并保存到etcd中。kube2sky为每个Service生成两条记录:
<service_name>.<namespace_name>.<domain> <service_name>.<namespace_name>.svc.<domain>
(3)skydns的启动参数-addr=0.0.0.0:53表示使用本机TCP和UDP的53端口提供服务。
创建DNS服务的Service配置文件如下:
[root@docker1 dns]# cat skydns-svc.yaml | grep -v '#' apiVersion: v1 kind: Service metadata: name: kube-dns namespace: kube-system labels: k8s-app: kube-dns kubernetes.io/cluster-service: "true" kubernetes.io/name: "KubeDNS" spec: selector: k8s-app: kube-dns clusterIP: 10.254.0.3 ports: - name: dns port: 53 protocol: UDP - name: dns-tcp port: 53 protocol: TCP
注意:skydns服务使用的clusterIP需要我们指定一个固定的IP地址,每个Node的Kubelet进程都将使用这个IP地址,不能通过Kubernetes自动分配。
另外,这个IP地址需要在kube-apiserver启动参数–service-cluster-ip-range指定的IP地址范围内。
2. 修改每个Node上的Kubelet启动参数
–cluster_dns=10.254.0.3 为DNS服务的ClusterIP地址–cluster_domain=cluster.local 为DNS服务中设置的域名
修改/etc/kubernetes/kubelet:
# vim /etc/kubernetes/kubelet KUBELET_ARGS="--cluster_dns=10.254.0.3 --cluster_domain=cluster.local"
或者修改/usr/lib/systemd/system/kubelet.service
[root@docker2 ~]# cat /usr/lib/systemd/system/kubelet.service [Unit] Description=Kubernetes Kubelet Server Documentation=https://github.com/GoogleCloudPlatform/kubernetes After=docker.service Requires=docker.service [Service] WorkingDirectory=/var/lib/kubelet EnvironmentFile=-/etc/kubernetes/config EnvironmentFile=-/etc/kubernetes/kubelet ExecStart=/usr/bin/kubelet --cluster_dns=10.254.0.3 --cluster_domain=cluster.local \ $KUBE_LOGTOSTDERR \ $KUBE_LOG_LEVEL \ $KUBELET_API_SERVER \ $KUBELET_ADDRESS \ $KUBELET_P 4000 ORT \ $KUBELET_HOSTNAME \ $KUBE_ALLOW_PRIV \ $KUBELET_ARGS Restart=on-failure [Install] WantedBy=multi-user.target
3. 创建skydns Pod和服务
通过kubectl create完成RC和Service的创建:[root@docker1 dns]# kubectl create -f skydns-rc.yaml replicationcontrollers/kube-dns-v9 [root@docker1 dns]# kubectl create -f skydns-svc.yaml services/kube-dns
创建完成后,查看到系统创建的RC、Pod和Service都已创建成功:
然后我们创建一个普通的Service,以redis-master服务为例:
[root@docker1 redis_yaml]# cat redis-master-service.yaml apiVersion: v1 kind: Service metadata: name: redis-master labels: name: redis-master spec: selector: name: redis-master ports: - port: 6379 targetPort: 6379
查看创建出来的Service:
[root@docker1 redis_yaml]# kubectl create -f redis-master-service.yaml [root@docker1 redis_yaml]# kubectl get services NAME LABELS SELECTOR IP(S) PORT(S) redis-master name=redis-master name=redis-master 10.254.7.160 6379/TCP
4. 通过DNS查找Service
使用一个带有nslookup工具的Pod来验证DNS服务是否能够正常工作:[root@docker1 demo]# cat busybox.yaml apiVersion: v1 kind: Pod metadata: name: busybox namespace: default spec: containers: - image: kube-registry:5000/busybox command: - sleep - "3600" imagePullPolicy: IfNotPresent name: busybox restartPolicy: Always
运行kubectl create -f busybox.yaml完成创建。
在该容器成功启动后,通过kubectl exec nslookup 进行测试:
[root@docker1 demo]# kubectl exec busybox -- nslookup redis-master Server: 10.254.0.3 Address 1: 10.254.0.3 Name: redis-master Address 1: 10.254.7.160
可以看到,通过DNS服务器10.254.0.3成功找到了名为”redis-master”服务的IP地址:10.254.7.160
如果某个Service属于自定义的命名空间,那么进行Service查找时,需要带个namespace的名字。下面以查看kube-dns服务为例:
[root@docker1 demo]# kubectl exec busybox -- nslookup kube-dns.kube-system Server: 10.254.0.3 Address 1: 10.254.0.3 Name: kube-dns.kube-system Address 1: 10.254.0.3
如果仅使用”kube-dns”来进行查找,则将会失败:
nslookup: can’t resolve ‘kube-dns’
查看多个容器组成的Pod时,要添加-c选项指定容器的名称
# kubectl logs kube-dns-v9-curdr --namespace=kube-system Error from server: a container name must be specified for pod kube-dns-v9-curdr # kubectl logs kube-dns-v9-curdr -c skydns --namespace=kube-system
5. DNS服务的工作原理解析
(1)kube2sky容器应用通过调用Kubernetes Master的API获得集群中所有Service的信息,并持续监控新Service的生成,然后定稿etcd中。查看etcd存储的Service信息
# kubectl exec kube-dns-v9-evgl6 -c etcd --namespace=kube-system etcdctl ls /skydns/local/cluster /skydns/local/cluster/default /skydns/local/cluster/svc /skydns/local/cluster/kube-system
可以看到在skydns键下面,根据我们配置的域名(cluster.local)生成了local/cluster子键,接下来是namespace(default和kube-system)和svc(下面也按namespace生成子键)。
查看redis-master服务对应的键值:
# kubectl exec kube-dns-v9-evgl6 -c etcd --namespace=kube-system etcdctl get /skydns/local/cluster/default/redis-master {"host":"10.254.7.160","priority":10,"weight":10,"ttl":30,"targetstrip":0}
可以看到,redis-master服务对应的完整域名为redis-master.default.cluster.local,并且其IP地址为10.254.7.160。
(2)根据Kubelet启动参数的设置(–cluster_dns),Kubelet会在每个新创建的Pod中设置DNS域名解析配置文件/etc/resolv.conf文件,在其中增加了一条nameserver配置和一条search配置:
nameserver 10.254.0.3 nameserver 202.96.128.86 search default.svc.cluster.local svc.cluster.local cluster.local options ndots:5
通过名字服务器10.254.0.3访问的实际上是skydns在53端口上提供的DNS解析服务。
(3)应用程序就能够像访问网站域名一样,仅仅通过服务的名字就能访问到服务了。
例如,设置redis-slave的启动脚本为:
redis-server –slaveof redis-master 6379
创建redis-slave的Pod并启动它。
之后,我们可以登录redis-slave容器中查看,其通过DNS域名服务找到了redis-master的IP地址10.254.7.160,并成功建立了连接。
通过DNS设置,对于其他Service(服务)的查询将可以不再依赖系统为每个Pod创建的环境变量,而是直接使用Service的名字就能对其进行访问,使得应用程序中的代码更简洁了。
参考资料
书:Kubernetes权威指南 P250
相关文章推荐
- 如何使用 bind 设置 DNS 服务器
- centos6.5上安装docker
- docker容器的网络信息查看
- 网友问答之:AD、DNS转发器、WINS不能自动启动
- 使用批处理命令设置windows系统的ip地址和dns附图
- 保护DNS服务器的几点方法小结
- DNS的工作原理图解说明
- 计算机名DNS网关IP(大家可以用来学习)
- 在windows下的安装Docker的教程
- 8个你可能不知道的Docker知识
- CMD和vbs修改 IP地址及DNS的实现代码
- linux下如何快速让DNS修改生效
- linux中查询dns示例
- MySQL DNS的使用过程详细分析
- winmydns DNS服务器架设
- Shell脚本获取本地网卡IP、mac地址、子网掩码、dns IP、外网IP
- windows服务器 的DNS服务器备份与还原步骤小结
- 浅析PHP程序防止ddos,dns,集群服务器攻击的解决办法
- Linux命令行修改IP、网关、DNS的方法
- 在Docker中自动化部署Ruby on Rails的教程