Kubernetes技术分析之DNS


【编者的话】Docker的流行激活了一直不温不火的PaaS,随着而来的是各类Micro-PaaS的出现,Kubernetes是其中最具代表性的一员,它是Google多年大规模容器管理技术的开源版本。本系列文章将逐一分析Kubernetes, 本文主要讲解如何开启DNS支持,以及其原理和使用方式。

1.开启DNS

Kubernetes支持2种服务发现方式,环境变量和DNS,其中环境变量是默认支持的,但是环境变量方式存在限制:Pod必须在Service之后创建,DNS则没有这个限制。

DNS是一种Cluster Add-on, 它随Kubernetes部署,但是需要配置启动:

- cluster turn-up

如果使用cluster turn-up,需要配置cluster/gce/config-default.sh
ENABLE_CLUSTER_DNS=true
DNS_SERVER_IP="10.0.0.10"
DNS_DOMAIN="cluster.local"
DNS_REPLICAS=1

- 手动方式

首先启动DNS server ReplicationController和Service,
配置文件模板:https://github.com/GoogleCloud ... s/dns

skydns-rc.yaml:
apiVersion: v1
kind: ReplicationController
metadata:
name: kube-dns-v6
namespace: kube-system
labels:
k8s-app: kube-dns
version: v6
kubernetes.io/cluster-service: "true"
spec:
replicas: 1
selector:
k8s-app: kube-dns
version: v6
template:
metadata:
  labels:
    k8s-app: kube-dns
    version: v6
    kubernetes.io/cluster-service: "true"
spec:
  containers:
  - name: etcd
    image: gcr.io/google_containers/etcd:2.0.9
    resources:
      limits:
        cpu: 100m
        memory: 50Mi
    command:
    - /usr/local/bin/etcd
    - -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
  - name: kube2sky
    image: gcr.io/google_containers/kube2sky:1.11
    resources:
      limits:
        cpu: 100m
        memory: 50Mi
    args:
    # command = "/kube2sky"
    - --kube_master_url=http://192.168.3.146:8080 #change to your master url
    - -domain=cluster.local
  - name: skydns
    image: gcr.io/google_containers/skydns:2015-03-11-001
    resources:
      limits:
        cpu: 100m
        memory: 50Mi
    args:
    # command = "/skydns"
    - -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
  dnsPolicy: Default  # Don't use cluster DNS.

skydns-svc.yaml:
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.210.250
ports:
- name: dns
port: 53
protocol: UDP
- name: dns-tcp
port: 53
protocol: TCP

创建后可以查看:
$ kubectl --namespace="kube-system" get pods
NAME                READY     STATUS    RESTARTS   AGE
kube-dns-v6-5y317   3/3       Running   0          2d

$ kubectl --namespace="kube-system" get services
NAME       LABELS               SELECTOR             IP(S)            PORT(S)
kube-dns   k8s-app=kube-dns...  k8s-app=kube-dns     10.254.210.250   53/UDP,53/TCP

DNS Server启动完成后,还需要配置kubelet:
--cluster_dns=10.254.210.250  #DNS service ip
--cluster_domain=cluster.local #default local domain

部署好的话可以验证下,现有以下services:
$ kubectl get services
NAME            LABELS                 SELECTOR            IP(S)            PORT(S)
frontend        name=frontend          name=frontend       10.254.159.131   80/TCP
redis-master    name=redis-master      name=redis-master   10.254.169.230   6379/TCP
redis-slave     name=redis-slave       name=redis-slave    10.254.70.184    6379/TCP

选择一个pod,进行DNS验证:
$ kubectl exec busybox -- nslookup frontend        
Server:    10.254.210.250
Address 1: 10.254.210.250

Name:      frontend
Address 1: 10.254.159.131

$ kubectl exec busybox -- nslookup redis-master
Server:    10.254.210.250
Address 1: 10.254.210.250

Name:      redis-master
Address 1: 10.254.169.230

$ kubectl exec busybox -- nslookup redis-slave
Server:    10.254.210.250
Address 1: 10.254.210.250

Name:      redis-slave
Address 1: 10.254.70.184

可以看到查询处理的ip和Service ip一致,说明DNS工作正常。

2.DNS说明

DNS Server包含3部分:
  • skyDNS: 提供DNS解析服务
  • etcd:用于skyDNS的存储
  • kube2sky:连接Kubernetes和skyDNS


实际上kube2sky会监听Kubernetes,当有新的Service创建时,就生成相应记录到skyDNS,一个Service包括2条记录:
<service_name>.<namespace_name>.<domain>
<service_name>.<namespace_name>.svc.<domain>

然后kubelet会在容器启动的时候配置根据/etc/resolv.conf:
$ kubectl exec busybox cat /etc/resolv.conf 
nameserver 10.254.210.250
nameserver 218.85.157.99
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

可以看到配置了DNS Service IP作为域名服务器,然后设置了default.svc.cluster.local svc.cluster.local cluster.local作为默认域名。

以redis-master service为例:
$ kubectl exec busybox -- nslookup redis-master
Server:    10.254.210.250
Address 1: 10.254.210.250

Name:      redis-master
Address 1: 10.254.169.230

$ kubectl exec busybox -- nslookup redis-master.default.cluster.local
Server:    10.254.210.250
Address 1: 10.254.210.250

Name:      redis-master.default.cluster.local
Address 1: 10.254.169.230

$ kubectl exec busybox -- nslookup redis-master.default.svc.cluster.local
Server:    10.254.210.250
Address 1: 10.254.210.250

Name:      redis-master.default.svc.cluster.local
Address 1: 10.254.169.230

对于Headless services,域名则对于所有Endpoints:
$ kubectl describe service frontend-headless
Name:           frontend-headless
Namespace:      default
Labels:         name=frontend-headless
Selector:               name=frontend
Type:           ClusterIP
IP:                None
Port:                  <unnamed> 80/TCP
Endpoints:        10.1.14.19:80,10.1.79.47:80,10.1.79.48:80
Session Affinity:     None
No events.

$ kubectl exec busybox -- nslookup frontend-headless
Server:    10.254.210.250
Address 1: 10.254.210.250

Name:      frontend-headless
Address 1: 10.1.14.19
Address 2: 10.1.79.47
Address 3: 10.1.79.48

参考



==================================================
作者简介
吴龙辉,现任网宿科技高级运营工程师,致力于云计算PaaS的研究和实践,活跃于CloudFoundry、Docker、Kubernetes等开源社区,贡献代码和撰写技术文档。

邮箱:wulh@chinanetcenter.com/wlh6666@qq.com

12 个评论

怎么理解headless service ?
没有VIP的service
https://github.com/GoogleCloudPlatform/kubernetes/blob/v1.0.1/docs/services.md#headless-services
使用DNS时,DNS server如何获得到k8s中pod的信息(etcd中)?如果dns server是本node的proxy感觉更合理一些
有个kube2sky组件,kube2sky会监听Kubernetes,当有新的Service创建时,就生成相应记录到skyDNS
请问,如果在创建Service过程中,kube2sky挂掉或未运行,在下次kube2sky重新启动后,会自动将挂掉期间创建的Service,生产相应记录到skyDNS吗?
会的
我也按上面的步骤做的,在宿主机上可以解释,在 pods 里就解析不了啊!
大神,我按照您的这个文章搭建,最终容器都起来了,为dns server指定了10.254.210.250的ip,但是发现容器内部和宿主机上都无法解析出来,宿主机和容器内部均无法访问10.254.210.250这个ip,大神知道是什么原因吗?还有请教一下busybox是用来做什么的?
先telnet 10.254.210.250 53试试
10.254.210.250的路由和转发有kube-proxy负责,具体的看kube-proxy有没有运行正常。

ps:
busybox只是个简单镜像,用来做验证,没什么特别的。
telnet 不通,master节点上kube-proxy没有启动,minion上的kube-proxy是起来了的,后尝试将master上的kube-proxy启动,但是仍旧无法解析。
每次执行nslookup的时候,都会耗时很长(30s)
这个有遇到过吗
大神, 我每次dns解析不同的service都得到的是同一个ip地址, 而且与那些service的cluster-ip不一致, 大神求帮助...

要回复文章请先登录注册