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/GoogleCloudPlatform/kubernetes/tree/v1.0.1/cluster/addons/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等開源社區,貢獻代碼和撰寫技術文檔。
郵箱:[email protected]/[email protected]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章