Kubernetes DNS 服务配置案例

在 Kubernetes 系统中,Pod 在访问其他 Pod 的 Service 时,可以通过两种服务发现方式完成,即环境变量和 DNS 方式。但是使用环境变量是有限制条件的,即 Service 必须在 Pod 之前被创建出来,然后系统才能在新建的 Pod 中自动设置与 Service 相关的环境变量。DNS 则没有这个限制,其通过全局的 DNS 服务器来完成服务的注册与发现。

Kubernetes 提供的 DNS 由以下三个组件组成:

  1. etcd: DNS 存储
  2. kube2sky: 将 Kubernetes Master 中的 Service(服务)注册到 etcd。
  3. skyDNS: 提供 DNS 域名解析服务。

这三个组件以 Pod 的方式启动和运行,所以在一个 Kubernetes 集群中,它们都可能被调度到任意一个 Node 节点上去。为了能够使它们之间网络互通,需要将各 Pod 之间的网络打通。

skydns 配置文件

首先创建 DNS 服务的 ReplicationController 配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
apiVersion: v1
kind: ReplicationController
metadata:
name: kube-dns-v8
namespace: kube-system
labels:
k8s-app: kube-dns
version: v8
kubernetes.io/cluster-service: " true "
spec:
replicas: 1
selector:
k8s-app: kube-dns
version: v8
template:
metadata:
labels:
k8s-app: kube-dns
version: v8
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
- -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: gcr.io/google_containers/kube2sky:1.11
resources:
limits:
cpu: 100m
memory: 50Mi
args:
# command = " /kube2sky "
- --kube_master_url=http://192.168.1.128:8080
- -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
volumes:
- name: etcd-storage
emptyDir: {}
dnsPolicy: Default

需要修改的几个配置参数如下:

  • kube2sky 容器需要访问 Kubernetes Master,需要配置 Master 所在物理主机的 IP 地址和端口号,本例中设置参数 –kube_master_url 的值为 http://192.168.1.128:8080。
  • kube2sky 容器和 skydns 容器的启动参数 -domain,设置 Kubernetes 集群中 Service 所属的域名,本例中为 cluster.local。启动后,kube2sky 会监听 Kubernetes,当有新的 Service 创建时,就会生成相应的记录并保存到 etcd 中。kube2sky 为每个 Service 生成两条记录:
    • ..;
    • ..svc.
  • skydns 的启动参数 -addr=0.0.0.0:53 表示使用本机 TCP 和 UDP 的 53 端口提供服务。

创建 DNS 服务的 Service 配置文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: v1
kind: Service
metadata:
name: kube-dns
namespace: kube-system
labels:
k8s-app: kube-system
labels:
k8s-app: kube-dns
kubernetes.io/cluster-services: " true "
kubernetes.io/name: " KubeDNS "
spec:
selector:
k8s-app: kube-dns
clusterIP: 20.1.0.100
ports:
- name: dns
port: 53
protocol: UDP
- name: dns-tcp
port: 53
protocol: TCP

注意,skydns 服务使用的 clusterIP 需要我们指定一个固定的 IP 地址,每个 Node 的 Kubernetes 进程都将使用这个 IP 地址,不能通过 Kubernetes 自动分配。

另外,这个 IP 地址需要在 kube-apiserver 启动参数 –service-cluster-ip-range 指定的 IP 地址范围内。

修改每个 Node 上的 Kubelet 启动参数

修改每台 Node 上 Kubelet 的启动参数:

  • –cluster_dns=20.1.0.100,为 DNS 服务的 ClusterIP 地址;
  • –cluster_domain=cluster.local,为 DNS 服务中设置的域名。

然后重启 Kubelet 服务。

创建 skydns Pod 和服务

通过 kubectl create 完成 RC 和 Service 的创建:

1
2
# kubectl create -f skydns-rc.yaml
# kubectl create -f skydns-svc.yaml

创建完成后,可以查看系统创建的 RC、Pod、Service 是否创建成功:

1
# kubectl get rc|pods|services --namespace=kube-system

DNS 服务的工作原理

让我们看看 DNS 服务背后的工作原理。

kube2sky 容器应用通过调用 Kubernetes Master 的 API 获得集群中所有 Service 的信息,并持续监控新 Service 的生成,然后写入 etcd 中。

1
2
查看 etcd 中存储的 Service 信息
# kubectl exec kube-dns-v8-xxxxx -c etcd --namespace=kube-system etcdctl ls /skydns/local/cluster

根据 Kubelet 启动参数的设置(–cluster_dns),Kubelet 会在每个新创建的 Pod 中设置 DNS 域名解析配置文件 /etc/resolv.conf 文件,在其中增加了一条 nameserver 配置和一条 search 配置。

最后,应用程序就能够像访问网站域名一样,仅仅通过服务的名字就能访问到服务了。

通过 DNS 设置,对于其他 Service 的查询将可以不再依赖系统为每个 Pod 创建的环境变量,而是直接使用 Service 的名字就能对其进行访问,使得应用程序中的代码更加简洁。